← All talks

Vesta Admin Takeover: Exploiting reduced seed entropy in $RANDOM

BSides Budabest 202541:2768 viewsPublished 2026-03Watch on YouTube ↗
Speakers
About this talk
Adrian Tiron - Vesta Admin Takeover: Exploiting reduced seed entropy in $RANDOM This presentation was held at #BSidesBUD2025 IT security conference on 21st May 2025. Vesta is a lightweight, web-based control panel that simplifies Linux server management, appealing to users seeking an intuitive alternative to traditional platforms like cPanel and Plesk. This presentation will examine a critical flaw in Vesta: an admin takeover exploit resulting from reduced seed entropy in the Bash $RANDOM variable. By transforming what was once a theoretical attack into a practical one, we successfully reduced the brute force domain of the seed by over 98%. This allows attackers to generate predictable random values, compromising the security of passwords and tokens. We will discuss the implications of this vulnerability and highlight best practices for enhancing server security in real-world applications. Adrian Tiron: I founded FORTBRIDGE on a simple principle: every client deserves senior consultants, not juniors supervised by seniors.Every FORTBRIDGE engagement is led by consultants with 10-20 years of hands-on offensive security experience. No juniors. No outsourcing. No bait-and-switch. You speak directly with the person testing your systems.We're CREST and DESC accredited, and our team holds OSCP, OSEP, OSWE, CRTO, CRTL, and cloud security certifications across AWS, Azure, and GCP. Our research has been featured in The Guardian, MarketWatch, The Register, and other major outlets.I specialise in web application security, API testing, cloud security architecture, and red teaming. With almost two decades in offensive security, I've spoken at BlueHat, BSides, PTS, OWASP, and DSO conferences across Europe and Asia.Our services:- Web & API Penetration Testing- Mobile Application Security- Cloud Security Assessment (AWS/Azure/GCP)- Red Teaming & Adversary Simulation- Security Architecture Review- LLM & AI Security TestingReady to secure your systems? Visit fortbridge.co.uk https://bsidesbud.com All rights reserved. #BSidesBUD2025 #vesta #exploit #entropy
Show transcript [en]

Welcome Adrian. >> Thank you very much James. Hello everyone and uh thank you for coming to my talk. Today I'll be talking about uh Vesta control panel admin takeover issue that I discovered and exploited and uh in particular I'll be talking about exploiting reduced seed entropy in bash random. Uh now if this doesn't make much sense that's because I had a lot of palinka last night. uh but I will do my best to to try to explain it and uh you can also feel free to to ask me questions at the end. So uh as I said I'm Adrien Tyron uh I'm a founder and principal consultant at Forbage. I got a couple of certifications in offensive security,

the classical OCP, uh certified red team operator and red team lead, couple of cloud security certifications and a few more certifications from offensive security like OAP and now working on OSW which is about exploiting web applications as I'll be talking today. uh and I've also I've been speaking at a couple of conferences lately uh like Blue Hat besides Dresden besides Kent and today uh at besides Budapest. So thank you very much for having me here today. What is this talk about? Well, it's about application security um which is one of the core things that we do at Forbridge. Uh basically it will be a mixture of web application exploitation and also binary uh exploitation as you'll see uh we'll be

starting with reviewing some PHP code and then we will dig deeper into a bit of C code. We will dig a bit into PHP internals and bash internals and we will come up with a very interesting exploit I would say. Uh also uh it is about exploiting uh the password reset uh tokens which is one of my favorite things to to investigate when looking at a web application. And as you can imagine that is because it's unauthenticated attack surface and this is one of the coolest thing that you can look at as a hacker right because it's unauthenticated you don't need credentials uh and it's also a very small attack surface in general. So if

you find the critical vulnerability in the in the un unauthenticated attack surface that is a big win uh for us as hackers. This also uh is classified as a as a cryptographic failure right because the password reset token should be cryptographically secure. So, OA top 10 in the latest update in 2021. Uh, it is second place as you can see there under uh cryptographic failures. So, first things first, a few words about Vesta control panel. It is a web-based control panel. It is used for managing Linux servers. It's similar to C panel VHM. And as a side note, uh we did research into all these control panels previously and we found some very interesting vulnerabilities. In case you're

