Last Comment Bug 375238 - External image requests send session cookies
: External image requests send session cookies
Product: Firefox
Classification: Client Software
Component: Security (show other bugs)
: unspecified
: All All
: -- critical with 1 vote (vote)
: ---
Assigned To: Nobody; OK to take it and work on it
Depends on:
Blocks: csrf
  Show dependency treegraph
Reported: 2007-03-24 18:39 PDT by Christoph Bußenius
Modified: 2016-08-25 13:33 PDT (History)
8 users (show)
See Also:
Crash Signature:
QA Whiteboard:
Iteration: ---
Points: ---
Has Regression Range: ---
Has STR: ---


Description User image Christoph Bußenius 2007-03-24 18:39:19 PDT
User-Agent:       Mozilla/5.0 (X11; U; Linux i686; en-US; rv: Gecko/20070325 Firefox/
Build Identifier: Mozilla/5.0 (X11; U; Linux i686; en-US; rv: Gecko/20070325 Firefox/

Image tags (<img>) on a malicious site can include images from any location
without the user being prompted.  If the tag's src attribute is some cgi script
(with arbitray query string parameters), downloading the image can result in
arbitrary actions on the server, because firefox sends any session cookies,
which makes the server believe that the action is authorized.

To illustrate the problem, have a look at this html code:
<img src="">

Downloading what is believed to be an image will change the Bugzilla user
profile.  It changes the tab "General Preferences" so that every setting is set
to the site default, except for the setting "Product chooser to use when
entering bugs", which is set to "Pretty chooser".  This will only work if you
have recently logged in to Bugzilla and have a session cookie.

To convince yourself, go to
(WARNING: This will change your Bugzilla settings!)

So, one might argue that Bugzilla should make sure that such requests are being
sent through POST rather than GET.  However this would be rather naive, because
the same problem exists for Javascript's form.submit, and there is also the
possibility to disguise submit buttons so that they don't look suspicious.
Plus, Bugzilla is by far not the only vulnerable web application.

I suggest that Firefox shouldn't send cookies for requests to external sites
that are due to <img>, <link>, <iframe>, <script> tags or similar.

Form contents should not go to external sites without warning the user, and
probably they should not send cookies.

I don't know who first came up with this kind of exploit, but it's related to
the discussions about "pharming", which came up on various mailing lists some
weeks ago.

Reproducible: Always
Comment 1 User image Gervase Markham [:gerv] 2007-03-26 01:48:37 PDT
CCing justdave, as a Bugzilla security issue is mentioned in the comments.

Comment 2 User image Christoph Bußenius 2007-03-26 10:19:22 PDT
I wrote:
> I suggest that Firefox shouldn't send cookies for requests to external sites
> that are due to <img>, <link>, <iframe>, <script> tags or similar.

I just realized that this is done by the setting which allows cookies for the originating site only.  However, this setting really should be default because of this security issue, and there should be a warning which discourages turning it of.

Still vulnerable is the meta redirect tag.  It is not affected by the preferences setting which I mentioned above.  This html code will change your Bugzilla settings (as described in my previous comment), even if you have restricted cookies to the orginating site:

<meta http-equiv="refresh" content="0; URL=">
(I'm sorry for the long lines.)

The following link demonstrates this:
(WARNING: This will change your Bugzilla settings!)

The possibility to send forms to external sites via Javascript's form.submit() is not affected by "for the originating site only", either.  As I mentioned in in my initial report, this cannot be fixed by telling Bugzilla to restrict actions to POST.

I have an example for this one too:
(WARNING: This will change your Bugzilla settings!)

Gervase, thank you for CCing justdave.  However, I would like to emphasize that this is primarily a browser issue.  By the way, Opera has been informed by a friend of mine.
Comment 3 User image Jesse Ruderman 2007-03-26 23:03:18 PDT
The attack described here is well-known and called "Cross-site request forgery".  Most believe that it is the web application's responsibility to fix it, not the web browser's.

This is probably a duplicate of one of the dependencies of bug 322301.

Can this bug report be made public?
Comment 4 User image Christoph Bußenius 2007-03-27 03:22:10 PDT
> The attack described here is well-known and called "Cross-site request
> forgery".

Obviously I was not aware of this fact :) In fact, describes exactly this problem.  As there are so many vulnerable web applications, I guess few people are aware of this kind of exploit.

I don't think there is any acceptable way for the web application to fix this.  If you put the session id into a hidden field, old browser tabs cannot be used any more---unless you use some Java script, which is not enabled in every browser.

I'd agree to make this bug report public.
Comment 5 User image Jesse Ruderman 2007-03-27 06:18:23 PDT
Instead of the session ID, you can use something unchanging about the user's login or cookie.  (Preferably one that changes if the user's site password changes.)
Comment 6 User image Christoph Bußenius 2007-03-27 10:53:02 PDT
Users tend to save HTML files or send it to friends, unknowing that it contains sensitive information (like, for instance, a cryptographic hash of their password).  This would enable their "friends" to engage in cross-site request forgery attacks.
Comment 7 User image burningmace 2013-08-09 15:24:01 PDT
Agreed on this one being a CSRF issue that should be fixed in the webapp, not the browser.

As for fixing CSRF, the standard mechanism is to generate a CSRF "token" (a random string) and embed it in the form, and store the token in the server-side session variables. Alongside it, you store the page which it should target. Then, on the receiving script, you verify that the token passed in the POST vars matches one of the tokens in your session vars, and that the associated target page is correct. Once it is used, the token is deleted from the array, making it useless. Additional security can be provided by making the tokens expire automatically after a few hours.

I do this in PHP by maintaining an array in the following format:

$_SESSION['csrf-tokens'] = array(
  array('token' => 'as2f4iuaXmvxs...', 'target' => '/search.php'),
  array('token' => 'KdtTYu9mCno8w...', 'target' => '/search.php'),
  array('token' => 's7R22jwe3dP6p...', 'target' => '/console.php'),

Each token is generated via entropy from /dev/urandom.

Having a single global CSRF token that is distinct from the session ID (e.g. a single var stored in the session) is also acceptable, but provides no damage limitation should the token be leaked. In the one-time token model, a leaked token allows for only one CSRF attack to be performed per leak, and only allows that token to be used on the specific target form that the token was generated for. In the single-token model, a leaked token means that all pages are vulnerable to CSRF.
Comment 8 User image burningmace 2013-08-10 04:18:10 PDT
To be clear, the tokens I showed above are not static - they are generated on the fly when a page is loaded that contains a form. The array I showed was just for descriptive purposes.

Note You need to log in before you can comment on or make changes to this bug.