Node express public accessible url security - node.js

Good day everyone.
I would just like to run this scenario past you to ensure that I don't have any gaping holes in my approach.
What I want to achieve.
1.Send a mail to a client with a url + parameter that can uniquely identify the client when he clicks on the url and the parameter gets sent to my express server.
2.My express app receives the parameter and decodes it to retrieve the parameter from the encoded string so that I can do a lookup of the customer.
My approach
1.When sending the mail I generate a base64 encoded string that uses the customer_id + '~' + customer_name as the url parameter on the mail I send out.
I also url encode the string.
2.When the user clicks the url and the request gets to my express server I decode the string to retrieve the customer details (customer_id and customer_name) then do a lookup for the customer.
The information I'm displaying is semi sensitive so I don't want anybody tampering with the url to see another client information.
Is my approach correct?
Thank you guys!

This is not that secure. Since you mentioned you are concatenating customer ID + name and just converting to base64, a knowledgeable user could simply decode it and then try variations to "potentially" access other users records.
As a general rule of thumb is not to pass any customer info as link parameter if its sensitive. Instead, create a UUID and store in against the customer record. I personally even set TTL on this UUID. Its a bit more harder to guess and a bit more secure. Then pass that as the link's parameter which could be used for lookup and further processing.
Hope this helps!

While the original approach is not secure, using MongoDB's ID's is not secure either. See this related question.
Unfortunately, MongoDB ID's are guessable, as they were not designed to be used as a source of entropy.
But it really depends on the value of what you are protecting with these URL's, and how much you are willing to compromise security for the sake of convenience. MongoDB ID's are certainly better than the original approach, and may be secure enough for you to be willing to accept the risk.
But if I saw that in your application while performing a security audit, I would mark it as a weakness and recommend that you use a Cryptographically Secure Psuedo-Random Number Generator ( CSPRNG ) such as /dev/urandom.

Related

How to generate one time url to get a feedback in nodejs

I am developing an app for traveling agents in an insurance company with MEAN stack. When a traveling agent is done with the customer, a unique URL must be emailed to the customer to get feedback. How can I generate that unique one-time URL? Or is there any other way to achieve this without creating an account for the customer? (like sending a responsive email to the customer and get feedback)
One way you could do this is to 'encrypt' the query string. So lets say you want this to be a 'one-time' URL.
On your node server, you generate a one time string like customerID=12343&timestap=time&action=something
Next, on the server you would run the string through an encryption algo to encrypt the string so after it may look something like sd8753454sd548787e54sd54SDe85432 <--(this is not valid just an example but would be unreadable)
Now, the email you send out with the link would be something like https://example.com/validate/sd8753454sd548787e54sd54SDe85432
The validate route will require the string, grab that and then 'decrypt' the string. You should now have the valid string customerID=12343&timestap=time&action=something, so your DB updates etc and flag in the DB that it was clicked OR use the timestamp to check if the URL is expired
This is just one way, and when talking about encryption and how strong you need it is a huge topic, this is just one method of many ways.

How to prevent a "replay" with Javascript SDK authResponse

