Protect remote resources when served with nodejs - node.js

This is more of an architecture question involving nodejs as implementation.
I have on a folder not exposed by the webserver files that I want to offer to the user.
The way nodejs should expose the resource to the end user is via a one shot link, that once is consumed is no longer available.
The user through the entire experience should never know the real location of the file.
I'm sure this is a common architecture pattern, but I have never implemented something similar.
Looking at scalability, the resource shouldn't be copy either on HD or RAM, and if possible the solution should not relay on a DB token tracking system.
I don't necessary need a code implementation, but a detail explanation on how I should implement it
Thank you so much

Give user a cookie
Create a temporary association (in db) between cookie and a generated ID for the user (or the hash of it, if you want to be fancy)
Give user the ID
When user requests resource by ID:
Test to see if the ID (or its hash, if you want to be fancy) is in the DB
If it is, give the user the resource and destroy the association between the user and the resource ID
There's a db token tracking system. Hey, that's the only way.

One way to avoid depending on a DB, would be to maybe create a symbolic link in the filesystem (based on the token), that would be removed after a request for it. Would not work satisfactory on windows though.
Example (psuedo):
Create token (guid, or similar)
symlink guid -> actual file
once request is completed, remove symlink
However, I don't think there is a reliable way of knowing if the file was successfully downloaded, so you better prepare for that. Some sort of pingback when the file was completely downloaded is probably the most reliable way that I can think of right now.
For scalability, make sure that the symlink is on a shared file system. Clustered node.js instances on the same server, will be fine though.
If this needs to be restricted to an authenticated user, you could combine the guid with your auth token, and prepend/append it before looking for a file.

Related

How to persist data in a command-line application?

I want to build a command-line application using Go or Node.js. I want to make it multiuser, so a login feature is needed. I can implement the login feature but I don't understand where should I store the user data which can be fetched any moment at runtime.
The user data is needed to check if a user is logged in or not if he is logged in which user it is.
Need help with a method to store user data to check logged in status
Edit:
I had thought of this- If the config file is present that the user is logged in else not. Then I realized that if one tampers the file, the whole point of login feature will get invalid. I am guessing there must be a better way to do it, which I am trying to know by asking here
Many cli utilities opt to store their configuration as a plain text file on the user's home directory.
You can use any of the available configuration formats such as JSON, TOML, etc.
Although it's good to mention that this is not a secure way of storing data and if users should not be able to see others information in any way this is not the preferred way.

How to prevent snooping by user of Mac app?

