On Oct 12, 2009, at 7:04 AM, Maciej Stachowiak wrote:
On Oct 9, 2009, at 4:36 PM, Mark S. Miller wrote:
The last of the links above should make the application to CORS
concrete. See also the dismissive replies which followed in that
thread. If you find these dismissals plausible, please imagine back
to
the world in which CSRF was first diagnosed (second bullet above) as
ask if CSRFs would have also seemed merely theoretical back then? In
both cases, the answer "well don't do that" seems to make sense on
first analysis for the same reasons.
Tyler claimed the vulnerability in his example could be avoided by
not identifying the origin of a cross-site request, but he did not
explain how. For example, if photo.example.com instead used a shared
secret to identify itself to strage.example.com, the exact same
scenario could occur.
I would argue that the vulnerability here is created by using a URI
to identify an access-controlled resource on a third-party site.
Some ways to safely perform the transaction include:
1) printer.example.net asks storage.example.org for a one-time write
access token for its per-user job spool (perhaps indicating that
photo.example.com is the only site authorised to use it), and hands
it to photo.example.com, which then uses it to write. It can't tell
photo.example.com to overwrite a different photo, because it cannot
acquire a write access token for that photo. CORS can help implement
this approach - it knows which part of a user's space is writable to
printer.example.net, and can use the Origin header to decide that
printer.example.net
2) storage.example.org can offer a "conditional write" service that
copies a file only if all parties listed in the request, plus those
listed in Origin, have write access. Then when photo.example.com
uploads a photo for spooling on behalf of printer.example.net, it
can list printer.example.net as one of the domains that must have
write access.
Either of these approaches works fine with CORS. Thus, I do not see
how the scenario argues against providing the Origin header.
I am sure there are solutions that do not use the Origin header at
all, solely using one-time token schemes. However, popular one-time
token schemes for cross-origin networking typically require a shared
secret, and thus cannot be done client-to-server. Thus, no form of
cross-origin client-side networking is helpful for implementing them.
CORS is helpful in these kinds of multi-party scenarios because it
allows you to bootstrap a secret token scheme from the client side,
by using the combination of Origin and a user credential such as a
cookie to grant the initial token, based on the user's pre-existing
access grants, and without the need for a shared secret between the
two sites that are party to the transaction.
As a side note, I should add that Tyler's scenario would be much
simpler overall if printer.example.net used a grant of read access to
the photo it wants to print on storage.example.org, instead of
granting write access to a new location. Or it can just ask
photo.example.com to read the photo from storage.example.org and send
the actual data. Either of these much less abusable than writing, and
would be a safer approach, whether or not the overall design depends
on secret tokens. The grant of read access can be one-time or time-
limited if necessary. Thus, I think the scenario is somewhat
contrived. Likely cross-site interactions would not involve such a
complex process to transfer data. The root of the vulnerability in
Tyler's scenario is writing in a shared namespace to transfer data,
instead of simply granting read access to the existing copy, or
transferring the actual data bits.
Regards,
Maciej