Dangerous Code Hidden in Plain Sight for 12 years

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right check this out i'm currently logged in as a normal user i don't have full access to this machine but if i run this program bam all of a sudden i'm a root user i've got full access to this machine pretty cool right this video is going to be a story and a technical explanation behind this vulnerability that lets attackers gain high privileged access this video is sponsored by sneak sneak scans your projects for known vulnerabilities in code dependencies containers and even configurations go try it out at sleek dot co slash potent function about 12 years ago this piece of code was pushed to a particular linux package and little did we know this was going to be a major bug in many linux operating systems and about two months ago the storms of lock 4g vulnerability was clearing out and just when people were starting to settle the security team from koalas dropped this research it's a local privilege escalation meaning that if you're a regular low privileged user you can become root or an administrator without any credentials pretty cool right this is kind of a big deal because anywhere from penetration testers to malwares could use this in good and bad ways the word authorization in linux systems would actually lose its meaning the research also stated that most linux distributions like ubuntu debian fedora centos all of them were pretty much affected all because they shipped one vulnerable package pre-installed so this code is from the package pull kit or policy kit it comes pre-installed in many linux distributions meaning that a lot of machines were vulnerable at that point in time so the vulnerable code that you saw was found in an executable named pkx which is part of the policy kit suite of tools but what exactly is pkx and what does it really do pkx is an executable that allows one user to execute commands as another user kind of like sudo now you might have used sudo before which gives you root access to non-root programs right similarly pkx can also provide these privileges to unprivileged programs now the question is what went wrong to understand that we need to look into some source code before we get into the real meat you should know some things about arguments so let's check them out real quick so let's say that you run a program like cat and you provide test.txt as an argument so the entire argument array is going to look something like this here the cat is the first argument the index zero the first arguments are usually going to be the name of the program itself in our case it's cat and the second argument is the file name that we just provided test.txt with the index 1. and these are all strings by the way but in memory the arguments of a process look something like this so you've got a bunch of arguments stacked at one place and then the environment variables are right next to it so first comes the list of arguments and then comes a list of environment variables so far so good now think about a question what really separates the arguments from the environment variables like what's really the boundary here this is an important question because the memory is contiguous so there's got to be a definitive boundary or else everything is just going to go south so there is a boundary here and that's null if the last element of the arguments is null that means that's where the arguments end and the environment variables begin remember that so consider our previous cat example so here the third element of the array is going to be null and that's where the arguments end and the environment variables begin great now that you're familiar with how the arguments are structured in memory we can understand the vulnerability let's continue so let's just dive right into pkx.c here's a loop that starts with the variable n set to one and it checks for the arguments provided to the pkx program at runtime such as you know dash dash help or whatever a few lines down we'll see this this is basically reading the nth argument and setting it to the variable path and a few more lines down the road we see this here it fetches the program's path and it sets it back to the arguments array hmm interesting but have you spotted the problem yet well here it is if you have not provided any arguments but we set the zeroth element in the arguments array to null which is usually supposed to be the name of the program but now it's null what do you think would actually happen here well let's walk the code initially n becomes 1 from this loop since it doesn't really match any case it would break out of this loop with the value n set to 1. you got to remember that down here it's trying to read the arguments of n which is basically one and we already know that it doesn't exist because we just set the arguments 0 to null that means the arguments should end there but regardless this line of code is still trying to read something that's out of bound so when it's doing this out of bounds read what do you think it's actually trying to read exactly it's the environment variables remember earlier we discussed that how the memory is laid out for arguments and the environment variables they were basically stacked right next to each other so here when it's trying to read the second argument it's in fact trying to read the first environment variable this value is stored as the path variable and ergo and out of bounds read also if the path variable doesn't start with a forward slash it writes the path back to arc v of n and that's an out of bound right so now we have two weird behaviors that we can somehow take advantage of these weird behaviors are also called as primitives so with these primitives we can inject any environment variable into a process but you might be like coda all this for just to set the environment variable of a process i mean we could literally do that by hand right what's the big deal yes we can add an environment variable when we start the process but there is a caveat there are some interesting environment variables to be considered and those are called unsecure environment variables so something like ld preload so that's an environment variable which is automatically filtered by ldso on any set uid bit programs or programs that run as another user if they aren't filtered it's an easy privilege escalation but linux is aware of these attacks and hence it restricts some environment variables to be passed down from parent to a child process so we can't really inject all kinds of environment variables but since we have this new primitive of out-of-bounds right we should be able to use it to inject insecure environment variables like ld preload and gain root privileges right pretty much yes but there's one small problem right after this out of balance right it calls clear env which means it clears out every environment variable so we need to find a way to execute the code from the point where it does the out of bounds right but before it clears out all the environment variables so that's the that's the execution frame that we've got and we got to find something interesting within that frame so let's take a look at the code again right after the out of bounds right there's a call to this interesting function called validate environment variables so inside this function there's a conditional call to g-print error this function is kind of important because it's like our main gadget basically this function helps us in getting privilege escalation here's how so this gprint error function normally prints utf-8 error messages but if the char set is not utf-8 it would actually call another function called iconv open from glibc so this will actually try to convert the error message into the right charge set using a conversion module so here's where the gold is we have full control over this conversion module so this is basically a shared library the idea is to trigger an error and set the charge set to something that's other than utf-8 which will trigger this g print error so this g print error function will recognize that the char set is different and it would try to convert them and to do that it requires a conversion module which we can specify using an environment variable called gconv path so an internal function called g icon v open is responsible for the conversion and this will basically look into the environment variable and get the malicious conversion module from there once it has our conversion module it would try to convert the char set but in reality it's actually executing our malicious code and more importantly it's executing it as root just so you know just like ld preload gconv path is also considered unsecure but the out of bounds right primitive will actually help us inject the environment variable back in all right let's craft the full exploit as you already know the main goal is to escalate the privileges from a regular user to a root user we have two primitives a out of bound read and an out of bound right with this we can read and write environment variables including the insecure environment variables and we can't use something like ld preload because all the environment variables are cleared out but we found a special gconv path environment variable that will be triggered before all the environment variables are cleared out so a perfect candidate so the idea is to inject the insecure environment variable gconvi path which lets us configure a conversion module which is basically our malicious shared library so firstly we will create a directory named gcomvpath equals dot and place an empty executable named pwn inside of it we're doing this because we want gconvie path equals to dot forward slash pwn to be written as the first environment variable using our out of bounds right primitive and we need to make sure that this has to be a valid path returned from the g find program in path function so hence we name the folder as g combi path equals to dot and then the pwn as a valid executable inside that folder then we run the pkx providing our environment variables we set the first environment variable to pwn the out of bounds read will actually read the first argument which is going to be envp of zero so p exact tries to find the file named pwn then we supply term equals two dots this will actually trigger the g print error because it wants to print to the screen that this is a suspicious input so when it does that it would actually trigger the whole execution tree so it would print the error message using the g print error next we provide path equal to the malicious directory that we just created when pkx tries to find the executable pwn it will try to actually search in a path and it's it's doing that using the function find program by path so we're setting the path environment variable to our directory such that it would actually find that executable inside there and it would return a valid value which looks something like this that's exactly what we want to be written to the environment variable right down here it tries to write this thing back to arguments of one but as we already know arguments of one is the environment variables of zero basically we've injected that string into the first element in the environment variables array finally we set the char set to bruh to trigger the codepath that thinks that this is not utf and it would try to do the conversion when it tries to do the conversion uh it tries to look inside the directory named phone because that's where it gets the conversion module from cool so we create a directory named phone and inside that we create a single file named gconv dash modules this file is like a mapping so this file basically says if the charge set is not utf-8 then use this module to convert it so this conversion module will be our malicious code a conversion module usually requires a few methods to work like gconvi in it and gconv so we'll add our own code inside of the init method so basically we do a simple shell execution we also set the uid and gid to zero this is because usually uid and gid are dropped when we switch the users or run as a different user so we want to set it back to zero because that's the ui dng idf root so finally we execute the bin sh and all there's left is to compile the shared module and also compile the exploit itself and pretty much run it so to do that i would use something like make file so let's try to run this and sweet we are root there we go by the way the full code is available on the github repository if you want to try checking it out i've also left some comments explaining the codepath so check it out if you have any sorts of confusions or whatever now the real question is why did nobody see this vulnerability it's been like 12 years and why was it not found before the answer is it was found it was found in like 2013 by this person named ryron he blogged about this out of bounds read and write with the arguments in his blog post named arcv silliness he just couldn't exploit this behavior back then but he did figure out the right root cause and then in 2019 there was this blog post on a ctf challenge where you had control over the second argument of a f open function and you had to get code execution from it and this involved playing around with gconv conversion modules so theoretically if you had put those two pieces together you might have had yourself a zero to exploit man i don't know but thanks to qualis now we know about this vulnerability and there are a lot of fixes so please update poll kit on your machines it should automatically do it like on ubuntu or whatever but if you cannot update it just straight up remove the pkx executable and if you're deploying applications using containers and if it's like vulnerable to the phone kit use something like sneak cli to detect it and fix the issues so for example i've got this docker image you can try the attack on this docker image if you want also the docker file is available on the github repository you can you know attack safely inside a container but anyways uh if i run sneak cli against this image it would immediately show me the vulnerability that exists inside this container image so something like this in your development or ops pipeline would be you know very useful i think anyways hope you all learned something new hope you enjoyed it shout out to sneak again for sponsoring this video thanks for watching and i'll see you in the next one peace [Music] you
Info
Channel: PwnFunction
Views: 121,209
Rating: undefined out of 5
Keywords:
Id: eTcVLqKpZJc
Channel Id: undefined
Length: 17min 59sec (1079 seconds)
Published: Fri Apr 08 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.