← All talks

[BSL2023] Dirty Stream Attack, turning Android share targets (...) - Dimitrios Valsamaras

BSides Lisbon39:58474 viewsPublished 2024-02Watch on YouTube ↗
About this talk
The Android operating system uses intents as its main means of exchanging information between applications. Besides messaging, file exchange is also possible by simply constructing an intent of action ACTION_SEND and using it to forward the desired file as an associated stream to another application. On the other end, the receiving app can define a filter in its manifest to inform the intent resolver to route the forwarded stream to a specific component. While the sender application can construct an implicit intent and delegate the decision of choosing the target to the user, it is also possible to explicitly define a component of another package and by the time that this is exported, to trigger it by using an explicit intent. The latter eliminates the need of user interaction and can be initiated at any time while the sender application maintains a foreground state. In this talk we describe an attack which exploits the case where the receiving application blindly trusts an incoming stream and proceeds with processing it without validation. The concept is similar to a file upload vulnerability of a web application. More specifically, a malicious app uses a specially crafted content provider to bear a payload which it sends to the target application. As the sender controls the content but also the name of the stream, the receiver may overwrite critical files with malicious content in case it doesn’t perform some necessary security checks. Additionally, when certain conditions apply, the receiver may also be forced to copy protected files to a public directory, setting the user’s private data at risk. ABOUT THE SPEAKER: A cybersecurity professional with expertise in mobile, web, and network penetration testing. Dimitrios holds a degree in Computer Science, majoring in Cryptography and Security, and has worked with top companies like Microsoft and Google. He is frequent speaker at prominent security conferences such as BlackHat, Nullcon, Insomni’hack, and Troopers. He is passionate about reverse engineering and was a member of one of Greece’s first reverse engineering research groups.
Show transcript [en]

okay so as I was saying we need to to to do this small change of schedule and Dimitri was so kind as to to to be here for for at this time so uh diit will be speaking about turning the dir stre the Tex so turning and right share targets into attack factors thank you Demitri and please go ahead hi everyone so uh I thank you for joining uh thanks to bides for having me here happy Universal I yes great job as always so uh before we start anyone related to mobile security mobile development and stuff and hands something all right okay for the rest is going to be a little bit hard anyway so

uh my name is demitrios I'm from Greece and uh here are few things about me so I'm engaged in computer security since uh 2002 I was a member of One of the first reverse engineering groups back in Greece and I started my career as a network security engineer for about 10 years then I jumped into developing for almost 5 years and the last five years I focused mainly on Android security while uh before I joined Microsoft's threat intelligence team as a senior security researcher I was leading another team which was conducting malw reviews for the Google Play store besides that I'm a father of two a boy and a girl and my free time I mostly write and play music

at least I I think so so before we start I would like to address a question which I get uh really often during my talks and this is how come a Microsoft security researcher talks about Android security so as I said before I have been following up with developments in cyber security for quite a long time and I can assure you although I think that you also agree with me on the fact that today's threats need a more let's say holistic approach so a bridge in your mobile device might have much more security impact that you may think in some cases can even touch your cooperates Network so I strongly believe that companies must evolve their Security Solutions in

order to protect their clients their customers across all platforms so I'm very proud of being a part of such an Initiative for Microsoft and with that being said let's jump right into the outline of this briefing which consists of the following topics so first of all we're going to talk about data and file sharing the Android operating system using content providers and then we are going to see what is a share Target what makes an up a share Target and why they are interesting in this context then we're going to explore uh the dirty stream attack we're going to see the root cause of this vulnerability pattern and we're going to see what happens when a third party app a Mal app

let's say successfully exploits the specific vulnerability and as we're going to see we can get a simple information disclosure and in many cases can reach up to code execution at this point we're going to wrap up actually and see also um an actual case of code execution so then we can we're going to see how we can protect Android apps from this or even similar type of attacks and we're going to close this briefing with some takeaways so content providers as you probably know or some of you know Android operating system Android apps are actually sandboxed each one trapped in its own data memory space which makes data and file sharing hard between them so in order to facilitate the data and