interested, you can find more writeups on our blog. It's used to manage domains databases websites chrome backups, pretty much everything you would expect from managing a a Linux server from a web interface. It's pretty lightweight from an architecture point of view. uh it's written in in PHP and PHP calls into some bash script and and these bash scripts do all the heavy lifting and as a another side note uh they seem to have been acquired last year by a company called outroll which is around the time we reported this critical issue to them. This is how the dashboard looks like. Pretty straightforward stuff. Very intuitive and very easy to use. You can manage like I said web DNS, mail

servers, databases, etc. Pretty standard stuff so far, right? So, uh we have access to the source code which we found on GitHub. Therefore, it makes sense to do a white box pen test. Uh most of the projects that we do, I would say are blackbox. Uh but if you actually want to find some very interesting very cool vulnerabilities uh I always recommend to to review the source code if you have access to it. So as I said the code is PHP uh there is no offiscation. If you ever looked at commercial PHP applications sometimes they're offiscated with ion cube or whatever encoder. So you need to find a way to deoffiscated etc. In this case

this wasn't necessary. Also, uh the code is pretty simple, I would say. I mean, there's no frameworks, there's no object-oriented code. Uh there's not, you know, abstraction layer over abstraction layers that make things hard to review. And we also looked uh what vulnerabilities have been reported previously and there were a few of them that got patched. Uh previously there were things like argument injection, command injection. Uh so obviously the lowhanging fruits have been uh fixed already. So I was wondering can we find one more critical because you know as hackers say there's always one more. Uh first however before digging into the core issue that we found. Uh let's review some uh dodgy code patterns

because we had to you know we had to go down the rabbit hole until we found the the issue that we exploited. So let's see some interesting first some interesting things. First uh the first dodgy code pattern it was uh when managing uh chrome uh chrome uh scripts. So first thing at the top here uh if you look there's no explicit authentication check and here at the end sorry at the bottom of the page here it calls an exec function uh which calls the add chron JavaScript and there's a couple of parameters um now most of these parameters are passed through escape shell arc which is fine because that is uh that is the way

they should do it. Uh they're sanitizing all the parameters before passing them to the uh exec function. So what does it check at the top? It checks if the request receivs

for CSRF issues. uh if you see here it checks if there's a token as a post parameter and if this token is uh different to what is in the session. So that's a basic CSRF check. No no no issue here to bypass. Uh so so far so good from an attacker's point of view. Uh and here at the bottom when it calls the add chron job it passes the user variable. uh but this user variable does not go through escape shell arc so there's no uh sanitization here so I was wondering is it possible to inject in this user variable and uh achieve some command injection that was my first thought so the question was uh where is the user

variable coming from it comes from the session variable and basically like I said there's no explicit authentication check it's just an implicit it authentication check. So they they rely on the fact that this variable session uh user will always be set. So I thought maybe I can find some session uh pollution vulnerability like maybe I can find some script which writes into this session variable something that I can control and maybe I can uh go back and to inject into that exact function. uh fortunately for them and unfortunately for me I couldn't bypass this. So it was a dead end but I thought it would be like an interesting avenue of exploitation. Let's move to the second uh dodgy code

pattern that I noticed which was in the uh gen SSL certificate. again at the top of the script uh there's no no explicit authentication check. So what this means is basically that I was able to generate uh TLS certificates as well. uh I was just triggering this script with whatever uh parameters I wanted and I was able to generate uh TLS certificate on the file system again at the bottom before calling the bash script uh all the parameters are passed through escape shell arc uh which is okay from their point of view. So here I thought okay uh I saw escape shell arc here. I've seen it being used previously. So I thought okay maybe maybe I can find some

zero day in PHP. So I wrote a fuzzer with lib fuzzer and I tried to uh exploit escape shell arc. Uh but I couldn't find any zero day or any bypass. I also tried to fuzz escape shell arc function with some very uh basic PHP script uh and I throw at it some u weird characters with weird encodings. I thought maybe I can terminate a bash uh PHP string uh like enclose the single quotes and then add the command or whatever. That didn't work either. So now let's look at the main issue that we discovered which is in the password reset process. As you can imagine when you trigger the password reset process you you'll

receive a very standard email uh which contains the username that you try to reset the password for. In my case admin because I'm trying to take over the admin account right which manages the full server. and you receive this code, this random code. So the obvious question is how is this code generated? Can I predict it? Can I brute force it? Can I attack it somehow so that I can uh reset the password of the admin account and take over the server? So I started reviewing the code. This is the PHP code uh which initiates the password reset process. Uh so basically uh what it does as I said it receives the user uh which again goes to escape

