COMMAND
"ClientSideTrojan"
SYSTEMS AFFECTED
Many web based systems
PROBLEM
Kragen Sitaker found following. Apparently Zope and many other
web-based systems suffer from a confused-deputy problem: browsers
are willing to visit URLs and submit forms based on untrusted web
page contents, and servers are willing to trust browsers that
submit forms and web page requests when they include Basic
Authentication or authentication cookies with those requests.
The Zope page describing the problem is at
http://www.zope.org/Members/jim/ZopeSecurity/ClientSideTrojan
This is sort of a variant of the "cross-site scripting" thing
(CERT Advisory CA-2000-02), in that it involves some of the same
mistaken trust relationships. The browser trusts random servers
to give it URLs; the URLs tell the browser to go to other
servers; the other servers trust the browser. In CA-2000-02, the
browser then has some trust relationship with the server, which
doesn't figure here.
The Zope page doesn't include a lot of detail on how this could be
used, but we can think there are essentially three cases:
a- server X sends you an evil form and JavaScript that
automatically POSTs the form --- to server Y, which trusts your
browser.
b- server X sends you a 30[12] Redirect or a Refresh that tells
you to GET a page from server Y; GETting the page has some kind
of evil side effect.
c- server Z, who might be totally innocent or might be server X,
sends you an innocent-looking form that gets POSTed to server
X. Server X 30[12] redirects to server Y; the innocent-looking
form does something evil.
d- server Z sends you an innocent-looking, but evil, form that
gets POSTed to server Y.
The irritation of this attack seems mainly to be that the attacker
needs know no secret about the victim, and so the same attack will
work equally for anyone authenticated to a particular service.
Randomly submitting a dummy form then isn't enough, and the attack
should be defanged for the cases:
1. Redirect to a GET action
2. Forced POST submission by Javascript
3. Evil innocent-looking form
But not of course in the general case for
4. Browser is vulnerable to cross-site scripting
If random Javascript can find out what's going on in another
window you're just as doomed as ever. (Bonus points for warning
users on login that their browser is vulnerable based on their
user-agent string - is there a list of historically vulnerable
browsers anywhere?)
SOLUTION
The solution to case (a) is simple; turn off JavaScript. If you
run a web site that might be impacted by this, force your users
to turn off JavaScript; don't let them into the site in the first
place if they have it turned on. This can be very simple --- a
one-line onLoad script on every page that redirects their browser
to a page that explains they must turn off JavaScript and why.
The solution to case (b) is just as simple; don't allow GET to
have an evil side effect, even if the user does have
authorization. This is usually a good idea anyway. GET requests
should be idempotent, and destructive operations usually aren't.
If there are GET requests that can do evil, someone could just as
easily link to them.
The solution to case (c) is already in place, and has been for
years: when following redirects on POSTs, the browser should use
GET on the resource it's redirected to, not POST.
The solution to case (d) is not quite clear.
The Zope page describes a number of mitigating measures:
- not viewing untrusted content when using a trusted browser (!)
- turning off JavaScript (of course)
- log out of sessions when you can (the Zope guys apparently
don't know that sending a 403 response to a query will cause
most browsers to ask for a username and password again; if
you can persuade the user to refuse, the browser will
generally have forgotten the username and password)
- Referer checks, which unfortunately don't work universally
Unfortunately, today's web leaks resource names --- URLs --- like
sieves, and so it's impossible to safely use URLs as
authenticators. Specifically, proxies save URLs, so the proxy
owners know them; httpd logs save URLs, so everybody at your ISP
knows them; and browsers send URLs in Referer: headers, so
everybody you link to knows them.
Given that it's common to issue some sort of session ID to a user
upon login (separate from, for example, a persistent
identification cookie), and that this won't easily be available
to an attacker, a quick and obvious way to kick this problem in
the nads would seem to be to embed the user's session ID in any
form resulting in a state change in their data (configuration,
purchase, whatever). Then, compare that supplied ID against the
authenticated session ID before actioning a GET/POST request.