file sharing process the Android operating system provides let's say a construction which is called content provider and component so simply said the app that wants to share some data can create a content provider from the other side an app that wants to access some data can create a content resolver in order to do that which content resolver acts let's say as a proxy object that will communicate with the cont provider now since we want uh we don't want to block our main thread we want uh we don't want to freeze our app let's say we can use um a cursor loader in order to to do to perform this process in the background and finally we can get

the result of this query by accessing a c object and getting the results and finally process these results so what I just described can be better visualized in this uh figure here so in one side we have the server an app which wants to share some data that can be structured data or a file so it creates a content provider and implements methods that can be used to query insert update or Del data this is let's say the server site of an APK on the other side we have another app which wants to access this data so it creates a cursor loader communicates with a content resolver and since the resolver as well as the provider

implements the same interface as so the resolver has also uh needs also to implement methods that can be used to query insert update orderly data and after this point these TW can start communicating and exchange info now at the applications code level uh content provider is one of the earliest created components indeed if we check the activity thread the main thread and check the main method we're going to see that when a process gets created one of the first step is to attach a Looper and a Handler to it and the next step is to bind the Android app with this specific thread for this reason the bind application method will send this message to the Handler to the

main message queue this is going to be picked up by the Handler and the Handler is going to call the handle bind application method which finally will call the install content providers given a list of the content providers that this app wants to implement so for each one of them they install provider is going to create a content provider object attaching info about um the package name that this content provider belongs to the class name the process name and most importantly The Authority which is something like an identity like an address which we can use in order to refer to this content provider system wise so at the consumer side the other app which wants to access this data can

create can acquire ation content resolver instance and use it in order to perform the query now when it comes to the query method a couple of interesting arguments is the first one which is the content URI so a Content URI is a URI which has a Content scheme it has the authority for which I talked to you about before we can use it like I said to uh refer to a specific content provider then we have a table name in case we want to narrow down our query to a specific subset of data and finally we have a file name in case we're dealing with with a file provider I'm going to explain the subase of file provider in

next few slides second important argument is uh the projection which is an array of strings with column names of the database that we want to query simply said finally when this process ends it will return a cursor object which from which we can use one of these G methods and finally process the results all right so file providers despite the fact that we can share files using content providers the Android operating system dedicates a class especially for this reason which is the file provider which is actually subclass of the content provider and apps can use it in order to share files and share files more securely let's say due to the fact that they can use now

content Uris instead of the file Uris that we know so far and we use more often we used to use more often so besides uh extending this uh class another thing that app wants to do has to do actually in order to share some files is to create an XML file which called which has paths looks like this one here and it can be used to map content uis to file uis finally a couple of interesting methods when it comes to open uh to the file provider class is open file which if we give a Content URI will return a file descriptor to the file that we this content U points to and the open asset file which is used

in case we want to query a subsection of a file to get a subsection of a file so let me now elaborate a little bit more in this path file that I said before that an app has to declare in order to share files so it's an XML file and uh it has a root element which is called paths and some child Elements which correspond to uh directories that are commonly used by Android apps so we have the root path for the root director of the device we have the file path for the internal file directory of an app we have the cash path for the internal cach directory and we have a couple of

attributes like the name which we can use it actually works something like like an allias let's say within a Content URI in order to represent this specific node within a Content URI finally we have path which we can use in order to uh Define a subsection actually sub directory within the directory that we are sharing and I know that this sounds a little bit confusing so I have a couple of examples so if we have this uh external path note let's say so this points to this file U right here and a more complete example we have uh this root path so we have the content U as I said before we have the content

provider which is the authority the com do example here so we use this um uh let's say Alliance test rout in order to index files within the root directory of the device from this root directory of course we can index files also in in the internal directory of the app all right so how we can get these files from this app the file provider the consumer now has to use the open input stream or the Open Access file descriptor using the content URI which corresponds to the file that wants to open so this will return as I said before a file descriptor which we can use in order to cash it to the external or internal

directory and as I said before we can finally use it uh I said a couple of slides ago that content providers are the suggested way to share data in a Droid why is that here is where the permissions come into place for example let's say you want to read the contacts of the user so you have to query the specific content provider but in order to query this content provider you need specific permissions so you need the contacts same goes for the read calendar you can't query the specific content provider you don't have the specific permission now what happens when it comes to third party apps third party apps a very actually important aspect when it comes to third party apps is if