shell arc which is fine from a security point of view and then it calls the bash script list user. So this list user script uh will um read information from a file uh about our admin user and in this file uh there is various things for about our user uh and one of these uh it's in JSON format because you see here it call JSON decode to parse this file and it reads the R key uh field from this file. And then it uses the hash equal function to check if the R key variable which is read from the file is equal to the post uh code variable which is the the code parameter from the URL that we just

clicked. Right? And this if this is equal it means okay I have the right token and then I can call this uh change user password and it allows me to change the password of the admin user and it calls the exact function again to to reset the password. So obviously what is really important here is the R key variable. R key variable uh you can see here is stored in the in the user conf because every user in Vesta has this uh file associated with it and it contains a couple of things uh basic settings that were configured. It contains the password which is stored in MD5 uh format. Obviously this is an issue but

this is not the main thing that that we're interested right now. And at the bottom it contains this R key. Uh and this R key is necessary. You need to have this right key uh variable in order to to be able to reset the administrator's password. And one very important thing that I need to mention here in order to reset uh the admin password you have this R key. And once you reset it the password, this RQ will be regenerated. So uh bottom line is that you can't just go uh to the password reset functionality, click on password reset for the admin user and receive a new R key every time. No, you'll always receive the same R

key. Uh doesn't matter how many time you click on it, how many time how many times you try to reset the password. uh you'll always receive an email with the same R key and once you resetted the password successfully then you will achieve two things you will change your password and you'll also generate a new R key. So this is important thing to to understand here. Uh so the let's look now at the bash script that actually changes the user password. Uh so the PHP API as I mentioned calls this bash script and as I explained previously uh when doing a successful password reset you are achieving two things uh which are highlighted here. The first

thing is that uh you generate a new R key and then the next thing is that you update the user password which is uh as you see here the second line it calls the update user value uh and it stores the the new password in MD5 format. And if you also look here in this script, uh a new R key is generated. And this new R key is generated with the bash function called generate password. Uh so I can tell you because I looked at all the code, this generate password is used often in the investa and it's used to generate uh new reset tokens or new passwords or every time uh they need new let's say

secure string. we will see what what this secures thing is actually uh how does it actually look like and how it's generated. So we need to review the generate password function. Now if you look at this generate password basically here it it generates a string with a length of 10 characters and these 10 characters are chosen from this uh matrix string which basically contain contains all the alpha numeric characters. So from zero to to nine all lowercase characters and all uppercase characters and basically it does a basic while here until uh until it generates a string with a length of 10 characters. And what it does is it uses the bash random variable to generate a random

number and then it uses the modular operator to basically uh generate an index within the length of the matrix uh string. So it chooses every time for for 10 iterations it chooses an an index a random index uh within the matrix string and that is your new password reset token. Uh now obviously I did a bit of googling and the first thing that popped up what was that the random variable is not crypto secure and it's a pretty small number between between 0 and 32,767 or something like that. So I thought okay it's not cryptocur this looks interesting and potentially exploitable. So I did a bit more googling and I found out this project on GitHub uh which is

called bash uh random cracker which which was created by a gentleman called Han halter. I'm not exactly sure how you pronounce it but you know credits to him for for building this project. And basically you can use uh this project to guess the seed and predict uh random numbers. So you can see here I'm calling bash run with the track argument and then I feed it three random variables. Uh and what it does is first thing it gets the seed which is 2 billion something and then it also it is able to predict the next three random numbers and I verify this by echoing the the next three uh random numbers that are generated in bashite. And you can see

that these numbers here are a perfect match with what bash random uh with what bash random cracker predicted. So it works very well. And the other interesting thing is that uh you can also seed the random variable and it will always generate the next random numbers because it's very deterministic. So I'm sitting it here with lit or 1337. I'm echoing three random numbers and it gives me uh some random numbers and I do this same thing again and again I'm getting the same random numbers. So it's giving giving it the same seed it will always generate the same random numbers which is uh very good for us because it means it's a it's a sure thing that we will be able

to exploit this if we get the seed right. So uh the next thing I I did was I started investigating this GitHub project. I reviewed the source code because I wanted to understand a bit better how does this actually work in practice what's happening uh behind the uh scene and I looked at the function which calculates the seed which you can see here on the right side. So basically it's very it's very simple stuff. If the seed is zero mainly it means you haven't seeded explicitly it will use a default seed which is 1 2 3 4 5 9 876 and then it does some basic uh arithmetic operations on it some division some multiplications etc which

