
okay hey everybody this talk says that it's about uh local privilege escalation in the Lenovo IM controller but that's just to draw you in it's like a bit of a lie so what this talk is really about is it's about the process of building a full exploit chain that is more or less complicated I think for a lot of people who are new to this this is sort of intimidating because what we always get to see is the finished product and that can be very very complicated but you don't see all the steps you don't see all the dead ends they ran into and I feel like at least for me when I was starting out that was something I was afraid to even get into because it felt like I didn't know what I was supposed to do and when I asked a bunch of people they were like just do that like just start making stuff happens and so what we're going to do is we'll start from a false positive so you know start with the failure I think who was it yeah learn from errors right um and a bunch of roadblocks but the the main goal is I want to make it less intimidating I want you to all look at the last slide where I show what the full chain is all the different parts of it and I want you to go in inwards and think if this if this presentation had started with that slide I would have zoned out I would have been like this is not for me and moved on and maybe at the end a few of you will feel like this is something I can do like maybe it's a lot of work but it's not something that's impossible or like Out Of Reach and that's my real goal so the details aren't important but the journey is and the the sort of more abstract approach and if you want to hear more details ask me afterwards because oh wow questions is cut off great um so this all started because I made a thing um I had to look through a bunch of donut assemblies I was doing some research in game City and unity does some annoying stuff like having a I am oh okay um so Unity has a modified.net runtime oh well this is okay um and that makes a lot of things a little complicated so I made a tool to automatically scan for Dangerous patterns so I could scan my whole steam Library no problem um and so I can mask again I can Define custom patterns and it can obtained analysis which actually turned out to be pretty useless in practice because if you get to that point you can probably just use a well-known like chain that already exists you don't need to find your own um unfortunately it's proprietary so I hate to disappoint all of you I wish it wasn't but that's not up to me unfortunately um so a colleague of mine was using it and said hey YouTube flag the Microsoft thread modeling tooling I was like that sounds pretty interesting let's take a look at that um so this is the output tool and what you see is a lot of false positives wrong on all of these didn't work out so that was a little disappointing so you know all false positive not great but then I spotted something else um I I hope you can see it it says Lenovo IM controller I hope um and that looked interesting so I I decided does my tool find anything else Lenovo related and I did find a bunch of little related stuff all of these are like in the Lenovo tooling um and that was great so where where do I stop huge code base also be bad enough okay fingers crossed oh this is some real life stuff uh I'll put it in okay okay I hope this is better um so where do you start looking it's a huge code base so stuff that's really interesting because you get a lot of bang for your buck libraries stuff with high prips that gives you local privilege escalation typically and things that do network communications because if you want remote code execution you kind of have to talk to the thing and then.net that's a bunch of quick ones and security serialization is everywhere still um if you find a binary formatter you've probably got code execution so congrats a lot of command injection vulnerabilities and you can do a surprising amount by just messing with paths if you can trick Microsoft into thinking something's an SMB it'll happily send you credentials so still great great source of of hacking into stuff um so this is what the actual output looks like the details aren't as important but this ticks all the boxes it's a utilities dll so that's probably a library that's used in a bunch of places doesn't have high privileges well it has a function called launch system process and user session so that's kind of promising does it do network communications well it's a system update plugin so it probably gets that update from somewhere so that takes all the boxes so this is where I started looking and throughout the talk I'll have this sort of status chart where I keep track of a more abstract view of things because that's a lot to keep track of and I hope this will be the thing if nothing else that you can remember about the talk so we're at the start and we want to get to profit and how do we do that well we look at stuff so at the very beginning we open all the things and when we open all the things we start looking at the thing we're interested in which is the launch system process in user session function and the nspi which is a nice tool which is sadly deprecated but still very useful um has an analyze feature which tells you where everything is used or something you're looking for so it tells me this is used nowhere which is disappointing so this is a false positive because maybe this is a dangerous function but it's not used anyway so that's not helpful okay but it's it's in an interface like it's an implementation of an interface so maybe that interface is used in places so let's Analyze That also not used anywhere so again very disappointing so at this point you kind of have to dig a Little Deeper I hope that you can see this it's a little hard to see the the takeaway is this is the the actual thing that starts the process that I'm interested in and like all the surrounding stuff takes care of putting it in the user session and so on but I I kind of really only care that I can run a system process in the end and so if I analyze that finally I find some stuff that actually uses it and the interesting bit here is that this is sort of it looks like this is in in a service support Library and if we look at where this is used this is a contract agent I don't know how many of you are familiar with like the concept of contracts and programming the basically it defines like an interface for RPC in the widest sense um so this is something you can send a request to and it will do something maybe we don't know that much about what's happening yet um so looking at this this is the interesting bit and it takes in this info argument and has a switch statement which has the launch processor system function depending on what's in that and that is just passed in as an argument so the the idea is we we kind of want to keep track of this info that's passed in here is what actually determines if we run a system in the end and then at the end it does some cleanup it deletes some files and that's all this method does and what I care about is can I get to this can I somehow manipulate this info that is passed into that so that I can execute stuff as system so this is only used by two other methods the first is called download and install application and it's in the contract agent so I'm thinking maybe I can send a request to install stuff and looking at this what I care about is at the bottom here is where that info comes from and where where does it originate well there's a method up here called get app information and at the top there's a request so the argument that's passed in here is like a really long class name request and that request determines all the rest that happens here so what I'm keeping track of is there's an install request that maybe I can send maybe I can send I don't know that yet but if I can control that maybe I can do stuff and so the other thing I look at is install only or install application only I think it's called it's a little small on my screen so this is similar at the bottom is this install call and at the very top here is that get app information call and if we compare these two that's a sort of weird thing you might notice so this one on the right is pretty short it does like get app information then it downloads it and then it installs it and this one on the left is install only so by name you would expect the one on the right this one to do more stuff it's supposed to download and install and the one on the left is install only but it's way longer so why so stuff like that is what I typically look for like things where I go huh that's interesting because that's where somebody put in some extra effort or made some extra steps to mitigate something or to try and circumvent something and they didn't do it in another spot so that's like some discrepancy that I care about and so if we look at the difference between these two get app information calls the only real difference is that the stud argument is true in one case and false in the other and just keep that in mind for now so it's almost an identical call and if we look at all the extra stuff that is done on the left side I'll enhance um first if you decompile stuff it will have generic variable names so let's name them something a little bit better so let's just call this a root path for you know reasons because time really is the reason so this is the root path and then this is the installer path because we're still in this context of like triggering the installation of some application and if you look at this line with pool flag 2 what it really does is it gets the full path of the installer and then checks that it starts with that root path so effectively it's just checking that we're in a path that's like below the root path so we're not in some arbitrary directory but we have to be starting with that root path that's the thing that it's checking so let's add that to our chart that's oh if we control the app info if then the next thing that happens is there's some path check so in my this is how I think about this this is my mental chart of stuff I really care about I don't care about a specific line of code I care about like an abstract sense of what it's doing where does data come from where does it go cut Nigel and um I'm sorry okay so that's the first thing the fact the the second thing that it does is it called some validation tool gets trust status verify checksum a lot of stuff and the debug output says the is not trusted so in my head I'm I'm not analyzing this further at this point I'm just thinking there's some kind of trust check maybe a checks a checksum probably because it says verify checksum maybe it checks signatures as well don't know uh doesn't matter at this point but in my mental chart I'm like there's a trusted check and after that is profit because that's when install application is called and if I get there and I control the app info I probably won because I can make it execute an installer as system well we can't yet I guess so not thumbs up um so let's recap a little bit it's almost an identical call so what does this third argument actually do and why does the program not seem to trust the input there are like these extra checks in one case but not in the other one and the only real difference is the start argument so what is that third argument I don't think you can see it on the projector but I'll enhance uh so the third argument is use cache file so if it uses a cached file from the file system somewhere it doesn't trust it so why and this is a really long method that you definitely can't read on the projector right now but we can do a maybe the people in the first row but we'll do a short mental exercise so a lot of code is error checking in other conditions that don't really matter if you're buck hunting because I only care about controlling this app info I don't care about all the other stuff if that's an error and like it acts like it errors out I can't control the admin for like the process is done no problems no worse so I I will mentally just think about some of it so let's highlight these I cannot return result kind of important I don't care about this catch like if there's an error I probably don't control anything and then this block it's like XML pausing and so on but I only care about where the data comes from like can I control that so I only kind of really only care about this line that assigns the result and then there's a small error handling don't have this bit at the top I do care about and then we do some magic with paint and this is what it looks like and hopefully it is readable in this shortened form and what we see is like this is kind of XML data and I'm just naming variables to make it easier to follow um and this XML text reader in the second to last line is also that like that's just sort of a wrapper around the XML data to make parsing easier but that's the bit where the data comes from and then the other thing is a path because path combined kind of indicates that it's probably supposed to be a path and like it looks like a path um and this path depends on the request there's a request app ID and so if we control the request we can probably do stuff with this path and then if used cache file is true so that's one of the two cases the one where it doesn't trust the input and the file exists with the path that it's just constructed it'll go into the statement and what it does is it does some validation we don't know what that does we haven't looked at it yet but if that passes it reads all text from that file and pauses it at the end and that's the result so if we can go through this check we can control the app info and now we'll we'll do a little audience participation um oh no wait first we'll add that to the mental chart so if Get Trust status is is going wrong we fail and that's it but if we succeed we control the app info because it's just read from that file and then we're good to go and so this is a path reversal you might have heard of it if you're from the security space which I assume a lot of you are um but if you're new to this what is the path reversal basically you can mess with the path you can make it go to The Parent Directory or the root directory or something else where you're not supposed to actually access by the intent of the programmer um and we control the request well well assuming we control the request the app ID what can we do audience participation no you're supposed to like yelling ideas or something oh we can also do a party well okay what do you prefer do we do a party like or do you want to suggest something what would you put as the app ID like if if nobody says anything I will nominate someone okay go yep yeah yeah you're exactly right so that is one of two uh main options you can do here so we'll do a little exercise called default Windows permissions so what's a directory that's or like where where do we control stuff well there's some locations on Windows where you can just create directories even as a guest and that's for example C your your Root Drive everybody can just create directories because uh reasons I guess also program data everybody can create directories that'll come in handy later and the common source of problems is that these permissions are inherited by default so if you just create a directory everybody can still create directories in there and guess who did that Lenovo did that uh up here is C program data Lenovo and it inherits uh write permissions for everybody yay all right maybe not yay um so we can probably control control an XML file that is red because we have this past reversal and we can just create a directory and see for example and put dot dot slash dot dot slash dot dot slash my directory and like dot XML I don't know uh and it'll read that request so we probably get to that trust status check but that's the second vulnerability here so in this box does anybody want to take a guess well you have to because this is audience participation and any any hands up this is this is a little more difficult to spot I think I nominate others you win it is a time of check time of use vulnerability because we pass on the path twice so this file gets open twice and if in between we maliciously swap it out it'll do the check on one file and then read another file so this is like a typical race condition but going back to the vulnerability decks uh talk to is the the short name for it time of check time of use so like if you think of race condition this is probably the kind of thing you're thinking of and in this case we can just swap the file out in between and you can do this in really clever ways like you can do file system watches and see like oh this file was accessed in about 10 nanoseconds I have to switch this file out but you really don't need to because this check takes quite a while you can just swap the file back and forth and that's good enough like you get maybe you're at maximum minute wait time or something and then you just hit the race condition so no need to be fancy about it um so that's a plan and this brings us back to if we control this request we can do that well first things first if we fail we can just try again it's a race condition so we raise so we we just Swap this file back and forth and send requests and at some point we'll just get lucky and swap the file in between no need to be fancy or extra smart about it and we'll do a little time warp because I only have 45 minutes and you also only have limited attention span and we'll skip a lot of tedious reverse engineering which isn't actually that interesting you kind of just Trace back where this data comes from it's it's really just sort of busy work in most cases there's no extra sanitization this request is fully user controlled and we also fully control the app ID no extra checks on it in the cache case that's also the reason the download case doesn't matter because for the download case it'll just fail because it can't download it if it's like a past reversal app ID it's like that's not in the catalog so we get this arrow for free as well so now where are we stuck at the path check so what do we do about that path check wait first we should check some assumptions because we've we've looked at a lot of stuff and we haven't actually done anything yet like we haven't interacted with this program at all so let's check that it actually works and Lenovo gives you this broker request agent that lets you just send arbitrary requests to this endpoint and has it handled and so if you send a request it does respond back in the way that you would expect it says requested application not contained in catalog so we probably got to roughly the point where we expected to get to so thumbs up to look further it's important to check your assumptions all the time I've skipped over a lot of parts where I already did this when I was actually doing the research but it's easy to get stuck if you have something in your head that you think is true but isn't actually and so I would really recommend just while you work on stuff always just think what are my assumptions what do I think is true because if if I got to here and it's like now that some checked like seven seven calls to XD that prevents this I probably might not have caught it with static analysis which brings us back to the path check so the installer path has to be a subpath of this long path which doesn't actually matter what it is the the thing that matters is we don't have right permissions here Lenovo actually in the subdirectory for IM controller prevents us from writing so they sort of worked it out I guess um and the check for the subpath is really hard to bypass like even with Sim link trickery or like messing with uh the the case sensitivity features that are relatively new in Windows like it's you what maybe you can but I haven't found a way to get around