the specific content provider is exported or no so in case it is exported any app can simply get files from uh the disc content provider shares if it is not exported then only apps which have the same user ID with this one can access these files and if you ask me if this Behavior can be more manageable yes it can by using the grand URI permission uh tag here which if it is said to true then an app can simply create an intent attach a file use this flag here in order to define a mode of operation read or write send it to another app the the other app will receive it and has temporary access to

the specific file right so let me test your how You observe this so another way now to share files to share access to content providers is by using this method here which is the grand URI permission which gets the package name gets the package name to which we want to provide access the URI for which we want to provide access and the mode of operation although I wouldn't suggest using this one if there are any developers around here and can anyone think why we don't supposed to use this one

nope all right so I guess uh when it comes to Play Store to Android play store each app let's say has a unique package name right when it comes though to of Market apps any app can use any package name so this method here doesn't check the uh signature of the app it doesn't verify the identity of the app so any app can claim you know I am this pack package here and I can get access to this uh let's say content provider to the file to the files or the data that you are selling so this is the idea here this app doesn't check uh the identity based on the signature just check the package

name that's uh that's the whole thing so don't use it simply if you're developing Android apps all right let's now see see what is a share Target so a share Target is an Android app which defines itself to handle data in files that comes from other apps and we have a lot of examples of them we have file image video video editors uh Messengers email clients we have a lot you name it so how we can create a share Target there are three main ways you can use an activity which match a spe specific intent filter or you can use the Chooser Target service or you can use the sharing shortcuts API in this one we're going to focus on the first

one which is uh the the activity all right so first of all to handle a file to handle a stream you must have an activity which will let's say somehow pass the specific file handle the specific file and you have to declare this in your manifest just pay attention because this is the way to actually uh identify the share targets these vulnerable apps let's say so so you define this activity you define in the uh Android manifest and the next step is to define the intent filter right so the intent filter is always filtering for uh intents of action sent or sent multiple the second is just in case we want to handle more than one

files at a time then uh we Define the type of the file that we want to process right and now how we can send a file to this uh share Target we are creating an intent of action send or send multiple we attaching this file as an EXO stream and we Define the data type finally we're creating another intent uh using the intent user method and uh finally we are calling the start activity using the second intent as an argument so if we put all these uh steps down we're going to have this code here which it's I would say simple and if we run this code you're going to have this uh sh sheet dialogue here so why this

happens why this uh triggers this dialogue here so this intent is Simplicity doesn't def find the app the package name the component that this intent should be sent to the file should be sent to so the user has to take a call and say I want this file to go to this app so you're going to see this one and this is a practical way for you to identify which share targets you have installed in your device you can long press on a file you can choose share and then you're going to see this uh this thing here which is a practical way for you to see which uh share targets are installed in your device all right so

how you handle this file now that's here is the the the catch so the majority of the apps that we have reviewed so far seem to follow a very very specific pattern and this pattern has the following steps so first of all they're trying to get the file name of the incoming file right and they do that by performing this query here they use the incoming URI the display name uh as a projection and they perform this query and they in order to get the file name now why they use the display name so there is a a fault impression that uh developers the app actually will be interacting with an actual file provider and the file provider the one

that I said before that is dedicated for the from the Android operating system has this uh display name as default this is a column which the file provider has so the developers think that they are dealing with an actual file provider it makes sense and they use that so they're going to get this file and they use it in order to create another file file so they use this uh another file in order to create an output stream then they use the incoming content URI in order to create uh an an input stream and finally copy the input stream to the output stream another question does anyone see something strange here something that is missing

sorry closing no no okay that that would make some uh checking what checking for the name yeah that's uh that's a good point because if you notice the file name as well as the incoming stream are controlled by the center by the other app so we have somehow to handle the file name and the incoming stream all right so now if you ask me how come and all these apps were following about the same let's say code pattern so there is a very interesting study by verd told which talks about vulnerability that we found in crowdsourced uh uh code examples and it mentions that uh 69 uh vulnerable code cases which were found in stock overflow were used in 2.9 th000