is very deterministic and basically at the end it will return the new seed and here on the left side it's the actual algorith I'm not sure if it's very here but I will try to explain what it does. Uh so basically uh there are two versions of the algorithm. One is in bash version 4 and then there's also a newer version called uh in in bash version five. So essentially every time you're asking for a new random number it uh it generates a new seed using the function on the right hand side and then uh basically it does again some very basic uh very basic arithmetic operations in order to uh calculate a new random number and it

does a very basic check at the end. Basically, it verifies here at the bottom if the new random number is equal to the previous random number. So, if they're equal, the function will call itself one more time to generate a new random number. So, this is just a basic check uh to make sure that it will always provide a new random number uh different to the previous one. That's it. So uh the next thing that I was curious about okay um how is the seeding actually done in bash. So I had to dig into the bash internals right now uh which is pretty basic C code. It sounds complicated but believe me it's it's not that

complicated. So I found a function seed rand which does the seeding of the random generator in bash. So what this function does is it calls get time of day API in C right and it reads the current uh time stamp and the current microscond into the TV variable and then it calls the SB run function and the as a parameter uh it passes the the seconds the microsconds and the speed of the current process and it simply exores these three values. So it just does an exor between the current second, current microscond and the current process ID. Now uh please pay attention to this highlighted area when it calls RAM with these three values because this is very

important uh and this is where the key vulnerability is. But to be honest, I didn't notice it in the beginning. Like it took me a while. Uh maybe a couple of days or something. I know until I actually realized what the issue is. So until I until I realized what the issue is, I had to go through a couple of steps and I I was brainstorming for some ideas of what could I do to exploit this. And the first idea was to brute force all values 4.3 billions. uh why 4.3 billions is because if we go back uh this uh SB run function the parameter of the function it's an unsigned long variable so unsigned long variables are

stored on four bytes which means four 4.3 billion values roughly so my first idea was obviously brute force this this is a terrible terrible idea very bad idea it I realized quickly that it's going to take weeks it's noisy and it's just not doable will and it's not practical and it's not sexy basically. So then I looked at a couple of other things as I mentioned. Uh one of the values that is passed is the get pit which is the process ID in general. Uh this is uh stored in on two bytes and it's pretty well known in the industry that it's brute forceable because it's a small value two bytes is brute forceable. The next thing

uh as I discussed microsconds are used. microsconds basically means that it is a number between zero and 1 million and uh you only need 20 bits to represent 1 million. So 20 bits again it's a pretty small number. This is also brute forceable. So the most important thing if we go back again the only remaining thing is the time stamp the current time stamp. Uh I realized so I thought maybe I can find some sort of uh information leak to leak that timestamp. So I did uh let's see now I did like a blackbox text. I looked at the endpoints uh and I was okay is there any endpoint that leaks that timestamp at the moment

of the password reset because that was the time stamp that I wanted. So I did find a couple of endpoints. However, the problem with these endpoints was that they were all authenticated. So it was not very useful. It was a bit of a chicken and egg problem, if you will, because I'm like, well, I need to be authenticated to get that time stamp, but if I'm authenticated, I don't need it anymore. I need some sort of authentication bypass. I need I need an unauthenticated uh endpoint to give me that uh that time stamp. So, this wasn't useful for me. It was a chicken problem. It didn't solve anything. And again, um, just to be clear, the time stamp that I

want is the time stamp at the moment of the password is set. That's it. That's the only time stamp that I'm interested in. Because if I get that, I figured it out that I could brute force the speed. I could brute force the microsconds. That would be doable. And again, if you have any any others ideas or any other tricks, uh, feel free to share it. I would be I'd love to to hear them. So um at this moment I was really out of ideas and one of the things that I do and I'm out of ideas and one of the things that I actually like to do is to review some PHP source code which is

written in C and one of the reason why that is is probably because I'm an XPHP developer and I understand a bit of basic C code as well. So I was like let me look how PHP does certain things and in PHP uh there is a function if you're familiar called LCG value which u generates Pto random numbers. Okay. And this LCG value function uses the LCG seed function to seed its number generation process. So I like let me have a look. Let's see how seeding is done here. Like we've seen how seeding is done in in bash and like let's have a look now. Let's see how the PHP guys are doing it. So um in this LCG function uh there are