I'm using the Javascript SDK to make a web page that is entirely static HTML and Javascript (i.e., it's not dynamically produced web markup via some web app). This web page occasionally uses Javascript to POST data to a server--data which should be tied to a particular Facebook user. I use FB.getLoginStatus to determine who the user is. This gives me authRepsonse JSON data which looks like this:
authResponse:
accessToken:"AAAC91..."
expiresIn: 3786
signedRequest:"Ws93YNGWQeOi..."
userID: "670..."
I can send the signedRequest to the server and decode it and validate it there (using my app's secret key), and then I know that the user is, in this case, "670...", so I can presumably safetly perform whatever operation is supposed to happen on the server. Here's the data I extract from the signed request:
{"algorithm"=>"HMAC-SHA256",
"code"=>
"2.AQAKT...|5hVFYWcu5a...",
"issued_at"=>1323403518,
"user_id"=>"670..."}
My question is, what prevents an adversary (who somehow got ahold of the encoded authResponse above) from just "replaying" the signedRequest data to my server at a much later time?
The "issued_at" param at first looked promising, but I don't have anything to compare that issued_at time to to see if I should accept this signedRequest or not. The "expiresIn" is another time related parameter, but it's not signed, so I can't trust it. Maybe "code" provides me with extra info, but I don't see how to decode that.
I expect I'm just thinking about this wrong, or using the API in a way I'm not supposed to. Any insights? Thanks.
First of all using an Message Authentication Code (MAC) is a fundamentally insecure approach to the problem of authentication. You should be storing this information as a server side state, so that this is never a threat. By using a cryptographic hash function as an HMAC you introduce the possibility of someone brute forcing your secret key. Cryptography should only be used when there is no other solution, instead you are using it to introduce a weakness. This is a gross misuse of cryptography.
That being said, you have an issued_at timestamp. Just take the current timestamp and subtract. make sure that value is greater than your session timeout.

Secure Token URL - How secure is it? Proxy authentication as alternative?

I know it as secure-token URL, maby there is another name out there. But I think you all know it.
Its a teqniuque mostly applied if you want to restrict content delivery to a certain client, that you have handed a specific url in advance.
You take a secret token, concatenate it with the resource you want to protect, has it and when the client requests the this URL on one of your server, the hash is re-constructed from the information gathered from the request and the hash is compared. If its the same, the content is delivered, else the user gets redirected to your webseite or something else.
You can also put a timestamp in the has to put a time to live on the url, or include the users ip adress to restrict the delivere to his connection.
This teqnique is used by Amazon (S3 and Cloudfront),Level 3 CDN, Rapidshare and many others. Its also a basic part of http digest authentication, altough there is it taken a step further with link invalidation and other stuff.
Here is a link to the Amazon docs if you want to know more.
Now my concerns with this method is that if one person cracks one token of your links, the attacker gets your token plain-text and can sign any URL in your name himself.
Or worse, in the case of amazon, access your services on an administrative scope.
Granted, the string hashed here is usually pretty long. And you can include a lot of stuff or even force the data to have a minimum length by adding some unnecessary data to the request. Maby some pseudo variable in the URL that is not used, and fill it up with random data.
Therefore brute force attacks to crack the sha1/md5 or whatever you use hash are pretty hard. But protocol is open, so you only have to fill in the gap where the secret token is and fill up the rest with the data known from the requst. AND today hardware is awesome and can calculate md5s at a rate of multiple tens of megabytes per second. This sort of attack can be distributed to a computing cloud and you are not limited to something like "10 tries per minute by a login server or so" which makes hashing approaches usually quite secure. And now with amazon EC2 you can even rent the hardware for short time (beat them with their own weapons haha!)
So what do you think? Do my concerns have a basis or am I paranoic?
However,
I am currently designing an object storage cloud for special needs (integrated media trans coding and special delivery methods like streaming and so on).
Now level3 introduced an alternative approach to secure token urls. Its currently beta and only open to clients who specifically request it. They call it "Proxy authentication".
What happens is that the content-delivery server makes a HEAD request to a server specified in your (the client's) settings and mimics the users request. So the same GET path and IP Address (as x_forwarder) is passed. You respond with a HTTP status code that tells the server to go a head with the content delivery or not.
You also can introduce some secure-token process into this and you can also put more restrictions on it. Like let a URL only be requested 10 times or so.
It obviously comes with a lot of overhead because additional request and calculations take place, but I think its reasonable and I don't see any caveats with it. Do you?
You could basically reformulate your question to: How long a secret token is needed to be safe.
To answer this consider the number of possible characters (alphanumeric + uppercase is is already 62 options per character). Secondly ensure that the secret token is random, and not in a dictionary or something. Then for instance if you would take a secret token of 10 characters long, it would take 62^10 (= 839.299.365.868.340.224 )attempts to bruteforce (worstcase; average case would be half of that of course). I wouldn't really be scared of that, but if you are, you could always ensure that the secret token is at least 100 chars long, in which case it takes 62^100 attempts to bruteforce (which is a number of three lines in my terminal).
In conclusion: just take a token big enough, and it should suffice.
Of course proxy authentication does offer your clients extra control, since they can way more directly control who can look and not, and this would for instance defeat emailsniffing as well. But I don't think the bruteforcing needs to be a concern given a long enough token.
It's called MAC as far as I understand.
I don't understand what's wrong with hashes. Simple calculations show that a SHA-1 hash, 160 bits, gives us very good protection. E.g. if you have a super-duper cloud which does 1 billion billions attempts per second, you need ~3000 billions billions years to brute force it.
You have many ways to secure a token :
Block IP after X failed token decoding
Add a timestamp in your token (hashed or crypted) to revoke the token after X days or X hours
My favorite : use a fast database system such as Memcached or better : Redis to stokre your tokens
Like Facebook : generate a token with timestamp, IP etc... and crypt it !

How to make an API call on my server accessible only from one URL

I don't know if the title is clear enough, anyway what I need to do is quite simple: I have some content you can access by an API call on my server; this content is user-related so when you request access to it, you must first wait for the owner to authorize you. Since this content will be probably embedded into blog articles or form posts I want it to be accessible only from the URL the user authorized to.
The only way that came to my mind is to check in some secure way where the request is coming from: the problem with this approach is that anybody could create a fake request, using a valid URL but coming from a non-authorized URL actually.
I'm looking for a way to solve this problem, even if this doesn't involve checking the actual URL but using some other approach or whatever. Feel free to ask any questions if this is not clear enough.
With Sessions:
If you generate a secure token, most languages have libraries to do such a thing, you will have to persist it probably in a session on your server. When you render the page which will access the other content you can add that token to the link/form post/ajax request on the page you wish to be able to access it from.
You would then match that token against the value in the user session if the token doesn't match you return an error of some sort. This solution relies on the security of your session.
Without Sessions:
If you don't have sessions to get around server persistance, you can use a trick that amazon s3 uses for security. You would create something like a json string which gives authorization for the next 30 seconds, 5 minutes, whatever is appropriate. It would need to include a timestamp so that the value changes. You would use a secret key on your sever that you combine with the JSON string to create a hash value.
Your request would have to include the JSON string as one request parameter. You would need to base64 encode it or some other means so that you don't run into special characters not allowed over http. The second parameter would be the output of your hash operation.
When you get the request you would decode the JSON string so it was exactly the same as before and hash it with your secret key. If that value matches the one sent with the request it means those are the two values you sent to the page that ultimately requested the content.
Warnings:
You need to make sure you're using up to date algorithms and properly audited security libraries to do this stuff, do not try to write your own. There may be other ways around this depending on what context this ultimately ends up in but I think it should be relatively secure. Also I'm not a security expert I would consult one if you're dealing with very sensitive information.

Is there any danger to creating UUID in Javascript client-side?

I need to generate UUID to eventually store in a database. Can I generate theses UUID from Javascript on the client browser (There are some examples here)?
Is there any security risk of doing it this way? I understand that anyone can modify the UUID before it's passed to the server for storing. So i'll need to check if they are trully unique before storing them in the database, but other than that, is there any other things to checkout?
(Sorry for my english, feel free to correct any grammar errors)
edit: To answer questions about why I would want to do this, it's because I can create a new object and it's identifier in Javascript and add it to my view and then make an AJAX call to the server to add it to the database. This way, I don't need to load it back from the database to know what is it's primary identifier.
Not really. As long as it's a simple identifier and nothing more, and you are indeed checking it for validity and uniqueness, it's no different than user accounts having an id in the url, for example.
Look at your URL bar. I bet 1296234 is the primary key of this question, but I can't really do anything with that information. Same deal with your script.
What benefit do you see in generating these client-side? In all honesty, the best option is to generate it server-side, out of the users reach. It may not give save you from any serious security issues, but it will cut down on redundant validation.
Is there some reason you can't have the database generate (increment) an ID?
If, like you say, you'll have to check the uniqueness of the value before submitting it anyway, why not just have whatever backend language you are using generate it. That would make it much more opaque.
Yes. The risk is not specific to UUID, any client-side generated ID has some risks, depending on what you do with the ID. The problem is that it's very hard to authenticate the Javascript. If you accept ID generated by client, you accept any IDs from the hackers.
The risks may include,
Session stealing. If you use the ID to identify the session, someone may use an existing ID as generated ID and the server may treat it as an existing session if proper care is not taking.
Duplicate keys. True UUID is random but someone can generate duplicate keys which will mess up your database.
You might find ways to defend against each of these attacks but that's passive protection. It might defeat the original purpose of generating IDs on the client, which is simple.

Resources