views:

131

answers:

5

We all know how hip it is to make our Ajax calls using address routing and HTTP-Get with parameters in the URL because the client side can cache those calls and thus server load is reduced, but where do you guys think the line is between "a neat way to address resources" and "disclosure vulnerability"? I'll give some examples-

Let's say I'm on my bank's website. In the background, my browser is HTTP-Getting to /onlinebanking/AForster/transactions. Of course I'm very paranoid about people knowing my bank account login ID, so I always make sure "remember me" is unchecked. However, does the fact that my browser accessed a URL with my login ID in it constitute a disclosure vulnerability?

What about if I'm on a forum, and I'm reading a restricted thread that normal users shouldn't know exists. My browser retrieves the contents of a thread by doing an HTTP-Get to /forum/Secret-Board/Im-Going-To-Kill-My-Brother/posts. Does the fact that I even accessed that URL with Ajax somehow reveal the existence of that thread to my brother?

Etc, etc. You can probably think of more scenarios. I really want the benefit of caching my Ajax calls on the client side, but in these instances, would Ajaxing to these URLs be considered a disclosure vulnerability?

A: 

The simplest way to avoid such disclosure is to use ID numbers instead of strings.

There's nothing revealing in /forum/Board-214/Thread-5625/posts or something like that.


Note that I'm not neccesarily agreeing with the problem, just providing a workaround.

What situations are there where a malicious user can get AJAX request URLs but not the response body?

SLaks
Browser history, routers, proxy, insecure server logs... there's more.
AviD
AJAX requests aren't stored in browser history. Routers (I believe) just forward packets and are unaware of HTTP. If his server logs are insecure, he's (probably) got bigger problems. However, you're right about proxies; thanks.
SLaks
A: 

It comes down to the fact that your users' browser, history, cache, etc, are not secret OR properly protected (there are many scenarios where these can be accessed by unauthorized users, the fact that you're asking the question shows that you're probably aware of them...).

So, don't assume that anything cached there will be protected - and don't allow any "sensitive" information to be cached there. "What is sensitive", you ask? Well, anything you wouldnt want to be revealed to any other user. Bank account, secret forums, username, session id, transaction details - none of this should be allowed to be cached or stored on the client.

It really is an excellent point you raise, since often developers rush in with AJAX and whatnot to improve usability, forgetting about protecting that information en route and at rest on the client.

AviD
If the enemy can get to the browser cache, anything you do or don't put in the URL won't help, as he'll be able to see the response body.
SLaks
Not if the body is not stored.
AviD
A: 

Since URLs are opaque identifiers to the web browser, the only purpose for adding human-readable text to them is to ease remembering.

The bank ought to use an anonymous ID in place of your name. While the connection is (hopefully!) encrypted, the URL will still be stored in your browser's history, where third parties can access it. An anonymous ID, or even temporary per-session ID, would be more secure.

The forum example contains an odd phrase, "restricted thread that normal users shouldn't know exists". Does it really matter whether normal users know a thread exists or not? The issue is that the thread's subject is disclosed in the URL, which is a vulnerability. The URL should probably be something like /forum/thread/12345/.

Honestly, this has nothing to do with CRUD, AJAX, or any of the other buzzwords you threw into your question. The issue is whether exposing secret information in plaintext is acceptable, and the answer is "no".

John Millikin
Urls sent to AJAX requests are not stored in history (AFAIK)
SLaks
@SLaks: That depends on the browser, and on the page's AJAX implementation. For example, uploading files via AJAX (which requires an iframe) will add history entries in Internet explorer. If the page is RESTful resources, then the URLs could be stored in the browser cache.
John Millikin
The content returned from the request is also stored in the browser cache. If the malicious user can see the content, he doesn't need the URL.
SLaks
Only unencrypted content is stored in the cache. Assuming a plain page with URLs to encrypted content (common in AJAX), examining the cache will display the URLs but not the content.
John Millikin
Do you mean to say that the cache will have an HTTPS URL but not have its content? Why?
SLaks
When it's a RESTful resource delivered over HTTP, with content delivered by HTTPS.
John Millikin
Another reason for human-readable text in REST URLs is to make it easier for people writing software to work with them. Usable APIs and all that.
Colin Coghill
A: 

So you're question raises a couple of points that I wish I knew more about, but I'll try my best to at least map things out...

Your browser is caching URLs that have private/secure information in the path, thus leaving a potential window to your private info to others. The implications:

  1. Someone could walk up to your computer when you are away, or, perhaps access your computer remotely, or -- if the proper precautions aren't taken on several levels -- use an XSS method to get your cached URLs via javascript.