two variables that are used S1 and S2. Okay, here you can see the S1 and here at the bottom you can see the S2 variable. And in a very similar manner uh this LCG seed function also calls get time of day. So this function also needs to to read the time stamp and the microscond. And then again in a similar manner this function does an exor here between the second and the microcond only it does a left bit shift by 11 positions here. and then lower when when it sets the S2 variable again it does an an exor uh and it uh it does a left bit shift by 11 position. So I looked at this and this got me thinking

like why does it do a left bit shift? Certainly as a developer you can remove that left bit shift and it will still work. So this got me thinking and I thought about it for a couple of days and I was like this there has to be a reason for this like there has to be some sort of security implication or something and uh yeah I I had to start thinking about this. Uh let's have another look again how the bash guys were doing the seed uh generation. You can see here that they're simply exoring the free values. uh the seconds, the microsconds, and the bit, right? We're simply ignoring free values. There's no left bit shifting.

There's no no sorts of bit shift, nothing. So, I was learning, could this be a problem? Cuz, you know, as a developer, as an a developer, I was thinking this would work even without the the left bit shift, but there has to be a specific reason why that left bit shift is there. And then I had an aha moment or an everya moment uh when I figured it out. So the issues with the seeding in bash are the following. Uh if we look let's start looking at all the variables one by one to see how this issue compound basically and lead to a practical exploit. The problem with the TV sec which represents the current time stamp in

memory it it allocates uh it there are eight bytes allocated for this variable but in practice only four bytes are enough and you can store time stamps from 1970 to about uh 2038 as a year as I mentioned again regarding the microsconds uh they also occupy eight bytes in memory but in practice it only uses 20 bits because there's only 1 million microsconds and 20 bits are enough to store to store this value. Now the get bit variable there it occupies four bytes in memory. Uh but in practice these values are very very small. So I did some testing. I created some fork bombs and the maximum pit that I that I achieved was around

660,000 uh which again needs 20 bits. So any value up to 1 million you can safely safely represent it on 20 bits but again uh the p value is the smallest value out of all these three values by far. So usually you need a lot less than 20 bits like maybe 10 15 bits something like that. So then I realized when you exert these three values uh what's going to happen is you're going to have the time stamp and because microsconds and get p are represented let's say on both of them on 20 bits you will only be changing the the lowest 20 bits of the time stamp. the upper 12 bits will always remain static and this

is what I mean by reduced ced entropy because they don't do any left bit shift the upper bits of the time stamp will always remain static and this is what will create a condition for us that will allow us to exploit this vulnerability now to make a note here get paid could be the only deal breakaker for an attacker here uh but As I mentioned, this would have to be like a very very high number in the billions so that when you do that exor, it changes some of the upper bits of the time stamp. But I ran this exploit a couple of times and this was never an issue. So, uh to summarize all the issues,

uh by only changing the the lower 20 bits of the current time stamp, uh we reduced the seed entropy. And what will happen in practice the seed uh will fall uh within an interval of approximately uh 12 dates around the current time stamp. So to give you a practical example, let's say I do a password reset right now. Today is the 21st of uh May I believe, right? Uh if I had the right Yeah. Okay. I didn't have that much polling, I guess. So today is 21st of May. If I do a password reset today, there will be a new time stamp and it will be let's say uh between one week before this date and one week after

this date roughly that so you can brute force this interval. So on the next slide uh we will calculate uh the minimum and the maximum time stamp after we do this exor operation. uh you will see that basically we will set all the bits all the lowest 20 bits to zero to get the minimum and then we'll set all the lowest 20 bits to one to get the maximum time stamp. So I think it's pretty clear uh that the time stamp is really the only relevant factor here. The bit the speed of the process and the microsconds are pretty much irrelevant. So some very uh sample uh very simple PHP code for visualization. Here at the top I'm getting the current

time stamp. Let's say it's today 21st of May. And then I create a mask which sets the lowest 20 bits to zero. You can see this here. And then I'm outputting this first time stamp which is the minimum time step. And then I do the opposite thing. Basically, I set all the lowest bits, the lowest 20 bits to one and I calculate the maximum and I display this new time stamp. And here you can see the output. So I did this test uh at some point last year. It was the original time stamp was the 8th of July and then the minimum was uh 29th of June when I set all the lowest 20 bits to zero. Right? So it was

