ACC “Nocheck” Security Vulnerability Report

On Monday, 18 January 2016, a critical security vulnerability was discovered in the Account Creation Assistance tool internal interface, which is used by volunteers to handle account requests.  The vulnerability was in the part of the software that handles user logins.  We shut down the tool as soon as the vulnerability was reported to us, and since then have patched the vulnerability.

The Vulnerability

The vulnerability was present in the logic that determines whether a user should be prompted to login in acc.php, and involved a URL parameter called nocheck, which seemed to play some role in the login process (see lines 76 through 120 of acc.php on GitHub).  It appears that the purpose of the nocheck parameter was to bypass the checks for the purpose of allowing the script to continue to the login process further along.

This is not the only piece of the puzzle, though.  As a result of poor coding practices and significant spaghetti code in various places related to user authentication and security, the bug was inadvertently hidden, then exposed to various degrees throughout the last several years.

Note that for the remainder of this section, hexadecimal hashes in parentheses, (likethis), indicate Git commit hashes of the specific versions of the code in question.

In recent versions of the tool, since June 2015 (afa126a1e8f20e9ac72ff01d25b9c57b106348fd), due to the nature of this vulnerability it could have been used by an attacker to gain access to private information, including account requesters’ IP addresses and email addresses, though not User-Agent information since the vuln does not appear to allow one to gain Administrator or CheckUser rights on the tool.  In addition, for an attacker to gain access to private information, they would have to reserve the request (see “Proof of Concept Attack” section below), generating a log entry and a notification to IRC.  A check of the tool logs have been completed, and we have found no evidence that the vulnerability was used to get private information during this period and we are confident that no private data was leaked.  However, based on what an attacker would have been able to do with the nocheck vulnerability without generating a log entry, it is possible that attackers have been able to view things such as the list of open account requests, the requested usernames, the account request ID, and the volunteer handling the account request.

However, between December 2014 (6c76d922edf2ce5840f15309d97ab6ccccad4e85) and June 2015 (afa126a1e8f20e9ac72ff01d25b9c57b106348fd), an unrelated bug in the code granted administrative access to the “community user”, meaning that an attacker who bypassed the login check using the ?nocheck URL parameter would have been able to see all open requests’ private data (IP address and email address) directly from the main page, without having to reserve any requests or generate any log entries.  Because of this, it is unknown whether this bug was used during this time period to expose private data.  Due to other intervening factors, though, despite the “community user” (i.e., the anonymous user) being accidentally granted administrative rights during this time, they would not have been able to carry out harmful actions, such as banning IP addresses from making account requests - and in any case, such actions would have been logged.

Between March 2014 (d81c191481f789735a1fdb1eead7d76986f7b5f3) and December 2014 (6c76d922edf2ce5840f15309d97ab6ccccad4e85), a different representation was used in the code for anonymous users.  During this time, as with since June 2015, an attacker would have been able to use ?nocheck to view private data only after reserving a request.  However, this would have actually broken the tool, preventing the requests list from completely loading and preventing handling/unreserving of the attacked request until a tool root manually unreserved the request through the database (the private data would still be exposed to the attacker, though).  That being said, since no instances of problems with the tool of this nature were encountered, it is unlikely that the vulnerability was used during this time period; furthermore, since there are no suspect entries in the logs, we are confident that no private data was leaked during this period.  It’s worth noting, though, that in this case, User-Agent data would have also been leaked, along with IP address and email address information.

From July 2008 (294840de48e7ec0e1bd29dcf3b32e2e387e4652d) to March 2014 (d81c191481f789735a1fdb1eead7d76986f7b5f3), the ?nocheck vulnerability was present, but inadvertently protected against by the use of a global $secure variable in the function that lists requests.  The variable would only be set if the user was properly verified as being logged in.  Therefore, it’s extremely unlikely that the vulnerability was exploited during this period.  However, it’s worth noting that if at any time ACC was used on a system which enabled register_globals, one would only have to use the URL parameters ?nocheck=1&secure=1 to bypass authentication.  The production ACC tool has only ever been run on the Wikimedia Toolserver (initially), where we don’t believe register_globals was ever enabled, and, since the Toolserver shut down, on Wikimedia Foundation Labs instances we control, and on which register_globals was never enabled.

