Page MenuHomePhabricator

Login CSRF
Closed, ResolvedPublic

Description

MediaWiki 1.15.2 and earlier is vulnerable to a cross-site request forgery (CSRF) vulnerability in both its HTML login interface and its API login interface.

Login CSRF is a particularly problematic kind of CSRF when it is combined with user scripting. An attacker can create an account with a user-specific script, then force another user (the "victim") to log in to that account. The prepared user script then takes control of the victim's browser. It can display a login form, apparently on the same domain, which captures the username and password of the victim when they submit the form.

See section 3 of this paper for more discussion of login CSRF:

http://www.adambarth.com/papers/2008/barth-jackson-mitchell-b.pdf

To counter this, MediaWiki 1.15.3 will apply the standard defence for CSRF, that is to ask for a secret "token" before it allows a login. In the HTML interface (Special:UserLogin), the token is provided via a hidden form field called wpLoginToken, which the browser will automatically submit.

In the API, the login process becomes:

  1. Submit a request with lgname and lgpassword, in the same way as you did for MediaWiki 1.15.2 and earlier. Save the cookies in the response.
    • An old unpatched server will respond with a response like {"login": {"result": "Success", ... }, assuming JSON format. If this occurs, you are logged in and can stop.
    • A patched 1.15.3 server will respond with {"login": {"result": "NeedToken", "token": ...}. Save the token from this response and proceed to step 2.
  1. Submit a request with the cookies from step 1, and additionally submit the parameter "lgtoken", with the value from the token in step 1.
    • If the session cookie was not submitted correctly, or if the server-side session expired, the server may respond with {"login": {"result": "WrongToken"}}. You can report this as an error to the user, or retry after a few seconds.
    • If everything was OK, the response will be {"login": {"result": "Success", ... } as in MediaWiki 1.15.2.

Version: 1.15.x
Severity: enhancement

Details

Reference
bz23076

Event Timeline

bzimport raised the priority of this task from to Medium.Nov 21 2014, 11:10 PM
bzimport set Reference to bz23076.

<quote>

  • If the session cookie was not submitted correctly, or if the server-side

session expired, the server may respond with {"login": {"result":
"WrongToken"}}. You can report this as an error to the user, or retry after a
few seconds.
</quote>
If the session cookie was not submitted the server respond again with {"login": {"result": "NeedToken", "token": ...}. This could cause a infinite loop during the login process.

Should be relatively trivial to fix...

This is not MediaWiki's problem; sanely-written clients will give up after a number of tries instead of sheepishly going into an infinite loop.

I agree, it's not a problem to solve infinite loops by client. But mw does not react as described

Bryan.TongMinh wrote:

Tokens are associated with sessions, so obviously a session cookie is required for it to work at all.

Step by step:

  1. I submit a request with lgname and lgpassword and save the token from this response
  2. I submit a request with parameter "lgtoken", with the value from the token in step 1. but without the cookies

This means the session cookie was not submitted correctly and I would expect {"result": "WrongToken instead of {"result": "NeedToken",

(In reply to comment #7)

Step by step:

  1. I submit a request with lgname and lgpassword and save the token from this

response

  1. I submit a request with parameter "lgtoken", with the value from the token

in step 1. but without the cookies

This means the session cookie was not submitted correctly and I would expect
{"result": "WrongToken instead of {"result": "NeedToken",

From comment #0:

  1. Submit a request with lgname and lgpassword, in the same way as you did for

MediaWiki 1.15.2 and earlier. Save the cookies in the response.

[...]

  1. Submit a request WITH THE COOKIES FROM STEP 1, and additionally submit the

parameter "lgtoken", with the value from the token in step 1.

(emphasis mine)

The cookie thing was mentioned in the original instructions, seems you missed it.