URL Vulnerabilities - security

I'm researching URLs that I'm building against the unique URL that google docs create once you select and send a URL to anyone.
My URL looks like: https://example.com/?doc=abcd123)
Should I encode the variable doc in base64? Should it betoken alike
wherewith the id and a key that the other end needs to decrypt?
Whatis The security issue we are vulnerable to?
How exactly can an attacker exploit this vulnerability?
What do we need to do to fix the vulnerability?

The name of this potential vulnerability is insecure direct object references. Potential, because it is not possible to see out of the example you have provided if you are affected. Let me put an example here.
If you allow for unauthenticated doc=myexcel.xls then this is an insecure direct object reference and you are affected. Someone will come and try to fuzz doc into getting doc=sensitive.xls.
If you allow for authenticated and authorized doc=myexcel.xls then this is a secure direct object reference and this would be ok too.
If you allow for unauthenticated doc=efa64d43-cca2-444c-9bcf-9f78b114bda4 where efa64d43-cca2-444c-9bcf-9f78b114bda4 is a UUID type 4 containing 128 bits of entropy pointing to a file you wish to download, then this is insecure indirect object reference and this would be ok.
You can read more about potential prevention in OWASP Cheat Sheets.

Related

Is it safe to use a UUID in a URL for semi-private data?

I run a landscaping company and have multiple crews. I want to provide each one with a custom URL (like mysite.com/xxxx-xxxx-xxxx) that shows their daily schedule. Going to the page will list the name, address and phone number of 5-10 customers for the day.
Is it safe/wise to use a UUID in a URL for semi-private data?
Depends on how safe you want it to be.
Are the UUIDs used for anything else? If not, they are fine for creating random URLs.
But, browser history would allow anyone using the same machine to find the URLs. Also, unless using https, a network sniffer could easily see the requested URLs and go to the same page.
Another concern is spider bots. Make sure nothing links to those pages, use a robots.txt to prevent indexing the site, but you still might find that some of the pages show up on search engines. It might be better to have the UUID set in a cookie and check that for determining which employee it is, lest your semi-private pages start showing up on google.
Whether or not that schema would work for you, depends on your threat model (as well as some implementation details). Without a concrete threat model, it is not possible to give a definitive answer to your question.
I can, however, give you some ideas about potential issues with the solution, so you can determine if they are relevant for your application. This is not a complete list.
On the implementation side of things:
Not all UUID generators are created equal. Ideally, you want to use a generator based on a cryptographically secure RNG, providing an UUID where every byte is chosen at random.
Using the UUID for a database lookup or similar operation is not necessarily a constant-time operation (and thus there might be side-channel attacks unless you implement the lookup by yourself)
Make sure your URI does not leak via referrer
Some tools attempt to detect 'secret' URLs to protect them from history synchronization or other automatic features. Your schema will most likely not be detected as 'secret'. It might be better to artificially lengthen your URI and to move your UUID into a query parameter.
You can further reduce attack surface with the usual methods (rate limiting, server hardening, etc.)
On the conceptual side of things:
A single identifier for both identification and authentication is not necessarily a bad thing. However, in most cases there is a need for an identification-only identifier – you must not use the 'secret' UUID in those scenarios
If a 'crew' consists of multiple people: you cannot revoke access for a single crew member
Some software (antivirus, browser, etc.) treats information in URLs as public information, and might upload them without user interaction

Node express public accessible url security

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.

How secure is it to use fragment identifiers to hold private data in URLs?

We know the URL itself is not a secure way to pass or store information. Too many programs will perform unexpected processing on the URL or even ship it over the network, and generally speaking, the URL is not treated with a high regard for its privacy.
In the past we've seen Bitcoin wallets, for example, which have relied on keeping a URL secret, but they found out the hard way there are too many ways in which a URL (sent via Skype, or emailed, or even just typing it into the Google Chrome omnibar) will get stored by a remote server, and possibly displayed publicly.
And so I thought URL would be forsaken forever as a means for carrying any private data... despite being extremely convenient, except now I've seen a few sites which are using URL fragments -- the portion of the URL after the '#' -- as a kind of 'secure' storage. I think the expectation is that Google won't parse the fragment and allow it to show up in search results, so that data shouldn't be published.
But that seems like a pretty weak basis for the security of your product. There would be a huge benefit to having a way to securely move data in URL fragments, but can we really rely on that?
So, I would really like to understand... Can anyone explain, what is the security model for fragment identifiers?
Tyler Close and others who did the security architecture for Waterken did the relevent research form this. They use unguessable strings in URI fragments as web-keys:
This leakage of a permission bearing URL via the Referer header is only a problem in practice if the target host of a hyperlink is different from the source host, and so potentially malicious. RFC 2616 foresaw the danger of such leakage of information and so provided security guidance in section 15.1.3:
"Because the source of a link might be private information or might reveal an otherwise private information source, … Clients SHOULD NOT include a Referer header field in a (non-secure) HTTP request if the referring page was transferred with a secure protocol."
Unfortunately, clients have implemented this guidance to the letter, meaning the Referer header is sent if both the referring page and the destination page use HTTPS, but are served by different hosts.
This enthusiastic use of the Referer header would present a significant barrier to implementation of the web-key concept were it not for one unrelated, but rather fortunate, requirement placed on use of the Referer header. Section 14.36 of RFC 2616, which governs use of the Referer header, states that: "The URI MUST NOT include a fragment." Testing of deployed web browsers has shown this requirement is commonly implemented.
Putting the unguessable permission key in the fragment segment produces an https URL that looks like: <https://www.example.com/app/#mhbqcmmva5ja3>.
Fetching a representation
Placing the key in the URL fragment component prevents leakage via the Referer header but also complicates the dereference operation, since the fragment is also not sent in the Request-URI of an HTTP request. This complication is overcome using the two cornerstones of Web 2.0: JavaScript and XMLHttpRequest.
So, yes, you can use fragment identifiers to hold secrets, though those secrets could be stolen and exfiltrated if your application is susceptible to XSS, and there is no equivalent of http-only cookies for fragment identifiers.
I believe Waterken mitigates this by removing the secret from the fragment before it runs any application code in the same way many sensitive daemons zero-out their argv.
The part after the # is not any more secure than any other part of the URL. The only difference is that it MAY be omitted from the web server access log. But the web server is not the threat.
As long as you store the secret, either in a URL or somewhere else where it can become public it is insecure. That is why we invented passwords, because they are supposed to only exist in peoples head.
The problem is not to find a way to store a secret in a URL.
That is impossible, because as you say: The probably will become public. If all you need is the URL, and it gos public, nobody cares what the original data is. Bacuse they have what they need, the URL. So to rely on the URL alone for authentication is.. moronic.
The The problem is to store your secrets in a secure way, and to create secure systems.