um um GitHub projects so just to make sure if the writer of this comment is around here I'm not implying that uh this code that you see here is actually vulnerable by itself but if you take this part of code this piece of code and you combine it with a copy file that we saw before then as we going to see in the next few slides we are going to have a big big issue all right so let's now Define the adversary model let's go to the de stream attack enough with Theory let's see what how we can do that how we can exploit this all right so uh in order to do this attack in

order to perform this like we need an APK we need the user to have this uh an APK installed in the device this is not that uh you know it can happen there are people here that they know that this thing can happen very very easily so we don't need any permission only internet just in case we want to download some kind of a payload or something but in generally uh we don't need any kind of permission all right so we're going to use this uh malware this uh Rogue APK in order to interact with the sh Target so the first step is we are going to send a request to the sh Target saying that we

want you to process this file so the sh Target as we saw before is going to take this uh stream and is going to ask for the name so since we are controlling this name we can politely ask the sh Target to override some kind of uh let's say important file this can be a library this can be uh a DEX file that loads from the internet directory or even JavaScript file which loads in some kind of a web View and uses uses it in JavaScript interface and so on or even that was a very actually common uh we could overwrite settings from the S reference directory and imagine that if the app is reading some kind of a critical setting

from this uh directory then you are going to have an actual security impact we're going to see something so that's the case and as you saw before the share Target is going to ask about the the actual file so give me the file now I want to to process this file since we are controlling this file we can um let's say send our payload there and see how the share Target will do that what we'll do with it actually all right so let's see how we're going to do it in practice so we're going to create a our file provider we are now the attackers let's say just to make clear so we are going

to modify we're going to to craft a content provider and we are going to modify a couple of methods override a couple of methods one is the uh query method of the content provider the other one is the open file and uh we will try to minimize the user interaction you saw before that the user has to click something so we will try to minimize that to erase that we we simply have an app which will exploit another app that's that's the whole idea that's the whole plan so this is how our content provider looks like it's not I didn't write anything of this so it's automatically added from uh uh the Android studio and uh the only thing

that we have to do is just to override the query method as well as the open file so how we override that what we are doing there so the first step is to convince the share Target that it's dealing with a file provider an actual file provider and why what we're going to do with that we're just adding columns which the file provider has like the display name that you saw before size data title and so on then we are getting the URI we are adding uh rows dynamically under this specific columns now why we do that um and we just don't hard code the names and all this kind of stuff so we do that

it's not that relevant so far we just do that in order to make the exploit more General and handle more than one share targets with just a single exploit uh we can encode use some kind of an encoding in order to bypass some kind of filtering when it comes from the share Target and finally we're going to attach all this info to the cursor object that we talked about before and set it back to the share Target all right so what happens with the open file the open file again we get the incoming URI and now we are getting the path query parameter and depending on this path query parameter we send our payload back to the share

Target so that's that's the whole idea so what we are going to send is the question so as I said before we can uh download something from the web but the Android APK packaging provides a very way cool way to package payloads and this is the assets files so you can simply put it there and pick it up from there that's the idea and why we did all that why we didn't hard code the names and all this kind of stuff so now you have an APK which you can give uh the package name of the share Target you can give the class name the app which the activity which will handle actually the Stream

and then you are going to create an intent uh which this time is explicit and what I didn't cover so far is how this content URI looks like so this is how the the payload looks like so we have the content scheme we have the authority which I'll exploore it right now we have a dummy path because why because in some cases uh the share Target checks if the content URI has a path in order to validate it so we can use any here it doesn't matter in this case then we have the path which corresponds to the uh payload that we want to send we have the name for the file that we want to overwrite size

sometimes the share Target might ask for the size and finally if we're going to encode or not the name so if we get this uh query in our content provider we're going to have exactly what you see here display name size data type all these entries so when the share Target will ask about these entries we're going to to send them back all right did make sense anyway so we're going to see an example so it will make I guess at the end so it should be understood by now that if we successfully manage to exploit this we are going to get the right access to the internal directory of an app so what uh as I said

