XSS & Command Injection in Android — MobileHackingLab ‘Post Board’ Write-up

Ajmal Moochingal
4 min readJan 16, 2024

--

A lab that covers XSS in a WebView within Android which could be exploited by other apps in the device, combined with a Command Injection leading to RCE.

Random image — generated by DALL-E

This post contains the solution to the lab challenge. If you’d like to try the lab first, try it over here : https://www.mobilehackinglab.com/course/lab-postboard

Objective

The challenge objective clearly says the following :

‘Exploit an XSS vulnerability in a WebView component to achieve RCE in an Android application.’

Got to look into the app for further analysis.

Discovering the bug

I tried running the app :

The app accepts ‘markdown’ input.

How does it behave with HTML input then ?

Black box payloads can be tried first always. Trying hello<img src=x onerror=alert(1)> .

This looks like the mentioned XSS vulnerability. Now there has to be a vector for another hypothetically ‘malicious’ app to reach this bug, otherwise it’s only as good as self-xss. Into the decompiled APK.

In AndroidManifest.xml , The ‘MainActivity’ of app is attached to an intent with ‘host’ postmessage and 'scheme' postboard . This must be it. So the app might be accepting VIEW intent calls with attached data in the URI format postboard://postmessage/?a=b . But what is the vulnerable parameter? Over to the decompiled MainActivity.java .

handleIntent() got the logic we're looking for. It's checking for host and scheme, but the payload need no parameter, its taken from the path (after doing base64 decoding). There are some interesting invocations using javascript: scheme. Got to dig in to these further. These might be the vectors for RCE probably - Android WebView can have custom JavaScript functions that is bridge to the Native Java code. For now, I can verify if the URL scheme is working.

This worked very well.

While inspecting the html file loaded in WebView, we can see native functions being invoked.

Found new function in WebAppInterface.java that is not used from the html.

To validate I tried the following payload :

hello again<img src=x onerror=window.WebAppInterface.postCowsayMessage('hi')>

cow saying hi

We have a cow ascii art being printed with the message from it — hi . Got to inspect this function further. postCowsayMessage() function executes a function runCowsay() - which contains the following code.

There’s a shell command being executed here, while message we passed to postCowsayMessage() being appended in the shell command. We can try command injection payloads here. hello1<img src=x onerror=window.WebAppInterface.postCowsayMessage('abc;id')>

Exploitation

As the final exploit, I will create a shell command to launch the intent of Postboard — which is equivalent of what a malicious app would do.

~ echo "hi<img src=x onerror=window.WebAppInterface.postCowsayMessage('msg;id;')>" | base64 -w 0 aGk8aW1nIHNyYz14IG9uZXJyb3I9d2luZG93LldlYkFwcEludGVyZmFjZS5wb3N0Q293c2F5TWVzc2FnZSgnbXNnO2lkOycpPgo=

Using the base64 message, the following would be the final command for launching exploit :

adb shell am start -a android.intent.action.VIEW -d "postboard://postmessage/aGk8aW1nIHNyYz14IG9uZXJyb3I9d2luZG93LldlYkFwcEludGVyZmFjZS5wb3N0Q293c2F5TWVzc2FnZSgnbXNnO2lkOycpPgo="

--

--