And the concern is legit, but you have already indicated what some of the steps you can take to aleiveate them are:

  • Don't have multiple windows open, some private, some not-so-private. Use private browser sessions for your private browsing. I actually had an idea for a Firefox add-on that would allow you to create a "dark list" of sorts, a list of domains that should always be in Incognito mode. That way you can be on your bank site, hop over to twitter, and it knows to have different sesssions, etc.

  • Set your browser to delete (or at least ask to delete) all personal data on each close.

  • On the server-side, no responsible web-app designer should EVER use credentials or personal data in the URL for a secure site. That's not slick, that's lazy. I think ID numbers or session ID's isn't much better (I'll get to that in point two). Your bank should use: /onlinebanking/UserServices/transactions as the RESTful url and should be confirming everything on each request, down to the IP, at the server level (mod_auth and a damn good cert). I get very exhausted hearing people talk about "reducing server load" or even "reducing database hits". The software is explicitly designed for receiving LOTS of requests. My HP laptop built 6 years ago that sounds like an old refrigerator was NOT designed to ease the server's work-load, and waiting 10 minutes for a poorly designed js script (see : new Yahoo! Mail client) makes me want to stab. And if there is nothing else the poor abused gigantic server should be expected to handle, it should be ensuring your security EVERY time.

Okay, that rant is over.

  • Can your brother see your cached URLs? Maybe. My girlfriend can tell when I've hit up the xxx sites even when I clear the history (why? because it still shows up in recently closed tabs! Yay privacy!) And those aren't being cached for RESTfulness, they are being cached cuz that's what browsers do. So you should taken the same precautions after going to a site withiamgoingtokillhimtonight/postsin the URL as you would to cover your...self...when you've gone to the pron sites or when you've been looking up birthday present ideas.

On to part to of my interpretation:

So yes, the URLs are cached and that's creepy for anyone who wants to peruse said cache to get in your business. But it seems the other concern you are expressing is what they can do with it, ie cross-browser-exploits. Can someone use that cached URL to make a script to get to your actual bank info and wipe you out? Yes. But, the advantage they gain if they already know how to do this is slight. It's more like saving them a step then leaving your keys hanging in the door. If I can somehow see your cache via js, and thus see your secure bank URL, then I could just as easily see your bank's URL if they didn't use a cute URL, and just as easily write my XSS around it. And if I can see your cache, I can most certainly see your cookies and steal those (only on the web are cookies worth more than cache). So the same rules pre-AJAX apply:

  • Users shouldn't write down passwords
  • Session cookies should expire at the end of sessions
  • web apps need to use white-lists, certs, and nonces to secure the integrity and authenticity of the user's requests.

I can not emphasize enough how much XSS success is based on the laziness (or ignorance) of developers (myself included) and the confusion and naivety of users. Most really big XSS scores involve social-hacking prior to internet hacking. A phishing scam or a letter from an old friend or Spanish prisoner, simply asking you to follow this innocent link or share some meaningless personal info. The one thing I could see with your bank example that would make it worse is that now I know from this site that your first name is Alex and from the URL that your last name is Forester. This may make digging up details to con you out of other information easier.

So the long and short of it, finally:

RESTfulness and AJAX doesn't pose much more of a threat then browser history and bad server-security ever has, and so the same rules apply both to users and to developers. But you are totally right that such RESTful URLs point out that we are getting worse about these practices instead of better; using the technology to be lazier instead of using the advantage to focus on the real hard work.

Well that was fun. Back to the salt mines.

Anthony
A: 

Great conversation, and all very interesting responses! Sorry I have to respond in bulk, but I was trying to get out of work quickly and I didn't have time to go figure out if I had an OpenID provider somewhere.

While my examples were made up, I did actually find myself in this scenario today. My project is moving out of design, and the first thing that's going to be built is the HTTP/JSON webservice. Yesterday I combed through all of the UI concepts and made a list of every point where some data needs to be provided by the webservice. Then, while I was trying to wedge all those actions into a consistent URL scheme, I found myself wanting to put some information into the GET requests that seemed a tad sensitive. I'll admit that my original post wasn't so much a question as it was a commentary on the potential security issues raised by RESTful webservices (particularly CRUD endpoints) used in this context. I had just never heard anyone talk about the subject from that perspective and I was interested in what you all thought.

I think the most useful answer to my question came from John Millikin who pointed out that iframe-based Ajax will indeed throw request URLs into the history, which I was surprised to learn. I'm pretty sure any XHR requests will only live on in the browser's cache, where the response is also available and at that point you have a much bigger problem. The mention of XSS attacks was another interesting point; there have been quite a few instances where people have found a way to disclose browser history, or get the cache of a certain URL. If someone knew my bank account ID was "AForster" and then found a way to get my cached version of /onlinebanking/AForster/transactions from the context of another domain, they could get quite a lot of information.

Oddly enough, I'm probably going to end up throwing caution into the wind and pass my sensitive data via GET, because this particular sensitive data isn't really sensitive at all, and it's a corporate intranet and we've got TLS underneath. There's a lot to be said for self documenting, human readable, easy to remember URLs. However, I do know that these requests will be logged by: 1) our webserver, 2) websense, and 3) our VPN infrastructure. And every home router I've ever owned has parental controls that can log URLs, and god forbid you run some fancy CMS /where/everything-damn-thing-is/addressed-by-title/ and then somebody finds a way to get your webserver's request logs. It's an acceptable tradeoff for me in my particular situation, but in a different situation I believe I could have quite some reason for concern.

Alex