Finally, the vulnerability was probably exploitable between June 2008 (7cc927dfb28b40d22b8ab243d8d006d4c485c54d), the time the nocheck parameter was originally coded into the tool, and July 2008 (294840de48e7ec0e1bd29dcf3b32e2e387e4652d), the introduction of usage of the $secure global variable.  During this time, there was no request reservation system, so private information probably would have been visible to an attacker without taking any actions that would generate a log entry.

Fortunately, the nocheck vulnerability was limited to acc.php.  Parts of the tool that used different entry-points, such as User Management (users.php) were never vulnerable to the nocheck bug, so we do not think it was ever possible for an attacker to, say, approve a rogue new account on the tool or take over another user’s account using this bug.

There is also a major mitigating factor protecting against private information leakage - since October 2010, the tool has automatically permanently purged the private data of a closed request older than a certain age.  From October 2010 through November 2012, that time was three months, and from November 2012 to the present, that time was (and is) 15 days, thus limiting the amount of private data that could possibly be exposed by exploiting this vulnerability.

Proof of Concept Attack

The following is the procedure for a proof of concept attack (with private information reveal) in the latest vulnerable version of ACC, identified by commit hash 81155069d38b7fcf01d5f5bda8ef76ea667b19a8.  To execute this proof-of-concept, you will need a fully set-up development installation of ACC checked out to the commit hash noted above.  You can also use the acc-vagrant environment to set up a ready-to-go ACC development installation, but remember to check out the above noted revision of the ACC code.

You will also need to have entered one or more unhandled account requests into your development environment.

For the instructions below, we will use “ACC” to refer to the URL of your ACC development installation.

Using your browser in its private browsing mode (to ensure that you are unauthenticated):

  1. Navigate to http://ACC/acc.php?nocheck - this will reveal a list of open requests
  2. Right click the request ID of any open request to gets its “zoom” page URL, and append &nocheck to it.  For example, http://ACC/acc.php?action=zoom&id=1&nocheck.  Navigate to this URL - this will reveal the information about this request, but not yet any private data.
  3. On the request information page, find the “Reserve” link.  Get its URL, then append &nocheck to it.  This yields something like http://ACC/acc.php?action=reserve&resid=1&nocheck.  Navigate to this URL.  This will return you to the ACC login page, but with a note that the request has been reserved.  Note that at this point, a permanent log entry is generated that the request was reserved to the user “[Community]”, and this would also generate an IRC notification on the production installation of the tool.
  4. Go back to the URL you generated in step 2.  Note that the request information page now indicates that the request has been reserved to “[Community]”, but still no private information is displayed.
  5. Find the “reveal link” on the page, which appears in two places - as “Reveal link”, and “(reveal to others)”, and get its URL.  This URL contains a hash that can be used to allow other tool users to see the private data of a request that’s not reserved to them - usually impossible unless you’re an Administrator or CheckUser on the tool.  As before, append &nocheck to the URL, which yields something like http://ACC/acc.php?action=zoom&id=1&hash=b8cd8fa15a5d71fb0e54dc7bc5c75bf0&nocheck - navigate to this URL.  The resulting page will display all request information, including the requesting user’s IP address and email address.

Note that partially mitigating this attack is the fact that two users can’t reserve the same request, so once a request was reserved for handling by a legitimate user, an attacker would not have been able to view its details until it was either closed or unreserved.

Moving Forward

It’s impossible in situations like this to assign blame to any one person.  As with most problems of significance, this vulnerability is the result of a chain of bad decisions, poor programming practices, lack of code review and oversight, and other problems, and had any one of these been changed, the chain would be broken and the vulnerability wouldn’t have happened, or at least would have been caught and fixed a lot sooner than it was.

For now, we have patched the vulnerability and done a basic review of the authentication code, and we believe the code to be safe enough to reactivate the tool.  In addition, a more thorough security audit is planned for the near-term, coinciding with a re-write of the tool’s security and authentication code.

To prevent situations like this in the future, we plan to institute the following changes:

The new coding standards will probably take some time to draft and write, but mandatory code reviews will be implemented immediately.

Finally, in response both to the discovery of this vulnerability and other unrelated events involving private request data, we also plan to, at some point in the near future, redesign the way private data is handled, and including in this new system some kind of explicit logging of viewing private data to establish a permanent audit trail.  This would not only allow us to track if private data has been viewed due to an exploit in the code, but also allow us to determine if otherwise authorized users may be abusing their access to stored private data.


Credit for discovering this vulnerability goes to the GitHub user wlritchi, who found it after coming across the ACC code and looking through it, and reported it to FastLizard4 for fixing.