start	end	text
0	5780	My name is Kyle Benack, you might know me as b3nack on Twitter, and I'm super stoked
5780	11980	to be presenting my Android application exploitation talk here at DEF CON Red Team Village.
11980	14100	Try saying that three times fast.
14200	19140	I also want to thank Joseph and Omar for inviting me.
19380	25760	I am a full-time security researcher, and in my spare time, I really enjoy testing Android applications.
25760	33680	This talk isn't targeting any specific skill level, and I hope all skill levels find the information in this talk useful.
33720	41680	Also, I'll be focusing on the application level vulnerabilities in the Android ecosystem.
42200	45540	So, let's get the party started.
46120	51260	Right off the bat, I just wanted to show all the exciting things we have in store today.
51260	54460	Here's my xMyMap for Android attack vectors.
54460	57900	We're going to be covering a little bit of each of these main subjects.
57940	66520	Everything from exported components, webviews, deeplinks, third-party SDKs, third-party plugins,
66520	71980	APIs, insecure cryptography, and insecure data and file storage.
72280	80200	I'll be focusing more on deeplinks just because I feel like this is an area that isn't researched as much,
80200	88660	and the possibilities for deeplinks are honestly endless because they can be chained with all kinds of other different vulnerabilities.
90360	98520	They behave the same way as exported activities in a way where they take users directly to an activity,
98520	104460	and they're honestly just a ton of fun, and I'm excited to share my research with you.
105060	109300	Also, this xMyMap will be available after the talk.
110280	111280	Alright.
112800	119660	Everybody has a methodology, so I wanted to go over my Android methodology a little bit before we get to the fun stuff.
119880	121820	First is the reconnaissance phase.
121980	128720	During this phase, I'm going to try to detect which framework is in use, whether it's native, Flutter, or React Native.
128720	137420	If there's any exported activities, if there's any custom deeplink schemas or regular deeplink schemas,
137420	145900	if there's any third-party plugin integrations or SDK integrations, as well as API keys.
146680	157560	So, this is pretty easily done with the AndroidManifest.xml because the AndroidManifest.xml is basically a blueprint for the entire application.
158520	169700	And I'll show you what key phrases that I look for, key entries, in AndroidManifest.xml as far as figuring out what framework is in use.
169780	171900	Next is the preparation phase.
172600	181660	So, using Objection, you can bypass most native and React Native applications' SSL.
182360	188100	Unfortunately, it doesn't work for Flutter because Flutter uses a different SSL library called BornSSL.
188140	196260	I will also show you what I use for split APKs because every once in a while, you'll run into a split APK.
197800	199880	Next is attack vectors.
199880	203240	This is what I'm going to spend most of my time on.
203400	211620	I have an example of WebViewXSS for native and Flutter, as well as some deeplink examples.
211620	220960	There's all kinds of awesome deeplink shenanigans to be had in combinations with other vulnerabilities.
221180	223160	Next is Unicode collisions.
223980	231200	I haven't found any write-ups yet that show that Android apps are vulnerable to Unicode collisions,
231200	237340	but they definitely are because Java methods and Kotlin methods both have Unicode mapping collisions.
238000	239940	And I will show examples of that.
240780	245420	Lastly, validation bypass via FlutterRoute.
246800	254420	And that's just an interesting implementation error that can lead to random results.
255620	257660	Now let's talk about the ecosystems.
260060	267060	It's important to understand the ecosystem of the different frameworks just to kind of figure out where you're going to go next
267060	273260	as far as exploiting the application or trying to find other bugs that are worth a bounty.
274760	283500	Native apps, the code base will be mostly Java or Kotlin with shared object files if the NDK is in use.
283640	292440	They're easier to decompile because there's a ton of tools out there that decompiles the code into readable format.
293280	297580	It's easier to read and statically analyze after it's decompiled.
298760	301540	And it imports AndroidX libraries.
302900	308860	AndroidX libraries are the newer libraries for native applications currently.
309000	316740	Flutter uses Dart. It's created with cross-platform compatibility in mind.
316740	329800	So when you install Flutter, you're installing this huge tool set where you code it once and you can deploy it basically to any platform.
330460	336280	Production binaries are not easy to reverse engineer because it's compiled to a .so file.
337620	348100	The debug APKs create a bin file which is easy to find the source code.
349800	355540	It's as easy as a grep command and then you get the Dart source back.
356380	365870	The APKs tend to be bulkier unless you optimize the deployment to specific architectures.
366560	373870	For React Native, these applications are mostly written in JavaScript then rendered with native activities.
374400	376890	And a lot of the plugins are under the com directory.
377680	381850	Moving on to detecting native Flutter and React applications.
381850	390350	For native, usually there's a lot of AndroidManifest entries and most of the activities are easy to find in the com directory.
390810	400930	I do this a lot with JADX where I'll find a path in the manifest and just trace it to the decompiled source code.
401210	408990	For Flutter, Flutter has flutter.embedding entry in the AndroidManifest.
408990	414810	There's also a folder called io.flutter in Flutter applications.
415310	419130	There will be shared object files in the lib directory.
420090	424730	In the release, there's libflutter.so and libapp.so.
424730	433410	If it's a debug Flutter application, you'll find in the Flutter assets directory kernelblob.bin.
433410	437330	And this is the file where you can grep for the Dart source code.
437330	440530	But it's not very likely you'll find one of these in production.
441910	457490	For React Native, the entry com.facebook.react in AndroidManifest.xml is a key indicator that React Native is in use, as well as a dev settings activity.
457490	464650	In the assets folder, you'll find an index.android.bundle file most of the time.
464650	469910	And this is all the JavaScript code that hooks into the native activities.
471430	481970	For the NDK and JNI, for the apps that use these, there's a shared object created in the lib directory.
482970	494830	You will find JNI calls in those shared object files, and then that will for sure tell you that the NDK is in use.
494830	503150	And you can decompile these shared object files with Ghidra or Dari2 and stuff like that.
504150	507890	Using Objection for SSL pinning bypasses.
507890	515190	So I use this script to automate the process of pulling the APK off of my device to my computer,
515930	523170	renaming it, and opening JADX on the fly for a quick static source code analysis.
524630	533670	Then, after I have the APK in that same directory, I'll use Objection to patch the APK.
534670	539990	And what Objection does is it creates another APK with an agent loaded.
540590	546850	And it tries to inject that agent into a launcher activity.
546850	553830	So when you launch that patched APK, it'll pause execution.
553830	559810	And when you use Objection Connect, you'll connect to that gadget.
559810	562930	And from there, you can bypass the SSL pinning.
565750	583630	If it's a split APK, then you can use patch-apk.py to patch the split APK and then save it as whatever name you want to.
583630	589290	And that Python script actually runs on top of Objection.
589290	592770	So if you have Objection installed, you're good to go.
594110	597870	And this works on React Native and native apps.
601170	602710	Demo time!
603350	609710	So, what I have here is an app that I own.
609710	616050	And I'm going to show you how to do this for the most part on the app I own, just so I don't make anybody angry.
618410	621810	So, what I'll do is...
625180	629840	So, what I have is that script is aliased to auto-apk.
629920	633840	And then all I have to do is put in the name of the app.
637640	640740	And then from here, it'll do the rest of the work for me.
641740	644120	Pulls it, puts it in the directory I'm in.
644560	657360	And then all I have to do is use my other aliased command to patch it.
658600	662840	So, this will install the gadget version I specified.
664520	670700	While it's doing that, I can uninstall this version of the app.
670940	678700	Because I have it automated to the point where it'll install the patched version on my device.
685590	691890	And you can customize this Objection patch apk command however you like.
691890	698430	Because sometimes the process will work without skip resources and skip native libs.
698430	705030	And sometimes there's entries in Android Manifest that throw off the process and cause errors and stuff.
705430	707810	So, it all depends on the application.
715710	722830	Looks like it's done loading the agent... I mean the free-to-gadget.
722830	734710	It re-signs the apk and puts it back in apk format and installs the apk on the device.
734710	745570	So, since this apk doesn't have an SSL component to it, it won't freeze on startup.
745690	752570	But production apps will stop execution because it will target the launcher activity.
758020	760980	Bypassing Flutter SSL pinning.
761180	766320	So, this is an entirely different beast in itself.
766320	770900	So, Flutter uses Dart programming.
772240	777000	I should say the Dart programming language which has it's own keystore.
777020	779600	And the SSL libraries are completely different.
779600	784180	It uses boring SSL to handle all of the SSL related functions.
784180	788200	There's two main ways to bypass SSL pinning locally.
788440	797540	And that's to find the SSL verification function in libflutter.so and change the response to true with a free-to-script.
798540	814180	If the plugin is used, then it's way easier to hook a plugin that is using SSL pinning than it is to decompile libflutter.so.
814180	817700	Find the offset to this exact method.
818780	827520	Trust me, I was trying to find the offset for a specific architecture and it wasn't super easy.
827540	831000	And I was having problems with compatibility with VMs.
831000	835790	So, I'm going to show the second plugin bypass method.
837520	841980	And later on, maybe in a YouTube video, I'll show the first one.
846330	855570	And I want to say thank you to Joe and Beckers for creating the free-to-script and finding the Java method being used for SSL pinning in this particular plugin.
856550	866270	So, running this command with the free-to-script waits for the method to execute.
866270	872830	And once it executes, it changes the response in route to true.
873950	877690	And I will show you exactly what I mean by that.
887220	901160	So, I have this exercise programmed into Android that has the SSL pinning plugin.
903700	911030	And so, if we use...
913770	915770	So, if we use this command...
921550	923070	This is actually...
923530	927770	This app...
939350	941250	Loading the script...
944770	947750	This will restart the app, I believe.
947770	951170	Because it injects the thread.
954010	960830	So, once the app is restarted, you'll see...
971300	990760	It doesn't matter what I put in for these, but just for demo purposes, it intercepts the pinning request every single time.
992740	996860	And just to show you what happens without this...
1002540	1004900	I'll exit out real quick.
1009830	1012310	And I'll go back to the activity.
1013270	1018010	So, without running the script, it actually does what it's supposed to do.
1018010	1024010	So, if I put that in there, whatever fingerprint...
1026190	1030050	It'll fail with the java exception.
1032050	1034310	And there's that.
1040010	1041870	Technical details of the Freedia script.
1041870	1052070	So, this is, from my understanding, the Freedia API calls in use are java.use and java.perform.
1052830	1063550	And java.use wraps a library in an object that can be used to modify calls to that library during runtime and return what is specified in the function.
1063650	1069310	Java.perform ensures the call is attached to the current running thread for the function to disable pinning.
1069310	1074650	And I believe that's why it restarts the application when you load the script.
1077640	1082380	Third-party SDK and API exploitation.
1082380	1091840	I can't emphasize enough the importance of reviewing third-party documentation to discover potential bugs.
1091840	1099460	So, demo apps make great POCs, and almost all third-party services have demo apps.
1100260	1112680	There's been numerous times where I'll be looking into a third-party integration and there's a demo app that shows how to quickly access the API.
1112920	1119960	But it doesn't check if it's an official app, if it's the official production app that's accessing it.
1119960	1124660	So, it's basically just like a doorway into the production app.
1124660	1134760	And it's even better if you can disclose sensitive data via some API call after you've SSL pinned the application.
1135900	1144420	Mobile endpoints sometimes have separate APIs, like completely different ones that aren't designed the same exact way.
1144940	1154020	And there could be different server headers, there could be calls without CSRF tokens.
1154020	1159480	There could be calls with just one authentication header for all the calls.
1159480	1175320	And sometimes you can even find the token in the Android app and use it to potentially elevate privileges and disclose more data.
1175800	1186440	So there could be a default one that's just set to the user's account, but then you can find another token that you can use in strings.xml or something like that.
1187250	1200800	And lastly, I found this in an engagement where S3 bucket keys were in strings.xml.
1200800	1207360	And I could upload and read the data in that bucket.
1207360	1216740	I could see what files there were, so there's stack traces, all kinds of different files in that S3 bucket.
1217060	1226120	And all I needed to do was add the keys in the bucket name to AWS Clive via the command line.
1229400	1236220	So there's all kinds of stuff that you can find as far as API exploitation and third-party SDK.
1236220	1251300	And there are some third-party integrations that you can actually overwrite certain parameters and perform link poisoning, which leads to spear texting, I like to call it.
1251300	1261180	Because I've literally been able to change the links in text messages to go wherever I wanted and not where, but it was under that company's name.
1266050	1279990	External file storage. So external file storage is essentially public on that device and any app can access external file storage.
1279990	1291690	Also, it's important to note that when you delete an app and that app saves data to external file storage, it doesn't disappear off that phone.
1291690	1303770	So a third-party app could scrape data from external file storage, literally these directories, and upload them to wherever they want, hypothetically.
1303770	1316810	But I would like to note that external storage behavior changes in API 29+, because they scope it per user and per app.
1317110	1327970	And shared storage has to be specified in order for files and data to be truly public. So it's a lot more stricter in the newer APIs.
1330580	1343230	And these environment.getExternalStorage calls can easily be automated into a recon script.
1347810	1364200	Native WebView XSS. So WebView XSS can be chained with deep links. So this can turn a quote-unquote self-XSS into a reflected XSS.
1365240	1378600	The identifiers for vulnerable WebViews are similar between native and Flutter apps. By default, native and Flutter apps aren't susceptible to XSS unless JavaScript is enabled.
1378600	1402320	So, for example, I have examples here for Java, Kotlin, and Flutter. They all look pretty similar, and as you can see, JavaScript is enabled, and the other main part is that user input isn't escaped.
1402320	1423320	Flutter WebView XSS via plugin. The official Flutter WebView plugin doesn't support alerting functions, but the development one does. And that's the interesting part, is that the plugin ecosystem kind of introduces vulnerabilities in a similar way that a WordPress environment does.
1423320	1446340	And the way the values are handled is slightly different because the Dart programming language is used. So, firstly, the form value is transferred to a WebView with a navigator push material page route. Secondly, the WebView where the value is going has with JavaScript true set.
1446340	1457180	And lastly, the user input value isn't escaped, and it's executed with eval JavaScript, which is built into the development plugin.
1458420	1483140	And now it's demo time. So, I have an exercise for this, too. Let's just say this application doesn't filter or escape what the user puts in as a username. And I almost put that backwards.
1488650	1500450	So, input whatever we want for the password. After the page loads, let's go to the profile. And bada-bing, bada-boom. We have stored XSS.
1507960	1529340	So, you can see here, if you see eval JavaScript in a Flutter app, as well as JavaScript set to true, it's definitely vulnerable if the development plugin is in use.
1531720	1547380	Native deep links. Deep links are specified in the Android manifest, and they can have a custom or web schema. Also, you can tell which activities have deep links by the intent filters.
1547380	1566320	In the example below, there's a scheme of flag 13 and a host of RCE assigned to RCE activity. What this means is that a deep link will send a user directly to RCE activity as long as those conditions are met.
1566320	1591230	And I'll show you exactly what I mean by that. So, if I use this adb shell example test command on Android, it'll send me directly to that activity. And that's the exact definition of a deep link, is it sends a user directly to a certain part of an Android application.
1593920	1615800	Flutter deep links. So, Flutter deep links are implemented via the plugin unilinks, and they are handled pretty much the same way as native applications, where the plugin intercepts the deep link and then routes the user to wherever the deep link router for the application wants.
1615800	1643020	However it's implemented, it'll send the user to that specific area. The Android manifest also has specific parts of that application that's assigned to the deep link. And the main thing is that they just look a lot different. The implementations just look a lot different because of the dark programming language and the async calls.
1644120	1661960	Native deep link to reflected XSS. This is where the fun starts. So, we're going to use a deep link and a vulnerable web view to basically create reflected XSS in a mobile application.
1662860	1676580	So, there's a couple preconditions that we need to have. It's a custom schema, so that way we know it's going to the mobile app. And the web view needs to have JavaScript enabled.
1676580	1699320	And the example below shows that JavaScript is enabled for the web view. And as long as the intent doesn't equal null, it's going to load the data from the query parameter totally secure and load it into that web view.
1701740	1736350	And it's demo time. So, the way you make deep link POCs is with HTML files. So, I'll just show you that it's just the same exact thing as a hyperlink. So, deep links are hyperlinks for mobile apps, basically, that take users directly to a specific part of an application.
1737330	1752510	And then, I'm going to push it to my device with adb push the deep link file name. And for simplicity, just sdcard download.
1755220	1794100	So, now if I go to downloads, and open the file, you can use any browser you want. It'll load the HTML file, and I'm just going to zoom in, click on this, it'll load in the web view, and it'll execute the JavaScript.
1800920	1812040	And this is the vulnerable web view I used. This will also be a part of one of my other examples.
1815200	1828440	Native deep link to LFI. Depending on how the deep link is implemented, it's definitely possible to include files on the device that aren't meant to be included.
1828440	1842620	I have actually found a deep link LFI and was awarded for it, so that inspired me to create a scenario where this is actually possible.
1842620	1855900	It's more likely that production apps will use a file provider or a PDF reader to do this, but still, for POC purposes, this is pretty fun.
1855900	1877090	As you can see from the code example below, the intent is sending a parameter called totally secure LFI, which is what we want to intercept and what we want to take advantage of to read files from the assets directory.
1879010	1890090	So, it's going to read whatever file we put as that parameter, totally secure LFI, and log it to the text view.
1892750	1895130	It's demo time.
1901990	1913090	So I have a totally separate POC for the LFI that I will show everybody real fast.
1913990	1930590	As you can see, it's the same deal as a hyperlink, except for it has the custom schema of XSS, the host of whatever, and the parameter of totally secure LFI, which equals the file we want to load into the web view.
1931990	1944470	We'll push this file once again to our device, and to SD card download.
1947740	1979030	Now we'll open the deep link. Actually, let's close this and go back to the files, open it in the browser, and it will load the contents in the web view.
1979690	1981670	More fun with deep links.
1981670	1989010	So I was curious if I could get remote code execution or command execution in general with a custom Go binary.
1989010	1999510	Turns out, I was able to get code execution and remote code execution via deep link with this specific scenario.
2001610	2011950	So, first I establish the process, and I get the run time of the custom Go binary, which is in the files directory of the application.
2011950	2025710	The intent param is the Go binary name, and the binary param is the command that the binary has programmed as an option.
2026330	2033770	Next, I make sure that I define a buffered reader to read the output for the command.
2035350	2053010	And also a string builder, so I can put the command output into the string builder, and then the buffer reader for each line will use the string builder to append the output to it.
2053950	2079150	Well, until the process finishes with processWaitFor, then once the process finishes, the string builder, also the log variable, will draw or print all the strings to the text view, which is defined as TV.
2081090	2088050	First, I implemented this in Java, and then I figured out how to do it in Kotlin.
2088050	2096490	The entire process was a lot of fun, and I'm really excited to share it.
2097510	2101110	Without further ado, it's demo time.
2107660	2117700	So, first, I thought it would be really cool just to see what the output should be.
2118200	2122860	So, let me exit out of this.
2124260	2134700	You can connect to a VM and phones via ADB once USB debugging is enabled, and establish a shell.
2135700	2137660	I'll show you how to do this.
2137660	2150880	Using ADB shell, we can navigate to this application's files directory, where the binaries are.
2151260	2163500	And then, the binaries that execute the commands are narnia.x86-64, because that's the architecture for this VM.
2165520	2176420	So, if I want to execute this binary, as long as I have permissions to execute it, I can just do that, and it says a parameter is needed.
2177820	2188800	I remember programming a help parameter, so the commands available are test1, rick, test2, potato, and test3.
2188800	2191520	So, let's try test1.
2193020	2195360	It's treasure. Okay, cool.
2197260	2198380	Test2.
2198900	2200320	It's underscore.
2201180	2202300	Test3.
2203780	2205580	So, treasure planet.
2207240	2211280	And, just for fun, let's see what rick is.
2211780	2215140	So, rick is definitely the rip roll YouTube video.
2216140	2218380	Because, you know, you have to have some fun.
2218380	2222600	While programming CTF exercises.
2223320	2232180	So, now that we know what the expected output is, let's try to execute commands via deep links.
2232380	2239520	Clear the terminal, and I will show you my POC.
2240220	2242580	HTML file.
2245870	2263890	So, as you can see, this particular activity has the schema flag13, a host of RCE, the parameters binary, and param test1.
2264770	2270050	So, the parameter called param is actually the binary command.
2270050	2286480	And, so, how to be able to make a deep link POC, I will show you exactly where to look in the application itself.
2286480	2303810	So, if I open Android Manifest for Android, right here.
2307120	2310820	So, the RCE activity is the one that we are looking for.
2311980	2321700	So, this is how, if you were looking to make deep link POCs, you would look for activities that have this intent filter.
2323580	2329540	And, then you can find out what the scheme is, and what the host is.
2329540	2349660	Now that I know what the scheme is and the host is, it's very valuable to see also what the activity has, because that could also disclose the params involved.
2351460	2356980	And it could disclose what params you can test out.
2356980	2365720	So, if you do shift-shift in Android Studio, you can go right to the activity.
2365720	2367100	So, that's what I'm going to do.
2369860	2376760	So, the params that were used for this were binary and param.
2376760	2393060	So, sometimes you can find specific parameters that the activity is looking for and use those to your advantage and find bugs.
2394200	2400120	Now, back to the demo.
2404330	2408790	So, we just have a normal blank RCE activity here.
2409570	2415950	We need to push this POC to the device itself.
2419270	2424710	And we'll push it to sdcarddownload, just for simplicity.
2434960	2441060	Now, what we want to find is the RCE POC.html.
2441060	2444120	You can open it with whatever browser you want.
2449880	2451320	Zoom in.
2451320	2456700	And with Android Studio VMs, it's CTRL and then dragging the mouse.
2458560	2462800	So, let's try the test1 command variable.
2466300	2471360	And that's awesome, but it output exactly the same as the terminal.
2473020	2483280	Test2, underscore, test3, plant.
2484160	2488720	And this should solve the flag for the exercise.
2488780	2493440	And also redirect the user.
2497730	2511970	So, needless to say, looking for intent params in the source code can disclose ways you can navigate to other parts of the navigation.
2512730	2520470	Or ways you can find bugs in sensitive data.
2521850	2537430	So, as an example, when the application is getting parameters, that's prime for you should append those to your deeplink POCs.
2540090	2542790	Just like this.
2550440	2553440	Now for Unicode collisions.
2553440	2561560	This is kind of uncharted territory as far as Android applications go.
2562240	2570100	So, Java and Kotlin both have Unicode mapping collisions.
2570100	2576900	It just depends on how the application is using Unicode.
2576900	2581740	This is prevalent in email.
2582260	2586980	So, password reset functions, for example.
2586980	2600620	It could exist in a database that converts Unicode to uppercase or lowercase characters.
2600620	2611440	This script right here just shows a simple way that I was able to confirm that Unicode collisions did exist in Java.
2611880	2629440	As you can see here, first I just tried to string to lowercase and uppercase the Unicode B character.
2630540	2639660	And if it equaled double S as to uppercase, it printed true.
2639660	2656940	And then, if the next one, I tried the email from the writeup that I was reading, which is included in my resources, to uppercase,
2658360	2663700	equaled what the POC was in that writeup, it was true, which it did.
2663700	2672320	Needless to say, Unicode collisions do exist in Android applications that use Java or Kotlin.
2672580	2675200	It just depends on the implementation.
2678820	2687400	I also included a Unicode collision example in Kotlin just because I don't think there's very many examples out there currently.
2687640	2694020	And this is actually one of the examples in Android as well.
2694020	2701960	So, this code is taking the post string value and converting it to all uppercase characters.
2702620	2708040	Databases sometimes do uppercase or two lowercase values to keep data consistent.
2708260	2715800	So, this is a very realistic test case that is worth testing.
2717260	2722400	Or, I guess, worth putting in your workflow for every application.
2724100	2732580	And it's important to note that Unicode collisions can affect mobile-to-web interactions.
2733800	2749440	Especially if the mobile app is connected to a database that I haven't tried out a Unicode collision yet with Firebase.
2749440	2758180	But definitely with certain types of databases, Unicode collisions could affect them.
2759060	2772560	And there was one instance where I saved my username as a Unicode character and I wasn't even able to run the Android app after that.
2772560	2785260	And the only way I could get access back to that specific account was to change my username from a Unicode character back to a regular character.
2785260	2794560	So, that's also important to remember that it could happen for production apps.
2799210	2805310	Authentication bypasses via insecure Flutter material page route.
2805310	2821510	So, navigator.push material page routes behave similarly to deep links except, if not implemented correctly, could bypass application logic and validations.
2821510	2828270	The example below is an example of a correct implementation.
2828270	2839630	You want to put these navigator.push routes after all of the form inputs. If you don't, I will show you what exactly happens.
2840110	2842170	It's kind of surprising.
2849050	2854390	So, this is an example of an insecure material page route.
2854390	2865910	And implementations that are like this can possibly have unexpected behavior and could leak sensitive data.
2866690	2894930	For example, if this was like a login form connected to a database and, for whatever reason, only the username was needed to link to the data for the user and it didn't check the password and pass validations because the navigator.push wasn't after the form inputs, then that could be all bad.
2898990	2901390	And it's demo time.
2910250	2924060	So, I have an example in here of an insecure navigator page route, which could potentially be an off-bypass.
2924060	2932400	So, you'll notice if I push signup, it says please enter your password and username.
2932400	2937880	If I just put password, it says please enter a username.
2938740	2944060	If I just put a username, it takes me...
2944060	2959080	It automatically brings me to the next page and doesn't really bother checking to make sure that my password was correct.
2959080	2977300	So, it's just another weird scenario, or I guess I should say odd scenario, where an implementation of a material page route located in the wrong spot could bypass validation.
2979660	2989300	And this is all because of the material page route being after the username value that was entered.
2990960	2996640	So, I'll show you what exactly I mean.
3002700	3015340	The material page route for this scenario is only validating that the username is not empty.
3018350	3027150	And if it's not empty, then the page route... these navigator push, basically, they're just like, alright, cool.
3028050	3038450	Everything before this being executed is good, so I'm going to send you to the next page, which is the home page.
3041920	3045060	And the validation ends down here.
3046040	3057120	So, ideally, the navigator page route should be after all of the validation takes place.
3064660	3069440	Easily bypassable and broken encryption.
3069760	3079820	So, plugins for Cordova and Flutter are more susceptible to this.
3079820	3088080	Any CBC cipher with a static initialization vector and hardcoded key.
3088540	3105840	Hardcoded XORs or XOR bitwise operators can be found in assembly, so it's important to note that you potentially could find keys that are hardcoded in shared object files.
3108380	3125300	It's going to be a little harder to identify, though, depending on the implementation, but decompiling those shared objects with Ghidra or Redari 2 will definitely show you any strings.
3127640	3135740	So, these two code examples are examples I've found in a Cordova app.
3135740	3138860	Or, not a Cordova app, React Native.
3139640	3143940	And I believe that they use a Cordova plugin.
3144600	3162700	And, so, in my opinion, there's really no point to use a plugin that encrypts data and decrypts it at runtime if you have a hardcoded encryption key.
3162700	3171920	Because once you find the hardcoded encryption key, it's basically... it's just all the protection from encrypting your data is gone.
3172600	3185040	So, when I was testing this application and I found this, I was able to decrypt the data pretty easily.
3186100	3195340	Luckily for them, there was nothing sensitive, which also made no sense to me. I wasn't sure why they would encrypt data that wasn't sensitive.
3197620	3216020	But, yeah, if you find a plugin that uses a hardcoded key and doesn't change it upon every use and a hardcoded initialization vector, there's really no point.
3216420	3221580	Because somebody can decompile the app and then use that key to decrypt all the data.
3222360	3227860	And I'll show you the script I used to do that on the next slide.
3233590	3240310	So, like I said before, static code analysis may reveal the encryption keys.
3240410	3246750	Then you can leverage them to decrypt potentially sensitive data with a Python script just to make it easier.
3246750	3250650	Because it's easier than making a proof-of-concept app.
3250650	3262470	Because in this situation, yeah, for encryption, making a proof-of-concept app would take a lot longer.
3264110	3267410	Because you really just need to decrypt the data that's encrypted.
3268630	3278570	You can also use a language of your choice to decrypt this, but this example is in Python and it was pretty easy to write up.
3279770	3284830	Reversing an XOR example. There's only two steps in the process of reversing an XOR encryption.
3285310	3292570	One, the XOR key. Two, applying the XOR key again to get the original data.
3293450	3303410	So, once you find an XOR key, or if you think you have an XOR key, just take the encrypted data and try applying the script to it.
3303410	3308910	And you'll know pretty quickly if it was XOR encryption being used.
3309270	3321620	It's also good to note that to keep a lookout for any byte arrays, because byte arrays can be converted back to plain text pretty easily as well.
3322090	3325050	And I have an example of that in this script.
3325050	3337650	Because in one of the exercises for Injured Android, there's a byte array that is supposed to be a clue to how to solve the actual flag.
3337650	3343170	So, I'll show you what I mean by that.
3343170	3347430	So, this is kind of a bonus demo time.
3348430	3360990	But, in this scenario, there's a byte array, which can easily be converted back to plain text.
3361930	3364630	I'll show you how to do that right now.
3364630	3384290	So, if we run the Python script that's in the slides, it gives back the encrypted string, the decrypted, or the byte array, which is here.
3388590	3397910	So, when you apply this XOR to when, it turns into this. And when you apply the XOR to this, it turns into when.
3404200	3413880	I'll go over some further technical details of how I implemented this activity.
3413880	3425560	After installing the Native Development Kit, you can create shared object files or native libraries with C++ and C.
3425560	3440260	And these can be used for a number of reasons. I mean, you could actually probably just program the entire Android application with JNI and the Native Development Kit.
3440260	3444540	It all depends on what your language or preference is.
3444960	3456520	Anywho, every JNI call for the shared object file will look something like that.
3456720	3462120	It'll have these attributes declared.
3462120	3482000	One interesting fact is that there's still a bug with this specific function, newStringUTF, where if it returns a Unicode character above a certain number, it will crash the entire app.
3482000	3486600	Now I'll show you how the shared object file is initialized and used.
3486600	3504900	So in the assembly activity, which is programmed in Kotlin, this is where I have a companion object that initializes the native library by using System.LoadLibrary.
3507900	3522180	In order to use the function, I had to declare this function as external and it has the same name as what's in the native lib.
3522180	3536140	This is important to note because while you're looking through assembly, you can track down the actual call faster if you know the method or the function being used.
3538200	3546360	Now that we're looking through this, you can see that XORString is the result of this method.
3547640	3561660	And that's one way we know that method was intended just to return a specific value or specific data.
3563790	3570470	And then XORString is being converted to UTF-8.
3570470	3586010	The bytes are being stored to a byte array so we can print it to the text view with bytes.content to string.
3586930	3594630	And that's why you see the byte array on that specific exercise, or CTF exercise.
3597810	3606070	Thank you everyone for listening to my talk. I am super grateful to have been given the opportunity to present here at DefCon Red Team Village.
3606510	3612350	I highly recommend you check out the OWASP Mobile Security Testing Guide if you want to get into mobile security.
3612950	3620790	And I will be sticking around for questions and answers in the Discord channel.
3620790	3633730	Also feel free to message me on Discord or Twitter whenever, and I will try to answer any questions you may have.
3633730	3636790	Thanks again, until next time.