before Android apps are sandbox so we shouldn't do that we don't supposed to do that each app has its own directory and there saves file files which are critical so we don't supposed to do that right so okay we got right access what what we that so we can search for uh libraries that they app might loads from there might load from there or um they on demand delivery modules a very cool uh plugin not plugin actually library from Google which uh is a little bit naughty when it comes to the uh Native files then uh we're going to search for Dex files imagine that this uploads some Dex files from there so we can get some kind of code execution and

as I said before uh we can see if they app load some critical settings from the suace directory so this is a cool trick now to bypass a couple of uh things so um while we were trying to overwrite a file we often encounter this problem here so the up was checking is does the file exist so if it exists I won't overwrite it so it makes sense right you have a let's say a a PDF editor or something you are sending a PDF to process so the PDF would check that this file exists so I'm not going to overwrite it so there is a way to bypass this type of check this exactly check here so what happens when uh an

Android app tries to read uh settings from the self preference directory giving the name of the file that this uh settings rely to so it will get the name so the surface implementation class actually will get the name it will do the following which I still don't understand why so it will do the following it will create a backup file so imagine you are giving the example XML file and you want to read some settings from there so it will get this file and it will simply create another file adding the dotb extension there all right so it will return this file back the next step is that the start loot from disk will will call

finally the lot from disk which will do the following it will check if the back file exists then delete the XML file the original XML file and uh replace it with ours just rename the back file to XML file so as you understand we don't have to override something we just have to write a file with do back extension and let this Behavior to do the rest and this actually was so cool behavior that I wrote uh CTF about it there were very few that that found this uh thing because you have to go I mean to search deeper how this thing works in order to do it so yeah that's the solution I guess and uh

can we read files using this exploit using the vulnerability so when it comes to reading files the idea is to try to convince the share Target to process one of its own files the share Target might also have content providers might share files by itself so we try to you know process your own file and what is important now here is where the share Target will save this file the the the result of this process how we can exploit that we are looking for Mis configured content providers lose file provider paths and as I said uh before the most important thing is where this file will be stored the result will be stored so why it is about to use a

custom file uh file provider and not uh let's say extend the default one so we can do something like that so developers don't mind very often they don't mind the path travs of characters so you can just jump out of the preconfigured sh directory and index any file so you can index a file which has some kind of uh let's say sensitive info and send it to the share Target so this is the one another thing that you can do is you can search for uh root paths or root uh let's say child elements which will point to the root director of the device and then you can do this you can again index a file which is has some kind of

critical info sensitive info so you're going to send this to the sh Target as we saw before the share Target will try to save it and if the share target saves this one in the external directory we can simply pick it up from there but there's a very cool trick to do so there is a display name query parameter from the file provider class which we can use again to modify the name of the file and uh Force the share Target to save this file to uh to the directory that we control right cool so let's see the impact what we did uh we checked about 20 and uh since this was uh published actually checked quite more and I think

that this uh analogy was even more now when it comes to vulner apps so all these apps that we checked had a common characteristic of more than 100 million installs each and in 50% uh of the cases we managed to get code execution sorry no uh 28% 55% were found to be vulnerable 18% we get information disclosure and 27% we didn't get anything all right so let's see now let's wrap up everything and see how this thing works in practice and this up that we're going to see has a more than 500 million installs according to the Google Play Store it's a browser and uh it is a share Target so as I said in the beginning how we can

identify it it has this uh let's say characteristics uh um intent filter which does exactly that filters for intens of function send so this is the sh the share Target the Ser uh the components which will handle the incoming stream and what this app was doing when it was getting an incom stream was doing the following so the first thing was as we saw so far in all of the cases to get the file name so get the file name then it was doing a couple of uh other things in order just to create a temporary c a unique temporary cash uh path so it was getting the md5 has of um the incoming URI it was concatenating the strings in

order to create a temporary cash unique cash path and then mistake here is of course that it was concatenating the name of the file with the with the actual path the one that created so you can do something like uh that you can send an intent which will jump out of the default cach directory so it was using this name in order to cach the file and of course you can finally let's say jump out and reach to the internal directory of uh of the app all right so we had right access okay so what we can do with that another cool thing uh which end up to be a duplicate for a CV but