I am creating a Chromium/Electron based Mac app. The app is essentially a browser for my customers to use a web service that I have no control over. My requirement is that users of my app (who may have root access on their Mac) should not be able to view the URLs the app is visiting, and should be unable to gain access to the cookies the app is storing. Normally it is not hard to MITM yourself, or attach a debugger to an app and dump memory to see the URLs and cookies.
How can I prevent these types of leaks to the user? If it's impossible, it may be acceptable to make it very hard so that a very high level of sophistication is needed.
Your users have full control of their devices, it is not possible to securely prevent them from proxying or exploring what your client-side app does. Obfuscation would seem like an option, but in the end, the http request that leaves your app will traverse the whole OS through different layers, and your user can easily observe that, if not else then in network packets (but usually much easier).
The only way it is possible to prevent the user from knowing what's happening is if you have your own backend. The frontend app (Electron) would make a request to your backend, which in turn could make any request with any parameters without the user being aware.
Note though that your backend could still be used as a proxy or oracle just like if the user was connecting to the real service. This might or might not be a problem in your case, depending on what you actually want to achieve and why.
The app is essentially a browser for my customers to use a web service that I have no control over. My requirement is that users of my app (who may have root access on their Mac) should not be able to view the URLs the app is visiting, and should be unable to gain access to the cookies the app is storing
Basically, you cannot (you could with the appropriate infrastructure. But you lack that infrastructure).
Network communications can be secured, to a point, using HTTPS (if you can't even use that, then you're completely out of luck - users wouldn't even need root access to the Mac to sniff traffic). You need to verify the server certificate to be sure you're connecting to the correct server.
One thing you might do - effectual just against wannabes, I'm afraid - is first run a test API call on some random server and verify that the connection either fully succeeds, with the proper server identification and matching IP, if the server exists, or that it properly fails if the server never existed. Anything else would be a telltale that someone has taken over the network layer, and at that point you could connect to a different server, making different calls, and lament that the server isn't answering properly.
Strings in memory can be (air quote) protected (end air quote) by having them available only for the shortest time, and otherwise stored in a different form - you can have for example an URL and a random byte sequence with the same length, then store the sequence and the XOR of the URL and the sequence. You can then reconstruct the URL every time you need it, remembering to clear it off any app caches it might find its way into. Also, just for the lols, you can keep a baker's dozen of different URLs sprinkled in the clear throughout the code. A memory dump at that point will turn out nothing useful.
Files, of course, can be encrypted with any one of several schemes - the files residing on the same machine that has to know how to decode them makes all such schemes ultimately vulnerable, but there again, you can try and obfuscate things. I once stored some information in a ZIP file - but it was just the header of an encrypted ZIP file, with the appropriate directory entry block glued at the end. The data were actually just gzipped in the clear, there was no password whatsoever. The guys that tried to decode the file thought it was a plain encrypted Zip file with the extension changed, wasted a significant amount of time with several Zip cracking tools, and ended up owing me a beer.
More than that, there is not much that can realistically be done.
A big advantage would be in outsourcing the API calls and "cookie" maintenance to an external service that you control, e.g. on Amazon AWS or Azure or similar. Then you could employ all kinds of protection schemes (for example: all outbound API calls could be stored in an opaque object, timestamped, nonced, and encrypted with your server's public key, and the responses sent encrypted with your client's unique key). Since this is relatively simple and cost-effective, it would also be my recommendation.

Meteor Security Permissions on Uploaded Images

I'm creating a Meteor chat app. I want users to be able to send images to each other, but users not in the group/conversation shouldn't be able to see the image. My first thought was to give an image a unique ID and store the image with this ID in a public folder in my or a 3rd party server.
For example, if the user uploads an image called "name.jpg", it could be stored in Amazon S3 as A3eedAcRCqCa32451.jpg. That way, anyone with the ID can access the image, but the only people with access to the ID would be those in the group chat, since I can ensure secure access using Meteor's publish and subscribe rules. However, this doesn't feel safe to me. Is my intuition right?
If yes, how else would I do it? I searched online and on StackOverflow and couldn't find another simple way to achieve this.
You usually have two things you can do when considering granting access to resources:
Authentication and access control
Indirect object references with sufficient entropy to make brute force attacks hopeless.
Point 1 is more or less obvious.
Point 2 is actually what you have already on your mind. To reason about the security of the second approach let's consider following:
The entropy of A3eedAcRCqCa32451.jpg is about 80 bits.
The count of the domain is 2^80 = 1208925819614629174706176.
An attacker can try to guess the secret.
Let's say, he can make 10 guesses a second and on average he will guess after |domain|/2 tries.
It would take the attacker ~2 mln years to guess.
Now the domain of 80 bits is a bit small from the security perspective. Make it 128 bits by using type 4 UUIDs. I believe you see where this is going.
It depends on the security level you want...
A more secure solution would be to store in a collection the imageId and userId of people that can access the image. When someone wants to access it, you just have to check if he's in the list of allowed users.
Then as you said you can use a 3rd party storage (personally I'm using ostrio:files with Dropbox integration, the docs about it aren't up to date but I made a pull request which was accepted on the dev branch with a working example, you can take a look at it here.)
The nice thing with ostrio:files is that it offers built-in functions like onAfterUpload or interceptDownload in which you can store data about access for the first and check if access is allowed for the second.

How secure are shared tables in CloudKit?

Imagine we are building a shared bookmarking app with the following tables:
Company (companyID)
User (userID, companyID)
Bookmark (bookmarkID, content, companyID)
A user should only be able to access the bookmarks which match their companyID.
Traditionally you would ensure this kind of security by not giving a client direct access to the database. Instead you would have a server that would authenticate the user, and the client would send a unique token to the server along with a request for Bookmarks. Once the server receives this token, it would know exactly which records in the Bookmarks table the user is allowed to access.
That's great, but what if you don't have a server, and you want to rely purely on CloudKit?
Since you don't have a server, it seems like you must allow full access to the Bookmarks table to each user. Then, the client side code would be responsible for preventing access to records that are off-limits. (E.g. When you send a retrieve Bookmark request, you would use a predicate such as companyID == 3.)
The question is how secure is a system like this which allows full access by the client, but limits it based solely on client side code?
(Note: For this question, assume an attacker jailbreaks their phone, and uses whatever means necessary to access data they aren't allowed to see. In the case where we were using a server, we don't care if they jailbreak their phone, since all requests still need to go through our servers. The only way they would be able to access data they can't see is if they found out the secret token that is assigned to another user. However, when the attacker has access to another user's phone, I'm assuming all bets are off: the attacker would be able to figure out the secret token that other client is using and then access that user's private data. Therefore, the original question I posed can ignore the case where the attacker has access to another person's phone, since even in the more secure version (with a server), all bets are off. In other words, assume the attacker has access to their own phone only for the following questions.)
Examples of things I am wondering:
Can the attacker figure out which credentials the client is using for CloudKit and then run custom queries against CloudKit?
Assuming I am using a predicate such as #"companyID == %#" and replacing the %# with the contents of a variable, can the attacker simply change the value of this variable before the query is sent?
Assuming I am using a predicate of the form #"companyID == 3", can the attacker simply change the string to #"true || companyID == 3" so that they get all records?
Can the attacker monitor network traffic and see requests that are being sent to CloudKit and then modify those using a man-in-the-middle technique?
Say I want to prevent duplicate companyIDs from being created so before I create a company, I run a query to fetch that companyID. Once I have the company stored in a local variable, I run code such as if companyID != nil { return } before I create the company. Can the attacker modify their client so that it doesn't execute this line of code? What if instead of companyID != nil, I use a boolean, companyExists. Would that make any difference?
Before I send a new bookmark to CloudKit to be saved, I run code such as bookmark[#"companyID"] = 3 to set the proper companyID. If the attacker changed this value to 4, for example, it would be a security violation. Can they do something of this nature?
Does the client matter? I'm primarily concerned with iOS, but what if I made an Android or JavaScript client? Would that make it any more/less secure?
Does the OS version matter? Should I only users to run the app if they are on the latest OS for maximum security, or does that not matter?
Are there any other things you can think of that would make this system less secure than the server based model? (I can think of at least one: If you had a bug in an old version of the app which printed the entire contents of a table, for example, there would be no easy way to correct this. A user could purposely avoid upgrading their app with the intent of stealing people's private data forever. The only way around this would be to migrate all the data to new tables that the old client doesn't know about. I'm sure this would be a pain.)

parse.com security

Recently I discovered how useful and easy parse.com is.
It really speeds up the development and gives you an off-the-shelf database to store all the data coming from your web/mobile app.
But how secure is it? From what I understand, you have to embed your app private key in the code, thus granting access to the data.
But what if someone is able to recover the key from your app? I tried it myself. It took me 5 minutes to find the private key from a standard APK, and there is also the possibility to build a web app with the private key hard-coded in your javascript source where pretty much anyone can see it.
The only way to secure the data I've found are ACLs (https://www.parse.com/docs/data), but this still means that anyone may be able to tamper with writable data.
Can anyone enlighten me, please?
As with any backend server, you have to guard against potentially malicious clients.
Parse has several levels of security to help you with that.
The first step is ACLs, as you said. You can also change permissions in the Data Browser to disable unauthorized clients from making new classes or adding rows or columns to existing classes.
If that level of security doesn't satisfy you, you can proxy your data access through Cloud Functions. This is like creating a virtual application server to provide a layer of access control between your clients and your backend data store.
I've taken the following approach in the case where I just needed to expose a small view of the user data to a web app.
a. Create a secondary object which contains a subset of the secure objects fields.
b. Using ACLs, make the secure object only accessible from an appropriate login
c. Make the secondary object public read
d. Write a trigger to keep the secondary object synchronised with updates to the primary.
I also use cloud functions most of the time but this technique is useful when you need some flexibility and may be simpler than cloud functions if the secondary object is a view over multiple secure objects.
What I did was the following.
Restrict read/write for public for all classes. The only way to access the class data would be through the cloud code.
Verify that the user is a logged in user using the parameter request.user ,and if the user session is null and if the object id is legit.
When the user is verified then I would allow the data to be retrieved using the master key.
Just keep a tight control on your Global Level Security options (client class creation, etc...), Class Level Security options (you can for instance, disable clients deleting _Installation entries. It's also common to disable user field creation for all classes.), and most important of all, look out for the ACLs.
Usually I use beforeSave triggers to make sure the ACLs are always correct. So, for instance, _User objects are where the recovery email is located. We don't want other users to be able to see each other's recovery emails, so all objects in the _User class must have read and write set to the user only (with public read false and public write false).
This way only the user itself can tamper with their own row. Other users won't even notice this row exists in your database.
One way to limit this further in some situations, is to use cloud functions. Let's say one user can send a message to another user. You may implement this as a new class Message, with the content of the message, and pointers to the user who sent the message and to the user who will receive the message.
Since the user who sent the message must be able to cancel it, and since the user who received the message must be able to receive it, both need to be able to read this row (so the ACL must have read permissions for both of them). However, we don't want either of them to tamper with the contents of the message.
So you have two alternatives: either you create a beforeSave trigger that checks if the modifications the users are trying to make to this row are valid before committing them, or you set the ACL of the message so that nobody has write permissions, and you create cloud functions that validates the user, and then modifies the message using the master key.
Point is, you have to make these considerations for every part of your application. As far as I know, there's no way around this.

Resources