
Cheers. Uh hello everyone. Thank you for coming to my uh first of all before I start I'm curious how many people into security offensive security vulnerability search and explanation. Yeah. Okay. Cool. I hope I hope you enjoyed that. Cool. So without further ado, I'll discuss about the restaurant control takeover in particular about exploiting reduced seat entropy by shangle. Uh if this stuff sounds a bit weird about using Dory, I'll I'll explain everything in detail in the next half an hour 40 minutes. So a few words about myself. I'm a founder and principal consultant. uh been in this industry for a number of years now. I got a couple of certifications in particular like the ones from office
of security like you know the classical ACP OSW and all that stuff and lately I started speaking at conferencing again spoke at Blue Hat in Israel a couple of conferences and today of course besides so thank you for What's this talk about? Well, obviously I'll be talking about application security because this is what I've been focusing for many many years. I started as a developer and then uh then I realized oh this is quite cool actually finding this in your own software and then in other people software and try to try to create an exploit for it as well. Oops, I skipped the slide. Uh yeah. So what we're going to be attacking today is password reset tokens. Uh this is one
of my uh favorite attack services to attack because it's authenticated. So you don't need any credentials. You don't need any is just it's there. Go for it. Yes. uh this is uh classified as u cryptographic failure in our top 10. I'm sure you heard about 10. So it's quite high up in the risk matrix from OAS. Now a couple of words about the best part control panel. So it's a web based control panel. It's used to manage Linux servers. So you can manage your I don't know web server, FTP server, domains, databases, whatever you need. It's similar to C panel, VHM, which are also quite popular as well. Uh and in case you're interested, we did
research in all these control panels. And if you want to know more, you can find details on our blog. It's uh it's written in PHP and Mash, which is quite interesting. I like PHP a lot because I started my my care as a PHP developer and it was one of the coolest things to hack then and it's still pretty cool. And as a side note, it seems that Vesta has been acquired sometime last year around the time we reported this issue to them. This is how it looks like. It's a pretty simple interface, right? Exactly what you'd expect from a software like this. As I said, it's got various options to manage the web stuff, DNS, mail,
database, pro backups, right? All the usual stuff that we expect. But again, this is authenticated. I'm really interested in the unauthenticated attack surface. So, uh, we have the source code. It's available on GitHub. So we're going to do social review or is it called white box pent test uh because when we build a white box test basically uh we are increasing our chances of finding more vulnerabilities or vulnerabilities that are hidden. Um I would say it's currently impossible to find and exploit such vulnerability in black box manner like there's no way to figure out how the passwords that are generated how you could exploit this cuz you will see like it's pretty easy to figure out that there's an issue the
password is set up if it's generation but trying to actually exploit it's a whole different story. So I did some research. Um there were some other CVs that have been reported previously. Uh they were quite trivial like argument injection command injection. So I was thinking can I find one more critical as some people would say there's always one more uh before to the actual issue. uh because this was not I didn't directly just went to the password set and found it exploited first I started reading the source code to get an understanding of structure of the code and I noticed some do code patterns so let's let's have a look first at some code patterns
the first one uh it's in this script called add chrome so as chrome like this is commonly for command and j so I'm going to try to I hope it's somewhat reasonable. Uh if you look at the top there's no explicit authentication check. Uh it does check here if it's a post request. So this is trivial to my pass. It then also checks the CSRF token. Again this is not actually an obstacle for attackers. And then it takes variable various variables from the post array like minute, hour, day, month like everything you need to set a chrome, right? And then the next thing it does here it it calls escape shell arc to standardize those
variables, right? And then it executes with the exact comm with the exact command in PHP. It executes a script called vadd and it passes all those parameters that have been sanitized with shell r. So the only variable I looked at there's a variable passed which is called user and this variable is not passed to escape shell. So I thought that's interesting like can we inject something that would be cool. So yeah can inject something in user to achieve remote execution. So where is this user variable coming from? It comes from session. You can see here it's it's taken from session and it's a sign user. So I thought I read the code again and I
thought maybe I can some sort of corion bit or something like that. Maybe I can find something really dodgy to override the station viable and from s user to override the user and then it to the cross. I couldn't find anything unfortunately. So this was a dead end but overall I think it was an interesting idea. So the next one next good logical that I noticed is in a script called VJ SSL 7. So basically this script is used to generate uh TLS servers right when you manage when you create various domains you then have the option to create uh TLS certificates with this script. So I file as well there's no explicit authentication check
the beginning of the script you can trigger this script unauthenticated and it will continuously write the TLS certificates on the server which I found quite fine. Um then again the same thing happens. Uh it takes the parameters from post it escapes them with escape shell r here and then it calls another pass. So I had an idea of writing a fuzzer for escape shell. I I wrote two fuzzers. One was in PHP and one was in C with new fuzzer. I thought maybe I will find the zero day except but unfortunately again I couldn't find anything. So now let's discuss the is the password reset process. When you trigger the password reset you receive an email similar to this one
which contains a couple of parameters. This is the user called admin because I want to reset for admin. And then there's the secret code which I ask myself how is this code generated? What can I do about this code? Maybe I can take over that. So I started reviewing the password reset process. Essentially, uh, when you're doing a password reset, it checks if the code that you submitted that comes from the link. Um, sorry. Um, yeah, it checks if the code is equal to a similar code which is read from a file from the file system. And if these two code uh match it means okay this is legit to my password reset attempt. So in that case I'm going to
reset the password of that user. Now u again this this I don't think is very visible. So I'm sorry about essentially the way this code is called internally is called an key. That's what it's called. So we we'll go and look at this key in a bit. Yeah, what is our key? Basically, every file, sorry, every user in the system has an associated file which is you can see here users admin has a user confile and here is the IP which contains that code for every user which you need to uh reset a password. Now I need to specify something very important about our key. This code is regenerated. So first is generated is when install vesta and then
this code is changed every time it was successful password set. So if you go and click 100 times uh reset password for admin you always get the same code. The only way you actually successfully reset the password this will be regenerated and this file. So you have to know to change is important.
So um the way works basically there are some PHP scripts and they call the scripts which do have anything. So in the case of password reset right it starts in PHP and then it calls this script calls called V change user password script and you can see that this script does two things first of all uh it changes the I key so the password reset was successful it will generate an IP as I mentioned and then because it also needs to change the user's password right so it password generate our key and set the new password for the user. Now when it generates the new key which you use which we use next time we do a
password reset it calls this bash function called generate password this generate password is used internally every time they did a a new secret stream like token a random password whatever so let's look at this gen password function this password function. It's a pretty standard function I would say. I've seen it many times the way you bring code for for password set. Basically, it takes a single matrix which contains all the alphab characters. So from zero to the all the upperase lowerase characters. It has a length of 10. So it will generate a string of 10 characters and it will do a while loop until it actually 10 characters. So how does it work? It uses the random variable,
right? Random variable which generates a number between 32,000 767 which is sorry which is the maximum v number that you can score on two bytes right and then it uses the model operator to get an index within the limits of this thing. basic stuff like I've seen this over and over and so most important thing that we're interested here is the random variable batch to see how how does it work how does it generate random number is it crypto secure no it's not crypto secure so as I was trying to figure out how random the algorith started doing some and luckily for me there's a gentle Jorian Walter I believe or I'm not sure how you pronounce it and he created this
cool project called cracker which basically uh does a lot of the work that I need to pronounce. So you can see some examples here. You can start by rand with a command called crack. You give three random numbers, right? And what what it will for you? It will find the seat that was generated which is 2 billion something. And then it will also give you the next three random numbers that would be generated the next random. And here I am validating I'm I'm doing an echo and I'm echoing three random numbers again. And you can see that these numbers are matching with these numbers. So I found the seat and it correctly predicted the next three random numbers as well.
Another interesting thing about is that it's deterministic as well. So here you can see that I'm initializing twice with the same se and every time it will generate the same random. So everything is very deterministic. Pretty cool.
So here I introd because I was curious to and I actually needed to understand how this algorithm actually works cuz later I had to redo it in Python. You will see why. So here you can see how the seat is generated. First time if the seat is zero it start with a default value like 1 2 3 4 5 9 whatever. And then it does some basic math operations every here. Oh my god, this this is really unbeable. I'm sorry about that. I can barely see myself. So long story short, uh here it uses this seat uh it uses this seat to generate a rand number. uh it only does a check that if the
current number generated is equal to the previous number, it calls itself again to generate a new number. So it makes sure that it doesn't generate two identical numbers in a row. Cool. So everything is very random. The next question uh that I needed an answer was how is the seeding done in bash. So I started reviewing the bash source code and I found uh this function called cand which does a few things here. It calls get time of day and it passes the TV structure. So basically this simply reads the current time stamp the time stamp and the microcond and then it calls SPR function uh which doesn't between seconds microsconds and the speed of the process and if you look at
SP it has a parameter which is called seed. So this is will be the seed right and the parameter type is outside long. So that means uh the parameter is stored in all four bytes and the maximum value will be around 4 4.3 billion. This is important. So a couple of initial ideas that I how do I explain this? The first idea was obviously I couldn't brute force all the 1.3 million values but it's actually a very terrible terrible idea. It takes weeks probably and it's very noisy and you probably could get caught as well. Somebody will notice something. Now a couple of observations. Um I've been looking at this type of issues for a long time and I can say
that get p is stored on two bytes in general. It's a small value and it's reforic which was used previously. The maximum value for microcond is 1 million and you can store that value on 20 bits. So this a small value and also for most important thing from the previous slide was the time stamp. So the question is can I get an like maybe from the headers whatever we find the question was can I find end point that is that expose a useful time. So the answer was yes, but they all authenticated. So that's a problem cuz I want to do every unauthenticated. I I look for authentication by password or something. I couldn't find anything
unfortunately. Yeah, like I said, the useful time stamp is the time stamp at the moment of the other case, I love if you could share with me. So I was out of ideas and like I said I love PHP being an XPHP developers uh developer. So I started the next thing when I'm out of ideas when I run a page like this is to look at the PHP source code. So like okay let me see how do these guys in PHP do the random number generation. So I looked at some functions like LCG value another function that were generating like random number right. So I was trying to stay in the same area and I found this
function at SCGC uh which uh in a very similar manner to cause get time update twice. So it is the time stamp the microconds and then it doesn't exert here. It doesn't exert between seconds and microconds but it shifts the microcs left by 11. And here it does the same thing again get time of day and then again it exerts seconds and microsconds and it does a left bit shift uh by 11. So I'm like what's this uh what's this left like why is this needed? Like I know there there has to be a purpose like my my spidey sense like this has to be security relevant because you could definitely get some numbers out of it
without like there has to be a purpose. What's the purpose? Let's look at me just get time seconds and no left bit shift anywhere. Is this a problem? That that was the question that kept bothering and I spent some time thinking about this and then I had like a revelation or come out or I realized that these are the the issues. So the TV seconds the second right this is the current time stamp. It talk eight bytes but four bytes are actually enough and you can store any time stamp starting from 1970 to 2038. Then is the microconds as I said these are 20 bits. You can represent any value between 0 1 million on 20 bits. Then there's the get
return. This is also very small number. I did a lot of testing. So I put some pressure system. The max that I got was around 600 6,000 on an system which again needs 20 bits. uh again most of the so 20 bit which was kind like the maximum like normally it's less and then when we sort these three values in bash what's going to happen is essentially only going to change the lowest 20 bits because there's no left bit shift the upper bits will remain static and that is the problem so this was the the now I have to make a note here that it could be a deal breaker here for an attacker But it have like it
have like a really high number in opinions which doesn't happen. I don't think the guys from the Linu are that randomization they don't really care about that I think they have like a lot bigger issue to be to be concerned to
sorry so u by changing only the lowest 20 bits we reduce entropy and what's going to happen is that the new seat will follow it in an interval of approximately 20 12 days sorry around around that time stamp. So it will be like roughly between let's say time stamp is now 25th the new generated time step will be from 19 July to end of July that's kind of where it fall you can be 100% sure so the next slide will the minimum where I put the lowest 20 bits to zero and then the max with the lowest 20 bits to set to one just to show you all this. So it should be clear that the test step is
really the only factor that matters here. The P the microconds completely irrelevant. So I created this PHP code for visualization. You can see I created a mask with the low 20 bits set to zero. I left I did a left one by 20 bits and then the minus one. Uh and then I create here a mask with low bits set to one and then I'm doing an oral page just to reach all those. This is just for visualization purposes. And here you can see the output. So this was the original time stamp when I which was around 8th of July last year. And then when I set the lowest 20 to zero, I got a day of uh 29th of June.
And then I said this one and I got 11th of July. So like I said, it's in a very small uh range. So I created a local first to test all this put this together. I extended bash random cracker. I added a method to force all the four billion plus seeds just because this was extremely fast. I discover areas. So I said perfect this works like cuz it's so fast like it makes no no point to optimize. Um and then I check if I can actually generate the password token which is stored in the user file as I mentioned. Of course we don't really need to brute force for for values. What I suggest is really just to brute force
the time for the last let's say 3 years. uh in chronologically in disorder and this is the the new method that I added to a cracker again not very sorry about that it just it's just like a very basic work force that that's all it does and here you can see the output in practice so I added black hole bash with a new parallel password and I passed the password say token and here it finds the seed brute forces all the seed and it finds the one and it says the se is 28th of June last year and this matches perfectly with what was in the file. So this works and then the next step was of course I
did this locally now I need to to make it work remotely in attack. So I created a turbo intruder script. Um in case you're not familiar with turbo intruder like turbo intruder is a plugin for the bite uh which has like a custom HTTP stack which is designed to to make the bin request attack to make it possible. So uh the PC is here in our GitHub repository. Once again what what I suggest is to brute force all time stamp. Let's say starting with now 2025 to 2022. So for the past few years I think that's a reasonable basic I'm making the assumption that best was installed in the last few years or that the password is set happened in the last
few years. second and what that means is there's 31.5 million tests per year in total that would be around 95 million attempts let's say 100 million which represents 90% optimization when you consider that we started from 4.3 billion which is the all the values that you can store in an assign wrong if you'd like to the procedure going through the optimization steps. uh we have a bug on having concrete CS where I explain the double race condition which is tricky and uh there are some some other is there on exploiting making it faster faster if necessary and here you can glorious u basically I going through the request and I got the the password and token
here and here I was already authenticated that in account that's really uh in case you're interested in some research of ours. Uh we had like I said a concrete CMS where I code execution by exploiting two race conditions. We also had the field dating applications where we found that a lot of data was publicly exposed.
And uh some other stuff that we did was weeded a toolkit uh just to have support from some DNS records and basically to increase our chances that the the fishing email will land in the inbox. That's it.
[Applause] Got one question. Can you optimize it more by sending password
at that point? >> Say that again.
>> Yes. the token would be updated shortly or the other. >> So as I said the the token you always get the same token. >> Yeah. >> Changes only when you successfully reset it. >> So like I said there's the one where it says you have to know it to change. So you can't just get a different
detail something that me as well. So in this case it would have been a lot easier to >> but in general it doesn't feel like good practice to me the one was valid. Yeah, I mean they they decided to hardcode it in a file. kind of getting at you any >> why probably lack of experience I guess I guess cuz there was a slide where I said they did have some TV injections right so now we're getting into more and more sophisticated stuff in this case [Music] generation I'm the effect of this case.
>> Are there any hardco? >> Uh just as far as I Yeah. And I I was only interested in maybe to do this fiction kind of thing. >> Yeah. >> I I remember I I fought myself this question where it was something like uh um like I was really interested in in that account being there. You know what I mean? So then I did some chase and oh yeah that in the is definitely there is definitely the first one that is so like yeah that's good and then because essentially it means I don't have to uh discover it. I don't have to like any I would have looked for that if that was an issue but unfortunately it wasn't
this last question just do you have any idea how many companies are using this? Yeah, there were like uh 35,000 at least exposed. Yeah. And and I reached out to them. They weren't communicated like they didn't really care and then I didn't I did some more googling and stuff and then I discovered there was an issue on GitHub. Uh they said like, "Yeah, we discontinued this and now please use this control panel." Okay, I guess this is better than nothing. Uh, but you know, probably a lot of a lot of their the companies that were using this cont like they probably don't Google and leave GitHub issues like I do and you know Yeah, but it's
like a situation. They don't have responsible disclosure responsibility on your shoulders and I told you you have three you're not interested. This is a real issue your customers and and good things I'm going to publish it. >> Yeah. Which which is what we did. We had to publish it. Okay. Like we have to >> Well, you got to public is not a good thing if they're not aware of it. >> Yeah. >> Yeah. Uh you might have already said something, but I was curious how long did it take your script to come? >> Uh couple of hours. Yeah. Again, depends like in practice there's a couple of factors that would obviously influence this like was the password reset last maybe like 3
months ago or 3 years ago something like that. And I mentioned some previous research. There's things you can do to optimize turbo on your side like maybe you could get the server collocated in the same let's say if they're in Amsterdam you can maybe also get server in Amsterdam right in AWS and that definitely helps things up there's a couple of other other
So today publication you can probably get
>> you probably when they said use the control panel. Did you have control panels? >> I I only checked the the password reset issue and you did I think I think it was secure now. >> Okay. >> So okay well it is secure. That was the only thing that I actually cared and other than that I didn't but that could look like pretty similar. It was made like a rebrand. This issue was fixed and other to be honest. I was only I was only this. see what you need to manage your service.
>> I I
there's no more questions. Yeah. Thank you again. Thank you.