like 9 days 9 days before the original time stamp and then I calculate the maximum and the maximum result was uh 11th of July. So 11th of July was 3 days after the original time stamp. So it started from in that case from - 9 days to + 3 days from the original time stamp 12 days interval in total. So uh first things first I started creating a local exploit basically to prove that this theory is actually working. I extended the project from the previous guy which is called bash random cracker. Once again, I added a method to brute force all the four billion seeds and this because I was lazy. Uh obviously you can optimize this

a bit which we'll discuss in a moment. Uh but I was lazy and I did this in Rust and one thing I noticed is that Rust is extremely fast. So speed was not an issue at all. And basically I checked if I can generate a password reset token uh which is identical to the one stored on the file system in the user conf file. Uh so our suggestion my suggestion is that I I'm making an assumption here to be fair. The assumption is that uh the admin user reset his password in the last three years or that Vesta was installed in the last three years. Right? So I think three years is a reasonable assumption and what we

propose is to go back let's say from today the moment when I'm starting the exploit I'm starting from the current time stamp and I'm going back for three years and I brute force all this time stamp and I think this this would give me like a very good very good probability that I will exploit this and if I have to if I really have to I can go back one more year two more years few more years and it doesn't make a large impact on my probabilities on or on the you know on the duration of the exploit But that would be like a really really bad scenario. I think three years is is pretty reasonable.

So you can see here uh the code in rust where I extended the bash random cracker. Uh basically as I mentioned previously I have uh brute forced all the time stamps four billion values uh simply because I was lazy and I didn't want to apply any optimization plus I was like very new in Rust code. So I got the proof of concept working. It's working. It's fast. It's good enough. Like uh let's go with it. Uh and of course uh I fed it the the password reset token in in user confile and in a couple of seconds really it already found the the password the yeah the pass the sorry the seed for the password reset token. So it

works very well and very fast. Yeah you can see here how I call it. This is uh bash run called. I added the argument password and as a parameter I passed the password reset token which you can see here at the bottom. It was stored in in a user confile and it starts brute forcing etc from 1970 and it found the seed that was used to generate this password reset token which is um a time stamp that corresponds to the date 28th of June last year which is like around the the date that u you saw me using previously. So I realized okay uh the local proof of concept is working very well and then

the next step was obviously I'm going to port this algorithm to Python and I'm going to create um a plugin for turbo intruder in case you're not familiar turbo intruder is a plugin for burpsuit which was created basically uh to make as the attacker say as the sorry as the developer says James Kettle to make the billion request attack feasible. Uh so it is like a c custom TCP IP stack. It optimized everything so that it can go very fast and and be able to send a billion uh requests uh in reasonable time. And I created my custom script uh which is called Vesta PC. You can find it here in our uh GitHub repository.

And as I said uh we propo we propose to brute force all time stamp in reverse chronological order. So if we start today, we will start from 2025 uh 21st of May and we would go back for three years. So in practice, this would mean that uh we would have to brute force uh 31.5 million attempts per year, right? I calculated here. And if we go back uh and brute force this for uh three years, it means 95 million requests, which is like 98% optimization, right? And if you want to see more turbo intruder uh optimization tips, you can see this blog here where we exploited some vulnerabilities in concrete CMS. So yeah, uh we in the end we managed to cut

it down from 4.3 billion to 100 million request which is again 90 90% reduction. And here you can see the glorious win. I used it in turbo intruder. I uh I was able to brute force the password reset token and I was able to set the admin password and here you can see I I'm already logged in once I was able to achieve this and I'm getting all this information about the admin account I think. Uh okay uh if you like to see more of our leading research uh you can see our research on concrete CMS uh which again we exploit the double risk condition to achieve remote code execution. Uh we also hacked the field dating

application last year. Uh you will see a talk about this today. And we also extended the evil jinx uh toolkit which is used for fishing. Uh basically we realized it was missing a lot of DNS records. So we added this capability for it in order to increase our fishing chances in order to increase the probability uh that the email will land in the victim's inbox. Yes. Q&A.

>> Hey Adrian, I think um if you have any questions, there's the Discord channel on the Bside's website. Um Adrian, you're going to be around. >> Yep. >> Uh so obviously you can speak to Adrian in the uh common areas between um between the uh presentations. So, thanks very much for all your energy and making it through that having sampled the local delights of uh Budapest. >> I will. >> Yeah. And um safe journeys back to to London, I believe. >> Yes. Thank you, Ra. >> Please show your appreciation for Adrian.