that was a cool CV anyway um so Google Play has a very cool Library which uh can be used in order to deliver up bundles in order of uh the apks that we know so far so what that means uh imagine that we have the Legacy apks where you no matter the device that you have you might have an armed device or whatever device you have you're going to to get the whole APK in your device installed so what the bundle does and what this Library does is um depending on your device is going to get only the module that you actually need the language that you need the library that you need and so on which is

very cool because you just download the base uh APK and then you can just download the next uh elements that you just need nothing more that's cool but this library has has a very very bad habit and this bad habit is to save uh Native files in the home directory of the app which is very bad and uh as you understand the first idea was why don't simply override this file so it was saving some files in the internal directory why we don't override it and this is the cool part that uh the browser was checking again if the file exists so it will simply didn't do it so now here's the the deal what this uh

library is doing so it has two uh uh directories the one is called unverified splits and the other one is called verified splits so when you download the base APK and you want to download the extra modules uh this Library will first download uh the extra module in the verified splits directory then it will check the signature of this uh APK of this module and and if it matches with the developer signature then it will save it here to the verified splits from there as you probably know or some of you know an APK is simple simply a zip file so it will explode the zip file and try to install the components of the extra components

that we need so now the idea was uh jump so now the idea was what will happen if we just write an APK to the verified splits so to our surprise uh uh the library simply got our APK exploded because it apparently thought that uh it matches actually pass the first the first check the signature so it exploded the APK uh override the files of uh the browser and we got our code execution here and how we got our code execution we got it this uh this plugin actually was used by this browser in order to uh let's say uh unzip files so we just override this uh these libraries and we got our code execution

here so again I repeat this is uh this is actually vulnerability which was passed uh after after we reported that it was D like I said before and the stet think just to mention here that with this library was the following so it was um uh registering a broadcast receiver and this broadcast receiver was getting the file name it was unprotected of course and was getting the file name of this file from an external app so it was getting an intent the other app was simply sending an intent here and was saying to this uh Library just install me this APK so it was doing that it was very cool uh CV in any case now it was

fixed this is fixed so it doesn't work anymore all right so this is how our exploit looks like as I said before we just uh sending an APK we overwriting the this uh these modules here all right right so that was about the code execution showcase now how we can protect Android apps from this attack right so guys I mean developers don't have to use the incoming file name in order to cash a file doesn't make much much sense right so you don't need to use this file name in order to to cash your file you can create a temporary file you can use this file in some other entry or something but don't need to use this one nor to C

it so if for let's say some kind of backwards compatibility or something you might you still have to use this file then you have to take extra stps in order to sanitize it and how we sanitize this I guess many of you are aware of uh the file upload vulnerabilities when it come to web apps this is this is a similar type of attack so you are sending a file to the web server you are trying to override something this is the same thing so you have to take the same steps in order to uh sanitize the file and uh a very important thing is at the end after you do you did all that

you have to make sure that the file that you are going to cast the one the result is under the directory that it's supposed to be so you are just comparing the path of this file with the path that it's supposed to be and if it's not there you just simply don't create the specific file all right so takeaways uh not much of a rocket science here consider all data which originate out of your app as unrusted now what is the the added here thing here you notice that this thing exploits this vulnerability exploits this vulnerability type exploits default components like the file provider or um there are many variant of this type of attack and this

is just like I said just one one type of the specific attack so it is actually it can be used with uh default default browsers of uh the mobile mobile it can be used with a lot a lot of things so when you are getting a file from uh outside of your app you always have to uh let's say uh sanitize it even if you're thinking that you're dealing with a system component that's my point uh for God's sakes don't load executables from your data directory I don't know why Google is doing that so avoid loading libraries Dex files and always replace if there are such files always replace them your next rest with some

clean uh let's say copies that's something you have to do always never installed uh applications outside of uh the Google Play Store of Market no way why because the Google Play Store makes sure that apps meet some specific criteria let's say meet some specific SDK uh let's say uh levels these kind of things so always always install apps from the Google Play Store despite the fact that you're not always as a I said 100% uh sure all right and uh that was the end thank you very much if there are any questions I will [Applause] be thank you any questions anyone it's kind of heavy topic uh let's wait for a while I believe Bruno wants to

something okay thank you thank [Applause] you