How do I protect sensitive information from cross site access?

My web application displays some sensitive information to a logged in user. The user visits another site without explicitly logging out of my site first. How do I ensure that the other site can not access the sensitive information without accept from me or the user?
If for example my sensitive data is in JavaScript format, the other site can include it in a script tag and read the side effects. I could continue on building a blacklist, but I do not want to enumerate what is unsafe. I want to know what is safe, but I can not find any documentation of this.
UPDATE: In my example JavaScript from the victim site was executed on the attacker's site, not the other way around, which would have been Cross Site Scripting.
Another example is images, where any other site can read the width and height, but I don't think they can read the content, but they can display it.
A third example is that everything without an X-Frame-Options header can be loaded into an iframe, and from there it is possible to steal the data by tricking the user into doing drag-and-drop or copy-and-paste.
The key point of Cross Site Attack is to ensure that your input from user which is going to be displayed, is legal, not containing some scripts. You may stop it at the beginning.
If for example my sensitive data is in JavaScript format, the other site can include it in a script tag
Yep! So don't put it in JavaScript/JSONP format.
The usual fix for passing back JSON or JS code is to put something unexecutable at the front to cause a syntax error or a hang (for(;;); is popular). So including the resource as a <script> doesn't get the attacker anywhere. When you access it from your own site you can fetch it with an XMLHttpRequest and chop off the prefix before evaluating it.
(A workaround that doesn't work is checking window.location in the returned script: when you're being included in an attacker's page they have control of the JavaScript environment and could sabotage the built-in objects to do unexpected things.)
Since I did not get the answer I was looking for here, I asked in another forum an got the answer. It is here:
https://groups.google.com/forum/?fromgroups=#!topic/mozilla.dev.security/9U6HTOh-p4g
I also found this page which answers my question:
http://code.google.com/p/browsersec/wiki/Part2#Life_outside_same-origin_rules
First of all like superpdm states, design your app from the ground up to ensure that either the sensitive information is not stored on the client side in the first place or that it is unintelligible to a malicious users.
Additionally, for items of data you don't have much control over, you can take advantage of inbuilt HTTP controls like HttpOnly that tries to ensure that client-side scripts will not have access to cookies like your session token and so forth. Setting httpOnly on your cookies will go a long way to ensure malicious vbscripts, javascripts etc will not read or modify your client-side tokens.
I think some confusion is still in our web-security knowledge world. You are afraid of Cross Site Request Forgery, and yet describing and looking for solution to Cross Site Scripting.
Cross Site Scripting is a vulnerability that allows malicious person to inject some unwanted content into your site. It may be some text, but it also may be some JS code or VB or Java Applet (I mentioned applets because they can be used to circumvent protection provided by the httpOnly flag). And thus if your aware user clicks on the malicious link he may get his data stolen. It depends on amount of sensitive data presented to the user. Clicking on a link is not only attack vector for XSS attack, If you present to users unfiltered contents provided by other users, someone may also inject some evil code and do some damage. He does not need to steal someone's cookie to get what he wants. And it has notnig to do with visiting other site while still being logged to your app. I recommend:XSS
Cross Site Request Forgery is a vulnerability that allows someone to construct specially crafted form and present it to Logged in user, user after submitting this form may execute operation in your app that he didin't intended. Operation may be transfer, password change, or user add. And this is the threat you are worried about, if user holds session with your app and visits site with such form which gets auto-submited with JS such request gets authenticated, and operation executed. And httpOnly will not protect from it because attacker does not need to access sessionId stored in cookies. I recommend: CSRF

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.

Resources