Hacker101 - Oauthbreaker

Hacker101 - Oauthbreaker

·

3 min read

Summary

Oauthbreaker is a moderate-difficulty challenge from hacker101 that showcases how an Android app that poorly implements Oauth can easily be exploited. The goal of the challenge is to exploit the authorization code flow and get access to the token.

Analysing the APK file

We start off by downloading the Android apk and analysing it using Jadx-gui. Now that we have the decompiled java code, we can analyse the AndroidManifest.xml (the application's blueprint).

  • The application has set the attribute android:usesCleartextTraffic="true”attribute android:usesCleartextTraffic="true”meaning it establishes unencrypted HTTP connections which are vulnerable to man-in-the-middle attacks.

  • The application has 2 activities: com.hacker101.oauth.MainActivity which is triggered when the application starts and com.hacker101.oauth.Browser which implements a webview that lets the application display browser windows in app.

Analysing the MainActivity

The MainActivity has 2 functions: onCreate, which is executed when the activity is created and OnClick, which is executed when the Authorize button is clicked, to grant the mobile application access to the user's data. Below is the code responsible for generating the authorization URL.

try {
    str = "https://aa9dc76bfbbedd6f60433813efa2ea6f.ctf.hacker101.com/oauth?redirect_url=" + URLEncoder.encode(this.authRedirectUri, StandardCharsets.UTF_8.toString()) + "login&response_type=token&scope=all"; // Dynamically build a url using authRedirectUri
} catch (UnsupportedEncodingException e) {
   e.printStackTrace();
}

The authRedirectUri is generated in the OnCreate function and it's value is set to the value of the redirect_uri parameter of data that triggered the activity.

Oauth and authorization code flow

Given that the application is implementing Oauth, i'll explain a few concepts before continuing. Imagine this, you are a developer who's writing code for your new application and would like to build a secure system to have a good user experience. You've had of this new application called Snyk that scans Github repos for known vulnerabilities and notifies you with possible fixes.

The catch is that Snyk requires access to your github account, but since you don't want to give out your Github credentials you login into it using Oauth and grant Snyk read-only access to all repos. Basically, Oauth is an authorization framework that allows users to grant third-party apps access to their account on other applications.

Below is the normal authorization code flow

  1. The application opens a browser to send the user to the OAuth server for authentication.

  2. The user logs in to the Oauth server, sees the authorization prompt, and approves the app’s request.

  3. The user is redirected back to the application with an authorization code in the query string.

  4. The application exchanges the authorization code for an access token.

Breaking the Oauth implementation

# Start MainActivity and pass in the data
$ adb shell am start -a android.intent.action.VIEW -d "oauth://login/?redirect_uri=expected-client.com""

The above adb command matches the MainActivity's intent-filter and triggers the activity. Given that the application establishes unencrypted HTTP connections based on the attribute android:usesCleartextTraffic="true”, an attacker can intercept the traffic and modify the redirect_uri to their server resulting in unauthorised access to the user's data.

Modifying the redirect_uri to a server that we own eg: my-subdomain.oast.fun and running the adb command opens the MainActivity of the application and we are presented with a button: Authorize Clicking on the button opens a browser with the generated url and a link is displayed with the name "Authorize Mobile Application"

Clicking on the link results in an error 404 Not Found with the message: "The requested URL was not found on the server" which is expected since the attacker url doesn't match the existing redirect URLs for the application. Looking closer at the browser searchbar, there is an access token in the format ^FLAG^...$FLAG$

We get a hold of the access token and since the scope is set to all, we have full access to the user's account.