# MediaChunks

chunk_text:
  or 10,000 users and just go to sleep, wake up, and get like username, password, and then later you could use that, then you go to like the banking-style fraud where you're manually like a mule, copy and pasting everything. And now you can go back to sleep again. Well, not entirely. You still need to act like semi-quick, but it allows you to do things at scale, which is always interesting and important for criminals. And it's what they do. The attacks we see are like, yeah, not to be unfriendly towards those types of people, but most of the problem creators are not the people that are really skilled. They learn a trick, and they just keep doing it until it doesn't work anymore. And with these SaaS-ified services, this creates that problem. The current threats, of course. So, current threats. My slides. Well, as I've said before, there's been a huge increase in, especially Microsoft 365 AATM attacks, phishing at a large scale, allowing backfraud to be more successful. Microsoft announced like a 111% increase in token replay. Well, that's both reverse proxy attacks and just malware stealing tokens from the browser or your system. But yeah, it's been growing and growing. And you can see that. So, if you like urlscan.io, which is if you hobby around with like, it's a showdown safari, but for phishing sites. And it allows you to search for like favicon hashes or like a specific CSS file or a specific URL. And it will increase. You can just see like minutes ago, new M365 phishing pages pop up. I've mentioned booking.com already. And that problem initially was mostly stealer malware getting onto the system of the hotel owner. And now you see that they've switched tactics because like malware and antivirus is like pretty annoying. Especially if it's like somebody else hosting everything for you, it's pretty great. And if you start looking into like phishing pages for booking.com hotel operators, it's just funny how much. And it's always something like complaint issue, whatever the fuck, or add-in D or BNB confirmation. And all of these point to something like this, which is enter like a login page, not for the end user, but for the hotel owner. And this is the first step in a whole like supply chain thing, where if you have access to the hotels, you


chunk_text:
  it's been growing and growing. And you can see that. So, if you like urlscan.io, which is if you hobby around with like, it's a showdown safari, but for phishing sites. And it allows you to search for like favicon hashes or like a specific CSS file or a specific URL. And it will increase. You can just see like minutes ago, new M365 phishing pages pop up. I've mentioned booking.com already. And that problem initially was mostly stealer malware getting onto the system of the hotel owner. And now you see that they've switched tactics because like malware and antivirus is like pretty annoying. Especially if it's like somebody else hosting everything for you, it's pretty great. And if you start looking into like phishing pages for booking.com hotel operators, it's just funny how much. And it's always something like complaint issue, whatever the fuck, or add-in D or BNB confirmation. And all of these point to something like this, which is enter like a login page, not for the end user, but for the hotel owner. And this is the first step in a whole like supply chain thing, where if you have access to the hotels, you can have access to the, like all the bookings and that allows you to do stuff like this. So this is something my colleague, Eric, he had a hotel booked in, I think it's Paris, where he was, he got like a notification via the system telling him that his booking wasn't completely correct. And then linking him to this page. And the funny thing is like the price is correct, they have all the information, they have your booking number. So this supply chain allows attackers to do like the best type of phishing, which is lots and lots of pre-information allowing you to fall for this. And it's funny because they're actually abusing the internal booking.com like messaging. So it would be just interesting to have like a live feed of all the messages going from into hotel owners and users, because I feel you might find lots and lots of the same messages there. But this problem, where Microsoft has been actively trying to fight this, booking seems to have a bigger issue. Mostly because if you look at the Microsoft pages, there's lots of like bot filtering tricks and lots of like, the attackers are doing


chunk_text:
  can have access to the, like all the bookings and that allows you to do stuff like this. So this is something my colleague, Eric, he had a hotel booked in, I think it's Paris, where he was, he got like a notification via the system telling him that his booking wasn't completely correct. And then linking him to this page. And the funny thing is like the price is correct, they have all the information, they have your booking number. So this supply chain allows attackers to do like the best type of phishing, which is lots and lots of pre-information allowing you to fall for this. And it's funny because they're actually abusing the internal booking.com like messaging. So it would be just interesting to have like a live feed of all the messages going from into hotel owners and users, because I feel you might find lots and lots of the same messages there. But this problem, where Microsoft has been actively trying to fight this, booking seems to have a bigger issue. Mostly because if you look at the Microsoft pages, there's lots of like bot filtering tricks and lots of like, the attackers are doing some effort to not get detected. And the booking.com are like YOLO. Look for the favicon hash and you'll find anything everywhere. So it seems that booking could learn from Microsoft in this regard. I'm still curious if it's a specific group who is using this attack. I feel it's many. Like there's one, somebody figured this out and then it spread. Like anything with this type is like back to the farmer, just like plow on, do the same thing over and over again. And then, well, in the end, you always have to fill out your credit card information. So that's where everything ends up. Cool. Yeah, we would like to explain something about the implementation, because we created a detection system, which we'll explain later on. But that also gave us some insights into implementations that are going around. And this is specific to Microsoft 365. Well, of course, you have Evil Jinx, the tool that's, it's used a lot because it's available on GitHub. The only problem is if you now spin Evil Jinx instance on a VPS, it's immediately spotted and flagged. So you have to do some tricks to fix that. But that's also


chunk_text:
  some effort to not get detected. And the booking.com are like YOLO. Look for the favicon hash and you'll find anything everywhere. So it seems that booking could learn from Microsoft in this regard. I'm still curious if it's a specific group who is using this attack. I feel it's many. Like there's one, somebody figured this out and then it spread. Like anything with this type is like back to the farmer, just like plow on, do the same thing over and over again. And then, well, in the end, you always have to fill out your credit card information. So that's where everything ends up. Cool. Yeah, we would like to explain something about the implementation, because we created a detection system, which we'll explain later on. But that also gave us some insights into implementations that are going around. And this is specific to Microsoft 365. Well, of course, you have Evil Jinx, the tool that's, it's used a lot because it's available on GitHub. The only problem is if you now spin Evil Jinx instance on a VPS, it's immediately spotted and flagged. So you have to do some tricks to fix that. But that's also why cyber criminals are using, well, other solutions such as the SaaS solutions. Another interesting implementation is the VNC in the browsers, already there for a long time as well. And I just think it's an interesting implementation because they are just streaming a VNC session in a browser, which looks like a real, that you're visiting a real website. So I just think that's an interesting approach to implement it. They have Evil Puppet, which is another implementation also available on GitHub, not really maintained, but it's, that's an implementation. With Evil Jinx, you need specific visual aids. For example, you have a Microsoft visual aid, a Google visual aid, which just modifies a little bit for the specific target, and the Evil Puppet is an attempt to just make it generic for all targets. So that's an interesting approach as well. The last two we've seen using our detection system. For example, we've seen an implementation using a PHP, which is the fourth one. We saw some interesting references to a really lame and old web shell. So he was using the proxy functionality from a web shell. They are using an AATM framework, which was quite interesting


chunk_text:
  why cyber criminals are using, well, other solutions such as the SaaS solutions. Another interesting implementation is the VNC in the browsers, already there for a long time as well. And I just think it's an interesting implementation because they are just streaming a VNC session in a browser, which looks like a real, that you're visiting a real website. So I just think that's an interesting approach to implement it. They have Evil Puppet, which is another implementation also available on GitHub, not really maintained, but it's, that's an implementation. With Evil Jinx, you need specific visual aids. For example, you have a Microsoft visual aid, a Google visual aid, which just modifies a little bit for the specific target, and the Evil Puppet is an attempt to just make it generic for all targets. So that's an interesting approach as well. The last two we've seen using our detection system. For example, we've seen an implementation using a PHP, which is the fourth one. We saw some interesting references to a really lame and old web shell. So he was using the proxy functionality from a web shell. They are using an AATM framework, which was quite interesting because you can see what the code exactly is doing and stuff like that. And the last one we also investigated, which was also interesting because they are using Cloudflare workers, which is serverless computing on Cloudflare. You just have to upload some code and that code is executed by Cloudflare. So they will fix the web server. They will, well, fix all the servers and stuff like that. We've seen using our detection system that there are quite a lot of AATM phishing websites hosted on domains ending with workers.dev, but that was the trigger like, okay, well, how are they doing this? How are they phishing you using Cloudflare? Well, we didn't have the code because we didn't have access to the Cloudflare account of the attacker, but the option we had was like, okay, let's just build this ourselves in Cloudflare and see how hard it is. And in the end, it was quite pretty simple. And here you can see the implementation live. It's about 150 lines of code. We also published this on GitHub, so you can just upload the code to Cloudflare and you can perform this attack yourself. And it's just forwarding all


chunk_text:
  because you can see what the code exactly is doing and stuff like that. And the last one we also investigated, which was also interesting because they are using Cloudflare workers, which is serverless computing on Cloudflare. You just have to upload some code and that code is executed by Cloudflare. So they will fix the web server. They will, well, fix all the servers and stuff like that. We've seen using our detection system that there are quite a lot of AATM phishing websites hosted on domains ending with workers.dev, but that was the trigger like, okay, well, how are they doing this? How are they phishing you using Cloudflare? Well, we didn't have the code because we didn't have access to the Cloudflare account of the attacker, but the option we had was like, okay, let's just build this ourselves in Cloudflare and see how hard it is. And in the end, it was quite pretty simple. And here you can see the implementation live. It's about 150 lines of code. We also published this on GitHub, so you can just upload the code to Cloudflare and you can perform this attack yourself. And it's just forwarding all the requests to Microsoft, and then it will send the username and password to Teams and of course the cookies, which you can use to log in as the victim. You can see if you take the cookies, put them in your browser, and you're simply logged in as the victim. That shows how easy it is. And it took like a few hours, so it's pretty easy as well to build. The code is on GitHub, on the link we've shared. Yeah, we've become part of the problem now. I don't know. Don't start the OST debate. Also we've seen some halt implementations. So they are not really forwarding all the requests that Microsoft is sending and receiving. But they, for example, only load the background image or the logo of the company. So they don't really care about the rest of the layout. The CSS that is able in Microsoft. So well, I will come later back on this because this has some trouble with our detections. And this is really, well, they use a lot of CAPTCHAs to protect our phishing websites, and it is also really effective. For example, this is Cloudflare turnstile, which is pretty


chunk_text:
  the requests to Microsoft, and then it will send the username and password to Teams and of course the cookies, which you can use to log in as the victim. You can see if you take the cookies, put them in your browser, and you're simply logged in as the victim. That shows how easy it is. And it took like a few hours, so it's pretty easy as well to build. The code is on GitHub, on the link we've shared. Yeah, we've become part of the problem now. I don't know. Don't start the OST debate. Also we've seen some halt implementations. So they are not really forwarding all the requests that Microsoft is sending and receiving. But they, for example, only load the background image or the logo of the company. So they don't really care about the rest of the layout. The CSS that is able in Microsoft. So well, I will come later back on this because this has some trouble with our detections. And this is really, well, they use a lot of CAPTCHAs to protect our phishing websites, and it is also really effective. For example, this is Cloudflare turnstile, which is pretty cool. You don't have to click anything. It's a CAPTCHA which just loads for a while. It's verifying and it just takes a few seconds and it will pass through if you are a human and it will block you if you're a bot. So we see a lot of criminals using this to hide their, for example, Evil Jinx instance. And it's really effective as well. It's so prevalent that we ended up deciding that if a new domain pops up from our detection and we then try to visit it, we get the turnstile. It's probably phishing. So we're just using this as an indicator now instead of the actual site. Yeah, something about the actors. As I've said before, there's a SaaS type service and there's more and more actors out there. These are some of the ones we've come into. But the interesting thing now is that initially you had like a very limited set of SaaS providers and they were like, it's a monthly or weekly pay type deal. And there's no like growing of it because the thing with the SaaS service is like it runs somewhere else. You can't like steal it. You


chunk_text:
  cool. You don't have to click anything. It's a CAPTCHA which just loads for a while. It's verifying and it just takes a few seconds and it will pass through if you are a human and it will block you if you're a bot. So we see a lot of criminals using this to hide their, for example, Evil Jinx instance. And it's really effective as well. It's so prevalent that we ended up deciding that if a new domain pops up from our detection and we then try to visit it, we get the turnstile. It's probably phishing. So we're just using this as an indicator now instead of the actual site. Yeah, something about the actors. As I've said before, there's a SaaS type service and there's more and more actors out there. These are some of the ones we've come into. But the interesting thing now is that initially you had like a very limited set of SaaS providers and they were like, it's a monthly or weekly pay type deal. And there's no like growing of it because the thing with the SaaS service is like it runs somewhere else. You can't like steal it. You can't keep it. So after two weeks, you have to like repay. So it's a great model for them. But also it contains the problem a bit. So what I'm now seeing is on the different forums, there's more and more providers saying like, hey, we can build you a reverse proxy for any website you like. And you get the code, which means if the Dutch like bank phishing scene says anything about what's going to happen here, it's that the moment you receive like the phishingpanel.zip for like 50 bucks, you open it, you control H and replace everything with like myleadpanel. And then you start selling that for like 50 bucks to recoup any of the costs you had for buying it. And that's the same thing that's going to be happening here. This is one of the providers. It's Evil Proxy. And the funny thing here was that they're also like doing like a weekly type deal. So you can see it. And in the... Do I have lasers? No, I have like switch screen. Almost broke it. So on the left, you can see like 10, 20 or 31 days and then the price and


chunk_text:
  can't keep it. So after two weeks, you have to like repay. So it's a great model for them. But also it contains the problem a bit. So what I'm now seeing is on the different forums, there's more and more providers saying like, hey, we can build you a reverse proxy for any website you like. And you get the code, which means if the Dutch like bank phishing scene says anything about what's going to happen here, it's that the moment you receive like the phishingpanel.zip for like 50 bucks, you open it, you control H and replace everything with like myleadpanel. And then you start selling that for like 50 bucks to recoup any of the costs you had for buying it. And that's the same thing that's going to be happening here. This is one of the providers. It's Evil Proxy. And the funny thing here was that they're also like doing like a weekly type deal. So you can see it. And in the... Do I have lasers? No, I have like switch screen. Almost broke it. So on the left, you can see like 10, 20 or 31 days and then the price and then whatever you want to phish. And the interesting thing in that one is that it's also targeting like PyP, npm.js and RubyGems, which would be pretty awesome to do like supply chain attacks on whatever you might like. But here it's still you have to like talk to someone and then get someone to deploy something. Like yesterday, I found this one, which feels more and more skinny to me, which is always fun. It's PhishXProxy. And this one gives you like a whole manual and you get an app. So meaning that this is something you could like probably open and reverse. And then it's your app and you call it, I don't know, PhishRickProxy. It's 20 bucks cheaper. And then the race to the bottom starts. And then in the end, people start giving it out for free. Problem grows, problem grows. The funny thing with PhishXProxy was that they had like a Telegram bot that allows you to do the payment, do the setup. And it helps you through the process, like deposit the Bitcoin here, do the thing, all that. And then there's Tycoon, one of the bigger ones, to be honest. In the right,


chunk_text:
  then whatever you want to phish. And the interesting thing in that one is that it's also targeting like PyP, npm.js and RubyGems, which would be pretty awesome to do like supply chain attacks on whatever you might like. But here it's still you have to like talk to someone and then get someone to deploy something. Like yesterday, I found this one, which feels more and more skinny to me, which is always fun. It's PhishXProxy. And this one gives you like a whole manual and you get an app. So meaning that this is something you could like probably open and reverse. And then it's your app and you call it, I don't know, PhishRickProxy. It's 20 bucks cheaper. And then the race to the bottom starts. And then in the end, people start giving it out for free. Problem grows, problem grows. The funny thing with PhishXProxy was that they had like a Telegram bot that allows you to do the payment, do the setup. And it helps you through the process, like deposit the Bitcoin here, do the thing, all that. And then there's Tycoon, one of the bigger ones, to be honest. In the right, you can see my elitist of speak. And, well, we just wanted to know like how much and where do you, where's the money going, please. And then something, nothing happened, but we did get access to a panel. And the funny thing with Tycoon, the funny thing with Tycoon is that if you have an organization that uses, doesn't use Linux on like endpoints or on desktops, it's pretty easy to detect because all their login happens from Linux systems. So if you just look at the sign-in logs and you filter out Android, it's not very hard to detect. But the thing is, you just don't send the money, but send the money and then you get this. And there's nothing you really have to do in order to actually get access. We looked at some of the, so we wondered like how much money are they making? And for Tycoon specifically, we've been able to like, it depends on the day, obviously, but it's like 660K in a year and a bit. So it's not bad. I mean, it's definitely not ransomware money. But at the same time, I feel it's quite a lot risk, risk less,


chunk_text:
  you can see my elitist of speak. And, well, we just wanted to know like how much and where do you, where's the money going, please. And then something, nothing happened, but we did get access to a panel. And the funny thing with Tycoon, the funny thing with Tycoon is that if you have an organization that uses, doesn't use Linux on like endpoints or on desktops, it's pretty easy to detect because all their login happens from Linux systems. So if you just look at the sign-in logs and you filter out Android, it's not very hard to detect. But the thing is, you just don't send the money, but send the money and then you get this. And there's nothing you really have to do in order to actually get access. We looked at some of the, so we wondered like how much money are they making? And for Tycoon specifically, we've been able to like, it depends on the day, obviously, but it's like 660K in a year and a bit. So it's not bad. I mean, it's definitely not ransomware money. But at the same time, I feel it's quite a lot risk, risk less, more risk-free. It's more risk-free. And I mean, you don't have to do much. I mean, it's a SaaS service. It's just like, press the button, it works. And then you get 660K. Interesting. One of the addresses is like a USDT address. And you can see that all the money is going to Binance in the end. So he's sending all his money to Binance. And I'm not a forensic person or related to the cops, but I feel that's pretty easy to figure out who this is. As long as he's not using like, I don't know, somebody that's giving him their Binance account. But as far as I know, your customer is still in effect. And it's pretty decently able to, you could be able to figure this out. Cool. Yeah, of course, the most important prevention and detection. Well, let's get started with prevention. Well, it is, compared to others, it is fairly easy on Microsoft 365. But the downside is that it requires some licenses, the P1 and P2 from AAD. And there are two main options. You can enforce phishing-resistant MFA. So POS keys and YubiKeys, for example. The downside is, it is not


chunk_text:
  more risk-free. It's more risk-free. And I mean, you don't have to do much. I mean, it's a SaaS service. It's just like, press the button, it works. And then you get 660K. Interesting. One of the addresses is like a USDT address. And you can see that all the money is going to Binance in the end. So he's sending all his money to Binance. And I'm not a forensic person or related to the cops, but I feel that's pretty easy to figure out who this is. As long as he's not using like, I don't know, somebody that's giving him their Binance account. But as far as I know, your customer is still in effect. And it's pretty decently able to, you could be able to figure this out. Cool. Yeah, of course, the most important prevention and detection. Well, let's get started with prevention. Well, it is, compared to others, it is fairly easy on Microsoft 365. But the downside is that it requires some licenses, the P1 and P2 from AAD. And there are two main options. You can enforce phishing-resistant MFA. So POS keys and YubiKeys, for example. The downside is, it is not really user-friendly yet. I don't think you can get a company with 1000 people, all use YubiKeys. And that's going to work well. Another option is device compliance. But this may have, well, you may have the same issue. It may be hard to implement as well, because you're going to block devices that may be on the network right now. But at least you have options. And there are many sites which you don't have. At the moment, lots of companies are moving to POS keys. But then if your account has a POS key, and the tooling strips out any reference to POS keys before sending it back to the user, you never get the POS key offering. And then it allows you to still log in with username and password and MFA. So you still end up being kind of vulnerable, or you need to train people, which is hard. Yeah, it's just hard. So let's just explain how the proxy works. I should definitely put this slide way in the front. Yeah, I made this image because of the ATM worker that I created on Cloudflare. So this explains how that was implemented. And it's a


chunk_text:
  really user-friendly yet. I don't think you can get a company with 1000 people, all use YubiKeys. And that's going to work well. Another option is device compliance. But this may have, well, you may have the same issue. It may be hard to implement as well, because you're going to block devices that may be on the network right now. But at least you have options. And there are many sites which you don't have. At the moment, lots of companies are moving to POS keys. But then if your account has a POS key, and the tooling strips out any reference to POS keys before sending it back to the user, you never get the POS key offering. And then it allows you to still log in with username and password and MFA. So you still end up being kind of vulnerable, or you need to train people, which is hard. Yeah, it's just hard. So let's just explain how the proxy works. I should definitely put this slide way in the front. Yeah, I made this image because of the ATM worker that I created on Cloudflare. So this explains how that was implemented. And it's a pretty simple concept, because the victim visits the ATM worker, so the fake fixie site. The ATM worker forwards the request directly to Microsoft. Then the response is as well sent to the ATM worker. And at that point, I'm replacing just a few links in the response. So the MicrosoftOnline.com links have to be replaced with the URL of your phishing website. And well, that pretty is what you have to do. And of course, you have to capture the username, password, and the cookies from the responses that are being transferred. And then you can post to Teams. So the only thing you have to do is forward all requests, do a little bit of stupid replacements, just very simple replacements, and grab the information out of it that you want. And that's all you have to do to create an ATM framework for Microsoft. So this is a pretty simple concept. I thought before I started with building this, I thought it was way, way harder. Yeah, you ended up copying somebody else's Python script and then just editing it to do this, right? Yeah, somebody already published a Cloudflare worker that was a reverse proxy, so


chunk_text:
  pretty simple concept, because the victim visits the ATM worker, so the fake fixie site. The ATM worker forwards the request directly to Microsoft. Then the response is as well sent to the ATM worker. And at that point, I'm replacing just a few links in the response. So the MicrosoftOnline.com links have to be replaced with the URL of your phishing website. And well, that pretty is what you have to do. And of course, you have to capture the username, password, and the cookies from the responses that are being transferred. And then you can post to Teams. So the only thing you have to do is forward all requests, do a little bit of stupid replacements, just very simple replacements, and grab the information out of it that you want. And that's all you have to do to create an ATM framework for Microsoft. So this is a pretty simple concept. I thought before I started with building this, I thought it was way, way harder. Yeah, you ended up copying somebody else's Python script and then just editing it to do this, right? Yeah, somebody already published a Cloudflare worker that was a reverse proxy, so I modified that one, of course. Because it was Node.js, I don't... Oh no, I don't know Node.js either. Well, that was important because of this, because we were already detecting website clones and phishing attacks on regular websites. And how we are doing is that we are placing a pixel in a real website. And whenever this pixel is being loaded from another website, we can alert a website owner that the website is copied manually or that there may be a reverse proxy in place. And then our colleague Eric came up with the idea, can we also use the same technique to protect Microsoft 365, well, tenants? And he came up with the Microsoft Custom Branding CSS. And when he came up with the idea, we were like, hey, if that's gonna work, that's really interesting because then we can protect Microsoft tenants and detect at least the phishing attempts. So we tried this by just adding a custom CSS to a Microsoft login page, pointing to the DidSomeoneCloneMe backend, which allows you to detect the phishing attacks. And well, it triggered a phishing attempt. So here you can see that the reverse proxy was hosted on


chunk_text:
  I modified that one, of course. Because it was Node.js, I don't... Oh no, I don't know Node.js either. Well, that was important because of this, because we were already detecting website clones and phishing attacks on regular websites. And how we are doing is that we are placing a pixel in a real website. And whenever this pixel is being loaded from another website, we can alert a website owner that the website is copied manually or that there may be a reverse proxy in place. And then our colleague Eric came up with the idea, can we also use the same technique to protect Microsoft 365, well, tenants? And he came up with the Microsoft Custom Branding CSS. And when he came up with the idea, we were like, hey, if that's gonna work, that's really interesting because then we can protect Microsoft tenants and detect at least the phishing attempts. So we tried this by just adding a custom CSS to a Microsoft login page, pointing to the DidSomeoneCloneMe backend, which allows you to detect the phishing attacks. And well, it triggered a phishing attempt. So here you can see that the reverse proxy was hosted on login.atm.tag and that it detected the phishing attempt. So that was pretty cool because we could use this technique to protect our customers. So we did. And in the first month, we were able to, well, connect 100 tenants. So we installed the CSS on direct tenants and we get all the detections that occurred. And well, to be honest, before I started with this, I didn't expect a lot of detection because I still thought ATM was for the specific people that used it and attacked it. And it was not really being used on scale. But in the first month, we had about 162 detections on the 100 different tenants. So within a month, I think that's quite a lot. And in nine months, we have about 1300 detections. And of course, the detections differ per company. For example, we have a company with about 50,000 employees and you can see that there are way more detections. Some tenants do not have any detection because they are just really, really small. So well, here we realized that it was quite a big problem going on. And even, that's why I explained the whole implementation, we do not detect


chunk_text:
  login.atm.tag and that it detected the phishing attempt. So that was pretty cool because we could use this technique to protect our customers. So we did. And in the first month, we were able to, well, connect 100 tenants. So we installed the CSS on direct tenants and we get all the detections that occurred. And well, to be honest, before I started with this, I didn't expect a lot of detection because I still thought ATM was for the specific people that used it and attacked it. And it was not really being used on scale. But in the first month, we had about 162 detections on the 100 different tenants. So within a month, I think that's quite a lot. And in nine months, we have about 1300 detections. And of course, the detections differ per company. For example, we have a company with about 50,000 employees and you can see that there are way more detections. Some tenants do not have any detection because they are just really, really small. So well, here we realized that it was quite a big problem going on. And even, that's why I explained the whole implementation, we do not detect all phishing attempts because some phishing framers do strip the CSS, of course. So this is just a tip. So, well, now we get a lot of alerts from all the tenants that are protected. You can also see that from that data, you can see that the phishing attempts are also performed across tenants. So here you see some things from the database. You can see that different protected tenants are receiving the same phishing website, phishing attempts. So you can just see that they are spraying the AATM across different organization on a big scale and just, well, try to hit everything. Before creating this software, we didn't know if this is going to be very effective because, of course, there's also always a chance for false positives. But this was quite, well, nice because we didn't have a lot of false positives. We just have to filter out a couple of domains and after that, the detection is very reliable. I will skip this one. Ah, cool. Well, no, I want to go back. I want to tell this. So it's pretty interesting. I just find this funny. Initially, we were like, oh, there's so many hits,


chunk_text:
  all phishing attempts because some phishing framers do strip the CSS, of course. So this is just a tip. So, well, now we get a lot of alerts from all the tenants that are protected. You can also see that from that data, you can see that the phishing attempts are also performed across tenants. So here you see some things from the database. You can see that different protected tenants are receiving the same phishing website, phishing attempts. So you can just see that they are spraying the AATM across different organization on a big scale and just, well, try to hit everything. Before creating this software, we didn't know if this is going to be very effective because, of course, there's also always a chance for false positives. But this was quite, well, nice because we didn't have a lot of false positives. We just have to filter out a couple of domains and after that, the detection is very reliable. I will skip this one. Ah, cool. Well, no, I want to go back. I want to tell this. So it's pretty interesting. I just find this funny. Initially, we were like, oh, there's so many hits, so many hits. And then we figured out that all these ranges are like Microsoft ranges and this is sandboxes hitting you and not the actual end user getting phished. But if you send alerts out based on this, you're like, you're dying. Your whole company is under attack. Everybody's going to die and there's actually nothing happening. And it's funny to see like Microsoft trying to do a thing too. So for the future, we've seen a huge increase in the offering of the, like offering of customization phishlets, just complete solutions. On the right, you can see like a live.com, just not even targeting companies anymore, but just targeting like end users. So you see that the value of the whole thing is going down because it's a live.com account is way less valuable, depending on the user, than like the more like Microsoft accounts, booking.com, hotel owner sites. And then at the same time, because it costs money there, you can see like people asking for generic reverse proxy options. And the next thing, at least in the Netherlands, is going to be bank phishing, where the whole process of asking for sending money or adding an


chunk_text:
  so many hits. And then we figured out that all these ranges are like Microsoft ranges and this is sandboxes hitting you and not the actual end user getting phished. But if you send alerts out based on this, you're like, you're dying. Your whole company is under attack. Everybody's going to die and there's actually nothing happening. And it's funny to see like Microsoft trying to do a thing too. So for the future, we've seen a huge increase in the offering of the, like offering of customization phishlets, just complete solutions. On the right, you can see like a live.com, just not even targeting companies anymore, but just targeting like end users. So you see that the value of the whole thing is going down because it's a live.com account is way less valuable, depending on the user, than like the more like Microsoft accounts, booking.com, hotel owner sites. And then at the same time, because it costs money there, you can see like people asking for generic reverse proxy options. And the next thing, at least in the Netherlands, is going to be bank phishing, where the whole process of asking for sending money or adding an account or adding your bank account to the phone, that's going to be automated via ITM. And that's going to allow them to work more efficiently because currently they're literally screenshotting the QR code and sending it to the user, which is stupid. So that's definitely going to happen. And in conclusion, it's going to be shit for a while, which is always good to have like an uplifting thing. We're going to see a large increase still, not just against targeted against companies, but targeting like regular users. Companies will need to like switch how they work with this. Passkeys are very good, but they're not the user experiences. And if you don't enforce your passkeys, once you've configured them, it will definitely leave you vulnerable. We're definitely out of time. Thank you so much for listening. And if you want like the free ITM for Microsoft 365, you can use our free option to detect this type of attack. So thank you very much. Thank you.


chunk_text:
  account or adding your bank account to the phone, that's going to be automated via ITM. And that's going to allow them to work more efficiently because currently they're literally screenshotting the QR code and sending it to the user, which is stupid. So that's definitely going to happen. And in conclusion, it's going to be shit for a while, which is always good to have like an uplifting thing. We're going to see a large increase still, not just against targeted against companies, but targeting like regular users. Companies will need to like switch how they work with this. Passkeys are very good, but they're not the user experiences. And if you don't enforce your passkeys, once you've configured them, it will definitely leave you vulnerable. We're definitely out of time. Thank you so much for listening. And if you want like the free ITM for Microsoft 365, you can use our free option to detect this type of attack. So thank you very much. Thank you.


chunk_text:
  { "webpage_url": "https://www.youtube.com/watch?v=zPbH-xJ_RpM", "title": "Offensive Development In Modern Languages - Cas Van Cooten", "description": "", "channel_url": "https://www.youtube.com/channel/UCgJoGNj3B2Mt2F3TUblcoOA", "duration": 1857, "channel": "OrangeCon", "uploader": "OrangeCon", "upload_date": "20240909" } This text was transcribed using whisper model: large-v2 Thank you, good afternoon, good to see you all here. My name is Cas van Kooten and today we're going to talk about languages, programming languages of course, but I wanted to start with a little bridge to languages in the classical sense of the word, because languages to me are really fascinating. Everyone or mostly everyone knows at least one language, most people know two, especially here in the Netherlands I think a lot of people know three, four, five or more languages, and the interesting thing is that languages are all related, like, right, they're like families in a big tree, you can see some languages are closer together, some are further apart, but that means that the more languages that you learn, the more parallels that you see between these languages, and that the easier it gets to learn new languages, the more that you know, and this is also true for programming languages, so a lot of people think that learning a new programming language is really hard, which it can be, it's not always easy, but actually every programming language is essentially doing the same thing, right, you're trying to achieve something programmatically, there's these constructs like logic statements, if else, whatever, there's loops in there, and this is kind of generic for every language, so the more programming languages that you learn, the easier it gets, and that's also a little bit of a flash forward to my call to action today, which is learn as many languages as you can, I'm a big fan of modern languages, can also be ancient boomer languages like C, that's up to you, but yeah, that will be my key message today. Of course, we're not only going to talk about languages, we're going to put it into a perspective a little bit of offensive development, so I tailored it a little bit to my world view, which is distinctly red, also useful of course for anyone that wants to automate more in their life, including blue teamers. A little bit about me, I'll skip through this a little bit, because we have a lot to discuss, but my name is Cas van


chunk_text:
  new programming language is really hard, which it can be, it's not always easy, but actually every programming language is essentially doing the same thing, right, you're trying to achieve something programmatically, there's these constructs like logic statements, if else, whatever, there's loops in there, and this is kind of generic for every language, so the more programming languages that you learn, the easier it gets, and that's also a little bit of a flash forward to my call to action today, which is learn as many languages as you can, I'm a big fan of modern languages, can also be ancient boomer languages like C, that's up to you, but yeah, that will be my key message today. Of course, we're not only going to talk about languages, we're going to put it into a perspective a little bit of offensive development, so I tailored it a little bit to my world view, which is distinctly red, also useful of course for anyone that wants to automate more in their life, including blue teamers. A little bit about me, I'll skip through this a little bit, because we have a lot to discuss, but my name is Cas van Kooten, I'm a red teamer at a big bank you may know here in the Netherlands, I call myself a malware linguist, because I really enjoy, as you may guess by now, learning new, especially modern languages like Go, Rust, Nim, and trying to apply that to the field of offensive security. So that's also what we're going to talk about today, you can find me on Twitter as well with some shitty memes mostly, but sometimes there's some knowledge sharing there as well, and I post some stuff on GitHub if you want some examples. So, let's take a step back to offensive development to start with. I think this situation, if you're in offensive operations, is all too familiar by now, I think over the last couple of years, probably five or more by now, we've seen this kind of race between red and blue, right, and this is not new, this has always been there, but especially in the area of OST, offensive security tooling, or open source tooling, depending on what your definition is, this is very relevant, because there's great tools that get published all the time, you can grab them off of GitHub and


chunk_text:
  Kooten, I'm a red teamer at a big bank you may know here in the Netherlands, I call myself a malware linguist, because I really enjoy, as you may guess by now, learning new, especially modern languages like Go, Rust, Nim, and trying to apply that to the field of offensive security. So that's also what we're going to talk about today, you can find me on Twitter as well with some shitty memes mostly, but sometimes there's some knowledge sharing there as well, and I post some stuff on GitHub if you want some examples. So, let's take a step back to offensive development to start with. I think this situation, if you're in offensive operations, is all too familiar by now, I think over the last couple of years, probably five or more by now, we've seen this kind of race between red and blue, right, and this is not new, this has always been there, but especially in the area of OST, offensive security tooling, or open source tooling, depending on what your definition is, this is very relevant, because there's great tools that get published all the time, you can grab them off of GitHub and run them on your client's network, and you will have a bad day, because, of course, the blue team is not sitting still, right, they are also looking at these great tools and making sure they are fingerprinted. So, to use these tools in practice, you need something of a development capability. So, the kind of least you can do is modify it, but there's other options as well. Essentially, there's three, and this comes down a little bit to a business decision, because as a red team, as an offensive team, you get the choice here, how much do you want to do, or how much do you want to pay, essentially. So, the first option is to purchase your offensive tooling, I think more and more we are seeing offensive security companies step up and offer tooling that you can use, which is kind of evasive by design, so you're kind of paying money to get tooling that works in practice, right, you don't have to change it anymore, there's commercial C2 frameworks, you have old toolkits like Outflank is offering now, for example, and, yes, you get all these options that you can essentially procure, so you


chunk_text:
  run them on your client's network, and you will have a bad day, because, of course, the blue team is not sitting still, right, they are also looking at these great tools and making sure they are fingerprinted. So, to use these tools in practice, you need something of a development capability. So, the kind of least you can do is modify it, but there's other options as well. Essentially, there's three, and this comes down a little bit to a business decision, because as a red team, as an offensive team, you get the choice here, how much do you want to do, or how much do you want to pay, essentially. So, the first option is to purchase your offensive tooling, I think more and more we are seeing offensive security companies step up and offer tooling that you can use, which is kind of evasive by design, so you're kind of paying money to get tooling that works in practice, right, you don't have to change it anymore, there's commercial C2 frameworks, you have old toolkits like Outflank is offering now, for example, and, yes, you get all these options that you can essentially procure, so you don't need to do it yourself. A very valid option, you can also choose to adapt the tooling, that's essentially what I just mentioned, you have open source tools, right, they work well, but they are fingerprinted, so if you modify them to get rid of the fingerprints, you can use them again. The downside of that is that it's, well, there's still some behaviour in there that you may not completely understand, because it's not your tool, right, the upside is that it saves you a lot of time, development time, essentially. And the last option is actually what we're going to focus on today, which is to develop your own tools. Developing your own tools is my personal favourite, because it's a lot of fun, first of all, but also it gives you 100% complete control of what you're building, right, that makes sense, but from an offensive perspective, that also means you have full control over the IOCs, the indicators that you're leaving in a client network, you have full control of what you're actually building. Of course, the downside, again, is that it takes the most time, but yeah, given the fact that it's a lot


chunk_text:
  don't need to do it yourself. A very valid option, you can also choose to adapt the tooling, that's essentially what I just mentioned, you have open source tools, right, they work well, but they are fingerprinted, so if you modify them to get rid of the fingerprints, you can use them again. The downside of that is that it's, well, there's still some behaviour in there that you may not completely understand, because it's not your tool, right, the upside is that it saves you a lot of time, development time, essentially. And the last option is actually what we're going to focus on today, which is to develop your own tools. Developing your own tools is my personal favourite, because it's a lot of fun, first of all, but also it gives you 100% complete control of what you're building, right, that makes sense, but from an offensive perspective, that also means you have full control over the IOCs, the indicators that you're leaving in a client network, you have full control of what you're actually building. Of course, the downside, again, is that it takes the most time, but yeah, given the fact that it's a lot of fun, in my experience, I would definitely recommend going there. So, when I say offensive development, or development in the context of offensive security, a lot of people immediately assume that I'm talking about malware development, but in my view, those two are a little bit different. I would actually say that malware development is a subset of offensive development. For the reasons that you see here, of course, offensive development encompasses everything that's used to support an offensive operations, right, and malware development I would define as everything that runs on your target system. Of course, the latter, malware development, is quite a different ballgame, because there you're dealing with these defences, you're dealing with EDR, you're dealing with network protocols, all these kinds of things. So, developing for on-target operations is quite challenging, but there's more to it. So, if you look at some of the examples here, you can see that a lot of supporting tooling, even like the knowledge management or the scripts that you use to automate your offensive operations, these are all part of offensive development. So, I wanted to mention that just to set the scene a little bit for what we're


chunk_text:
  of fun, in my experience, I would definitely recommend going there. So, when I say offensive development, or development in the context of offensive security, a lot of people immediately assume that I'm talking about malware development, but in my view, those two are a little bit different. I would actually say that malware development is a subset of offensive development. For the reasons that you see here, of course, offensive development encompasses everything that's used to support an offensive operations, right, and malware development I would define as everything that runs on your target system. Of course, the latter, malware development, is quite a different ballgame, because there you're dealing with these defences, you're dealing with EDR, you're dealing with network protocols, all these kinds of things. So, developing for on-target operations is quite challenging, but there's more to it. So, if you look at some of the examples here, you can see that a lot of supporting tooling, even like the knowledge management or the scripts that you use to automate your offensive operations, these are all part of offensive development. So, I wanted to mention that just to set the scene a little bit for what we're going to discuss later. And one other thing that I wanted to mention before we actually get to the programming languages is the development part of offensive development, because we hackers are very known to kind of sitting like a monkey behind a keyboard and putting out some code that's like POC code, right? A lot of GitHub tools that you see actually have a disclaimer that says, this is a POC, I wrote this in one night, I was drunk, whatever, don't run this in production, and then everyone takes it and runs it in production, right? So of course, working code is better than perfect code, but I would argue for a little bit more of a developer mindset in the field of offensive development or any development that we're doing in the context of security. Because bad code, bad code or maybe a code that you wrote very quickly or whatever, has a real impact. First of all, it can bother other people, right? If you're, for example, publishing your code on GitHub or you're collaborating on it with colleagues, and you have like one big chunk of code in one file that's not annotated, there's no


chunk_text:
  going to discuss later. And one other thing that I wanted to mention before we actually get to the programming languages is the development part of offensive development, because we hackers are very known to kind of sitting like a monkey behind a keyboard and putting out some code that's like POC code, right? A lot of GitHub tools that you see actually have a disclaimer that says, this is a POC, I wrote this in one night, I was drunk, whatever, don't run this in production, and then everyone takes it and runs it in production, right? So of course, working code is better than perfect code, but I would argue for a little bit more of a developer mindset in the field of offensive development or any development that we're doing in the context of security. Because bad code, bad code or maybe a code that you wrote very quickly or whatever, has a real impact. First of all, it can bother other people, right? If you're, for example, publishing your code on GitHub or you're collaborating on it with colleagues, and you have like one big chunk of code in one file that's not annotated, there's no comments, the variables are named very specifically or you have like I, J, X, Y, Z, then everyone reading this is like, oh, what's this? And maybe if it's open source, people decide not to maintain or not to contribute to your project, because it's not readable, right? This is very easy to avoid. It just takes a little bit of a mindset while you're programming. Stability is another concern. This is usually for malware or like POCs, this is not a big problem, but when you're writing on target implants, for example, C2 implants that need to run for weeks or months, maybe years on end, you really don't want a memory leak in there or some oversight that causes it to crash at a random time during the year. So, that's a real concern as well. And finally, of course, we are security professionals. Bad code also impacts security. Now, a small disclaimer here. I don't want to shit too much on Paul, who is the maintainer of Havoc, because that's actually an excellent project. This is just the last example I could find of vulnerabilities being in security tools. The source security tools in this example, but


chunk_text:
  comments, the variables are named very specifically or you have like I, J, X, Y, Z, then everyone reading this is like, oh, what's this? And maybe if it's open source, people decide not to maintain or not to contribute to your project, because it's not readable, right? This is very easy to avoid. It just takes a little bit of a mindset while you're programming. Stability is another concern. This is usually for malware or like POCs, this is not a big problem, but when you're writing on target implants, for example, C2 implants that need to run for weeks or months, maybe years on end, you really don't want a memory leak in there or some oversight that causes it to crash at a random time during the year. So, that's a real concern as well. And finally, of course, we are security professionals. Bad code also impacts security. Now, a small disclaimer here. I don't want to shit too much on Paul, who is the maintainer of Havoc, because that's actually an excellent project. This is just the last example I could find of vulnerabilities being in security tools. The source security tools in this example, but it also happened to Cobalt Strike, for example. It's funny that we are security professionals, right? But the moment we start coding, sometimes we kind of forget the principles that we teach to others all the time. Of course, you know all the web vulnerability stuff, but there's much more to it. And I think proper dev practice also means that when we are developing something, we should be really conscious about what we're doing, who's going to be able to communicate with it, will someone be able to intercept that traffic and abuse it, stuff like this. The good news is that it's not really hard to adopt this developer mindset, as I call it. It takes some maybe getting used to, some switching, but it's actually, yeah, it's just a couple of principles that can really help you get a long way. There's a couple of principles like, of course, commenting your code, structuring it well, depending on which language you are using, and trying to minimize the repetition of code. Just a couple of principles can already help you really elevate your POCs to the next level. There's a couple of books as well. I particularly enjoyed


chunk_text:
  it also happened to Cobalt Strike, for example. It's funny that we are security professionals, right? But the moment we start coding, sometimes we kind of forget the principles that we teach to others all the time. Of course, you know all the web vulnerability stuff, but there's much more to it. And I think proper dev practice also means that when we are developing something, we should be really conscious about what we're doing, who's going to be able to communicate with it, will someone be able to intercept that traffic and abuse it, stuff like this. The good news is that it's not really hard to adopt this developer mindset, as I call it. It takes some maybe getting used to, some switching, but it's actually, yeah, it's just a couple of principles that can really help you get a long way. There's a couple of principles like, of course, commenting your code, structuring it well, depending on which language you are using, and trying to minimize the repetition of code. Just a couple of principles can already help you really elevate your POCs to the next level. There's a couple of books as well. I particularly enjoyed this one, which are interesting to read as a security professional, because they kind of take a step back and go through these concepts that can really help you put the developer in offensive development. And I also found that AI, so Copilot or whatever AI assistant you are using, can actually help a lot here. There's a couple of prompts or a couple of keywords like idiomatic code, that if you ask it that, it will come back and kind of get all the knowledge that it took from the Stack Overflow geeks and dump it on you, which is actually really good when you're learning a new language, right? Because you may be used to some low-level language and suddenly you're programming something in Python and all these idioms, so the practices in that specific language are very different than you're used to. So having AI kind of look over your shoulder, be very pedantic about the style that you use, the structuring of your code can help a lot. So let's actually get into the programming languages then. Also there, when choosing a language for your offensive project, I think we can just look at what normal


chunk_text:
  this one, which are interesting to read as a security professional, because they kind of take a step back and go through these concepts that can really help you put the developer in offensive development. And I also found that AI, so Copilot or whatever AI assistant you are using, can actually help a lot here. There's a couple of prompts or a couple of keywords like idiomatic code, that if you ask it that, it will come back and kind of get all the knowledge that it took from the Stack Overflow geeks and dump it on you, which is actually really good when you're learning a new language, right? Because you may be used to some low-level language and suddenly you're programming something in Python and all these idioms, so the practices in that specific language are very different than you're used to. So having AI kind of look over your shoulder, be very pedantic about the style that you use, the structuring of your code can help a lot. So let's actually get into the programming languages then. Also there, when choosing a language for your offensive project, I think we can just look at what normal developers are doing, right? On the right here, you see the Stack Overflow developer survey, which is like a yearly thing that they do where they ask which programming languages do you currently use, which is like the blue lines here, and which ones would you like to use in the coming year, which is the red lines over there. It's quite interesting to look at, honestly. They have a lot more questions as well, so I would recommend looking at that survey online if you have the chance. But there's a couple of trends that you see, for example, Rust, of course, being hyped as always. Python is the number one that's, I think, for many years now. And that's very relevant for us security professionals to know as well, especially when you're writing on target malware. We've seen this with Nim, for example. If no one is using the language legitimately and suddenly this suspicious binary pops up that's written in Nim and it's doing some weird allocations, then antivirus is just like, get out of here, because that's not going to happen, right? So the prevalence of a language actually helps in evasion. But, of course, every


chunk_text:
  developers are doing, right? On the right here, you see the Stack Overflow developer survey, which is like a yearly thing that they do where they ask which programming languages do you currently use, which is like the blue lines here, and which ones would you like to use in the coming year, which is the red lines over there. It's quite interesting to look at, honestly. They have a lot more questions as well, so I would recommend looking at that survey online if you have the chance. But there's a couple of trends that you see, for example, Rust, of course, being hyped as always. Python is the number one that's, I think, for many years now. And that's very relevant for us security professionals to know as well, especially when you're writing on target malware. We've seen this with Nim, for example. If no one is using the language legitimately and suddenly this suspicious binary pops up that's written in Nim and it's doing some weird allocations, then antivirus is just like, get out of here, because that's not going to happen, right? So the prevalence of a language actually helps in evasion. But, of course, every language has kind of intrinsic design principles and elements that also make it relevant to choose as an offensive practitioner. A couple of considerations. I think one of the main considerations for offensive development is whether the language is interpreted or compiled. So interpreted means that there's like an interpreter that you need on the system already to read the code line by line and execute it. Python, I think, is the most famous example here. The downside is that the portability of the language really dives, because you need to have that interpreter on the system to do anything. The upside is if the interpreter is on the system already, it's great. If you're doing off target operations, this is great, because the interpreter can really help you get started quickly and, yeah, hit the ground running, so to say. Compiled, on the other hand, means that when you're done coding, you compile an artifact, so like an executable for Windows, for example, elf binary for Linux, whatever, and you can take that, drop it anywhere where it's compiled for, and just run it. This is usually what you would do for like actual malware development. You would choose


chunk_text:
  language has kind of intrinsic design principles and elements that also make it relevant to choose as an offensive practitioner. A couple of considerations. I think one of the main considerations for offensive development is whether the language is interpreted or compiled. So interpreted means that there's like an interpreter that you need on the system already to read the code line by line and execute it. Python, I think, is the most famous example here. The downside is that the portability of the language really dives, because you need to have that interpreter on the system to do anything. The upside is if the interpreter is on the system already, it's great. If you're doing off target operations, this is great, because the interpreter can really help you get started quickly and, yeah, hit the ground running, so to say. Compiled, on the other hand, means that when you're done coding, you compile an artifact, so like an executable for Windows, for example, elf binary for Linux, whatever, and you can take that, drop it anywhere where it's compiled for, and just run it. This is usually what you would do for like actual malware development. You would choose a compiled language, because you're not dependent on that runtime, right? Very important as well is is the language high level or low level? Now, this is a bit vague, maybe hard to define, but in general, a language kind of intrinsically gives you some level of abstraction, right? I think Python probably is the most famous example of a very high level language, meaning that there's a lot of abstractions in Python that make the code very readable. Sometimes Python almost reads like natural English, but the abstractions mean that you're typing that and you're not exactly sure what's happening under the hood, right? The opposite of that is low level, where you're essentially giving the computer literal instructions in almost in computer language. This is what happens in C, right, or even assembler, where really, like, you have to think about what's the computer doing, and it's not abstracting anything for you. It's literally doing what you're saying, which brings a lot of risks as well, like safety in C is a big topic now that Rust jumped into, but, yes, it's a consideration depending on your product that matters. Performance. In my experience, performance is a little


chunk_text:
  a compiled language, because you're not dependent on that runtime, right? Very important as well is is the language high level or low level? Now, this is a bit vague, maybe hard to define, but in general, a language kind of intrinsically gives you some level of abstraction, right? I think Python probably is the most famous example of a very high level language, meaning that there's a lot of abstractions in Python that make the code very readable. Sometimes Python almost reads like natural English, but the abstractions mean that you're typing that and you're not exactly sure what's happening under the hood, right? The opposite of that is low level, where you're essentially giving the computer literal instructions in almost in computer language. This is what happens in C, right, or even assembler, where really, like, you have to think about what's the computer doing, and it's not abstracting anything for you. It's literally doing what you're saying, which brings a lot of risks as well, like safety in C is a big topic now that Rust jumped into, but, yes, it's a consideration depending on your product that matters. Performance. In my experience, performance is a little bit less important for most security tooling. Usually, unless you're writing, like, a highly concurrent port scanner, for example, we really don't care that much about performance, where normal developers would care a lot more, but still, if you're writing a project that does care about performance, of course, you need to factor that in, because some languages are less performant than others, and it can also really differ per use case as well. Portability. Already mentioned compiled languages, where you just get a binary and can drop it somewhere. I also consider cross compilation to be a part of this, where you can sit on Linux, compile something for Windows or for MacOS, and I think especially modern languages are very good at this, where, for example, in Golang, you write your code, if you don't use any OS-specific libraries, then you can just compile it for whatever, right? Nim also did this. I think they natively offered support for what was it, the Nintendo Switch or something like that, so modern languages are good at this, but, of course, you need to keep it in mind and consider if it's even relevant for your project. Then the prevalence.


chunk_text:
  bit less important for most security tooling. Usually, unless you're writing, like, a highly concurrent port scanner, for example, we really don't care that much about performance, where normal developers would care a lot more, but still, if you're writing a project that does care about performance, of course, you need to factor that in, because some languages are less performant than others, and it can also really differ per use case as well. Portability. Already mentioned compiled languages, where you just get a binary and can drop it somewhere. I also consider cross compilation to be a part of this, where you can sit on Linux, compile something for Windows or for MacOS, and I think especially modern languages are very good at this, where, for example, in Golang, you write your code, if you don't use any OS-specific libraries, then you can just compile it for whatever, right? Nim also did this. I think they natively offered support for what was it, the Nintendo Switch or something like that, so modern languages are good at this, but, of course, you need to keep it in mind and consider if it's even relevant for your project. Then the prevalence. I think I already discussed this at the start of this slide. Prevalence essentially means how much is a language used? The more it's used, the more it will blend in. Simple as that. And, finally, I also put developer experience here, which is an often overlooked fact, because people are saying, oh, Rust is the new fastest language, or, no, everyone is using C, you should use C, but when I code in C, personally, I become very unhappy, so that's essentially what developer experience means, right? Is there a good community? Is the compiler helping you fix your errors? Again, AI is now a part of this as well, so, essentially, how do you feel when coding in a certain language? This is arguably maybe the most important option when choosing a language. Maybe it doesn't really matter to you, that's also fine, but it's something to consider before choosing a language, for sure. Typing is also part of a language. For those who don't know, typing essentially means that you're telling a language what type you want a certain variable to be. That's sometimes it's optional, like in Python, you are allowed to define types. It's not


chunk_text:
  I think I already discussed this at the start of this slide. Prevalence essentially means how much is a language used? The more it's used, the more it will blend in. Simple as that. And, finally, I also put developer experience here, which is an often overlooked fact, because people are saying, oh, Rust is the new fastest language, or, no, everyone is using C, you should use C, but when I code in C, personally, I become very unhappy, so that's essentially what developer experience means, right? Is there a good community? Is the compiler helping you fix your errors? Again, AI is now a part of this as well, so, essentially, how do you feel when coding in a certain language? This is arguably maybe the most important option when choosing a language. Maybe it doesn't really matter to you, that's also fine, but it's something to consider before choosing a language, for sure. Typing is also part of a language. For those who don't know, typing essentially means that you're telling a language what type you want a certain variable to be. That's sometimes it's optional, like in Python, you are allowed to define types. It's not always very strict. Some languages are very pedantic about this. I think it's nice, because exactly this happens, right, where you're coding something, and you do something weird, where suddenly a string enters the production line of integers, and then, in the former case, your IDE or your text editor can already tell you, hey, there's something weird going on here, right, and sometimes people just code something, and it's like, oh, I guess we're doing strings now, and when you run that on a target, it will do silly things, right, so typing is also something to take into account. So how do you actually choose a language? Well, definitely do not use this decision tree, but it's like an example of your, yeah, like a mind map that you could use to choose a language, right? You have all these properties that I just mentioned. You can essentially just Google them for new languages, like, okay, how performant does O, and you will get a lot of people saying, oh, Rust is better, and you look into Rust, and then you get people saying C is better, so you get into this rabbit hole, but in the end,


chunk_text:
  always very strict. Some languages are very pedantic about this. I think it's nice, because exactly this happens, right, where you're coding something, and you do something weird, where suddenly a string enters the production line of integers, and then, in the former case, your IDE or your text editor can already tell you, hey, there's something weird going on here, right, and sometimes people just code something, and it's like, oh, I guess we're doing strings now, and when you run that on a target, it will do silly things, right, so typing is also something to take into account. So how do you actually choose a language? Well, definitely do not use this decision tree, but it's like an example of your, yeah, like a mind map that you could use to choose a language, right? You have all these properties that I just mentioned. You can essentially just Google them for new languages, like, okay, how performant does O, and you will get a lot of people saying, oh, Rust is better, and you look into Rust, and then you get people saying C is better, so you get into this rabbit hole, but in the end, you could almost make like an Excel sheet, map all the properties, find the ones that matter to you, and Bob's your uncle, that's the language you will use. Of course, there's a strong level of preference there as well, but in very high terms, I think the kind of lower level-ish languages would be used a lot for malware development, right? Especially if you need all the control you can get, then this is the classical choice. I think this is the less classical choice for real malware development, but again, if you're writing something that doesn't need to run on a victim system, or it's not necessarily malware, then I think something like Go or even Python are excellent choices. So let's give a couple of examples of languages. I only have half an hour today, so I picked two. You can already guess that the first one is Rust, right, because I did want to address some of the hype, what's true and what's not true about the hype. So Rust is a very interesting language, right? It's kind of jumping in the successor spot of C, even though C is still around a lot. Rust is


chunk_text:
  you could almost make like an Excel sheet, map all the properties, find the ones that matter to you, and Bob's your uncle, that's the language you will use. Of course, there's a strong level of preference there as well, but in very high terms, I think the kind of lower level-ish languages would be used a lot for malware development, right? Especially if you need all the control you can get, then this is the classical choice. I think this is the less classical choice for real malware development, but again, if you're writing something that doesn't need to run on a victim system, or it's not necessarily malware, then I think something like Go or even Python are excellent choices. So let's give a couple of examples of languages. I only have half an hour today, so I picked two. You can already guess that the first one is Rust, right, because I did want to address some of the hype, what's true and what's not true about the hype. So Rust is a very interesting language, right? It's kind of jumping in the successor spot of C, even though C is still around a lot. Rust is trying to be safe C, right? So it's giving you all these tools, a very strong and strict compiler that's helping you write low-level code that's also safe. Now, the safety doesn't always matter that much for us malware developers, and that has some implications on the code that we write, because we will need to use a lot of unsafe clauses, but I think for anything else, it's really interesting, because that part about stability of security, Rust kind of solves intrinsically. It doesn't solve everything, don't get me wrong. It solves a lot of commonly made errors. It solves by using this mechanism that we call the borrow checker. The borrow checker is essentially just a tool that checks who is the owner of certain data at a certain time. That's like the easiest way to summarize it. Definitely won't get into all the rules of the borrow checker here, but what it means is essentially at compile time, or if you're using linters or whatever, then even before, it will look at who's the owner of certain variables and if it's not moving in a way that it shouldn't be. So it's not being accessed by another


chunk_text:
  trying to be safe C, right? So it's giving you all these tools, a very strong and strict compiler that's helping you write low-level code that's also safe. Now, the safety doesn't always matter that much for us malware developers, and that has some implications on the code that we write, because we will need to use a lot of unsafe clauses, but I think for anything else, it's really interesting, because that part about stability of security, Rust kind of solves intrinsically. It doesn't solve everything, don't get me wrong. It solves a lot of commonly made errors. It solves by using this mechanism that we call the borrow checker. The borrow checker is essentially just a tool that checks who is the owner of certain data at a certain time. That's like the easiest way to summarize it. Definitely won't get into all the rules of the borrow checker here, but what it means is essentially at compile time, or if you're using linters or whatever, then even before, it will look at who's the owner of certain variables and if it's not moving in a way that it shouldn't be. So it's not being accessed by another function that's not the owner of it. There's no race conditions about the data. All kinds of stuff like this are being checked by this borrow checker. We will have an example about what this looks like. Important to mention is that there's no garbage collection, so other languages like Go, for example, they have a garbage collector, so that's like a part of the runtime that comes in once in a while, checks is this variable still used, no, cleans it up, but that borrow checker has a performance impact, so it's actually bad for real-time or embedded applications. Rust does not have that, so that's an advantage performance-wise. Another advantage is that it gives you really verbose errors, like if you did something stupid, it will literally say you did something stupid here in this line at this character and fix it in this way. So a lot of those issues are usually fixable very easily, and it's very well adopted. There's a mature ecosystem. It's used a lot now. Here's some examples to get you started. The slides, by the way, with links are on my GitHub if you want to click the links instead of taking


chunk_text:
  function that's not the owner of it. There's no race conditions about the data. All kinds of stuff like this are being checked by this borrow checker. We will have an example about what this looks like. Important to mention is that there's no garbage collection, so other languages like Go, for example, they have a garbage collector, so that's like a part of the runtime that comes in once in a while, checks is this variable still used, no, cleans it up, but that borrow checker has a performance impact, so it's actually bad for real-time or embedded applications. Rust does not have that, so that's an advantage performance-wise. Another advantage is that it gives you really verbose errors, like if you did something stupid, it will literally say you did something stupid here in this line at this character and fix it in this way. So a lot of those issues are usually fixable very easily, and it's very well adopted. There's a mature ecosystem. It's used a lot now. Here's some examples to get you started. The slides, by the way, with links are on my GitHub if you want to click the links instead of taking pictures. So that's something you could do. One thing that I really liked about Rust is the fact that there's quite a mature linter, which we call Clippy. So Clippy has a pedantic mode where it gets really uptight about everything that you're doing. I found that really nice when first developing Rust because it also checks are you writing well-structured code, are you writing idiomatic code, stuff like this. It really helps you pick up the language. So if you give Rust a spin, I would advise to use Clippy. If you're up for it, put it in pedantic mode. There's also easier going modes, but it really helps write the code. So here's an example. We will go through it part by part. In this example, we are not only using the standard library. This example is actually some code that shows a message box with okay or cancel a couple of times, so really, really basic. So we use the Win32 library. That's actually a Microsoft-built library because, of course, they're also using Rust in Windows now. So that's quite mature. There's two variants. There's one that's literally just the API wrappers, or there's a more Rustified


chunk_text:
  pictures. So that's something you could do. One thing that I really liked about Rust is the fact that there's quite a mature linter, which we call Clippy. So Clippy has a pedantic mode where it gets really uptight about everything that you're doing. I found that really nice when first developing Rust because it also checks are you writing well-structured code, are you writing idiomatic code, stuff like this. It really helps you pick up the language. So if you give Rust a spin, I would advise to use Clippy. If you're up for it, put it in pedantic mode. There's also easier going modes, but it really helps write the code. So here's an example. We will go through it part by part. In this example, we are not only using the standard library. This example is actually some code that shows a message box with okay or cancel a couple of times, so really, really basic. So we use the Win32 library. That's actually a Microsoft-built library because, of course, they're also using Rust in Windows now. So that's quite mature. There's two variants. There's one that's literally just the API wrappers, or there's a more Rustified version, which is this variant. Then we enter the main loop, and there's a couple of interesting things happening here. So first off, you see the kind of error handling that Rust has. Rust has a very specific error handling mechanism where you usually return a result. A result can either be okay or error, and then at the end of the function, you return the okay. If it's not okay, you return the error. This doesn't look like much, but it actually allows a lot of subfunctions to look at this result of another function and verify if it did what you wanted. If you're returning a result, you can also return upstream errors in this way by using the question mark operator. So it doesn't always have to be super verbose. It is sometimes, because Rust is just a verbose language. And another interesting point is that everything in Rust is immutable by default. So if you want a mutable variable, a variable that you need to edit, you actually have to specify that it's mutable. Again, it doesn't seem like much, but this has huge implications in the logic that Rust uses to check if you're not


chunk_text:
  version, which is this variant. Then we enter the main loop, and there's a couple of interesting things happening here. So first off, you see the kind of error handling that Rust has. Rust has a very specific error handling mechanism where you usually return a result. A result can either be okay or error, and then at the end of the function, you return the okay. If it's not okay, you return the error. This doesn't look like much, but it actually allows a lot of subfunctions to look at this result of another function and verify if it did what you wanted. If you're returning a result, you can also return upstream errors in this way by using the question mark operator. So it doesn't always have to be super verbose. It is sometimes, because Rust is just a verbose language. And another interesting point is that everything in Rust is immutable by default. So if you want a mutable variable, a variable that you need to edit, you actually have to specify that it's mutable. Again, it doesn't seem like much, but this has huge implications in the logic that Rust uses to check if you're not making a mistake. Then we go to the actual Windows API call. Again, we see the error handling. This time we have a result that contains an option. So an option is either something, some value or none. Again, having this type just gives you the option to verify whether you actually got a result. It's a bit more sturdy than just using the none in value in Python, for example, in terms of typing. And then you see here you have all the okay results with a value or you return the error and that error would be handled by the question mark by the caller. Here's the dreaded unsafe block. I wanted to show that unsafe is not necessarily bad, right? Because Rust often gets ridiculed a bit in the malware development space where the unsafe is just one big unsafe block. But if you use it properly, it's just a contract that says, okay, here I'm becoming responsible for the potential unsafety of whatever I'm calling within. That's just what Rust is telling you to do because in this block, the compiler cannot guarantee safety anymore, so you need to think about, okay, is this the white


chunk_text:
  making a mistake. Then we go to the actual Windows API call. Again, we see the error handling. This time we have a result that contains an option. So an option is either something, some value or none. Again, having this type just gives you the option to verify whether you actually got a result. It's a bit more sturdy than just using the none in value in Python, for example, in terms of typing. And then you see here you have all the okay results with a value or you return the error and that error would be handled by the question mark by the caller. Here's the dreaded unsafe block. I wanted to show that unsafe is not necessarily bad, right? Because Rust often gets ridiculed a bit in the malware development space where the unsafe is just one big unsafe block. But if you use it properly, it's just a contract that says, okay, here I'm becoming responsible for the potential unsafety of whatever I'm calling within. That's just what Rust is telling you to do because in this block, the compiler cannot guarantee safety anymore, so you need to think about, okay, is this the white variant? I need to give it a white string, right? Stuff like this you need to think about so it actually makes it quite explicit. And then you have a standard match clause which returns the result. The other example that I wanted to give is Go. Sorry, guys, I'm running a little bit over time here, but I'll take a couple minutes more. Go, I think, is very interesting because it's both really useful on the target system as compiled binaries, .exes, for example, as well as on the server. Go is very performant. It has a very good concurrency mechanism that we'll have a quick look at in a bit. It has a really good standard library. There's packages for everything that you can imagine. And the syntax is actually really simple. So I would argue that Go is almost as easy to learn as Python, and it gives you these advantages of a really portable and performant compiled language, right, because Python clearly has some performance issues, and that's where Go is really valuable. So another example here which we'll go through quickly, we see some packages being imported. You see the formatting and networking, synchronization. This


chunk_text:
  variant? I need to give it a white string, right? Stuff like this you need to think about so it actually makes it quite explicit. And then you have a standard match clause which returns the result. The other example that I wanted to give is Go. Sorry, guys, I'm running a little bit over time here, but I'll take a couple minutes more. Go, I think, is very interesting because it's both really useful on the target system as compiled binaries, .exes, for example, as well as on the server. Go is very performant. It has a very good concurrency mechanism that we'll have a quick look at in a bit. It has a really good standard library. There's packages for everything that you can imagine. And the syntax is actually really simple. So I would argue that Go is almost as easy to learn as Python, and it gives you these advantages of a really portable and performant compiled language, right, because Python clearly has some performance issues, and that's where Go is really valuable. So another example here which we'll go through quickly, we see some packages being imported. You see the formatting and networking, synchronization. This is all standard library, so despite the fact that it has import, it means just that it's importing it from the standard library, so you don't need to install anything to use this. And then this code is essentially a very concurrent port scanner in just I think it's like 30 lines of code. So what we're doing here is just, well, preparing the port scan, right? We're not doing any argument parsing or stuff like that, but the key call here is actually the Go keyword, because with the Go keyword, that means you're starting a Go routine, and Go routine is Go's implementation of concurrency. Essentially this call means that we're calling this function, which is this one, we'll take a look at that in just a minute, and it's starting it concurrently. So it's just starting a background job essentially, and continuing with the rest of the loop. So what we're doing here is starting 1024 instances of this scan port function. Now to manage that concurrency, we're using something that's called a wait group. Essentially it's just a counter that says, okay, we go up to 1024 in this case, and then whenever every instance is


chunk_text:
  is all standard library, so despite the fact that it has import, it means just that it's importing it from the standard library, so you don't need to install anything to use this. And then this code is essentially a very concurrent port scanner in just I think it's like 30 lines of code. So what we're doing here is just, well, preparing the port scan, right? We're not doing any argument parsing or stuff like that, but the key call here is actually the Go keyword, because with the Go keyword, that means you're starting a Go routine, and Go routine is Go's implementation of concurrency. Essentially this call means that we're calling this function, which is this one, we'll take a look at that in just a minute, and it's starting it concurrently. So it's just starting a background job essentially, and continuing with the rest of the loop. So what we're doing here is starting 1024 instances of this scan port function. Now to manage that concurrency, we're using something that's called a wait group. Essentially it's just a counter that says, okay, we go up to 1024 in this case, and then whenever every instance is done, we decrement one, and this wait call is just blocking until all the processes are done. So the actual scanner implementation is also really simple. One thing that I wanted to highlight is the defer call, which is quite nice. It means call this whenever the scope ends, so either when the function exits, we call it, or when an unexpected error occurs. So just a really clean way to do your cleanup, stuff like that, and also the cleanup in case of errors, which is not usually the case. And then you have the error handling, which can be quite verbose in Go. Usually you would see something like this, but the inverse, so if the error is not nil, then we do some error management. Other than that, this just scans a single port, so the result again in 30 lines is a MMOP for poor people. So that's actually all I had to say today. Again, the call to action would be, please look into every language you can get your hands on, play with it, adhere a little bit as best as you can to good developer practice, build your own tools, and yeah, remember


chunk_text:
  done, we decrement one, and this wait call is just blocking until all the processes are done. So the actual scanner implementation is also really simple. One thing that I wanted to highlight is the defer call, which is quite nice. It means call this whenever the scope ends, so either when the function exits, we call it, or when an unexpected error occurs. So just a really clean way to do your cleanup, stuff like that, and also the cleanup in case of errors, which is not usually the case. And then you have the error handling, which can be quite verbose in Go. Usually you would see something like this, but the inverse, so if the error is not nil, then we do some error management. Other than that, this just scans a single port, so the result again in 30 lines is a MMOP for poor people. So that's actually all I had to say today. Again, the call to action would be, please look into every language you can get your hands on, play with it, adhere a little bit as best as you can to good developer practice, build your own tools, and yeah, remember that new languages are not as hard to pick up as the first language that you ever picked up. Thank you very much.


chunk_text:
  that new languages are not as hard to pick up as the first language that you ever picked up. Thank you very much.


chunk_text:
  { "webpage_url": "https://www.youtube.com/watch?v=T92verdYJAQ", "title": "Attacking Primary Refresh Tokens Using Their MacOS Implementation - Dirk-Jan Mollema & Olaf Hartong", "description": "", "channel_url": "https://www.youtube.com/channel/UCgJoGNj3B2Mt2F3TUblcoOA", "duration": 2360, "channel": "OrangeCon", "uploader": "OrangeCon", "upload_date": "20240909" } This text was transcribed using whisper model: large-v2 Welcome to our story. So we spent quite some time on building slides, fortunately we're not the only ones having cool slides, so that's cool. So we have a couple of topics to talk about. So first of all, we're going to explain a little bit what primary refresh tokens are and how they are used. We're going to explain a little bit more about the new protocol versions that we found during our research that may be different than the Microsoft website. So yes, they're not even documented. Then we're going to highlight the secure enclave a little bit, which is basically the TPM implementation on macOS. We're not going to drop zero days. At least, we didn't even think we had a zero day up until we submitted it to Microsoft and then they wanted to have a phone call. So it turns out it was, in their opinion, a critical one, so we can't demo and explain everything. We're going to show you some stuff that still works and is interesting, but not everything until it's patched, which is probably somewhere next year, maybe. And that's primarily because it involves all operating systems and implementations there, so that's complicating it a little bit for them. So I'm Olaf. Of course, I like Warm Hugs, thanks to Disney, and I'm a security researcher and detection engineer at Falcon Force, and I'm on Twitter, and I'm joined with Dirk-Jan. Hi, I'm Dirk-Jan. I have my own company called Outsider Security. I've been doing that for two and a half years. I like to research weird protocols, well, not so weird protocols, maybe all of the things are standardized. I like diving into basically all the modern Microsoft products, been researching Anthra since four or five years, when it was still called the good old Azure AD. I also have a Twitter account. If you want to keep up with the new research that I'm publishing there, you're more than welcome to. So actually, our story started quite a while ago, because we were talking about primary freeze tokens, and Olaf was like, well, you're talking about Windows, but I also


chunk_text:
  We're going to show you some stuff that still works and is interesting, but not everything until it's patched, which is probably somewhere next year, maybe. And that's primarily because it involves all operating systems and implementations there, so that's complicating it a little bit for them. So I'm Olaf. Of course, I like Warm Hugs, thanks to Disney, and I'm a security researcher and detection engineer at Falcon Force, and I'm on Twitter, and I'm joined with Dirk-Jan. Hi, I'm Dirk-Jan. I have my own company called Outsider Security. I've been doing that for two and a half years. I like to research weird protocols, well, not so weird protocols, maybe all of the things are standardized. I like diving into basically all the modern Microsoft products, been researching Anthra since four or five years, when it was still called the good old Azure AD. I also have a Twitter account. If you want to keep up with the new research that I'm publishing there, you're more than welcome to. So actually, our story started quite a while ago, because we were talking about primary freeze tokens, and Olaf was like, well, you're talking about Windows, but I also have a Mac here, and I don't know how it works over there. I was like, well, I don't know how Mac works, so maybe we can do it together, and Olaf knows how Mac works, and I know a thing or two about tokens, and we did that, like, in the end of 2022. We found some interesting protocol versions. We worked on implementing them, and then we were kind of laying it, or we left it around for a while. Basically, we're both quite busy. We don't see each other every week, so we decided to submit it for a conference, and at that point, the talk was accepted, so we were like, well, now we kind of need to finalize it, make these slides and stuff. So then we basically wrapped up the research in April or May of this year, and then we found out that actually Microsoft released a completely new version, like, two weeks before we looked at it again, so we could kind of go back to square one and look at the new protocol version, which was entirely different from anything we've seen before. So this is also where we found out


chunk_text:
  have a Mac here, and I don't know how it works over there. I was like, well, I don't know how Mac works, so maybe we can do it together, and Olaf knows how Mac works, and I know a thing or two about tokens, and we did that, like, in the end of 2022. We found some interesting protocol versions. We worked on implementing them, and then we were kind of laying it, or we left it around for a while. Basically, we're both quite busy. We don't see each other every week, so we decided to submit it for a conference, and at that point, the talk was accepted, so we were like, well, now we kind of need to finalize it, make these slides and stuff. So then we basically wrapped up the research in April or May of this year, and then we found out that actually Microsoft released a completely new version, like, two weeks before we looked at it again, so we could kind of go back to square one and look at the new protocol version, which was entirely different from anything we've seen before. So this is also where we found out the new version, coded it, reported it to Microsoft, and also added the support for the tools for it, and now we can talk about most of it, but again, some of the stuff is still being worked at by Microsoft, and we wrapped this up in this nice little storybook. Yeah, so of course, every story needs some characters, right? So we have our quick fish Quinn, who's implementing codes, that may be us, or that may be Microsoft, that's not that relevant now. Then we have our main character, probably, who is the pathfinder that actually wants to navigate and try to find all the nice paths that we can actually utilize. Then we have Sir Block a lot, he wants to build dams because he wants to protect everything or keep stuff from leaking, and then we have our kingfisher, who actually loves fishing, of course. So from there, we started a lot of research. There is some prior research that we encountered, sort of after we found our own stuff and started Googling, if other people did, Thomas Nauenheim from Gluconia, he is also quite a really good researcher. He found some stuff, how to replace


chunk_text:
  the new version, coded it, reported it to Microsoft, and also added the support for the tools for it, and now we can talk about most of it, but again, some of the stuff is still being worked at by Microsoft, and we wrapped this up in this nice little storybook. Yeah, so of course, every story needs some characters, right? So we have our quick fish Quinn, who's implementing codes, that may be us, or that may be Microsoft, that's not that relevant now. Then we have our main character, probably, who is the pathfinder that actually wants to navigate and try to find all the nice paths that we can actually utilize. Then we have Sir Block a lot, he wants to build dams because he wants to protect everything or keep stuff from leaking, and then we have our kingfisher, who actually loves fishing, of course. So from there, we started a lot of research. There is some prior research that we encountered, sort of after we found our own stuff and started Googling, if other people did, Thomas Nauenheim from Gluconia, he is also quite a really good researcher. He found some stuff, how to replace some of the PRTs that he found on his Mac, and he wrote that up, so it's definitely worth looking at this blog. Just to get everybody in the same mindset, we want to kind of highlight the basics of the PRTs. We're not going to explain everything because we don't want to fry your brain too much, but essentially how tokens and authentication works on unmanaged Windows hosts, that's quite important. So we have our user, and our user wants Teams access, right? So he signs into Teams, Teams will actually request tokens from EnterID, which will be an access token and a refresh token, and then uses that refresh token against Entra again to get access tokens to the Teams backend, and maybe other access tokens to Exchange and SharePoint. And it's important to note the difference where a refresh token can request an access token, and an access token is only for one specific use. Yes, so this is on unmanaged hosts, and these are basically the standard OAuth protocols. However, if you are on a managed Windows device, then the flow gets a little bit more complicated, because we don't want to sign users into each


chunk_text:
  some of the PRTs that he found on his Mac, and he wrote that up, so it's definitely worth looking at this blog. Just to get everybody in the same mindset, we want to kind of highlight the basics of the PRTs. We're not going to explain everything because we don't want to fry your brain too much, but essentially how tokens and authentication works on unmanaged Windows hosts, that's quite important. So we have our user, and our user wants Teams access, right? So he signs into Teams, Teams will actually request tokens from EnterID, which will be an access token and a refresh token, and then uses that refresh token against Entra again to get access tokens to the Teams backend, and maybe other access tokens to Exchange and SharePoint. And it's important to note the difference where a refresh token can request an access token, and an access token is only for one specific use. Yes, so this is on unmanaged hosts, and these are basically the standard OAuth protocols. However, if you are on a managed Windows device, then the flow gets a little bit more complicated, because we don't want to sign users into each app individually, have each app manage their own tokens, have everything asynchronously sign out, all that kind of things. So on Windows, the user doesn't sign into apps, they actually sign into the device. And that means that when they sign in, LSAS will take those credentials, and LSAS is going to request our primary refresh token, and the primary refresh token is a single sign-on token. So once that is in our session, it will be valid to sign in to basically anything that's also running on our device. So if the user starts Teams, and Teams in this case is acting as a OAuth client, Teams will actually ask the broker for some tokens. So in this case, Teams is not directly authenticating to Entra, it's actually asking the broker to do that on Windows or on other operating systems, because they also work with a token broker. And the token broker is asking LSAS, hey, can I use this PRT? LSAS is going to do some cryptography, and it's going to actually send the correct PRT, basically assertion, so something that's signed by LSAS. That's being used to talk to Entra, Entra gives out the tokens, the


chunk_text:
  app individually, have each app manage their own tokens, have everything asynchronously sign out, all that kind of things. So on Windows, the user doesn't sign into apps, they actually sign into the device. And that means that when they sign in, LSAS will take those credentials, and LSAS is going to request our primary refresh token, and the primary refresh token is a single sign-on token. So once that is in our session, it will be valid to sign in to basically anything that's also running on our device. So if the user starts Teams, and Teams in this case is acting as a OAuth client, Teams will actually ask the broker for some tokens. So in this case, Teams is not directly authenticating to Entra, it's actually asking the broker to do that on Windows or on other operating systems, because they also work with a token broker. And the token broker is asking LSAS, hey, can I use this PRT? LSAS is going to do some cryptography, and it's going to actually send the correct PRT, basically assertion, so something that's signed by LSAS. That's being used to talk to Entra, Entra gives out the tokens, the broker gives the tokens to Teams, and that is how Teams basically can access all of its services that it needs to do. So instead of Teams doing the refresh token dance directly, it's asking LSAS to use the PRT, and in that way, it can do the same thing as any other app can do in our session. So just some facts about these primary refresh tokens. We're going to cover this in the whole talk, so this is kind of important. So primary refresh tokens are single sign-on tokens. So once you have one of these, you can sign in to anything that your account can also sign in. It can be a native app, it can be like a CLI, basically it is a true single sign-on token. The primary refresh token is also the mechanism in which a user identity is linked to a device identity. So if you are familiar with how Microsoft 365 works, very often you see conditional access policies that require a certain device state, like the device being compliant or hybrid joint, and that is also done through the same primary refresh token mechanism. So the primary refresh token is tied


chunk_text:
  broker gives the tokens to Teams, and that is how Teams basically can access all of its services that it needs to do. So instead of Teams doing the refresh token dance directly, it's asking LSAS to use the PRT, and in that way, it can do the same thing as any other app can do in our session. So just some facts about these primary refresh tokens. We're going to cover this in the whole talk, so this is kind of important. So primary refresh tokens are single sign-on tokens. So once you have one of these, you can sign in to anything that your account can also sign in. It can be a native app, it can be like a CLI, basically it is a true single sign-on token. The primary refresh token is also the mechanism in which a user identity is linked to a device identity. So if you are familiar with how Microsoft 365 works, very often you see conditional access policies that require a certain device state, like the device being compliant or hybrid joint, and that is also done through the same primary refresh token mechanism. So the primary refresh token is tied to a user and also tied to a device. Now a primary refresh token is obviously very powerful, so that's why it needs a session key to operate. So that's like a cryptographic key that proves that we are authorized to use this primary refresh token, and the session keys, because they are so sensitive, they will be protected by a trusted platform module on Windows, secure enclave on macOS, as we'll see in a little bit, and it also binds the PRT to a device. So even if your system, on a modern Windows device, you'll not be able to steal these kind of tokens. So because PRTs are single sign-on tokens, they fit kind of in this token hierarchy. So at the top we have a primary refresh token, of which we only have like one or two, and with primary refresh tokens we can request regular refresh tokens or access tokens. Refresh tokens are there per app, and access tokens are there per service that each app is accessing, so we have more access tokens than refresh tokens, and we have more refresh tokens than primary refresh tokens. So there's also a few protocol versions. On Windows,


chunk_text:
  to a user and also tied to a device. Now a primary refresh token is obviously very powerful, so that's why it needs a session key to operate. So that's like a cryptographic key that proves that we are authorized to use this primary refresh token, and the session keys, because they are so sensitive, they will be protected by a trusted platform module on Windows, secure enclave on macOS, as we'll see in a little bit, and it also binds the PRT to a device. So even if your system, on a modern Windows device, you'll not be able to steal these kind of tokens. So because PRTs are single sign-on tokens, they fit kind of in this token hierarchy. So at the top we have a primary refresh token, of which we only have like one or two, and with primary refresh tokens we can request regular refresh tokens or access tokens. Refresh tokens are there per app, and access tokens are there per service that each app is accessing, so we have more access tokens than refresh tokens, and we have more refresh tokens than primary refresh tokens. So there's also a few protocol versions. On Windows, basically what we have is PRT version 2, and Windows is of course the platform that is fully controlled by Microsoft, so they can make it in any way they want. But on other operating systems, they don't have all the same controls. They sometimes have to rely a bit on what the operating system offers. So especially on macOS, they had to kind of roll with whatever implementation Apple was doing and not have their own full control. So to accommodate that, they made a PRT version 3, and they also introduced a new PRT version that's actually not tied to a device. So how does the device actually get a PRT in the first place? And this is all, again, going to be related to a lot of crypto, so whenever a device is registered in Entra, it's going to generate a private key. It's going to generate a public key based on that private key, and those are RSA keys. With these keys, it's going to do the device registration, which means that the device will get a certificate, and it's also getting a transport key for extra security during the transport. This is very similar on


chunk_text:
  basically what we have is PRT version 2, and Windows is of course the platform that is fully controlled by Microsoft, so they can make it in any way they want. But on other operating systems, they don't have all the same controls. They sometimes have to rely a bit on what the operating system offers. So especially on macOS, they had to kind of roll with whatever implementation Apple was doing and not have their own full control. So to accommodate that, they made a PRT version 3, and they also introduced a new PRT version that's actually not tied to a device. So how does the device actually get a PRT in the first place? And this is all, again, going to be related to a lot of crypto, so whenever a device is registered in Entra, it's going to generate a private key. It's going to generate a public key based on that private key, and those are RSA keys. With these keys, it's going to do the device registration, which means that the device will get a certificate, and it's also getting a transport key for extra security during the transport. This is very similar on macOS, so the biggest difference is that on Windows, it's going to send this as a bcrypt RSA blob, which is like a Windows internal structure, and on macOS, it's actually using this JSON web key standard, which means that the RSA key is presented as a JSON structure. And the specifications for this are written by somebody who used to work at Microsoft called Michael Jones. We'll see his name a few more times because he's involved a lot in all of these OAuth or all the other specifications surrounding this. So how does a PRT work on Windows schematically? So whatever we do, we start with some kind of authentication material. It can be a password, it can be something like a FIDO key, and with that, we authenticate to our Windows device, and at this point, our Windows device will send a signed payload to Entra. So it's signed with the private key of the device. We prove that it's actually this device that is issuing this PRT request. The device then receives a primary refresh token and a transport key encrypted session key. So the session key is not in plain text, it's actually encrypted with


chunk_text:
  macOS, so the biggest difference is that on Windows, it's going to send this as a bcrypt RSA blob, which is like a Windows internal structure, and on macOS, it's actually using this JSON web key standard, which means that the RSA key is presented as a JSON structure. And the specifications for this are written by somebody who used to work at Microsoft called Michael Jones. We'll see his name a few more times because he's involved a lot in all of these OAuth or all the other specifications surrounding this. So how does a PRT work on Windows schematically? So whatever we do, we start with some kind of authentication material. It can be a password, it can be something like a FIDO key, and with that, we authenticate to our Windows device, and at this point, our Windows device will send a signed payload to Entra. So it's signed with the private key of the device. We prove that it's actually this device that is issuing this PRT request. The device then receives a primary refresh token and a transport key encrypted session key. So the session key is not in plain text, it's actually encrypted with the transport key, which also ties it to our 3PM, so it's actually tied to the hardware of the device. Once we have this session key, then we can start using the primary refresh token. So we sign a payload with the session key, we send that to Entra, then Entra is going to give us a token for a specific app, for example, for Teams. But again, this is going to be encrypted, and it's going to use the session key to decrypt that payload. It's going to be encrypted with a standard called JWE, or JSON Web Encryption. So it's related to the JSON Web Token standard, but it's actually encrypted. So that's how it works on Windows. On macOS, however, it's quite a bit more complicated. And you see in this slide, on the top right, there is this little sunny symbol. And this you'll see on a few more slides, and it essentially means that this is one of the key slides of this talk. So there's quite a few complex things here in the presentation, but if you need to remember a few slides, it must be these slides. So pay attention there, the rest


chunk_text:
  the transport key, which also ties it to our 3PM, so it's actually tied to the hardware of the device. Once we have this session key, then we can start using the primary refresh token. So we sign a payload with the session key, we send that to Entra, then Entra is going to give us a token for a specific app, for example, for Teams. But again, this is going to be encrypted, and it's going to use the session key to decrypt that payload. It's going to be encrypted with a standard called JWE, or JSON Web Encryption. So it's related to the JSON Web Token standard, but it's actually encrypted. So that's how it works on Windows. On macOS, however, it's quite a bit more complicated. And you see in this slide, on the top right, there is this little sunny symbol. And this you'll see on a few more slides, and it essentially means that this is one of the key slides of this talk. So there's quite a few complex things here in the presentation, but if you need to remember a few slides, it must be these slides. So pay attention there, the rest you can sort of sleep or read them afterwards. And basically on macOS, the procedure looks as follows. So we still log in, so we use our credentials to authenticate. And in this case, it's not going to directly send that to Entra, but it's actually following the authorization code flow, which is standard OAuth flow. This case is using that for this specific client, and it's actually sending an on-the-fly generated transport key to Entra. So there's no device yet at this point. We haven't registered our device yet. Which means that the primary refresh token that we receive is not going to be bound to a device. After that, it's actually going to register the device, so now we have a device. Then it's sending the first PRT, plus a payload that is signed with the private key of our device. So we prove now that this was requested by a real device, we send that to Entra. Then we get back a new PRT, and this is called a device-bound PRT, because it's linked to our device. Plus, again, a session key that is encrypted with our transport key. And with that, we can again request tokens.


chunk_text:
  you can sort of sleep or read them afterwards. And basically on macOS, the procedure looks as follows. So we still log in, so we use our credentials to authenticate. And in this case, it's not going to directly send that to Entra, but it's actually following the authorization code flow, which is standard OAuth flow. This case is using that for this specific client, and it's actually sending an on-the-fly generated transport key to Entra. So there's no device yet at this point. We haven't registered our device yet. Which means that the primary refresh token that we receive is not going to be bound to a device. After that, it's actually going to register the device, so now we have a device. Then it's sending the first PRT, plus a payload that is signed with the private key of our device. So we prove now that this was requested by a real device, we send that to Entra. Then we get back a new PRT, and this is called a device-bound PRT, because it's linked to our device. Plus, again, a session key that is encrypted with our transport key. And with that, we can again request tokens. So you see that there's essentially two different primary refresh tokens involved. There is this first primary refresh token that's actually not linked to a device, because the device registration happens afterwards. And there's a second primary refresh token that is actually device-bound, and it is linked to our macOS device specifically. And this is all possible with the PRT protocol version 3. Yeah, so the biggest difference here, and I think my mic is at some point joining, is two implementations that we actually looked at. So this is back in 2022, when version 4 wasn't a thing yet. Basically, we started with Edge. So Edge on Mac allows you to sign in and then join the tenant that you're a part of, only for Edge. And then you have SSO within Edge for all the things that you want to access, right? So that's where the device-less PRT first came on our radar. The second version is if you want to be a little bit more in control of your Mac users and manage them, actually, you can use Intune. There's other products, of course. And for this, Microsoft built their own SSO extension that you need to


chunk_text:
  So you see that there's essentially two different primary refresh tokens involved. There is this first primary refresh token that's actually not linked to a device, because the device registration happens afterwards. And there's a second primary refresh token that is actually device-bound, and it is linked to our macOS device specifically. And this is all possible with the PRT protocol version 3. Yeah, so the biggest difference here, and I think my mic is at some point joining, is two implementations that we actually looked at. So this is back in 2022, when version 4 wasn't a thing yet. Basically, we started with Edge. So Edge on Mac allows you to sign in and then join the tenant that you're a part of, only for Edge. And then you have SSO within Edge for all the things that you want to access, right? So that's where the device-less PRT first came on our radar. The second version is if you want to be a little bit more in control of your Mac users and manage them, actually, you can use Intune. There's other products, of course. And for this, Microsoft built their own SSO extension that you need to install. And this will actually generate that device-bound PRT that you saw in the previous slides. So if we would go back, so that left bit, the PRT plus the transport key only, that's basically the device-less version, which will be used by Edge. The bottom one over here will be used by Intune. So there are two different PRTs. Sometimes they might still live on the same system. So that's something, if you're a techer, that could be interesting to look at, because they are differently protected. In our discussions with Microsoft, we also learned that there are other platforms doing similar stuff, like Android, iOS, all kinds of other obscure OSes, maybe, as well. But we didn't really look at it, because we were already distracted enough by this. So on Edge, if you start logging on as a user in Edge, so not via the browsing methodology, but for the application itself, you would see a similar flow, as you would see from a lot of other OAuth flows. But you also get a PRT back. So basically, how that works, as Stirkjohn explained earlier, is you log on, you get an authorization code, which you receive


chunk_text:
  install. And this will actually generate that device-bound PRT that you saw in the previous slides. So if we would go back, so that left bit, the PRT plus the transport key only, that's basically the device-less version, which will be used by Edge. The bottom one over here will be used by Intune. So there are two different PRTs. Sometimes they might still live on the same system. So that's something, if you're a techer, that could be interesting to look at, because they are differently protected. In our discussions with Microsoft, we also learned that there are other platforms doing similar stuff, like Android, iOS, all kinds of other obscure OSes, maybe, as well. But we didn't really look at it, because we were already distracted enough by this. So on Edge, if you start logging on as a user in Edge, so not via the browsing methodology, but for the application itself, you would see a similar flow, as you would see from a lot of other OAuth flows. But you also get a PRT back. So basically, how that works, as Stirkjohn explained earlier, is you log on, you get an authorization code, which you receive from that flow. It will on-the-fly generate that RSA key, and it will receive a primary refresh token back from the Entra portal with the session key, right? And from there, it will actually start using that, which is RSA encrypted, and you get like all these tokens back. And then from there, it will actually start, you can actually start utilizing this. So yeah, as I just mentioned, the PRT v3 flow for this is fairly similar to how it works on Windows, with probably the biggest distinction where macOS for the PRT v3 flow, it will store it in the keychain together with the session key, as I'll show you in a second, whereas on Windows, it will be used with the DPM if you have one. But the response is equally encrypted, and it has a session key to actually allow you to prove that you have access to it. And this is just a screenshot of how it looks. On the keychain, as I mentioned, it's stored in your local keychain. If you have an iCloud-enabled account, it will be in your iCloud, which has additional risks, of course, if you can imagine if you get


chunk_text:
  from that flow. It will on-the-fly generate that RSA key, and it will receive a primary refresh token back from the Entra portal with the session key, right? And from there, it will actually start using that, which is RSA encrypted, and you get like all these tokens back. And then from there, it will actually start, you can actually start utilizing this. So yeah, as I just mentioned, the PRT v3 flow for this is fairly similar to how it works on Windows, with probably the biggest distinction where macOS for the PRT v3 flow, it will store it in the keychain together with the session key, as I'll show you in a second, whereas on Windows, it will be used with the DPM if you have one. But the response is equally encrypted, and it has a session key to actually allow you to prove that you have access to it. And this is just a screenshot of how it looks. On the keychain, as I mentioned, it's stored in your local keychain. If you have an iCloud-enabled account, it will be in your iCloud, which has additional risks, of course, if you can imagine if you get phished on that. And basically, it is protected, so you can show password, and then you get a password prompt. So you still need to have the user password if you are attacking this user. But usually you can phish for that, right? And then you get this JSON blob that you see in there. And if you would look at that, you would see the secret, which is your PRT, and then the session key, where you can basically start using this, so you can start replaying this. I forgot to click. Of course, you can build road tools and road DX, so we can also use this to actually get our tokens this way. And of course, this is very sensitive, so it's a very hard thing to do. This is probably the biggest OST that we're going to release for you today. Everybody can copy-paste, of course. So in Windows, it's tied to all kinds of hardware capabilities. On macOS, it's just like in the key chain, it just says session key. You copy-paste it out on any device that you want, and then it also works there. So you can just copy-paste the single sign-on out


chunk_text:
  phished on that. And basically, it is protected, so you can show password, and then you get a password prompt. So you still need to have the user password if you are attacking this user. But usually you can phish for that, right? And then you get this JSON blob that you see in there. And if you would look at that, you would see the secret, which is your PRT, and then the session key, where you can basically start using this, so you can start replaying this. I forgot to click. Of course, you can build road tools and road DX, so we can also use this to actually get our tokens this way. And of course, this is very sensitive, so it's a very hard thing to do. This is probably the biggest OST that we're going to release for you today. Everybody can copy-paste, of course. So in Windows, it's tied to all kinds of hardware capabilities. On macOS, it's just like in the key chain, it just says session key. You copy-paste it out on any device that you want, and then it also works there. So you can just copy-paste the single sign-on out to wherever you want. That's the v3 implementation. So we figured this out, and we thought, like, okay, this is how it works. This is where it ends. And then we were just doing it again to see if we could still reproduce it, just to make sure that Microsoft didn't change the implementation. And they did change the implementation. We suddenly saw like pre-RT protocol version 4, and we're like, what is this? Why is this there? So it turns out to be the new platform SSO, and I think you're actually going to talk about the platform SSO here. Yeah, so this is a fairly recent thing. It was in preview for a while. I think they released it maybe three, four months ago, where Intune now has the capability to use the platform SSO module, which is actually leveraging the Apple native SSO extension that runs from the operating system. So this is not Microsoft developed. They're just piggybacking off actual Mac OS implementation. And the cool thing here is this is actually really nice. So they're leveraging this basically through Intune. You can say, okay, I want to use this or that. So you could use


chunk_text:
  to wherever you want. That's the v3 implementation. So we figured this out, and we thought, like, okay, this is how it works. This is where it ends. And then we were just doing it again to see if we could still reproduce it, just to make sure that Microsoft didn't change the implementation. And they did change the implementation. We suddenly saw like pre-RT protocol version 4, and we're like, what is this? Why is this there? So it turns out to be the new platform SSO, and I think you're actually going to talk about the platform SSO here. Yeah, so this is a fairly recent thing. It was in preview for a while. I think they released it maybe three, four months ago, where Intune now has the capability to use the platform SSO module, which is actually leveraging the Apple native SSO extension that runs from the operating system. So this is not Microsoft developed. They're just piggybacking off actual Mac OS implementation. And the cool thing here is this is actually really nice. So they're leveraging this basically through Intune. You can say, okay, I want to use this or that. So you could use the old plugin, or you can now also use the platform extension. And here, it would be actually a similar implementation as Windows has, where they're also utilizing the Mac version of a TPM chip. And that has quite a lot of benefits, and in our research, it kind of looked like that even the Mac implementation looks safer than the Windows one, which is kind of ironic. So in Apple terms, the secure enclave is what would be a TPM. The implementation is similar, slightly different. And because they control the full ecosystem from hardware to software, they have some benefits there where they don't have to make it that compatible with all kinds of CPU vendors. So if you were really into this stuff, I don't understand the half of it, but there is a really good support article on the Apple website that explains in detail how this chip works and how you can interoperate with it. And it's just quite a nifty implementation. So basically, on the Intune site, you can build your own onboarding profiles. And here, you can actually select that use secure enclave key. And that is the new feature that they added.


chunk_text:
  the old plugin, or you can now also use the platform extension. And here, it would be actually a similar implementation as Windows has, where they're also utilizing the Mac version of a TPM chip. And that has quite a lot of benefits, and in our research, it kind of looked like that even the Mac implementation looks safer than the Windows one, which is kind of ironic. So in Apple terms, the secure enclave is what would be a TPM. The implementation is similar, slightly different. And because they control the full ecosystem from hardware to software, they have some benefits there where they don't have to make it that compatible with all kinds of CPU vendors. So if you were really into this stuff, I don't understand the half of it, but there is a really good support article on the Apple website that explains in detail how this chip works and how you can interoperate with it. And it's just quite a nifty implementation. So basically, on the Intune site, you can build your own onboarding profiles. And here, you can actually select that use secure enclave key. And that is the new feature that they added. You can enable or disable the shared device key. Please disable that, because it's not the best thing to enable. Then it gets uploaded to your iCloud, and it actually lowers the security barrier, and the rest is just padding that you have to assign it. And then once you enroll your Mac into Intune, which is just a company portal like you would on Windows, it's happy. It shows all kinds of stuff. And then after that, actually, the important stuff begins. Because now the platform SSO module from Apple kicks in. So first, you have to register your device in Intune. And then it goes into the second phase, where you have to re-authenticate with your local admin account. And of course, you can automate this as well if you want to have a better user experience. And it actually starts probing you as well for a passkey. And the passkey, again, is tied to the secure enclave. So it's a device-bound flow that you're following. And basically, you're allowing the company portal to utilize that to get into the nicer bits of crypto. All right. So the device registration, if you have a secure enclave, it's going


chunk_text:
  You can enable or disable the shared device key. Please disable that, because it's not the best thing to enable. Then it gets uploaded to your iCloud, and it actually lowers the security barrier, and the rest is just padding that you have to assign it. And then once you enroll your Mac into Intune, which is just a company portal like you would on Windows, it's happy. It shows all kinds of stuff. And then after that, actually, the important stuff begins. Because now the platform SSO module from Apple kicks in. So first, you have to register your device in Intune. And then it goes into the second phase, where you have to re-authenticate with your local admin account. And of course, you can automate this as well if you want to have a better user experience. And it actually starts probing you as well for a passkey. And the passkey, again, is tied to the secure enclave. So it's a device-bound flow that you're following. And basically, you're allowing the company portal to utilize that to get into the nicer bits of crypto. All right. So the device registration, if you have a secure enclave, it's going to look slightly different than if you don't. So it is, again, going to be an API request. So if you have watched some of my previous talk on device registration, it's going to look very similar. We're just going to send a token to Entram. And in the request, we see the certificate signing request and also the transport key being uploaded. But the biggest difference is that this implementation actually uses elliptic curve keys. So they're no longer RSA keys, but they're now elliptic curve keys. Same goes for the transport key. So it's being uploaded as a JSON web key blob. So we just see the key, the public values of the key. And of course, the private part of the key remains on the device here, in this case, in the secure enclave. And then we get back a certificate. And in the certificate, we also see that it's done with elliptic curve keys, so with a very specific curve. So if we look at PRT3 versus PRT4, then we see that PRT3 uses RSA keys. However, the PRT4 used the secure enclave-based keys. And I guess that it was not Microsoft's decision to use elliptic


chunk_text:
  to look slightly different than if you don't. So it is, again, going to be an API request. So if you have watched some of my previous talk on device registration, it's going to look very similar. We're just going to send a token to Entram. And in the request, we see the certificate signing request and also the transport key being uploaded. But the biggest difference is that this implementation actually uses elliptic curve keys. So they're no longer RSA keys, but they're now elliptic curve keys. Same goes for the transport key. So it's being uploaded as a JSON web key blob. So we just see the key, the public values of the key. And of course, the private part of the key remains on the device here, in this case, in the secure enclave. And then we get back a certificate. And in the certificate, we also see that it's done with elliptic curve keys, so with a very specific curve. So if we look at PRT3 versus PRT4, then we see that PRT3 uses RSA keys. However, the PRT4 used the secure enclave-based keys. And I guess that it was not Microsoft's decision to use elliptic curve, but it was Apple's decision because they want to use this with their secure enclave. And secure enclave uses ECC keys basically natively. So it was probably Apple kind of nudging them or maybe forcing them to actually go this way with the PRT4. And it also means that the PRT4 is slightly different. So the starting point to get a PRT4 is, again, going to be this device-less PRT. So it still does the device-less PRT first. Maybe there is a flow to do it differently, to start with a PRT4 PRT. But we only saw the upgrade happening from PRT3 to PRT4. We didn't look at how the other authentication flows work with the passkey yet. So there's probably more to explore here. And again, you also see the sun in the corner. So this is, again, one of these important slides. And what it's going to do, it's going to send this PRT3 kind of primary refresh token. Actually, it used the primary refresh token to get the regular refresh token that's valid to request a PRT. And it's going to sign that with the device key. So it's using the elliptic curve digital signature algorithm.


chunk_text:
  curve, but it was Apple's decision because they want to use this with their secure enclave. And secure enclave uses ECC keys basically natively. So it was probably Apple kind of nudging them or maybe forcing them to actually go this way with the PRT4. And it also means that the PRT4 is slightly different. So the starting point to get a PRT4 is, again, going to be this device-less PRT. So it still does the device-less PRT first. Maybe there is a flow to do it differently, to start with a PRT4 PRT. But we only saw the upgrade happening from PRT3 to PRT4. We didn't look at how the other authentication flows work with the passkey yet. So there's probably more to explore here. And again, you also see the sun in the corner. So this is, again, one of these important slides. And what it's going to do, it's going to send this PRT3 kind of primary refresh token. Actually, it used the primary refresh token to get the regular refresh token that's valid to request a PRT. And it's going to sign that with the device key. So it's using the elliptic curve digital signature algorithm. And it's also going to use a standard called elliptic curve Diffie-Hellman with inferior session keys, I believe. So actually, it's not going to use session keys in this case. But for every request, it's going to do a Diffie-Hellman key exchange and create a temporary key. So when it receives the primary refresh token back, there's no session key involved here. But the response is actually going to be encrypted with the negotiated session key or temporary session key using the ECDH key exchange. And if we want to use it, then we actually have to, again, sign our request with the private key of the device. So that's different also from the PRT3 and the PRT2 flow, because these are not signed by the device. But in this case, we do sign it with the device private key. Again, we do this Diffie-Hellman key exchange to negotiate a key with Entra. And the response will get us our tokens. And the tokens will, again, be encrypted. So we need to decrypt this. And everything that is part of this old decryption, either in this step or in this step, has to go via the secure enclave. Because secure


chunk_text:
  And it's also going to use a standard called elliptic curve Diffie-Hellman with inferior session keys, I believe. So actually, it's not going to use session keys in this case. But for every request, it's going to do a Diffie-Hellman key exchange and create a temporary key. So when it receives the primary refresh token back, there's no session key involved here. But the response is actually going to be encrypted with the negotiated session key or temporary session key using the ECDH key exchange. And if we want to use it, then we actually have to, again, sign our request with the private key of the device. So that's different also from the PRT3 and the PRT2 flow, because these are not signed by the device. But in this case, we do sign it with the device private key. Again, we do this Diffie-Hellman key exchange to negotiate a key with Entra. And the response will get us our tokens. And the tokens will, again, be encrypted. So we need to decrypt this. And everything that is part of this old decryption, either in this step or in this step, has to go via the secure enclave. Because secure enclave is the one that actually holds the private keys. So the steps are actually very similar, both of the steps. It's the device signing the request. And it's the response that is actually encrypted using elliptic curve keys. So how does this look on the wire? We see, again, a request. So it's the PRT version 4. And the request actually contains a JSON web token. And this JSON web token is generated by the device. So in the header, we'll see the certificate from the device. So it's, again, the certificate that was issued to our device when we did the registration. And again, the biggest difference here is that the algorithm changes to elliptic curve instead of RSA signatures. And then when we request a token, or we receive the token back, then we see this encrypted blob. So this looks like a JSON web token. But again, this is not a JSON web token. This is JSON web encryption, or JWE. And in the header, we see all these weird fields. I'm not a cryptography expert. But basically, these are the initialization factors for the elliptic curve Diffie-Hellman. And with all of this data, then you


chunk_text:
  enclave is the one that actually holds the private keys. So the steps are actually very similar, both of the steps. It's the device signing the request. And it's the response that is actually encrypted using elliptic curve keys. So how does this look on the wire? We see, again, a request. So it's the PRT version 4. And the request actually contains a JSON web token. And this JSON web token is generated by the device. So in the header, we'll see the certificate from the device. So it's, again, the certificate that was issued to our device when we did the registration. And again, the biggest difference here is that the algorithm changes to elliptic curve instead of RSA signatures. And then when we request a token, or we receive the token back, then we see this encrypted blob. So this looks like a JSON web token. But again, this is not a JSON web token. This is JSON web encryption, or JWE. And in the header, we see all these weird fields. I'm not a cryptography expert. But basically, these are the initialization factors for the elliptic curve Diffie-Hellman. And with all of this data, then you can basically negotiate a key. So I didn't come up with all of this. This is from a RFC. So it's about key agreement with elliptic curve Diffie-Hellman, and ferial static, or ECDES. And then they use the CONCAT KDF to basically generate a derived key. And the derived key is actually used as a encryption key. And guess who wrote this document? Michael Jones. Good memory. Very good. Or maybe you knew it already. So essentially, that is how PRTv4 works. Yeah, and it was kind of funny, since he wrote most of the tools for PRTv3, and he started to build like a v4 version, started digging into the RFCs, and was, well, complaining a bit on how complicated it was. And then he built his first POC, and he ran it, and it's like, it worked. It's like completely dumbfounded that it's actually working, but it was cool to observe. Yeah, so the biggest surprise during this whole research is that we could reproduce it in like a Friday morning for some reason. So the RFCs were quite all right, and the documentation from Apple was also quite nice, giving examples. And like, if you calculate the


chunk_text:
  can basically negotiate a key. So I didn't come up with all of this. This is from a RFC. So it's about key agreement with elliptic curve Diffie-Hellman, and ferial static, or ECDES. And then they use the CONCAT KDF to basically generate a derived key. And the derived key is actually used as a encryption key. And guess who wrote this document? Michael Jones. Good memory. Very good. Or maybe you knew it already. So essentially, that is how PRTv4 works. Yeah, and it was kind of funny, since he wrote most of the tools for PRTv3, and he started to build like a v4 version, started digging into the RFCs, and was, well, complaining a bit on how complicated it was. And then he built his first POC, and he ran it, and it's like, it worked. It's like completely dumbfounded that it's actually working, but it was cool to observe. Yeah, so the biggest surprise during this whole research is that we could reproduce it in like a Friday morning for some reason. So the RFCs were quite all right, and the documentation from Apple was also quite nice, giving examples. And like, if you calculate the derived key, this is what the results should be. So it allowed us to create a proof of concept pretty quickly. Yeah, for the people that ever developed for Mac OS, generally, their development documentation is pretty terrible. This bit was amazingly documented, really good, or at least compared to the rest, right? So... It had just the important part that we needed. Exactly. Yeah. Let's not talk about the quality of the rest. The rest of it was kind of meh. Still the PRT is saved in the keychain, as with everything, or mostly everything on Apple, if it's implemented well. But there's one big distinction. So we can still look at it. If we fill in our password, we can see that the secret at least is there. There is some more protection on it. So they try to constrain access to it with entitlements and access controls. So technically only the Microsoft identity SSO extension should be able to read this value unless you're like a local user and you overwrite that. So it's already slightly more protected on the keychain side. If you look what's in there, that's basically this blob. So we do see that


chunk_text:
  derived key, this is what the results should be. So it allowed us to create a proof of concept pretty quickly. Yeah, for the people that ever developed for Mac OS, generally, their development documentation is pretty terrible. This bit was amazingly documented, really good, or at least compared to the rest, right? So... It had just the important part that we needed. Exactly. Yeah. Let's not talk about the quality of the rest. The rest of it was kind of meh. Still the PRT is saved in the keychain, as with everything, or mostly everything on Apple, if it's implemented well. But there's one big distinction. So we can still look at it. If we fill in our password, we can see that the secret at least is there. There is some more protection on it. So they try to constrain access to it with entitlements and access controls. So technically only the Microsoft identity SSO extension should be able to read this value unless you're like a local user and you overwrite that. So it's already slightly more protected on the keychain side. If you look what's in there, that's basically this blob. So we do see that secret. But the biggest thing that's now missing is the session key, since this is handled by the secure enclave. So as an attacker, I can copy this, but I can't do anything with it because I don't have the rest of the material to actually finish the authentication that you need to do with that whole flow from the device code side. So this is a small screenshot from the Microsoft website. And as we started with, it always needs a device ID and a session key, which turns out not to be accurate because we don't have a session key for the device-less version. Or we do have a session key for the device-less version, but no device ID. And then for PRT4, it's the other way around where the session key is derived from that Diffie-Hellman exchange. So we created this small table, and again, a sun, because if you're looking at these kinds of things on the wire, or if you're analyzing it, it could be useful to sort of remember where it's coming from and what is actually the difference. The validity is the same. So also on the Microsoft website, it says the validity


chunk_text:
  secret. But the biggest thing that's now missing is the session key, since this is handled by the secure enclave. So as an attacker, I can copy this, but I can't do anything with it because I don't have the rest of the material to actually finish the authentication that you need to do with that whole flow from the device code side. So this is a small screenshot from the Microsoft website. And as we started with, it always needs a device ID and a session key, which turns out not to be accurate because we don't have a session key for the device-less version. Or we do have a session key for the device-less version, but no device ID. And then for PRT4, it's the other way around where the session key is derived from that Diffie-Hellman exchange. So we created this small table, and again, a sun, because if you're looking at these kinds of things on the wire, or if you're analyzing it, it could be useful to sort of remember where it's coming from and what is actually the difference. The validity is the same. So also on the Microsoft website, it says the validity is 14 days, which is a blatant lie. They all work for 90 days, and that's going to be the same and will be the same probably forever. Right. So, we do have one demo that actually we were allowed to show you, and that's Dirk-Jans. Yes. So, one of the interesting things is that the device-less PRT, it started with a normal device code authentication flow, and a normal device authentication flow is just a standard OAuth flow. So there's no magic involved in there. It's just like filling in specific parameters. You don't need to have a device. You don't need to have advanced crypto. So that means that we can actually also phish users to follow that flow using attacker-in-the-middle phishing, for example, with Evil Jinx, and then actually use that to request a device-less primary phish token. So we ask users to sign in once, and normally you would get some cookies from that. The problem with cookies is that Microsoft is very keen at revoking those, and they're kind of a bit of like a black box because you don't know when your cookie is going to be valid, what the constraints are. However, we


chunk_text:
  is 14 days, which is a blatant lie. They all work for 90 days, and that's going to be the same and will be the same probably forever. Right. So, we do have one demo that actually we were allowed to show you, and that's Dirk-Jans. Yes. So, one of the interesting things is that the device-less PRT, it started with a normal device code authentication flow, and a normal device authentication flow is just a standard OAuth flow. So there's no magic involved in there. It's just like filling in specific parameters. You don't need to have a device. You don't need to have advanced crypto. So that means that we can actually also phish users to follow that flow using attacker-in-the-middle phishing, for example, with Evil Jinx, and then actually use that to request a device-less primary phish token. So we ask users to sign in once, and normally you would get some cookies from that. The problem with cookies is that Microsoft is very keen at revoking those, and they're kind of a bit of like a black box because you don't know when your cookie is going to be valid, what the constraints are. However, we can also phish for device-less PRTs, and device-less PRTs, they're way more robust because Microsoft isn't just going to revoke them. They're valid for 90 days, and we can renew them, and we can extend their validity, and we can even upgrade them to full primary phish tokens if we want. So a little demo. And here I've set up a local Evil Jinx instance, and I'm just going to do it locally so I don't actually own this Microsoft Xero online domain, even though it would be a nice name. So this is our victim. He's going to visit our webpage, and I changed this phishlet to ask for a specific token. So we're going to enter our username, enter the password. We're also prompting the victim for MFA because then we will phish the MFA, and it also means that we have a token with MFA rights. And then here what we do is we pick up this code. So this is the authorization code, and the authorization code is normally exchanged by like a native app for a token. And most phishing sites, they will actually automatically exchange it or pick up the cookies or something like


chunk_text:
  can also phish for device-less PRTs, and device-less PRTs, they're way more robust because Microsoft isn't just going to revoke them. They're valid for 90 days, and we can renew them, and we can extend their validity, and we can even upgrade them to full primary phish tokens if we want. So a little demo. And here I've set up a local Evil Jinx instance, and I'm just going to do it locally so I don't actually own this Microsoft Xero online domain, even though it would be a nice name. So this is our victim. He's going to visit our webpage, and I changed this phishlet to ask for a specific token. So we're going to enter our username, enter the password. We're also prompting the victim for MFA because then we will phish the MFA, and it also means that we have a token with MFA rights. And then here what we do is we pick up this code. So this is the authorization code, and the authorization code is normally exchanged by like a native app for a token. And most phishing sites, they will actually automatically exchange it or pick up the cookies or something like that. But here we want to have this code because, first of all, this code can only be exchanged once. So if it's already exchanged, then we can't use it anymore. But this allows us to request a device-less PRT. So from here on, we move it to the Linux machine with rote-tx, and that requests a device-less PRT. And with this device-less PRT, we can request arbitrary tokens for anything. So this would work in like native app scenarios with browser scenarios as well. I could just pop up a browser and single sign on to anything, and this will keep working for like 90 days. If we want to add a device claim, because why not, then we can also register a device using this same device as PRT, because it's used as an input in the whole device registration flow. So the legit systems also use this device as PRT as a start of the flow. So if you want, we can also register a device, first of all, with this PRT, so that we do with the PRT off module. We specify the version 3, because we are using this new protocol. You can actually also


chunk_text:
  that. But here we want to have this code because, first of all, this code can only be exchanged once. So if it's already exchanged, then we can't use it anymore. But this allows us to request a device-less PRT. So from here on, we move it to the Linux machine with rote-tx, and that requests a device-less PRT. And with this device-less PRT, we can request arbitrary tokens for anything. So this would work in like native app scenarios with browser scenarios as well. I could just pop up a browser and single sign on to anything, and this will keep working for like 90 days. If we want to add a device claim, because why not, then we can also register a device using this same device as PRT, because it's used as an input in the whole device registration flow. So the legit systems also use this device as PRT as a start of the flow. So if you want, we can also register a device, first of all, with this PRT, so that we do with the PRT off module. We specify the version 3, because we are using this new protocol. You can actually also leave that out, because the v2 works with the same PRTs. It's a different crypto involved, but it doesn't matter which protocol you use, v2 and v3 there. The things are exchangeable, basically. We ask a token for the device registration service scope, and then after that, we register our fake device. And this device is obviously not going to have a TPM. We're going to do the new registration flow. So actually, this is going to register a fake macOS device. It's going to pretend we have a secure enclave. So it's going to generate no RSA keys in this case, but elliptic curve keys. And then once we have this device, then we can upgrade this PRT to a PRTV4 device bound PRT. So this will bind it to our new device. And we see that the session key here is empty, because this is PRTV4. So then we don't have a session key anymore, but we have a PRT that is bound to our device, and that we need to use these elliptic curve keys to actually use the PRTs. So the final step, we use it with the PRTOff module, and we specify the version 4.


chunk_text:
  leave that out, because the v2 works with the same PRTs. It's a different crypto involved, but it doesn't matter which protocol you use, v2 and v3 there. The things are exchangeable, basically. We ask a token for the device registration service scope, and then after that, we register our fake device. And this device is obviously not going to have a TPM. We're going to do the new registration flow. So actually, this is going to register a fake macOS device. It's going to pretend we have a secure enclave. So it's going to generate no RSA keys in this case, but elliptic curve keys. And then once we have this device, then we can upgrade this PRT to a PRTV4 device bound PRT. So this will bind it to our new device. And we see that the session key here is empty, because this is PRTV4. So then we don't have a session key anymore, but we have a PRT that is bound to our device, and that we need to use these elliptic curve keys to actually use the PRTs. So the final step, we use it with the PRTOff module, and we specify the version 4. So in this case, I'm asking for a token for graph.microsoft.com from my favorite application, Microsoft Teams. And then it will give us a token. And we'll see with this token, it's like on behalf of Teams. So with this, we will be able to extract any data from Teams. This is how it works with the native flow. There's also, of course, PRTV4 single sign-on tokens for the web-based flow. Those also work slightly differently than like the normal PRT authentication on a website. So I didn't have time to implement that yet, but it's possible, because we have like a full primary token bound to a specific device. Now, there's also some things that we can use on Windows with this. So there is some protocol magic that allows us to do some things we're not supposed to. But again, we were going to do this talk, and Microsoft asked us to like, hey, can you give us a heads up what you're actually going to discuss? We didn't think it was a big thing. They wanted to fix it nonetheless, so we agreed not to talk about it until it's fixed. And I don't know when they're


chunk_text:
  So in this case, I'm asking for a token for graph.microsoft.com from my favorite application, Microsoft Teams. And then it will give us a token. And we'll see with this token, it's like on behalf of Teams. So with this, we will be able to extract any data from Teams. This is how it works with the native flow. There's also, of course, PRTV4 single sign-on tokens for the web-based flow. Those also work slightly differently than like the normal PRT authentication on a website. So I didn't have time to implement that yet, but it's possible, because we have like a full primary token bound to a specific device. Now, there's also some things that we can use on Windows with this. So there is some protocol magic that allows us to do some things we're not supposed to. But again, we were going to do this talk, and Microsoft asked us to like, hey, can you give us a heads up what you're actually going to discuss? We didn't think it was a big thing. They wanted to fix it nonetheless, so we agreed not to talk about it until it's fixed. And I don't know when they're going to fix it exactly. I know they're working on it, but basically, we're not going to be able to show you all the other stuff. But this works. This is just following the protocols. You can fish people, and instead of fishing for cookies, which is boring, everyone already does that. You can fish for primary fish tokens, way more fun. A little bit about defenses, to wrap it up. Yeah, of course, like any responsible person dropping bad stuff, we also want to help you defend against it. Sad news is you can't fully. Like also Rick's talk is probably going to suck for a while, and then we're going to be better. But Microsoft offers some options. Some require licenses, some not so much. You can restrict it quite a bit with conditional access policies, depending on what you require on it. Quite complicated to do really, really well, and there will at some point maybe be a loophole. So you can supplement that with require only compliant devices, which is something you can check against. Bit stronger, still something that we probably will be able to fake as an attacker. Another thing you could do if


chunk_text:
  going to fix it exactly. I know they're working on it, but basically, we're not going to be able to show you all the other stuff. But this works. This is just following the protocols. You can fish people, and instead of fishing for cookies, which is boring, everyone already does that. You can fish for primary fish tokens, way more fun. A little bit about defenses, to wrap it up. Yeah, of course, like any responsible person dropping bad stuff, we also want to help you defend against it. Sad news is you can't fully. Like also Rick's talk is probably going to suck for a while, and then we're going to be better. But Microsoft offers some options. Some require licenses, some not so much. You can restrict it quite a bit with conditional access policies, depending on what you require on it. Quite complicated to do really, really well, and there will at some point maybe be a loophole. So you can supplement that with require only compliant devices, which is something you can check against. Bit stronger, still something that we probably will be able to fake as an attacker. Another thing you could do if you have that luxury is restrict your device registration to the maximum of one or two. The way it works, if you use Intune, you enroll your own device, right? So you need to be able to at least register one device. But a lot of companies also allow you to log on with your phone. Maybe you have an iPad, right? So then you already are free. So there are some gaps there as well. You can also, what you can also do is limit the token lifetime on non-corporate, bring your own non-managed devices. So at least the scope and the impact might be slightly less. So if we get a PRT then, and we can use it, then at least we can use it for a shorter amount of time. So still not perfect. And of course, you can still build detections where a user is registering a new device from an already registered device, which is not really what you would expect in a normal onboarding flow. So all of them, not great. Microsoft is actually working on patching the vulnerable flows that we weren't allowed to talk about. And also they're exploring mechanisms to disallow


chunk_text:
  you have that luxury is restrict your device registration to the maximum of one or two. The way it works, if you use Intune, you enroll your own device, right? So you need to be able to at least register one device. But a lot of companies also allow you to log on with your phone. Maybe you have an iPad, right? So then you already are free. So there are some gaps there as well. You can also, what you can also do is limit the token lifetime on non-corporate, bring your own non-managed devices. So at least the scope and the impact might be slightly less. So if we get a PRT then, and we can use it, then at least we can use it for a shorter amount of time. So still not perfect. And of course, you can still build detections where a user is registering a new device from an already registered device, which is not really what you would expect in a normal onboarding flow. So all of them, not great. Microsoft is actually working on patching the vulnerable flows that we weren't allowed to talk about. And also they're exploring mechanisms to disallow the reuse or certain of those tokens for revised registration, which will probably be the biggest blocking point, because then you can't do all the stuff that we showed you earlier. Of course, there's a lot of other things to explore. So Mr. Jones wrote quite some other RSCs that we probably can still dig into and sometimes be frustrated about. And I already see somebody very waiting for us. So that will be the end. And we would like to thank you for your attention. Questions is probably, is that still possible?


chunk_text:
  the reuse or certain of those tokens for revised registration, which will probably be the biggest blocking point, because then you can't do all the stuff that we showed you earlier. Of course, there's a lot of other things to explore. So Mr. Jones wrote quite some other RSCs that we probably can still dig into and sometimes be frustrated about. And I already see somebody very waiting for us. So that will be the end. And we would like to thank you for your attention. Questions is probably, is that still possible?


chunk_text:
  { "webpage_url": "https://www.youtube.com/watch?v=bAHqEefF7Ok", "title": "Confusion Attacks: Exploiting Hidden Semantic Ambiguity In Apache HTTP Server! - Orange Tsai", "description": "", "channel_url": "https://www.youtube.com/channel/UCgJoGNj3B2Mt2F3TUblcoOA", "duration": 2617, "channel": "OrangeCon", "uploader": "OrangeCon", "upload_date": "20240909" } This text was transcribed using whisper model: large-v2 Hi, this is Orange, it's my pleasure to become a speaker at OrangeCon, and you know how this means a lot to me, yes. So today I will present the Confucius attack, and let's get started with today's presentation. First I want to ask, is there anyone here who hasn't heard of the Pudge HTTP server before? If so, please raise your hand. Okay, well, I believe I can skip the introduction. And I want to ask an additional question. How many people here are under 30 years old? Wow, there are so many young generations. Okay, a Pudge is an open source project that is nearly 30 years old. So I guess it might be older than some of you here. And because it has existed since the early days of the internet, it has accumulated a lot of technical depth. And another key point is that a Pudge enables CGI by default, which greatly increases the potential attack surface. And lastly, a Pudge is the only web server that can perfectly integrate with PHP. Since a Pudge and PHP were born almost in the same year, a Pudge was the first choice to use PHP in the early days. A Pudge also met several customizations for PHP, which led to several ways to configure PHP. For example, just for the fast CGI protocol, there are over six different modules to choose from. Especially, each module has different directives. All of these make it complex to set up a PHP environment. And furthermore, some directives not only look very similar, but also have identical usage and effects, which can cause confusion easily. If a website admin didn't understand the intention behind each directive, it's easy to make mistakes and create security risks. For example, when the website admin wants to set up PHP on his server, he might come across two common directives, addHandler and addType. And which one do you think is correct? Actually, both are correct. This method can properly get the PHP running. So does this mean both configurations are all good? Firstly, being correct does not mean being secure. And under certain conditions, addType has been proven


chunk_text:
  lastly, a Pudge is the only web server that can perfectly integrate with PHP. Since a Pudge and PHP were born almost in the same year, a Pudge was the first choice to use PHP in the early days. A Pudge also met several customizations for PHP, which led to several ways to configure PHP. For example, just for the fast CGI protocol, there are over six different modules to choose from. Especially, each module has different directives. All of these make it complex to set up a PHP environment. And furthermore, some directives not only look very similar, but also have identical usage and effects, which can cause confusion easily. If a website admin didn't understand the intention behind each directive, it's easy to make mistakes and create security risks. For example, when the website admin wants to set up PHP on his server, he might come across two common directives, addHandler and addType. And which one do you think is correct? Actually, both are correct. This method can properly get the PHP running. So does this mean both configurations are all good? Firstly, being correct does not mean being secure. And under certain conditions, addType has been proven to be vulnerable. And allowing attackers to disclose the PHP source code remotely. And we will discuss the reason later. And the last thing I want to mention about Apache, and I believe it's also the most important one, is from my years working in offensive security, I have observed that websites who use Apache tend to have more massive environments. Also I can't think of any reason to use Apache other than for CGI. In practice, many servers are still running Apache and hosting a lot of third-party web services like Tomcat or Nginx locally. Also, they tend to use rewrite lua to organize the request. And usually the file system on the server is also a mess, with a lot of strange files sitting under the web root. So today our talk's mission is to break this type of the Apache HTTP server. You will learn how to identify such vulnerable servers and break them just like a piece of cake today. Okay, before we dive into the topic, let me introduce myself first. And you have already known I'm Orange, and currently I'm the principal security researcher at DevCore. I have spoken at several top-hacking conferences, and


chunk_text:
  to be vulnerable. And allowing attackers to disclose the PHP source code remotely. And we will discuss the reason later. And the last thing I want to mention about Apache, and I believe it's also the most important one, is from my years working in offensive security, I have observed that websites who use Apache tend to have more massive environments. Also I can't think of any reason to use Apache other than for CGI. In practice, many servers are still running Apache and hosting a lot of third-party web services like Tomcat or Nginx locally. Also, they tend to use rewrite lua to organize the request. And usually the file system on the server is also a mess, with a lot of strange files sitting under the web root. So today our talk's mission is to break this type of the Apache HTTP server. You will learn how to identify such vulnerable servers and break them just like a piece of cake today. Okay, before we dive into the topic, let me introduce myself first. And you have already known I'm Orange, and currently I'm the principal security researcher at DevCore. I have spoken at several top-hacking conferences, and my research has got a number of honors, such as the Top 10 Web Hacking Techniques, Pong to Pong Champion, and Ponging Award. So why we focus on Apache? At the beginning of this year, I started to explore some open-source projects with widespread internet impacts, such as the Apache and the Nginx. I have even delved into some RFCs to deepen my understanding. And upon a close review of the Apache source code, I smelled something bad in its coding style. Primarily, Apache relied on hundreds of small modules working together to handle a client's HTTP request. The source code includes 136 modules, and about half of them are either enabled by default or commonly used by website admins. And what's even more surprising is that these modules also share and maintain a very large structure while working together. The slide shows what the structure looks like, including all the elements involved in handling an HTTP request. In Apache, all modules rely on this massive structure for synchronization, communication, and even data exchange. And step into the internal, an HTTP request will pass through several phases, and the modules act like players in a game of catch, passing the


chunk_text:
  my research has got a number of honors, such as the Top 10 Web Hacking Techniques, Pong to Pong Champion, and Ponging Award. So why we focus on Apache? At the beginning of this year, I started to explore some open-source projects with widespread internet impacts, such as the Apache and the Nginx. I have even delved into some RFCs to deepen my understanding. And upon a close review of the Apache source code, I smelled something bad in its coding style. Primarily, Apache relied on hundreds of small modules working together to handle a client's HTTP request. The source code includes 136 modules, and about half of them are either enabled by default or commonly used by website admins. And what's even more surprising is that these modules also share and maintain a very large structure while working together. The slide shows what the structure looks like, including all the elements involved in handling an HTTP request. In Apache, all modules rely on this massive structure for synchronization, communication, and even data exchange. And step into the internal, an HTTP request will pass through several phases, and the modules act like players in a game of catch, passing the structure from one to another. And when a module's turn, it focuses on completing its own task. And once done, it passes the structure to the next. This type of collaboration is not new from a software engineering perspective. Each module simply focuses on its own task. And as long as everyone finishes their work, then the client can enjoy the service provided by Apache. And this approach might work well with a few modules. However, since any module can modify any value in this structure, when there are over 100 modules today, without any good standard or guidelines, can they still work together? Thus, our research was born. So our research focused on the relationships and interactions between these modules. Each module might be implemented by different people, and subjected to years of iterations and code refactors. Do they really still know what they are doing? Even if they understand what they are doing, what about the implementation detail of others? They need to collaborate together. And however, if a module accidentally modifies a structure felt it considered unimportant, but it's crucial for another module, it could affect the later decisions. And furthermore, if there's any misunderstanding between any


chunk_text:
  structure from one to another. And when a module's turn, it focuses on completing its own task. And once done, it passes the structure to the next. This type of collaboration is not new from a software engineering perspective. Each module simply focuses on its own task. And as long as everyone finishes their work, then the client can enjoy the service provided by Apache. And this approach might work well with a few modules. However, since any module can modify any value in this structure, when there are over 100 modules today, without any good standard or guidelines, can they still work together? Thus, our research was born. So our research focused on the relationships and interactions between these modules. Each module might be implemented by different people, and subjected to years of iterations and code refactors. Do they really still know what they are doing? Even if they understand what they are doing, what about the implementation detail of others? They need to collaborate together. And however, if a module accidentally modifies a structure felt it considered unimportant, but it's crucial for another module, it could affect the later decisions. And furthermore, if there's any misunderstanding between any field within this large structure, it can create security risks as well. So from this starting point, we have developed three different types of attacks. As all of them are more or less related to the misuse of the structure, we have named this attack service ConfusionAttack. And the following are the attacks we have developed. As this is a completely new attack service, the first person to dive into, of course, can find the most bugs easily. So this ConfusionAttack made me the person who is currently holding the most vulnerability from the Apache HTTP server. Additionally, because these vulnerabilities are based on legacy architectural issues, so most of the patches are not backward compatible. So updating Apache to the latest version might break old configurations. Therefore, for many production servers, simply applying the update to the latest version is not a good idea. Okay, let's dive into our main topic. First, I would like to discuss the attack called FileNameConfusion. This attack occurs when different modules handle the file name using different standards. Literally, the field FileName should represent a file system path. But however, in Apache, some modules treat it as a URL. If we think of


chunk_text:
  field within this large structure, it can create security risks as well. So from this starting point, we have developed three different types of attacks. As all of them are more or less related to the misuse of the structure, we have named this attack service ConfusionAttack. And the following are the attacks we have developed. As this is a completely new attack service, the first person to dive into, of course, can find the most bugs easily. So this ConfusionAttack made me the person who is currently holding the most vulnerability from the Apache HTTP server. Additionally, because these vulnerabilities are based on legacy architectural issues, so most of the patches are not backward compatible. So updating Apache to the latest version might break old configurations. Therefore, for many production servers, simply applying the update to the latest version is not a good idea. Okay, let's dive into our main topic. First, I would like to discuss the attack called FileNameConfusion. This attack occurs when different modules handle the file name using different standards. Literally, the field FileName should represent a file system path. But however, in Apache, some modules treat it as a URL. If we think of HTTP context, some modules consider the field as a file system, but some others are not. The inconsistency between these modules will create vulnerabilities. The first module consider the file name as a URL is RewriteModule. This module allows website admin to redirect a request to any file or URL. I believe this is by design to enhance user experience. However, this convenience feature also introduced certain issues. For example, the RewriteModule will treat the substitution result as a URL in all cases. For example, if the website admin sets the following rule to target the username right after the path slash user to open the corresponding profile in the file system. So when you access the slash user slash orange, the module will open and output the file content of slash var user orange profile. However, what if you add one more question mark today? %3f is the URL encoded format for the question mark. During the name translation phase, the RewriteModule will first process the rule and generate the corresponding destination target, just like this path. After the generation, even if the destination is the file system path, the RewriteModule will treat all the result as a URL


chunk_text:
  HTTP context, some modules consider the field as a file system, but some others are not. The inconsistency between these modules will create vulnerabilities. The first module consider the file name as a URL is RewriteModule. This module allows website admin to redirect a request to any file or URL. I believe this is by design to enhance user experience. However, this convenience feature also introduced certain issues. For example, the RewriteModule will treat the substitution result as a URL in all cases. For example, if the website admin sets the following rule to target the username right after the path slash user to open the corresponding profile in the file system. So when you access the slash user slash orange, the module will open and output the file content of slash var user orange profile. However, what if you add one more question mark today? %3f is the URL encoded format for the question mark. During the name translation phase, the RewriteModule will first process the rule and generate the corresponding destination target, just like this path. After the generation, even if the destination is the file system path, the RewriteModule will treat all the result as a URL and separate the query part by the question mark. So there's a path truncation here, and this is our first primitive. You can use a question mark to truncate the path and to access unintended files. For here, we use this truncation to access the secret, which is normally inaccessible. Although it might seem a minor issue for now, please remember it because it will be used heavily in our later attacks. Okay, next, who else considers the file name as a URL? The proxy module, too. At first glance, this seems makes sense because the purpose of the proxy is to redirect the request to other URLs. So when we consider this behavior on its own, it doesn't appear to be a problem. However, if your server relies on the file-based access control, it can be risky. For example, this is a common password-protected configuration using the file directive to prevent unauthorized users from accessing admin.php. This type of authentication can be bypassed by default when the target is running under the phpfpn. Imagine when you visit a URL like this today, admin.php, %3f, and ooo.php. First, during the HTTP lifecycle of the access control phase, the authentication module


chunk_text:
  and separate the query part by the question mark. So there's a path truncation here, and this is our first primitive. You can use a question mark to truncate the path and to access unintended files. For here, we use this truncation to access the secret, which is normally inaccessible. Although it might seem a minor issue for now, please remember it because it will be used heavily in our later attacks. Okay, next, who else considers the file name as a URL? The proxy module, too. At first glance, this seems makes sense because the purpose of the proxy is to redirect the request to other URLs. So when we consider this behavior on its own, it doesn't appear to be a problem. However, if your server relies on the file-based access control, it can be risky. For example, this is a common password-protected configuration using the file directive to prevent unauthorized users from accessing admin.php. This type of authentication can be bypassed by default when the target is running under the phpfpn. Imagine when you visit a URL like this today, admin.php, %3f, and ooo.php. First, during the HTTP lifecycle of the access control phase, the authentication module will compare your requested file name with the protected file admin.php. At this point, your file name is admin.php?oo.php, which is totally different. So at this time, Apache didn't think you need authentication. However, to support various protocols like HTTP or FTP, the proxy module will rewrite the file name into the following URL and sends it to the backend php service. Since the backend receives the file name in a strange format, the php also implements some workarounds to adapt this behavior. php normalizes this unusual file name first and spreads it by the question mark to get the original original file name for execution. So the original authentication required admin can be bypassed with just a single question mark. Of course, it's not just admin.php. There are more risky configurations that can be found on GitHub, such as the only local accessible php info and admin, which is blocked by default. Through the inconsistency between the authentication module and proxy module, all of this can be bypassed by just a single question mark. Okay, this is our first confusion attack. The next attack we are diving into is the confusion based on the document loot. Let's consider this


chunk_text:
  will compare your requested file name with the protected file admin.php. At this point, your file name is admin.php?oo.php, which is totally different. So at this time, Apache didn't think you need authentication. However, to support various protocols like HTTP or FTP, the proxy module will rewrite the file name into the following URL and sends it to the backend php service. Since the backend receives the file name in a strange format, the php also implements some workarounds to adapt this behavior. php normalizes this unusual file name first and spreads it by the question mark to get the original original file name for execution. So the original authentication required admin can be bypassed with just a single question mark. Of course, it's not just admin.php. There are more risky configurations that can be found on GitHub, such as the only local accessible php info and admin, which is blocked by default. Through the inconsistency between the authentication module and proxy module, all of this can be bypassed by just a single question mark. Okay, this is our first confusion attack. The next attack we are diving into is the confusion based on the document loot. Let's consider this common Apache rewrite rule for a moment. When you visit the URL slash html slash about, what file do you think Apache will actually open? It's either about dot html under the loot folder or the file from the document loot at slash var slash triple w and slash html. Which one do you think the Apache will open? If you think Apache will open the slash about dot html, please raise your hand. And if you think Apache will open the bottom one, please raise your hand. Oh, more people think it's just the bottom one. Okay, actually, Apache answers both. Magic, right? Yeah, this is also our second confusion. For any given rewrite rule, Apache always tries to open both the past version with and without the document loot. This allows us to intentionally access the files outside the web loot, especially the loot directory. You might be wondering, hey, does this mean we can access the slash etc slash passwd? The answer is yes, but not entirely. Technically, the server indeed accesses the password file, but the Apache HTTP server's built-in access control blocks our access. You can see the default configuration is denied all. However, the


chunk_text:
  common Apache rewrite rule for a moment. When you visit the URL slash html slash about, what file do you think Apache will actually open? It's either about dot html under the loot folder or the file from the document loot at slash var slash triple w and slash html. Which one do you think the Apache will open? If you think Apache will open the slash about dot html, please raise your hand. And if you think Apache will open the bottom one, please raise your hand. Oh, more people think it's just the bottom one. Okay, actually, Apache answers both. Magic, right? Yeah, this is also our second confusion. For any given rewrite rule, Apache always tries to open both the past version with and without the document loot. This allows us to intentionally access the files outside the web loot, especially the loot directory. You might be wondering, hey, does this mean we can access the slash etc slash passwd? The answer is yes, but not entirely. Technically, the server indeed accesses the password file, but the Apache HTTP server's built-in access control blocks our access. You can see the default configuration is denied all. However, the built-in access control by default allows the access to the folder slash user slash share. And thanks for this configuration, we now have a limited arbitrary file access on Apache HTTP server. For example, we can access the documentations on the slash user slash share to learn how to use SSH. However, from the real-world case, such as the rule in the slide, the extension like .html is still the restrictions that keep us from being truly free. So you might ask, can we access the file outside the .html extension? I'm not sure if you remember the primitive of the press truncation from the file name confusion earlier. We can combine them together using a question mark to truncate the extension. So theoretically, as long as the target prefix of a rewrite rule is controllable, we can access nearly the entire slash user slash share. This is a blast. Even the tutorial from the official Apache website has problematic examples. And okay, we now know the loot codes. And what can we do with these attacks? First, we can disclose arbitrary server-side source code. Since Apache decides whether to ask you the script or not based on the current


chunk_text:
  built-in access control by default allows the access to the folder slash user slash share. And thanks for this configuration, we now have a limited arbitrary file access on Apache HTTP server. For example, we can access the documentations on the slash user slash share to learn how to use SSH. However, from the real-world case, such as the rule in the slide, the extension like .html is still the restrictions that keep us from being truly free. So you might ask, can we access the file outside the .html extension? I'm not sure if you remember the primitive of the press truncation from the file name confusion earlier. We can combine them together using a question mark to truncate the extension. So theoretically, as long as the target prefix of a rewrite rule is controllable, we can access nearly the entire slash user slash share. This is a blast. Even the tutorial from the official Apache website has problematic examples. And okay, we now know the loot codes. And what can we do with these attacks? First, we can disclose arbitrary server-side source code. Since Apache decides whether to ask you the script or not based on the current virtual host or directory, so access the full path through a virtual host that doesn't support PHP allows us to easily expose its source code. And since we have broken the trust of the only accessing the document loop, the entire slash user slash share has now become our platform. So the next step is to find out what files under this folder we can exploit. We can leverage existing tutorial examples, unit tests, or even packages from programming language to become our gadgets. So the first gadget we are going to demonstrate is leveraging the library office, which is installed on Ubuntu desktop by default. We can leverage the language switch feature in the help files to achieve accesses. Or we can disclose sensitive information. For example, if you install the WebSocket D, the daemon will, by default, include an example PHP script called dumpenv.php. You can directly access the file to leak sensitive environment variables. And additionally, if the target has the service like nginx or jt installed, the default web loops are also located under the slash user slash share. So you can download sensitive application data, such as the web.xml. Here we demonstrate how to ask


chunk_text:
  virtual host or directory, so access the full path through a virtual host that doesn't support PHP allows us to easily expose its source code. And since we have broken the trust of the only accessing the document loop, the entire slash user slash share has now become our platform. So the next step is to find out what files under this folder we can exploit. We can leverage existing tutorial examples, unit tests, or even packages from programming language to become our gadgets. So the first gadget we are going to demonstrate is leveraging the library office, which is installed on Ubuntu desktop by default. We can leverage the language switch feature in the help files to achieve accesses. Or we can disclose sensitive information. For example, if you install the WebSocket D, the daemon will, by default, include an example PHP script called dumpenv.php. You can directly access the file to leak sensitive environment variables. And additionally, if the target has the service like nginx or jt installed, the default web loops are also located under the slash user slash share. So you can download sensitive application data, such as the web.xml. Here we demonstrate how to ask you the PHP info to leak sensitive information by DeviCale package. Even some PHP or font end packages, their tutorials or debug content, even some PHP or font end packages, their tutorials or debug console can be leveraged as well, such as the jQuery, magpie, or the jpgraph. For example, we use the tutorial from the jQuery feed to read arbitrary file content. Okay, by now, you can see the possibilities of this primitive. You can see the possibilities of this primitive are huge. Local gadgets are endless, and all that remains is to find more powerful gadgets or more universal gadgets. But you might be curious and asking about can we jump out of the slash user slash share? Of course we can. And that brings out our third primitive. To draw back from the slash user slash share, a patch by default follows the symbolic links. So we can leverage this feature to draw back from user share. So any package that has a symbolic link in its installation folder can become a stepping stone to access more gadgets for further exploitations. Here are some useful symbolic links we have discovered so far. You can read the CACTI


chunk_text:
  you the PHP info to leak sensitive information by DeviCale package. Even some PHP or font end packages, their tutorials or debug content, even some PHP or font end packages, their tutorials or debug console can be leveraged as well, such as the jQuery, magpie, or the jpgraph. For example, we use the tutorial from the jQuery feed to read arbitrary file content. Okay, by now, you can see the possibilities of this primitive. You can see the possibilities of this primitive are huge. Local gadgets are endless, and all that remains is to find more powerful gadgets or more universal gadgets. But you might be curious and asking about can we jump out of the slash user slash share? Of course we can. And that brings out our third primitive. To draw back from the slash user slash share, a patch by default follows the symbolic links. So we can leverage this feature to draw back from user share. So any package that has a symbolic link in its installation folder can become a stepping stone to access more gadgets for further exploitations. Here are some useful symbolic links we have discovered so far. You can read the CACTI logs under slash var slash log, read the SORA configuration under slash etc, and even access the Redmine files. And here we will demonstrate a remote code execution trend on Redmine through a double hop jump. There's an instance folder that can jump to slash var slash lib under Redmine. And within that folder, the config directory can also jump to the slash etc slash Redmine, which contains a lot of Redmine's database configuration and its secret key. So by using an insecure rewrite rule, we can access the secret key used by Redmine through a double hop jump. And since Redmine is a Ruby on Rails application, the content of the secret key is actually the key for signing and encrypting. So the next step should be obvious. Embedding a malicious object into the cookies, signing and encrypting with the non-key, and then get code execution through the server-side deserialization. Okay, that's our second confusion attack. The last attack I'm going to introduce is the confusion based on the handler. This is also an attack that leverages a piece of technical depth in Apache server's legacy architecture. Back to our initial question. Why can both directives, one for aiding


chunk_text:
  logs under slash var slash log, read the SORA configuration under slash etc, and even access the Redmine files. And here we will demonstrate a remote code execution trend on Redmine through a double hop jump. There's an instance folder that can jump to slash var slash lib under Redmine. And within that folder, the config directory can also jump to the slash etc slash Redmine, which contains a lot of Redmine's database configuration and its secret key. So by using an insecure rewrite rule, we can access the secret key used by Redmine through a double hop jump. And since Redmine is a Ruby on Rails application, the content of the secret key is actually the key for signing and encrypting. So the next step should be obvious. Embedding a malicious object into the cookies, signing and encrypting with the non-key, and then get code execution through the server-side deserialization. Okay, that's our second confusion attack. The last attack I'm going to introduce is the confusion based on the handler. This is also an attack that leverages a piece of technical depth in Apache server's legacy architecture. Back to our initial question. Why can both directives, one for aiding a handler and one for aiding a type, can run PHP properly? This is actually due to a legacy conversion in Apache, or you could say it's part of its technical depth. Before Apache enters the main handler for processing the HTTP, if the handler field is empty, Apache will take the value in the field of content type as its handler. So our third handler confusion is preying around this behavior. In Apache, sometimes the content type can be transformed into the handler. Yes, it can be transformed into the handler. So what can we do? Let's show you something fun first. Imagine that your server is running PHP using the add-type directive and you access the file config.php. Since the file extension is .php, during the type checker, during the first type During the type checker, during the first type checker, the patch will assign the corresponding value to the content type field based on your configuration. And PHP will know, oh, it is his responsibility to handle this request. The normal process works well. However, before entering the main handler fast, the legacy conversion, we mentioned earlier, will convert the content type into the handler. So this


chunk_text:
  a handler and one for aiding a type, can run PHP properly? This is actually due to a legacy conversion in Apache, or you could say it's part of its technical depth. Before Apache enters the main handler for processing the HTTP, if the handler field is empty, Apache will take the value in the field of content type as its handler. So our third handler confusion is preying around this behavior. In Apache, sometimes the content type can be transformed into the handler. Yes, it can be transformed into the handler. So what can we do? Let's show you something fun first. Imagine that your server is running PHP using the add-type directive and you access the file config.php. Since the file extension is .php, during the type checker, during the first type During the type checker, during the first type checker, the patch will assign the corresponding value to the content type field based on your configuration. And PHP will know, oh, it is his responsibility to handle this request. The normal process works well. However, before entering the main handler fast, the legacy conversion, we mentioned earlier, will convert the content type into the handler. So this explains why both add-type and add-handler are effective. But what if any module accidentally overrides the content type before reaching the run handler phase? For example, you can trigger a filter error in the most security module. If the most security finds an error, the module will think, oh, it has made some mistakes and want to send out some error message. And since the error message is in HTML, it sets the current content type to HTML2. So the config, which was supposed to be askew as PHP, is treated as a plain HTML now, exposing all the sensitive content to outside. So this is also our first primitive for handler confusion. By abusing the old handler confusion mechanism, we can disclose any PHP source code by overriding the content type. Theoretically, all directives based on content type are affected by this issue. But if we think deeper, the nature of this issue is actually that there are no clear guidelines for the use of the field content type. It can be set by a config directive during the request or use the content type header in the server response. A patch cannot distinguish which one it is while


chunk_text:
  explains why both add-type and add-handler are effective. But what if any module accidentally overrides the content type before reaching the run handler phase? For example, you can trigger a filter error in the most security module. If the most security finds an error, the module will think, oh, it has made some mistakes and want to send out some error message. And since the error message is in HTML, it sets the current content type to HTML2. So the config, which was supposed to be askew as PHP, is treated as a plain HTML now, exposing all the sensitive content to outside. So this is also our first primitive for handler confusion. By abusing the old handler confusion mechanism, we can disclose any PHP source code by overriding the content type. Theoretically, all directives based on content type are affected by this issue. But if we think deeper, the nature of this issue is actually that there are no clear guidelines for the use of the field content type. It can be set by a config directive during the request or use the content type header in the server response. A patch cannot distinguish which one it is while using the field. So ideally, if we can control the content type, we can invoke arbitrary handler. So can we really do that? It's very promising. However, there's still one last piece of the puzzle. The situation is not as simple as it seems. And in practice, all the code paths that can modify the content type are old after the legacy transformation. So even we can modify the content type through the server response, it turns out to be useless. So what can we do next? Don't worry. We turn to the RFC to servers. The RFC 3875 is the specification for CGI. And the section 6.2.2 introduced the local redirect response. The local redirect response works like this. If the CGI returns the status of 200 and includes a location header, instead of handling it as a client-side redirect by the browser, the CGI treats this location target as a server-side redirect. And a patch implementation of this server-side redirect will open a new HTTP life cycle and copy the original field of the content type to this new structure. So, for example, if you can control the response header through CGI, that means you can control the


chunk_text:
  using the field. So ideally, if we can control the content type, we can invoke arbitrary handler. So can we really do that? It's very promising. However, there's still one last piece of the puzzle. The situation is not as simple as it seems. And in practice, all the code paths that can modify the content type are old after the legacy transformation. So even we can modify the content type through the server response, it turns out to be useless. So what can we do next? Don't worry. We turn to the RFC to servers. The RFC 3875 is the specification for CGI. And the section 6.2.2 introduced the local redirect response. The local redirect response works like this. If the CGI returns the status of 200 and includes a location header, instead of handling it as a client-side redirect by the browser, the CGI treats this location target as a server-side redirect. And a patch implementation of this server-side redirect will open a new HTTP life cycle and copy the original field of the content type to this new structure. So, for example, if you can control the response header through CGI, that means you can control the content type field. And when the patch sees the status is 200, it performs the server-side redirect and starts a new round of HTTP processing. And in this new round, the content type header returned by the earlier CGI is pressed into the structure. And after the legacy content type handler conversion, the content type we provided becomes the handler and allows us to invoke arbitrary handler. So, this is our second primitive. It's the ability to code arbitrary handler. And basically, the entire CGI family follows this feature. So, including but not limited to the WSGI, FastCGI, or UWSGI. As for how to trigger this server-side redirect, here we provide two scenarios. One is the CRF injection, and the other is the SSRF that can fully control the response header. And we will use the CRF injection as the example below. In the normal case, this type of vulnerability will be treated as an XSS because you can inject HTML into the content. However, if you override the content type with a name called the server status, then you can lack sensitive information that should only be accessible from the local host. You can also easily transform an image


chunk_text:
  content type field. And when the patch sees the status is 200, it performs the server-side redirect and starts a new round of HTTP processing. And in this new round, the content type header returned by the earlier CGI is pressed into the structure. And after the legacy content type handler conversion, the content type we provided becomes the handler and allows us to invoke arbitrary handler. So, this is our second primitive. It's the ability to code arbitrary handler. And basically, the entire CGI family follows this feature. So, including but not limited to the WSGI, FastCGI, or UWSGI. As for how to trigger this server-side redirect, here we provide two scenarios. One is the CRF injection, and the other is the SSRF that can fully control the response header. And we will use the CRF injection as the example below. In the normal case, this type of vulnerability will be treated as an XSS because you can inject HTML into the content. However, if you override the content type with a name called the server status, then you can lack sensitive information that should only be accessible from the local host. You can also easily transform an image into your PHP backdoor by setting the content type to PHP. You can even achieve SSRF through the proxy module. And this SSRF allows you to control request headers and can read all the response. And super thanks to the convenience brought by the proxy module, the most awesome thing about this SSRF is that it can also access the local Unix domain sockets. So, lastly, let's demonstrate how to turn this SSRF into a RCE. Here, we used a common trick in CTF. The official PHP docker image, by default, comes with peer, a PHP extension manager. And the peer CMD is the entry point used to manage manage the package. So, we can leverage this SSRF to ask you the peer CMD to do further exploitations. For example, we exploit a command injection in the run test command. And we can get a reverse shell easily to ask you arbitrary commands. So, please do not report a header-based CRF injection as an XSS again. It's really a waste. Because today, you have learned a new way to exploit. This type of bug has the potential to become RCE. Here, my presentation is almost coming to the end. And


chunk_text:
  into your PHP backdoor by setting the content type to PHP. You can even achieve SSRF through the proxy module. And this SSRF allows you to control request headers and can read all the response. And super thanks to the convenience brought by the proxy module, the most awesome thing about this SSRF is that it can also access the local Unix domain sockets. So, lastly, let's demonstrate how to turn this SSRF into a RCE. Here, we used a common trick in CTF. The official PHP docker image, by default, comes with peer, a PHP extension manager. And the peer CMD is the entry point used to manage manage the package. So, we can leverage this SSRF to ask you the peer CMD to do further exploitations. For example, we exploit a command injection in the run test command. And we can get a reverse shell easily to ask you arbitrary commands. So, please do not report a header-based CRF injection as an XSS again. It's really a waste. Because today, you have learned a new way to exploit. This type of bug has the potential to become RCE. Here, my presentation is almost coming to the end. And before closing, I want to say maintaining open source is really challenging. Especially keeping a project for 30 years. You have to make it convenient for end users and compatible with all versions. The entire development process is built upon a pile of legacy code and technical depth. So, if there are any Apache developers in the audience today, I want to say thank you for all of your hard work. And before we finish, let's have a few takeaways. So, first, the question mark is a powerful tool that allows you to truncate arbitrary paths. You can bypass SS control and authentication easily by playing the inconsistency between the modules. And next, the rewrite rule contains the hidden trap that allows access to the system loop. And lastly, by controlling the response header, you can invoke arbitrary internal handler through the legacy conversion mechanism. Also, there are some future works. For example, for example, different distributions have different configurations. So, exploring such as the FreeBSD or even on-premise applications could reveal more load-by-default SCL and reveal more local gadgets and symbolic links. And finally, due to the time constraint, I'm not able to introduce some real-world cases. But you


chunk_text:
  before closing, I want to say maintaining open source is really challenging. Especially keeping a project for 30 years. You have to make it convenient for end users and compatible with all versions. The entire development process is built upon a pile of legacy code and technical depth. So, if there are any Apache developers in the audience today, I want to say thank you for all of your hard work. And before we finish, let's have a few takeaways. So, first, the question mark is a powerful tool that allows you to truncate arbitrary paths. You can bypass SS control and authentication easily by playing the inconsistency between the modules. And next, the rewrite rule contains the hidden trap that allows access to the system loop. And lastly, by controlling the response header, you can invoke arbitrary internal handler through the legacy conversion mechanism. Also, there are some future works. For example, for example, different distributions have different configurations. So, exploring such as the FreeBSD or even on-premise applications could reveal more load-by-default SCL and reveal more local gadgets and symbolic links. And finally, due to the time constraint, I'm not able to introduce some real-world cases. But you can imagine there must be countless rewrite rules to figure out. There are a lot of SCLs to be bypassed and a lot of hidden CGI's out there. Applying all the techniques we discussed today to bug bounty hunting is now your mission. Okay, this is the end of my presentation. If you have any questions, here's my contact information. And thank you for being here again. Thanks.


chunk_text:
  can imagine there must be countless rewrite rules to figure out. There are a lot of SCLs to be bypassed and a lot of hidden CGI's out there. Applying all the techniques we discussed today to bug bounty hunting is now your mission. Okay, this is the end of my presentation. If you have any questions, here's my contact information. And thank you for being here again. Thanks.


chunk_text:
  { "webpage_url": "https://www.youtube.com/watch?v=8FAqOkgte8o", "title": "Securing Devices Or Profit? Examining The Device Security Of A Network Appliance Vendor - Hal Martin", "description": "", "channel_url": "https://www.youtube.com/channel/UCgJoGNj3B2Mt2F3TUblcoOA", "duration": 1671, "channel": "OrangeCon", "uploader": "OrangeCon", "upload_date": "20240909" } This text was transcribed using whisper model: large-v2 you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you you


chunk_text:
  { "webpage_url": "https://www.youtube.com/watch?v=481SI_HWlLs", "title": "From COM Object Fundamentals To UAC Bypasses - Tijme Gommers", "description": "", "channel_url": "https://www.youtube.com/channel/UCgJoGNj3B2Mt2F3TUblcoOA", "duration": 1521, "channel": "OrangeCon", "uploader": "OrangeCon", "upload_date": "20240909" } This text was transcribed using whisper model: large-v2 Welcome, everyone, to this talk titled Elevate Your Knowledge from COM Object Fundamentals to UAC Bypasses. Whoa. A UAC popup. Let me quickly click that away. Because I would first like to introduce myself. My name is Thijm Gommers. I perform offensive cybersecurity operations, research and innovation at the ABN Amro Bank. Actually recently joined the bank previously. I had actually the same role at Northwave Cybersecurity, which is a cybersecurity firm in the Netherlands. And as a side quest in life, I perform digital forensics at Hunted, which is a Dutch television show. So you might sometimes see me on NPO3 somewhere in a corner hacking into a mobile phone. And I'm the author of some exploits and some malware, which I published on my GitHub profile. My username is my first name. So you can find it there. It's actually the case for all my social media profiles. So if you have any questions afterwards after this presentation, feel free to send me a message. Because I'll probably talk for 30 minutes straight. So today I'm going to teach you three things. First, tokens and privileges in the Windows operating system. And especially when you log into your system. Afterwards, secondly, user account control and how that interconnects with those tokens and privileges when you log in. And thirdly, which seems not related, the component object model in Windows, which will be a high overcross course, because it's pretty, it can get pretty complicated. And hopefully at the end, we'll be able to combine the three into a demo, which shows how we can actually bypass UAC. And hopefully by then you also know how that technically works on the water. So let's get into those tokens and privileges. Let's say you boot your Windows computer or you connect to it remotely. You press control alt delete. What happens then is that a process called WinLogon, which runs a system, will actually spawn a new process called Logon UI. And this is the UI that you see when you log in. That we see right there as well. And you enter your credentials. And you press enter to try to authenticate. What then


chunk_text:
  a message. Because I'll probably talk for 30 minutes straight. So today I'm going to teach you three things. First, tokens and privileges in the Windows operating system. And especially when you log into your system. Afterwards, secondly, user account control and how that interconnects with those tokens and privileges when you log in. And thirdly, which seems not related, the component object model in Windows, which will be a high overcross course, because it's pretty, it can get pretty complicated. And hopefully at the end, we'll be able to combine the three into a demo, which shows how we can actually bypass UAC. And hopefully by then you also know how that technically works on the water. So let's get into those tokens and privileges. Let's say you boot your Windows computer or you connect to it remotely. You press control alt delete. What happens then is that a process called WinLogon, which runs a system, will actually spawn a new process called Logon UI. And this is the UI that you see when you log in. That we see right there as well. And you enter your credentials. And you press enter to try to authenticate. What then happens is that Logon UI will actually forward those credentials to WinLogon again, the WinLogon process. And on its turn, that process will forward the credentials to LSAS, which is the local security authority subsystem service. Which is a fancy name for basically the process that manages authentication and authorization within Windows. Now when your credentials are correct, LSAS will actually create a token for you, which is your own personal token that is linked to your account. And this token will be returned back to WinLogon. And what WinLogon will do with it, it will spawn a new process called UserInit using your token. So UserInit is the first process that spawns in your Windows computer using your privileges. And UserInit does a bunch of things. But the most important one is starting explorer.exe, which we all know. And then your actual Windows desktop environment is visible to you. Now, what does such a token actually look like? It's a struct of data, and I'm not going to go into depth of all the attributes that it has, because there are a lot of them. But I'm going to cover some important ones. One which you all know is


chunk_text:
  happens is that Logon UI will actually forward those credentials to WinLogon again, the WinLogon process. And on its turn, that process will forward the credentials to LSAS, which is the local security authority subsystem service. Which is a fancy name for basically the process that manages authentication and authorization within Windows. Now when your credentials are correct, LSAS will actually create a token for you, which is your own personal token that is linked to your account. And this token will be returned back to WinLogon. And what WinLogon will do with it, it will spawn a new process called UserInit using your token. So UserInit is the first process that spawns in your Windows computer using your privileges. And UserInit does a bunch of things. But the most important one is starting explorer.exe, which we all know. And then your actual Windows desktop environment is visible to you. Now, what does such a token actually look like? It's a struct of data, and I'm not going to go into depth of all the attributes that it has, because there are a lot of them. But I'm going to cover some important ones. One which you all know is the SID, Security Identifier, which is a unique ID for your user in the Windows operating system, and maybe even in the domain you are in. It also contains group security IDs, so the SIDs of the groups that you are a part of, you are a member of. For example, the built-in users group or the built-in administrators group. And at the bottom, you can also see it contains something with medium, mandatory label, medium mandatory level, sometimes called integrity level or integrity label or mandatory level. It's all the name for the same thing. And in this case, it's medium, and I'll cover it later on in the presentation. Now, it contains a lot of more stuff, but I think for this presentation, there's one more important thing in that token, and that's the list of privileges that are assigned to you. For example, the SE shutdown privileges for you to be able to shut down your computer. For example, the SE shutdown privileges for you to be able to shut down your computer. All those privileges that you have in the list that are assigned to you have certain attributes. So, for example, a privilege can be


chunk_text:
  the SID, Security Identifier, which is a unique ID for your user in the Windows operating system, and maybe even in the domain you are in. It also contains group security IDs, so the SIDs of the groups that you are a part of, you are a member of. For example, the built-in users group or the built-in administrators group. And at the bottom, you can also see it contains something with medium, mandatory label, medium mandatory level, sometimes called integrity level or integrity label or mandatory level. It's all the name for the same thing. And in this case, it's medium, and I'll cover it later on in the presentation. Now, it contains a lot of more stuff, but I think for this presentation, there's one more important thing in that token, and that's the list of privileges that are assigned to you. For example, the SE shutdown privileges for you to be able to shut down your computer. For example, the SE shutdown privileges for you to be able to shut down your computer. All those privileges that you have in the list that are assigned to you have certain attributes. So, for example, a privilege can be enabled for you to use right now, or it can be disabled, but present, which means you can enable it without any further privileges required, and you can use it. Or it could be, for example, that it's not present at all, and then you cannot use those privileges at all in your token. And there are many more privileges. Another example is the SE load driver privilege, for example, to load a kernel driver in memory. So, if you log in to your Windows computer and you launch the CMD shell as a standard user, so not as a local admin, and you run a UMI, you'll see which kind of privileges are assigned to you. And we can see that right here. We've got five privileges assigned, some of them are disabled, and some of them are enabled. And we can see that we are running in medium integrity. Now, you would say that if you log in as local administrator instead of as a standard user, you would get more privileges. But that is actually not the case. You would get the same amount of privileges and the same integrity label, and that is because of something


chunk_text:
  enabled for you to use right now, or it can be disabled, but present, which means you can enable it without any further privileges required, and you can use it. Or it could be, for example, that it's not present at all, and then you cannot use those privileges at all in your token. And there are many more privileges. Another example is the SE load driver privilege, for example, to load a kernel driver in memory. So, if you log in to your Windows computer and you launch the CMD shell as a standard user, so not as a local admin, and you run a UMI, you'll see which kind of privileges are assigned to you. And we can see that right here. We've got five privileges assigned, some of them are disabled, and some of them are enabled. And we can see that we are running in medium integrity. Now, you would say that if you log in as local administrator instead of as a standard user, you would get more privileges. But that is actually not the case. You would get the same amount of privileges and the same integrity label, and that is because of something called UAC, user account control, which was introduced in Windows Vista. So, if you try to do this on Windows XP and log in as a local administrator, you would see that you would actually get all the privileges that you would want. And you would say that you would be running in high integrity, but that was not a thing in Windows XP because UAC wasn't introduced yet. So, let's briefly take a look at what user account control actually is and how it affects your tokens from Windows Vista onwards. So, the login as a local administrator on Windows Vista onwards is somewhat the same as a standard user login. It became similar. The only exception or difference is that instead of returning one token, LSS will return two tokens on login. One token is a filtered token with only five privileges that we saw earlier, running in medium integrity. And the other one is an elevated token with all the privileges that you need for a local admin, running in high integrity. And WinLogon will spawn user init and explorer.exe using the filtered token. But of course, as an administrator, you can perform actions with your elevated


chunk_text:
  called UAC, user account control, which was introduced in Windows Vista. So, if you try to do this on Windows XP and log in as a local administrator, you would see that you would actually get all the privileges that you would want. And you would say that you would be running in high integrity, but that was not a thing in Windows XP because UAC wasn't introduced yet. So, let's briefly take a look at what user account control actually is and how it affects your tokens from Windows Vista onwards. So, the login as a local administrator on Windows Vista onwards is somewhat the same as a standard user login. It became similar. The only exception or difference is that instead of returning one token, LSS will return two tokens on login. One token is a filtered token with only five privileges that we saw earlier, running in medium integrity. And the other one is an elevated token with all the privileges that you need for a local admin, running in high integrity. And WinLogon will spawn user init and explorer.exe using the filtered token. But of course, as an administrator, you can perform actions with your elevated token in high integrity mode. And this is how that looks like. You log into your PC, you see Explorer running. It runs in medium integrity with the filtered token. You right-click your CMD, run as admin. You can send the UAC pop-up, and there you go. You're running in high integrity with all the privileges you need. Now, what exactly is that integrity mode? This was a little bit more complicated than that. What exactly is that integrity mode? This was also introduced with UAC, and it's pretty important, actually. Almost all objects in Windows have an integrity mode. And with an object, you can think about a process or a file or maybe a directory. So, for example, the CRoot directory has an integrity mode of high. There are a lot of available integrity levels, but the most common ones we're going to cover right now are medium and high. And the rule of thumb is, to modify or interact with such an object, you need to have the same integrity level or higher. And this is also why, with your standard local admin login, you cannot just drop a file in the CRoot, because you would need


chunk_text:
  token in high integrity mode. And this is how that looks like. You log into your PC, you see Explorer running. It runs in medium integrity with the filtered token. You right-click your CMD, run as admin. You can send the UAC pop-up, and there you go. You're running in high integrity with all the privileges you need. Now, what exactly is that integrity mode? This was a little bit more complicated than that. What exactly is that integrity mode? This was also introduced with UAC, and it's pretty important, actually. Almost all objects in Windows have an integrity mode. And with an object, you can think about a process or a file or maybe a directory. So, for example, the CRoot directory has an integrity mode of high. There are a lot of available integrity levels, but the most common ones we're going to cover right now are medium and high. And the rule of thumb is, to modify or interact with such an object, you need to have the same integrity level or higher. And this is also why, with your standard local admin login, you cannot just drop a file in the CRoot, because you would need to confirm the UAC pop-up there, because it runs in high integrity, that folder. And I'm going to give another example, which was pretty wild to me, when I found out. So, let's say we run a shell in medium integrity. We are logged in as a local admin. And we create a file called file.txt, and we list the ACLs on the file, the access control list. We can see that we are the owner, and we have full control over the file, so we can do anything we want with it. Let's now say we spawn a new CMD shell in high integrity mode, and we adjust the integrity mode of file.txt. So, we set it using ICALCLS. I spelled that correctly, but it doesn't matter. And we use set integrity level high. That works, and we can now revert back to the medium integrity shell, and we can list the ACLs again. We can see that we still have full control over the file, but there's now a high integrity label involved. When we now try to write to that file, we actually get an access denied, although we have that full control. So, now you may


chunk_text:
  to confirm the UAC pop-up there, because it runs in high integrity, that folder. And I'm going to give another example, which was pretty wild to me, when I found out. So, let's say we run a shell in medium integrity. We are logged in as a local admin. And we create a file called file.txt, and we list the ACLs on the file, the access control list. We can see that we are the owner, and we have full control over the file, so we can do anything we want with it. Let's now say we spawn a new CMD shell in high integrity mode, and we adjust the integrity mode of file.txt. So, we set it using ICALCLS. I spelled that correctly, but it doesn't matter. And we use set integrity level high. That works, and we can now revert back to the medium integrity shell, and we can list the ACLs again. We can see that we still have full control over the file, but there's now a high integrity label involved. When we now try to write to that file, we actually get an access denied, although we have that full control. So, now you may understand that from an attacker point of view, you would actually want to bypass UAC, because you probably want to write, for example, to the C drive or C Windows folder, or maybe you want to load a kernel driver, you need the privileges in the elevated token, or maybe you want to impersonate another user which you need those privileges for. So, how do we bypass UAC? Why don't we just use the CMSTP Lua and CM Lua COM object and COM interface? Why not? So, let's, to explain how that works, let's first take a look at the component object model briefly, and see how that works and looks like. COM is actually a client server model, which allows you to perform interprocess communications. So, it's much like an HTTP API. You've got your client, which talks to a server, the API, and you offload work to the server. One COM that works the same, but it's mostly on the same machine. So, you've got your client, which could be your program or your exploit or your client.exe, which invokes a COM object, the server, which could be a DLL hosted on the machine. That is on the


chunk_text:
  understand that from an attacker point of view, you would actually want to bypass UAC, because you probably want to write, for example, to the C drive or C Windows folder, or maybe you want to load a kernel driver, you need the privileges in the elevated token, or maybe you want to impersonate another user which you need those privileges for. So, how do we bypass UAC? Why don't we just use the CMSTP Lua and CM Lua COM object and COM interface? Why not? So, let's, to explain how that works, let's first take a look at the component object model briefly, and see how that works and looks like. COM is actually a client server model, which allows you to perform interprocess communications. So, it's much like an HTTP API. You've got your client, which talks to a server, the API, and you offload work to the server. One COM that works the same, but it's mostly on the same machine. So, you've got your client, which could be your program or your exploit or your client.exe, which invokes a COM object, the server, which could be a DLL hosted on the machine. That is on the same machine. It can also happen in a network on different machines. This is called DACOM, distributed COM. When you communicate with the server, it goes over the network. What we see at the bottom here is somewhat of the flow of how that looks like when you want to communicate with a COM object. And a COM object is basically just a class that you can program yourself with attributes and functions, and you can initiate that class. And you can do the same with a COM object. So, in your client, you would ask Windows to initiate a certain COM object for you, and you do that via a GUID that is assigned to that COM object, which is a unique ID for the COM object. And if you are authorized to do so, Windows will initiate that COM object for you, and you will get a reference back. And using that reference, you can call functions in the COM object. And all that interaction afterwards happens via RPC. This is also why DACOM works over the network, also via RPC. And one of the advantages of COM objects is that the objects themselves are hot swappable, and


chunk_text:
  same machine. It can also happen in a network on different machines. This is called DACOM, distributed COM. When you communicate with the server, it goes over the network. What we see at the bottom here is somewhat of the flow of how that looks like when you want to communicate with a COM object. And a COM object is basically just a class that you can program yourself with attributes and functions, and you can initiate that class. And you can do the same with a COM object. So, in your client, you would ask Windows to initiate a certain COM object for you, and you do that via a GUID that is assigned to that COM object, which is a unique ID for the COM object. And if you are authorized to do so, Windows will initiate that COM object for you, and you will get a reference back. And using that reference, you can call functions in the COM object. And all that interaction afterwards happens via RPC. This is also why DACOM works over the network, also via RPC. And one of the advantages of COM objects is that the objects themselves are hot swappable, and I'll give an example of that as well. Let's first take a look at a library or code that is non-hot swappable. Let's say we want to provide users on systems with a file system library that has a function to move a file. And we see that library on the top right here. Some pseudocode. It copies the file, and then it deletes the source. It's ugly, but it works. And we can compile it to this file system library dot object, and we can then ship that code to customers or clients or whatever. And they can write a program that uses that function, and they then compile it and statically link it with our file system library, and that would work. But now let's say that, unfortunately, we forgot the delete file line. Then we would have to recompile our library, which would work, but then we'd also have to reship it. And the clients all need to be recompiled with the new implementation and be statically linked to it, which is really inefficient. So you cannot swap the file system library without recompiling or changing anything in the client. And this is something that COM fixes.


chunk_text:
  I'll give an example of that as well. Let's first take a look at a library or code that is non-hot swappable. Let's say we want to provide users on systems with a file system library that has a function to move a file. And we see that library on the top right here. Some pseudocode. It copies the file, and then it deletes the source. It's ugly, but it works. And we can compile it to this file system library dot object, and we can then ship that code to customers or clients or whatever. And they can write a program that uses that function, and they then compile it and statically link it with our file system library, and that would work. But now let's say that, unfortunately, we forgot the delete file line. Then we would have to recompile our library, which would work, but then we'd also have to reship it. And the clients all need to be recompiled with the new implementation and be statically linked to it, which is really inefficient. So you cannot swap the file system library without recompiling or changing anything in the client. And this is something that COM fixes. So here's the same example, but in COM. We've got the same function, but in this case, we would register it as a COM object in Windows, which you can do using the Windows API. You just need to pass a GUID of your COM object, which you would like to use. And then every client that has that COM object on his computer can initiate the COM object via Windows COM using that GUID. And there's no further reference to during compilation time to that COM object at all. So it all happens on runtime. The object is initiated, and you can then use the move file operation on the object. And now let's say you forgot the delete file line here. It doesn't matter. You just recompile the COM object and re-register it. And for the movefile.exe, the client, you don't have to do anything else. It just works, because it all happens during the runtime. Now, COM is a binary interface standard, which also means that different types of programming languages can communicate with each other this way. So your COM component can, for example, be written in Golang, while the client may be written in Java.


chunk_text:
  So here's the same example, but in COM. We've got the same function, but in this case, we would register it as a COM object in Windows, which you can do using the Windows API. You just need to pass a GUID of your COM object, which you would like to use. And then every client that has that COM object on his computer can initiate the COM object via Windows COM using that GUID. And there's no further reference to during compilation time to that COM object at all. So it all happens on runtime. The object is initiated, and you can then use the move file operation on the object. And now let's say you forgot the delete file line here. It doesn't matter. You just recompile the COM object and re-register it. And for the movefile.exe, the client, you don't have to do anything else. It just works, because it all happens during the runtime. Now, COM is a binary interface standard, which also means that different types of programming languages can communicate with each other this way. So your COM component can, for example, be written in Golang, while the client may be written in Java. And usually, you cannot include a Golang library in your Java application unless you do some porting. With COM, that's possible, because the communication is a binary interface standard, and it happens on runtime. So this was some pseudocode, by the way. If you want to actually copy a file, for example, you would have to program yourself all this code. So it gets kind of messy, and it's a lot of overhead, which is why I don't like programming in COM myself. But it works, and it has some positive sides to it. So if you want to know in Windows which COM objects you can actually use, which are available to you, you can look in the registry. You can look in HKEYCLASSESROOT slash CLASSID, or CLSID, which will list all the COM objects available to you. You can see all the GUIDs right here, and on the right, you see the DOLs that are linked to it, where the COM objects are actually located. And we've also got a subkey called interface, and these contain all the interfaces which you can use to talk to the COM objects. So they contain the function definitions, for example, to


chunk_text:
  And usually, you cannot include a Golang library in your Java application unless you do some porting. With COM, that's possible, because the communication is a binary interface standard, and it happens on runtime. So this was some pseudocode, by the way. If you want to actually copy a file, for example, you would have to program yourself all this code. So it gets kind of messy, and it's a lot of overhead, which is why I don't like programming in COM myself. But it works, and it has some positive sides to it. So if you want to know in Windows which COM objects you can actually use, which are available to you, you can look in the registry. You can look in HKEYCLASSESROOT slash CLASSID, or CLSID, which will list all the COM objects available to you. You can see all the GUIDs right here, and on the right, you see the DOLs that are linked to it, where the COM objects are actually located. And we've also got a subkey called interface, and these contain all the interfaces which you can use to talk to the COM objects. So they contain the function definitions, for example, to actually move the file. Now, there's some fun stuff in COM. It works pretty closely together with UAC, pretty nicely together with UAC. There's a registry key in Windows, which you can see right here, which you can look up on your Windows machine, called COM auto-approval list. And this allows you to auto-elevate certain COM objects or certain functionality in COM objects to use your elevated token instead of the filtered token. There's only one constraint, and that is that the calling function, your client, must be a valid binary from Microsoft. And as a hacker, you don't have one, of course. So the thing is, the check that they perform to see if a binary is from Microsoft is weak. What they do is the COM object actually uses the process status API, PSAPI, to verify the calling process. And PSAPI uses the process environment block of a certain process to check the image path name of the process. Now, in processes in Windows, the process environment block is a piece of memory that you can modify yourself in your own process. And you can say in your own process that you want to get the process environment


chunk_text:
  actually move the file. Now, there's some fun stuff in COM. It works pretty closely together with UAC, pretty nicely together with UAC. There's a registry key in Windows, which you can see right here, which you can look up on your Windows machine, called COM auto-approval list. And this allows you to auto-elevate certain COM objects or certain functionality in COM objects to use your elevated token instead of the filtered token. There's only one constraint, and that is that the calling function, your client, must be a valid binary from Microsoft. And as a hacker, you don't have one, of course. So the thing is, the check that they perform to see if a binary is from Microsoft is weak. What they do is the COM object actually uses the process status API, PSAPI, to verify the calling process. And PSAPI uses the process environment block of a certain process to check the image path name of the process. Now, in processes in Windows, the process environment block is a piece of memory that you can modify yourself in your own process. And you can say in your own process that you want to get the process environment block in the struct. You want to have the process parameters. You want to reference the image path name. And you can just change it to explorer.exe. And this is exactly the check that the COM objects do, see if explorer.exe is invoking the COM object, for example. And this would allow you to actually copy a file in an elevated way with your elevated token. So you can copy a file to the C root drive without consenting to the UAC pop-up. Now, that is nice, of course. We can copy a file to the C root drive. But is that really, really bad or not? And maybe there are other COM objects that we can abuse in a more fancy way. And I think Logbit used this COM object a few years ago. It's called the CMSTP Lua COM object that they found in the COM auto approval list. CMSTP Lua stands for Connection Manager Surface Transport Profile. And this is actually a DLL that manages your VPN connections, for example, in your Windows operating system. The Lua that's behind it stands for Limited User Account Control, which is now known as... stands for Limited User Account, which


chunk_text:
  block in the struct. You want to have the process parameters. You want to reference the image path name. And you can just change it to explorer.exe. And this is exactly the check that the COM objects do, see if explorer.exe is invoking the COM object, for example. And this would allow you to actually copy a file in an elevated way with your elevated token. So you can copy a file to the C root drive without consenting to the UAC pop-up. Now, that is nice, of course. We can copy a file to the C root drive. But is that really, really bad or not? And maybe there are other COM objects that we can abuse in a more fancy way. And I think Logbit used this COM object a few years ago. It's called the CMSTP Lua COM object that they found in the COM auto approval list. CMSTP Lua stands for Connection Manager Surface Transport Profile. And this is actually a DLL that manages your VPN connections, for example, in your Windows operating system. The Lua that's behind it stands for Limited User Account Control, which is now known as... stands for Limited User Account, which is now known as User Account Control. So it confirms that we can also elevate this COM object. The thing is that copy file would be a documented COM object or a documented function in a COM object. But CMSTP Lua and CM Lua are not documented in Windows. So you cannot find out, or you can find out, but you cannot find out via documentation what functions you can call in an elevated way. So how would that work? Well, luckily, Microsoft ships debug symbols for every DLL in the Windows operating system. So you can just put your DLL in a disassembler of choice, in this case, Binary Ninja. And you can search for the interface name, in this case, CM Lua. And what you'll see on the left is all the functions of the interface that we can call on the COM object. And one of the interesting ones is shell exec. And we see the implementation on the right. What we see is that it accepts some arguments, and those arguments are passed to a Windows API function called shell execute extensive w, which is basically a function that allows you to execute a CMD command,


chunk_text:
  is now known as User Account Control. So it confirms that we can also elevate this COM object. The thing is that copy file would be a documented COM object or a documented function in a COM object. But CMSTP Lua and CM Lua are not documented in Windows. So you cannot find out, or you can find out, but you cannot find out via documentation what functions you can call in an elevated way. So how would that work? Well, luckily, Microsoft ships debug symbols for every DLL in the Windows operating system. So you can just put your DLL in a disassembler of choice, in this case, Binary Ninja. And you can search for the interface name, in this case, CM Lua. And what you'll see on the left is all the functions of the interface that we can call on the COM object. And one of the interesting ones is shell exec. And we see the implementation on the right. What we see is that it accepts some arguments, and those arguments are passed to a Windows API function called shell execute extensive w, which is basically a function that allows you to execute a CMD command, for example, or start a process with arguments. And so can we. So I developed a client.exe for this COM object, which firstly defines the interface of the COM object. We need to do that manually because it's not defined anywhere else. It contains the shell execute function, which we want to execute. And afterwards, I can use it to initiate the COM object. And we've got a function of that right here. So this is the GUID of the interface. This is the GUID of the COM object. And we instruct Windows COM to initiate the object for us in an auto-elevated way, which we see right here. Now, this would only work if we are explorer.exe. So before we run this, we actually need to spoof our process environment block to include that we are explorer.exe. And then we can invoke the initiated COM object. And then we can run the shell exec function on it with something like cmd.exe slash k slash wemi slash priv to see what kind of privileges that we have. I compiled this. I'll also publish it after this talk. I'll show QR code, which you can use to download the source code.


chunk_text:
  for example, or start a process with arguments. And so can we. So I developed a client.exe for this COM object, which firstly defines the interface of the COM object. We need to do that manually because it's not defined anywhere else. It contains the shell execute function, which we want to execute. And afterwards, I can use it to initiate the COM object. And we've got a function of that right here. So this is the GUID of the interface. This is the GUID of the COM object. And we instruct Windows COM to initiate the object for us in an auto-elevated way, which we see right here. Now, this would only work if we are explorer.exe. So before we run this, we actually need to spoof our process environment block to include that we are explorer.exe. And then we can invoke the initiated COM object. And then we can run the shell exec function on it with something like cmd.exe slash k slash wemi slash priv to see what kind of privileges that we have. I compiled this. I'll also publish it after this talk. I'll show QR code, which you can use to download the source code. And it also includes all kinds of smaller programs to communicate with COM objects so you can try it out yourself. I compiled it for you so you can just run it straight away. And I'll demo that right now. So let's start our Windows VM. Let's run a wemi slash priv to list the current privileges. We are logged in as an administrator, but we are running with a filter token. You can see that because we only have five privileges and our integrity level is currently medium. Now we run the compiled UAC bypass with cmd.exe and we can see that a new cmdl shell executes. And in this cmd shell, we can run wemi slash priv again. And hopefully we'll see all the privileges, but some of them are disabled, which is not a bad thing because we can enable them. And if we look at the integrity level we are in right now, we can see that we are running in high integrity mode. And I also created a program for you, which I also published to enable all the privileges in this current process. We are running that right now. Hopefully that's successful. And we


chunk_text:
  And it also includes all kinds of smaller programs to communicate with COM objects so you can try it out yourself. I compiled it for you so you can just run it straight away. And I'll demo that right now. So let's start our Windows VM. Let's run a wemi slash priv to list the current privileges. We are logged in as an administrator, but we are running with a filter token. You can see that because we only have five privileges and our integrity level is currently medium. Now we run the compiled UAC bypass with cmd.exe and we can see that a new cmdl shell executes. And in this cmd shell, we can run wemi slash priv again. And hopefully we'll see all the privileges, but some of them are disabled, which is not a bad thing because we can enable them. And if we look at the integrity level we are in right now, we can see that we are running in high integrity mode. And I also created a program for you, which I also published to enable all the privileges in this current process. We are running that right now. Hopefully that's successful. And we list our privileges again. And then we'll see that all privileges are now enabled. And we've successfully bypassed UAC without any pop-ups shown to the user. So thank you very much. If you want to have the source code, scan the QR code, the presentation is also included. And also if you want to ask me any questions, feel free to ask them on social media or maybe there is some time for questions. Well, thank you very much. Are there any questions in the audience? Hi, thanks for the talk. Did you report this to Microsoft and did you get any response? Did you get any response? I did not report it to Microsoft, so I didn't get any response. It is actually a technique that was used by LockBit, I think about a year ago or two years ago. And I'm not sure if they will fix it. I wonder if they actually see it as a boundary of privilege escalation in that way. So no, I did not report it. So it's free for you to use right now. Thank you very much. Any other questions? So thank you very much for the presentation. I'm wondering if


chunk_text:
  list our privileges again. And then we'll see that all privileges are now enabled. And we've successfully bypassed UAC without any pop-ups shown to the user. So thank you very much. If you want to have the source code, scan the QR code, the presentation is also included. And also if you want to ask me any questions, feel free to ask them on social media or maybe there is some time for questions. Well, thank you very much. Are there any questions in the audience? Hi, thanks for the talk. Did you report this to Microsoft and did you get any response? Did you get any response? I did not report it to Microsoft, so I didn't get any response. It is actually a technique that was used by LockBit, I think about a year ago or two years ago. And I'm not sure if they will fix it. I wonder if they actually see it as a boundary of privilege escalation in that way. So no, I did not report it. So it's free for you to use right now. Thank you very much. Any other questions? So thank you very much for the presentation. I'm wondering if you're aware about any antivirus software that can detect this behavior of accessing these common objects, because it looks like this type of privilege escalation or UARC bypass can be detected by the sandbox of antivirus by simply monitoring all the methods that are being called on the common object model. So you want to know if there's a way to detect it? Yeah, I'm wondering if you're aware about any software that can detect it right now. I think I'm not sure if Windows Defender for Endpoint will detect it, but I think a lot of security operations centers have rules for these kinds of UARC bypasses. For example, the Windows APIs that are being called can be hooked, so one knows that a common object is being initiated, and I think most of the common objects that are vulnerable to this UARC bypass are also known. So there are some GitHub repositories which list them all, so you can definitely write a detection rule to detect all of these UARC bypasses. I'm not sure which products do that by default. Well, thank you very much. I'm afraid that's all about the time we have for this session. I


chunk_text:
  you're aware about any antivirus software that can detect this behavior of accessing these common objects, because it looks like this type of privilege escalation or UARC bypass can be detected by the sandbox of antivirus by simply monitoring all the methods that are being called on the common object model. So you want to know if there's a way to detect it? Yeah, I'm wondering if you're aware about any software that can detect it right now. I think I'm not sure if Windows Defender for Endpoint will detect it, but I think a lot of security operations centers have rules for these kinds of UARC bypasses. For example, the Windows APIs that are being called can be hooked, so one knows that a common object is being initiated, and I think most of the common objects that are vulnerable to this UARC bypass are also known. So there are some GitHub repositories which list them all, so you can definitely write a detection rule to detect all of these UARC bypasses. I'm not sure which products do that by default. Well, thank you very much. I'm afraid that's all about the time we have for this session. I would like to thank you very much for your elevating talk, and we have a challenge going for you. Thank you very much. My pleasure. Round of applause, please.


chunk_text:
  would like to thank you very much for your elevating talk, and we have a challenge going for you. Thank you very much. My pleasure. Round of applause, please.


chunk_text:
  { "webpage_url": "https://www.youtube.com/watch?v=39N9qJk55Ac", "title": "Exploiting The Core: A Deep Dive Into Kernel Driver Vulnerability Hunting - Jan-Jaap Korpershoek", "description": "", "channel_url": "https://www.youtube.com/channel/UCgJoGNj3B2Mt2F3TUblcoOA", "duration": 1958, "channel": "OrangeCon", "uploader": "OrangeCon", "upload_date": "20240909" } This text was transcribed using whisper model: large-v2 Yes, my name is Jan-Jaap Koopenshoek, I'm a Red Teamer and Reverse Engineer for Northway Cybersecurity and in this talk I want to give you a primer into Kernel Driver Vulnerability Research, specifically for Windows Kernel Drivers. And my aim with this presentation is to give you the knowledge and the tools that you need to start your own research in this area. To do that, I have different topics I want to discuss. First I'll give a bit of context about offensive use of Kernel Drivers. Then I'll discuss our own research at Northwave and give some overview of that. And then we'll do a deep dive into the technical details, first about how drivers work and how they are used. And then I will show you some common vulnerabilities that you might be able to find in Kernel Drivers if you start your own research. And we'll end with some automated tools and a conclusion. Imagine that this castle is your computer's security. So you can see it has very steep walls. It maybe has watchers on the walls. And this will pretty much keep an attacker out, or so you think. Because if the whole system is actually built on a core that is instable or insecure, an attacker that has access to the core can bypass any security measures and topple the whole system. And this image also lets me show you a bit about the difference between user mode and kernel mode. In user mode, we have our normal user. We even have our admin user. We even have an elevated admin user, as Taima talked about in the previous talk. And then we have one level lower, the actual kernel. And on this level, all security measures are basically off. And you can bypass a lot of the security measures that are normally existing. We have also seen the power of kernel drivers recently in the news. A small bug in one security product caused a lot of computers and systems over the whole world to topple and stop working. And this shows you a bit about what an attacker can do with access to


chunk_text:
  is your computer's security. So you can see it has very steep walls. It maybe has watchers on the walls. And this will pretty much keep an attacker out, or so you think. Because if the whole system is actually built on a core that is instable or insecure, an attacker that has access to the core can bypass any security measures and topple the whole system. And this image also lets me show you a bit about the difference between user mode and kernel mode. In user mode, we have our normal user. We even have our admin user. We even have an elevated admin user, as Taima talked about in the previous talk. And then we have one level lower, the actual kernel. And on this level, all security measures are basically off. And you can bypass a lot of the security measures that are normally existing. We have also seen the power of kernel drivers recently in the news. A small bug in one security product caused a lot of computers and systems over the whole world to topple and stop working. And this shows you a bit about what an attacker can do with access to kernel driver vulnerabilities. And indeed, we see that attackers are also actively abusing kernel drivers in their attacks. Here we see a news article about a North Korean APT, and they use kernel drivers to gain more privileges on systems. And also a financially motivated attacker that is described here, they also use these kinds of techniques to help their hacking attempts. And also from the offensive security side, the ethical hackers, there are a lot of tools that use kernel drivers. This is an example by Outflank, a tool that can dump LSS credentials through a kernel driver, thereby bypassing some security measures in user space. There's also Backstab, Blackout. These tools have the same goal of disabling antivirus by using a vulnerable kernel driver. And there's also an initiative by security researchers called LOL Drivers. And it contains a list of a lot of known drivers that are vulnerable in this way and can be used for malicious purposes. And in a recent research published by Kaspersky, we also see that the bring your own vulnerable driver attacks are really gaining popularity over the last years. So yeah, that really shows you how important this is. And that


chunk_text:
  kernel driver vulnerabilities. And indeed, we see that attackers are also actively abusing kernel drivers in their attacks. Here we see a news article about a North Korean APT, and they use kernel drivers to gain more privileges on systems. And also a financially motivated attacker that is described here, they also use these kinds of techniques to help their hacking attempts. And also from the offensive security side, the ethical hackers, there are a lot of tools that use kernel drivers. This is an example by Outflank, a tool that can dump LSS credentials through a kernel driver, thereby bypassing some security measures in user space. There's also Backstab, Blackout. These tools have the same goal of disabling antivirus by using a vulnerable kernel driver. And there's also an initiative by security researchers called LOL Drivers. And it contains a list of a lot of known drivers that are vulnerable in this way and can be used for malicious purposes. And in a recent research published by Kaspersky, we also see that the bring your own vulnerable driver attacks are really gaining popularity over the last years. So yeah, that really shows you how important this is. And that is a nice bridge into our own research in this area. So let's first start with introducing the team. I did not do this research on my own. I did it together with Alex, our reverse engineer at Northwave. Also Thijm Gommers, the previous speaker when he still worked at Northwave. He also worked on this project. And finally me. So some statistics about our research. We created a database of around 5,000 drivers. And we filtered them to see which drivers have good potential for analysis. I'll get to that later. And in these drivers that we manually analyzed of about 80, we found 35 vulnerabilities in 24 drivers. So that gives you a bit of an indication in how large of a percentage of drivers are actually vulnerable. If you do a bit of filtering, you can actually get almost, well, we got almost 30% vulnerable drivers. Of these, 12 could be used for privilege escalation and 4 could disable the EDR in a similar way to Backstab and the other project. So some highlights of our research. We found a vulnerability in Ivanti Pulse Secure. Well, this is a very well-known product. And we found a way


chunk_text:
  is a nice bridge into our own research in this area. So let's first start with introducing the team. I did not do this research on my own. I did it together with Alex, our reverse engineer at Northwave. Also Thijm Gommers, the previous speaker when he still worked at Northwave. He also worked on this project. And finally me. So some statistics about our research. We created a database of around 5,000 drivers. And we filtered them to see which drivers have good potential for analysis. I'll get to that later. And in these drivers that we manually analyzed of about 80, we found 35 vulnerabilities in 24 drivers. So that gives you a bit of an indication in how large of a percentage of drivers are actually vulnerable. If you do a bit of filtering, you can actually get almost, well, we got almost 30% vulnerable drivers. Of these, 12 could be used for privilege escalation and 4 could disable the EDR in a similar way to Backstab and the other project. So some highlights of our research. We found a vulnerability in Ivanti Pulse Secure. Well, this is a very well-known product. And we found a way to do privilege escalation in the VPN client. This is also posted on our blog. Another one that we recently found is in Macrium. This is enterprise backup software. And we also found a way to do privilege escalation based on a vulnerability in a driver of this software. And a final highlight is LogMeIn. You might all know this from Hamachi, which used to be popular back in the day for gaming. But it's also used in enterprises. And here we also found a privilege escalation in the remote desktop software, and specifically the kernel driver used there. So some highlights of what we can achieve. Now let's dive into getting you the tools to do similar research and get your own vulnerabilities. So the first step to do research is to actually gather the drivers. So how do you do that? There are several sources that you can consider. Most obvious choice is the Microsoft Update Catalog. This is where Windows downloads drivers from. If you couple a certain device and it doesn't know the driver, it gets it from this catalog. And it's pretty easy to scrape this and extract all kinds of drivers from it. A


chunk_text:
  to do privilege escalation in the VPN client. This is also posted on our blog. Another one that we recently found is in Macrium. This is enterprise backup software. And we also found a way to do privilege escalation based on a vulnerability in a driver of this software. And a final highlight is LogMeIn. You might all know this from Hamachi, which used to be popular back in the day for gaming. But it's also used in enterprises. And here we also found a privilege escalation in the remote desktop software, and specifically the kernel driver used there. So some highlights of what we can achieve. Now let's dive into getting you the tools to do similar research and get your own vulnerabilities. So the first step to do research is to actually gather the drivers. So how do you do that? There are several sources that you can consider. Most obvious choice is the Microsoft Update Catalog. This is where Windows downloads drivers from. If you couple a certain device and it doesn't know the driver, it gets it from this catalog. And it's pretty easy to scrape this and extract all kinds of drivers from it. A drawback that we found for this is that because Microsoft has quite some strict policies for accepting drivers, there is some security screening on the drivers in this catalog. So we found that the percentage of vulnerable drivers in this catalog was lower than what we found in different ways. So what you could also consider is going to vendor websites themselves. This is just an example of a vendor, but there are many vendors. You could scrape their pages and gather drivers in that way. But that's obviously a lot of work. Another source is Driver Identifier or the like. There's a ton of driver updater software in existence and you could reverse engineer how they get their drivers and try to pull the drivers out of their database. And finally, there's also VirusTotal. This service is usually used to upload malware, but a lot of people upload also legitimate software there and it is cached for anyone with a license to download it. And we also downloaded a lot of drivers from VirusTotal for our research. So that's also a source that I can recommend. So once you have all these drivers, you need to do some filtering


chunk_text:
  drawback that we found for this is that because Microsoft has quite some strict policies for accepting drivers, there is some security screening on the drivers in this catalog. So we found that the percentage of vulnerable drivers in this catalog was lower than what we found in different ways. So what you could also consider is going to vendor websites themselves. This is just an example of a vendor, but there are many vendors. You could scrape their pages and gather drivers in that way. But that's obviously a lot of work. Another source is Driver Identifier or the like. There's a ton of driver updater software in existence and you could reverse engineer how they get their drivers and try to pull the drivers out of their database. And finally, there's also VirusTotal. This service is usually used to upload malware, but a lot of people upload also legitimate software there and it is cached for anyone with a license to download it. And we also downloaded a lot of drivers from VirusTotal for our research. So that's also a source that I can recommend. So once you have all these drivers, you need to do some filtering because there will be duplicates, there will be different versions of the same driver, and in newer versions a vulnerability might already be fixed, so it's really not worth looking into the older drivers at this point. So you want to keep only the most recent version. You can filter drivers by signature because some vendors are known to pay close attention to their security, for example Microsoft themselves, antivirus vendors. So if you want to find easy vulnerabilities, you might want to exclude those drivers. You want to find drivers that need no special permission because if you need to have special permission to interact with the device, it's going to be more difficult to perform research on it. And finally, you can also do some automated analysis. At the end of the presentation I'll get to some tools that you can use for this, but if automated tools find bugs in the code or interesting points to look at, this can be a good starting point to start your manual research. So once we have a list of our drivers, the next step is to actually load them onto a test system. So to do this, we need


chunk_text:
  because there will be duplicates, there will be different versions of the same driver, and in newer versions a vulnerability might already be fixed, so it's really not worth looking into the older drivers at this point. So you want to keep only the most recent version. You can filter drivers by signature because some vendors are known to pay close attention to their security, for example Microsoft themselves, antivirus vendors. So if you want to find easy vulnerabilities, you might want to exclude those drivers. You want to find drivers that need no special permission because if you need to have special permission to interact with the device, it's going to be more difficult to perform research on it. And finally, you can also do some automated analysis. At the end of the presentation I'll get to some tools that you can use for this, but if automated tools find bugs in the code or interesting points to look at, this can be a good starting point to start your manual research. So once we have a list of our drivers, the next step is to actually load them onto a test system. So to do this, we need to know about different types of drivers. So there are plug-and-play drivers and there are the legacy drivers. Plug-and-play basically works like this. You connect a device to your computer and the computer then loads the specific driver needed for that device. This means that if you want to analyze a driver, you need to actually plug in the right device or find a way to spoof that device. So that's a bit more tricky than looking at legacy drivers, which can manually be loaded or are just loaded at the system boot. So for your first research, I would recommend looking at the legacy drivers because that is just easier and quicker. And specifically, I would recommend looking at device drivers. There are many different types of drivers with different ways to communicate with them. There's file system drivers, there's network drivers, but the device drivers are the most easy to interact with. There's just a simple system call that you can use to interact with it and there's many exploitation examples for these types of drivers. So this is really easy to get started for your own research. So how do we actually load the drivers then? Well,


chunk_text:
  to know about different types of drivers. So there are plug-and-play drivers and there are the legacy drivers. Plug-and-play basically works like this. You connect a device to your computer and the computer then loads the specific driver needed for that device. This means that if you want to analyze a driver, you need to actually plug in the right device or find a way to spoof that device. So that's a bit more tricky than looking at legacy drivers, which can manually be loaded or are just loaded at the system boot. So for your first research, I would recommend looking at the legacy drivers because that is just easier and quicker. And specifically, I would recommend looking at device drivers. There are many different types of drivers with different ways to communicate with them. There's file system drivers, there's network drivers, but the device drivers are the most easy to interact with. There's just a simple system call that you can use to interact with it and there's many exploitation examples for these types of drivers. So this is really easy to get started for your own research. So how do we actually load the drivers then? Well, there's a very easy example. You can just download software from the vendor and run the vendors installer to get the software. But not always do you have the vendors installer. So sometimes it can also be really easy to just use the service management tool from Windows to load the driver onto your system. I have put the commands here for future reference. So once the driver is loaded, we need to actually analyze the driver. So here I will dive into a bit of the technical details. I will first show you how a driver looks from a development perspective. So in the C source code, and then I will dive into how this looks in assembly from a reverse engineering perspective. So a driver starts with the driver entry function. As you may know, other software usually start from a main function. Well driver entry is basically the main function for the driver. And it has a couple of tasks, but the most important ones are creating a driver device. At least that is for device drivers. Well here it creates the device and this is actually the object that can later be used to interact with


chunk_text:
  there's a very easy example. You can just download software from the vendor and run the vendors installer to get the software. But not always do you have the vendors installer. So sometimes it can also be really easy to just use the service management tool from Windows to load the driver onto your system. I have put the commands here for future reference. So once the driver is loaded, we need to actually analyze the driver. So here I will dive into a bit of the technical details. I will first show you how a driver looks from a development perspective. So in the C source code, and then I will dive into how this looks in assembly from a reverse engineering perspective. So a driver starts with the driver entry function. As you may know, other software usually start from a main function. Well driver entry is basically the main function for the driver. And it has a couple of tasks, but the most important ones are creating a driver device. At least that is for device drivers. Well here it creates the device and this is actually the object that can later be used to interact with the driver. And after the object is created, it creates several handlers for different events that can happen with the driver. So we see here create, read, write and device control. Create is called when the user actually tries to communicate with the device. Then read and write can be called when the user is reading from the driver device or writing to the driver device, because it is basically a file to Windows. And the final one is the most interesting to us, which is the device IO control handler. And this actually handles the explicit communication from the user with the driver. And here we see the device IO control handler. It always has a specific format, so if you do your vulnerability research, you will definitely encounter this function. And here we see a bit of the steps. So firstly we see at the top, it gets the device IO control and this contains a code that is basically an index for the type of action that the driver needs to perform. So the user gives this ID and the driver does a lookup and performs the right action. And then there's the system buffer. And this


chunk_text:
  the driver. And after the object is created, it creates several handlers for different events that can happen with the driver. So we see here create, read, write and device control. Create is called when the user actually tries to communicate with the device. Then read and write can be called when the user is reading from the driver device or writing to the driver device, because it is basically a file to Windows. And the final one is the most interesting to us, which is the device IO control handler. And this actually handles the explicit communication from the user with the driver. And here we see the device IO control handler. It always has a specific format, so if you do your vulnerability research, you will definitely encounter this function. And here we see a bit of the steps. So firstly we see at the top, it gets the device IO control and this contains a code that is basically an index for the type of action that the driver needs to perform. So the user gives this ID and the driver does a lookup and performs the right action. And then there's the system buffer. And this is a buffer that the user gives to the driver with some data. It can be arbitrary data. And it's good to know that it consists of an input buffer and an output buffer from the user perspective. But in the kernel, this is merged into a single buffer. So there are also some vulnerabilities that are due to this fact, or at least do have to do with this fact. Now here we see a switch case statement for looking up the IO control code and performing the right action. And important for vulnerability research is knowing where the user input is. And in this case, it is the system buffer, the sizes of the system buffer, and also the IO control code. So we will see later how this can affect vulnerabilities. So that's how the driver looks. The next step is actually interacting with it. So you have the driver loaded on your system and then you want to know what is the device call that I want to interact with. There are two ways to find out. You can look in the driver itself, look for the strings, and usually there are some strings that immediately


chunk_text:
  is a buffer that the user gives to the driver with some data. It can be arbitrary data. And it's good to know that it consists of an input buffer and an output buffer from the user perspective. But in the kernel, this is merged into a single buffer. So there are also some vulnerabilities that are due to this fact, or at least do have to do with this fact. Now here we see a switch case statement for looking up the IO control code and performing the right action. And important for vulnerability research is knowing where the user input is. And in this case, it is the system buffer, the sizes of the system buffer, and also the IO control code. So we will see later how this can affect vulnerabilities. So that's how the driver looks. The next step is actually interacting with it. So you have the driver loaded on your system and then you want to know what is the device call that I want to interact with. There are two ways to find out. You can look in the driver itself, look for the strings, and usually there are some strings that immediately pop out and show you the device object. Another way is to use WinObject. It's a sysinternals tool and it also lists all the devices available on the system. And usually you can find by the name that a certain one is the one you need to use. And once you know that, you can actually interact with it. It's two calls. The first one is create file, which is the call to open a specific file. And since the device object is also a file on Windows, you can just open it in that way. And then you can interact with it using device IO control system call. And here we also see the user data being passed, first the device IO control code, then the data and the sizes. I skipped some details here to keep it clear for brevity, but the Microsoft documentation is pretty clear on how to use this. You might encounter some access controls. The first access control is defined through SDDL, the security descriptor definition language. I always forget that acronym. But it controls which kind of users can actually interact with the driver. So if you want to start your own research,


chunk_text:
  pop out and show you the device object. Another way is to use WinObject. It's a sysinternals tool and it also lists all the devices available on the system. And usually you can find by the name that a certain one is the one you need to use. And once you know that, you can actually interact with it. It's two calls. The first one is create file, which is the call to open a specific file. And since the device object is also a file on Windows, you can just open it in that way. And then you can interact with it using device IO control system call. And here we also see the user data being passed, first the device IO control code, then the data and the sizes. I skipped some details here to keep it clear for brevity, but the Microsoft documentation is pretty clear on how to use this. You might encounter some access controls. The first access control is defined through SDDL, the security descriptor definition language. I always forget that acronym. But it controls which kind of users can actually interact with the driver. So if you want to start your own research, it's easiest to look for drivers without an SDDL or a very permissive SDDL that permits any user to communicate with the driver. Another access control is in the create function. Remember that we had that handler for the create event. In that handler, the driver can also implement all kinds of checks. Is the process that is interacting what I expect? Is there a signature on the process? Is the right user connecting? So you also want to find a driver that doesn't do any checks in the create function. So let's move into the reverse engineering part. As you might know, usually you don't have the source code. So you will have to look at the assembly and open it in the disassembler and try to find out what you need to look at. Here I will show the C code and the assembly side by side to give you a view of how this looks like from a reverse engineering perspective. Here we have again the driver anti-function and I'll step through it with you. Here we see that it initializes a couple of strings. On the right, you can also see that you see the same


chunk_text:
  it's easiest to look for drivers without an SDDL or a very permissive SDDL that permits any user to communicate with the driver. Another access control is in the create function. Remember that we had that handler for the create event. In that handler, the driver can also implement all kinds of checks. Is the process that is interacting what I expect? Is there a signature on the process? Is the right user connecting? So you also want to find a driver that doesn't do any checks in the create function. So let's move into the reverse engineering part. As you might know, usually you don't have the source code. So you will have to look at the assembly and open it in the disassembler and try to find out what you need to look at. Here I will show the C code and the assembly side by side to give you a view of how this looks like from a reverse engineering perspective. Here we have again the driver anti-function and I'll step through it with you. Here we see that it initializes a couple of strings. On the right, you can also see that you see the same strings in our disassembler. This shows you already the devices that are created. These are also the devices you can look up to communicate. Then it actually creates the device with these two system calls. Then it moves on to initialization of the handler functions. On the right in the assembly, the function names don't make any sense. It's just the offsets. If you look at the offsets into the array, you can actually see 70, 80, and E0. This actually gives you an indication of which handler it is. First there is a fallback handler for all the events that are not implemented. Here we see that create, close, and device control are created. These are directly mapped to 70, 80, and E0. If we see something is written at offset E0, we always know that that function is our device I-O control handler. Here I have given the functions clearer names. If we look more closely at the device I-O control handler, we see it first gets some data from the user input, the IRP, the request packet, the I-O request packet. It gets the I-O control code at offset 18. It gets the input and output buffer


chunk_text:
  strings in our disassembler. This shows you already the devices that are created. These are also the devices you can look up to communicate. Then it actually creates the device with these two system calls. Then it moves on to initialization of the handler functions. On the right in the assembly, the function names don't make any sense. It's just the offsets. If you look at the offsets into the array, you can actually see 70, 80, and E0. This actually gives you an indication of which handler it is. First there is a fallback handler for all the events that are not implemented. Here we see that create, close, and device control are created. These are directly mapped to 70, 80, and E0. If we see something is written at offset E0, we always know that that function is our device I-O control handler. Here I have given the functions clearer names. If we look more closely at the device I-O control handler, we see it first gets some data from the user input, the IRP, the request packet, the I-O request packet. It gets the I-O control code at offset 18. It gets the input and output buffer length. It's a bit optimized on the right, but you can at least see that one of the lengths is obtained. It also obtains the system buffer. That one is most interesting for us because it contains all the user inputs. Here we see a lot of branching statements on the right. This usually indicates a switch case statement. We see that it checks the I-O control code and performs the right action. Now that we have a bit of an overview of how drivers work, it's time to go into the actual vulnerabilities. The first one that is interesting is the dangerous legitimate functionality, as I like to call it. This is very similar to Dynamite. As you know, Dynamite was developed to blow up mountains and create pathways that trains could pass through or other things, but it can actually be used in wrong ways. Just the same it is with drivers. A well-known example is Dell. They had a driver that allowed an administrator to read and write to arbitrary locations in kernel memory. This is very easy for debugging purposes, but in production this can be very dangerous and gives us a read-write primitive that we


chunk_text:
  length. It's a bit optimized on the right, but you can at least see that one of the lengths is obtained. It also obtains the system buffer. That one is most interesting for us because it contains all the user inputs. Here we see a lot of branching statements on the right. This usually indicates a switch case statement. We see that it checks the I-O control code and performs the right action. Now that we have a bit of an overview of how drivers work, it's time to go into the actual vulnerabilities. The first one that is interesting is the dangerous legitimate functionality, as I like to call it. This is very similar to Dynamite. As you know, Dynamite was developed to blow up mountains and create pathways that trains could pass through or other things, but it can actually be used in wrong ways. Just the same it is with drivers. A well-known example is Dell. They had a driver that allowed an administrator to read and write to arbitrary locations in kernel memory. This is very easy for debugging purposes, but in production this can be very dangerous and gives us a read-write primitive that we can use to do all kinds of privilege escalation. Here you see the user inputs on the left and also user inputs on the right. The left one is for the read, I believe, and the right one is for the write. In the end, it all comes down to a memmove call. Understanding these kinds of vulnerabilities is just looking for the memmoves and seeing if there's any user input in there, and then it's definitely an interesting point. Another dangerous legitimate functionality is terminating a process. This is a vulnerability that we found in our research. Here we see that a value is read from the system buffer and it's given as the first argument to a function that I have given a recognizable name already. If we go down into the function, I'll spare you the details, but in the end it does open process and terminate process on the process ID given by the user. You can already imagine that this can be very nice to disable EDR, for example. A third example is physical memory mapping. Here we found, I believe it was Tijmer that found this one, a driver that does mmMapIO space and


chunk_text:
  can use to do all kinds of privilege escalation. Here you see the user inputs on the left and also user inputs on the right. The left one is for the read, I believe, and the right one is for the write. In the end, it all comes down to a memmove call. Understanding these kinds of vulnerabilities is just looking for the memmoves and seeing if there's any user input in there, and then it's definitely an interesting point. Another dangerous legitimate functionality is terminating a process. This is a vulnerability that we found in our research. Here we see that a value is read from the system buffer and it's given as the first argument to a function that I have given a recognizable name already. If we go down into the function, I'll spare you the details, but in the end it does open process and terminate process on the process ID given by the user. You can already imagine that this can be very nice to disable EDR, for example. A third example is physical memory mapping. Here we found, I believe it was Tijmer that found this one, a driver that does mmMapIO space and it maps some physical memory into a user-writable location. Users can actually read and write to arbitrary locations in physical memory. Here is again the user input and it's stored in the physical address parameter for mmMapIO space. This is again an example of a dangerous legitimate functionality. The next type is the very well-known buffer overflow. Yes, it also happens in drivers and it's very interesting to exploit this. I have a couple of examples. The first one is in the Macrium backup software and here we see that the user input determines the size of a buffer that is allocated here and later this buffer, you can see the same offset 2C0, is used on the bottom and it's used as the buffer for reading a file input into it. There is a length given into the buffer, but it's actually unrelated to the length that the user gives in earlier. So this is an example of where the user can just determine the size of the buffer and overrun it. Another overflow that we found is a registry key. Here we see that a location is allocated with a thousand hexadecimal bytes and you would think okay


chunk_text:
  it maps some physical memory into a user-writable location. Users can actually read and write to arbitrary locations in physical memory. Here is again the user input and it's stored in the physical address parameter for mmMapIO space. This is again an example of a dangerous legitimate functionality. The next type is the very well-known buffer overflow. Yes, it also happens in drivers and it's very interesting to exploit this. I have a couple of examples. The first one is in the Macrium backup software and here we see that the user input determines the size of a buffer that is allocated here and later this buffer, you can see the same offset 2C0, is used on the bottom and it's used as the buffer for reading a file input into it. There is a length given into the buffer, but it's actually unrelated to the length that the user gives in earlier. So this is an example of where the user can just determine the size of the buffer and overrun it. Another overflow that we found is a registry key. Here we see that a location is allocated with a thousand hexadecimal bytes and you would think okay that's pretty long, but registry keys can actually also get pretty long. There's 255 characters per segment and you can have an arbitrary number of segments in the registry, so it's definitely possible to overrun this buffer. We can see that it's stored in RBX, then on the right RBX is stored in RCX and here is actually our user input. And here we see that the user input is copied into the buffer, thereby overrunning the buffer and giving us a heap overflow that can be exploited for all kinds of things. The next example is a data leak. Kernel memory contains a lot of sensitive data that is explicitly not available for user memory. If you can leak arbitrary data from the kernel, this can definitely contain interesting things that you can abuse in all kinds of ways. Here we see that this is where the input and output buffer come into play, because if we provide here a very small input buffer and a very large output buffer, the kernel will integrate that in a single large buffer that is completely uninitialized. Here we see that from that buffer it copies 100 hexadecimal bytes and then it


chunk_text:
  that's pretty long, but registry keys can actually also get pretty long. There's 255 characters per segment and you can have an arbitrary number of segments in the registry, so it's definitely possible to overrun this buffer. We can see that it's stored in RBX, then on the right RBX is stored in RCX and here is actually our user input. And here we see that the user input is copied into the buffer, thereby overrunning the buffer and giving us a heap overflow that can be exploited for all kinds of things. The next example is a data leak. Kernel memory contains a lot of sensitive data that is explicitly not available for user memory. If you can leak arbitrary data from the kernel, this can definitely contain interesting things that you can abuse in all kinds of ways. Here we see that this is where the input and output buffer come into play, because if we provide here a very small input buffer and a very large output buffer, the kernel will integrate that in a single large buffer that is completely uninitialized. Here we see that from that buffer it copies 100 hexadecimal bytes and then it writes it back to the same location again. But this means that the user can actually read from the output buffer the uninitialized data that was in the kernel input buffer, so this leaks about 100 hexadecimal bytes of kernel memory to the user. The next vulnerability is kernel handle leaks. I have found a nice analogy in practice in this image on the left. This is a burglar that puts a device through your door and pulls on the handle to actually open the door. This handle is not supposed to be reachable from the outside. In a similar way, the kernel handle should not be reachable from user mode, but you actually need to specify this. A lot of developers forget to specify this flag. Then the handle from the kernel is in the user handle table, so if you enumerate that handle table, you can actually find the handle that you can use for writing to a process, killing a process, etc. An example of this. Here we see an open process call and there are some attributes given to it, but the attributes are set to r15 and r15 is 0, xor with itself. In this


chunk_text:
  writes it back to the same location again. But this means that the user can actually read from the output buffer the uninitialized data that was in the kernel input buffer, so this leaks about 100 hexadecimal bytes of kernel memory to the user. The next vulnerability is kernel handle leaks. I have found a nice analogy in practice in this image on the left. This is a burglar that puts a device through your door and pulls on the handle to actually open the door. This handle is not supposed to be reachable from the outside. In a similar way, the kernel handle should not be reachable from user mode, but you actually need to specify this. A lot of developers forget to specify this flag. Then the handle from the kernel is in the user handle table, so if you enumerate that handle table, you can actually find the handle that you can use for writing to a process, killing a process, etc. An example of this. Here we see an open process call and there are some attributes given to it, but the attributes are set to r15 and r15 is 0, xor with itself. In this case, we see that the attributes are 0, so no flags have been given, also not the kernel flag. In this case, we can actually open an arbitrary process from the kernel and use the handle from user mode. Another example is method direct and here the analogy is the Turkish ice cream man. You have probably seen the videos where the ice cream man seems to give an ice cream, but just as the user takes the cone, he pulls the ice cream away again. In a similar way, this is exploited in the kernel. With a certain communication method, user writes and kernel reads can happen concurrently. You can see where this is going. If the driver is not checking it correctly, the driver can do some kind of a check. In between, the user changes the data, the check passes, and the drive actually reads incorrect data. If you ever see method indirect or method out direct, this is definitely something to look at, because the driver needs to really closely handle the interaction with the user. They need to do some kind of locking to make sure operations are atomic. How does this look? This is


chunk_text:
  case, we see that the attributes are 0, so no flags have been given, also not the kernel flag. In this case, we can actually open an arbitrary process from the kernel and use the handle from user mode. Another example is method direct and here the analogy is the Turkish ice cream man. You have probably seen the videos where the ice cream man seems to give an ice cream, but just as the user takes the cone, he pulls the ice cream away again. In a similar way, this is exploited in the kernel. With a certain communication method, user writes and kernel reads can happen concurrently. You can see where this is going. If the driver is not checking it correctly, the driver can do some kind of a check. In between, the user changes the data, the check passes, and the drive actually reads incorrect data. If you ever see method indirect or method out direct, this is definitely something to look at, because the driver needs to really closely handle the interaction with the user. They need to do some kind of locking to make sure operations are atomic. How does this look? This is encoded in the identifier, the device IO control code. You can decode it with, for example, this online decoder and it shows you the communication method. If you decode these values, you can find these kinds of interesting things to look at. These are the vulnerability types that I wanted to discuss with you. Let's move on to the automated tools. The first one that is well known in this area is Popcorn. This tool is used to find the first vulnerability type that I discussed, the dangerous legitimate functionality. Not only that, but it tries to find specific functions that are used in the driver. This can help you. If you know that a dangerous function is used, you can then look if user input ends up in there. That makes a very interesting case for possible vulnerabilities. A more recent tool that was released is by the VMware Threat Analysis Unit. They aim to improve over the design of Popcorn and some other tools. They use IDA. They scripted some IDA scripts to perform the same kind of actions, but in a faster and more fault-tolerant way. Let's move to the conclusion. Kernel drive vulnerabilities have impact. We


chunk_text:
  encoded in the identifier, the device IO control code. You can decode it with, for example, this online decoder and it shows you the communication method. If you decode these values, you can find these kinds of interesting things to look at. These are the vulnerability types that I wanted to discuss with you. Let's move on to the automated tools. The first one that is well known in this area is Popcorn. This tool is used to find the first vulnerability type that I discussed, the dangerous legitimate functionality. Not only that, but it tries to find specific functions that are used in the driver. This can help you. If you know that a dangerous function is used, you can then look if user input ends up in there. That makes a very interesting case for possible vulnerabilities. A more recent tool that was released is by the VMware Threat Analysis Unit. They aim to improve over the design of Popcorn and some other tools. They use IDA. They scripted some IDA scripts to perform the same kind of actions, but in a faster and more fault-tolerant way. Let's move to the conclusion. Kernel drive vulnerabilities have impact. We have discussed how it is actually used in practice by a lot of threat actors. It gives a lot of powerful tools to an attacker. That makes research also very important for us as security researchers, red team operators. There are many vulnerabilities to be found. Our research has shown that with some analysis we could find almost 30% of the drivers that we looked at to be vulnerable. You can contribute. I hope with this presentation you have a bit of the knowledge, a bit of the background and some tools that can get you started with this kind of research. Thank you for your attention. Thank you very much. Are there any questions in the audience? You said when creating your database you would only use the latest version of the driver because vulnerabilities could be fixed, but if you bring your own vulnerable driver would it be useful to bring an older version as well? I heard myself saying it and I thought this might come up, but indeed for bringing your own vulnerable drivers also old vulnerabilities are really interesting, but the thing with old vulnerabilities is usually that they are already publicly known, so it's


chunk_text:
  have discussed how it is actually used in practice by a lot of threat actors. It gives a lot of powerful tools to an attacker. That makes research also very important for us as security researchers, red team operators. There are many vulnerabilities to be found. Our research has shown that with some analysis we could find almost 30% of the drivers that we looked at to be vulnerable. You can contribute. I hope with this presentation you have a bit of the knowledge, a bit of the background and some tools that can get you started with this kind of research. Thank you for your attention. Thank you very much. Are there any questions in the audience? You said when creating your database you would only use the latest version of the driver because vulnerabilities could be fixed, but if you bring your own vulnerable driver would it be useful to bring an older version as well? I heard myself saying it and I thought this might come up, but indeed for bringing your own vulnerable drivers also old vulnerabilities are really interesting, but the thing with old vulnerabilities is usually that they are already publicly known, so it's really not worth putting your research time into it if you can also find it with a Google search. So that's the reason that I would suggest excluding those kinds of drivers. Okay, thank you. And EDR will permit it most of the times. And one of the first slides, it said 08, was it a hex address or was it a handle to… One of the first slides, let me see. It was about user input, sending it to the kernel. This one? 0x8. No? Yeah. The case… Is it a memory address? Which? Oh, this one. Yeah. Oh yeah, that's the device IO control code and it has a specific format that can also be parsed by that online parser that I showed later and it encodes all kinds of attributes about how the interaction goes, but in the end it's just an identifier that the driver uses to perform a certain action. Because in kernel you also have ASLR, I think. Yeah, there's also kernel ASLR and all kinds of protection measures. Okay, thank you, Claire. One last question, maybe, from the audience? No? All right, then we're almost ready for our lunch, but first I would


chunk_text:
  really not worth putting your research time into it if you can also find it with a Google search. So that's the reason that I would suggest excluding those kinds of drivers. Okay, thank you. And EDR will permit it most of the times. And one of the first slides, it said 08, was it a hex address or was it a handle to… One of the first slides, let me see. It was about user input, sending it to the kernel. This one? 0x8. No? Yeah. The case… Is it a memory address? Which? Oh, this one. Yeah. Oh yeah, that's the device IO control code and it has a specific format that can also be parsed by that online parser that I showed later and it encodes all kinds of attributes about how the interaction goes, but in the end it's just an identifier that the driver uses to perform a certain action. Because in kernel you also have ASLR, I think. Yeah, there's also kernel ASLR and all kinds of protection measures. Okay, thank you, Claire. One last question, maybe, from the audience? No? All right, then we're almost ready for our lunch, but first I would like to thank you for your talk and I would like to present you with a challenge coin. Yes, thank you. Thank you very much. Round of applause, please.


chunk_text:
  like to thank you for your talk and I would like to present you with a challenge coin. Yes, thank you. Thank you very much. Round of applause, please.


chunk_text:
  { "webpage_url": "https://www.youtube.com/watch?v=9S7gEz12nWs", "title": "An Angel, Python, Root And Config Walked Into A Bar... - Timothy Hjort", "description": "", "channel_url": "https://www.youtube.com/channel/UCgJoGNj3B2Mt2F3TUblcoOA", "duration": 1421, "channel": "OrangeCon", "uploader": "OrangeCon", "upload_date": "20240909" } This text was transcribed using whisper model: large-v2 First talk after lunch, please take it away. Hello everyone. You probably read the title. An angel, Python, root and config walked into a bar. My name is Timothy Hjort and you guys are probably wondering why did they do that and who let this guy up here? That's not probably not a good idea. So, welcome to my talk. So, my name is Timothy Hjort, as I mentioned. I work with vulnerability research at Outpost 24, a Swedish cybersecurity company. My work is primarily focused around automating vulnerability detection for already known vulnerabilities. I have a master of science and engineering computer security, missing one physics course, but almost. I think hardware is cool. That's how I got started in this field. I like software architecture, especially the consequences around them, like what happens if you have a poor design in your software architecture. And I love cheap hardware. So, our focus is going to be the consequences of subpar patching and poor software design, as you might have surmised from my previous sentences. We're going to be looking at a device from a company called Zyxel. It's a NAS 326. Or we could also be honest and say that I'm going to be standing here and brag. So, we will be talking a little bit about how the design of this thing caused quite a few issues, right? So, earlier this year, I released a blog with the help of my company about five different zero days on that device. And it's contained, for example, an unauthenticated Python code injection, a remote code execution through a config upload, and a pseudo-like privilege escalation, and some other information. And most importantly, a backdoor called NSA Rescue Angel, the angel part of our joke. So, we'll begin by how this process actually started, because it might be a bit interesting. So, at some point in time, I was tasked with finding an already known vulnerability that IBM had found called ZVE-2023-27992. It's a Python code injection. And I worked on it before they published their awesome blog that's describing how they did it. So, I worked on it, and my work involved


chunk_text:
  and poor software design, as you might have surmised from my previous sentences. We're going to be looking at a device from a company called Zyxel. It's a NAS 326. Or we could also be honest and say that I'm going to be standing here and brag. So, we will be talking a little bit about how the design of this thing caused quite a few issues, right? So, earlier this year, I released a blog with the help of my company about five different zero days on that device. And it's contained, for example, an unauthenticated Python code injection, a remote code execution through a config upload, and a pseudo-like privilege escalation, and some other information. And most importantly, a backdoor called NSA Rescue Angel, the angel part of our joke. So, we'll begin by how this process actually started, because it might be a bit interesting. So, at some point in time, I was tasked with finding an already known vulnerability that IBM had found called ZVE-2023-27992. It's a Python code injection. And I worked on it before they published their awesome blog that's describing how they did it. So, I worked on it, and my work involved unpacking firmware, decompiling binaries in Python bytecode, and digging through it. And at some point, we did also purchase the device that was involved here, so we could start testing on it. And back then, I didn't really find any interesting. I found the thing I was looking for, but nothing else. But we had a student evening at some point, where students from a local school or university or whatever it's called in English, they were coming to our company, and they were going to get to see, like, what are we doing? And I was tasked with representing my department and showed them a typical case of what we do. And I thought that this IBM thing was very typical, because it involved a lot of research, decompiling, and magic. Magic. It made me look cool-ish. So, I got back to it, and like, revisited my work to prepare the presentation slides. And when I was doing that, I was being a little bit, like, slacking on the job and started digging around into some unrelated files on it. And I stumbled upon an interesting binary with the SUID bit set. Now, this is local on my machine,


chunk_text:
  unpacking firmware, decompiling binaries in Python bytecode, and digging through it. And at some point, we did also purchase the device that was involved here, so we could start testing on it. And back then, I didn't really find any interesting. I found the thing I was looking for, but nothing else. But we had a student evening at some point, where students from a local school or university or whatever it's called in English, they were coming to our company, and they were going to get to see, like, what are we doing? And I was tasked with representing my department and showed them a typical case of what we do. And I thought that this IBM thing was very typical, because it involved a lot of research, decompiling, and magic. Magic. It made me look cool-ish. So, I got back to it, and like, revisited my work to prepare the presentation slides. And when I was doing that, I was being a little bit, like, slacking on the job and started digging around into some unrelated files on it. And I stumbled upon an interesting binary with the SUID bit set. Now, this is local on my machine, but on the actual device, it's owned by root. So, I looked at this interesting name, Remote Help CDI, that's cool. And I looked inside it. Specifically, I unpacked all the strings I could find in it. And I found some funny strings. So, OpenBackdoor.sh and NSA Rescue Angel. And my thought here, preparing this student presentation thing, was, well, that's suspicious. So, we did the presentation, yada yada, things were successful, and I asked my boss, like, hey, can I continue poking into this device? Because, well, it was end of life at the point, but I still wanted to dig into it, because this looked very interesting. And I happened to know that Zyxel had a couple of similar vulnerabilities with remote code execution that did get a lot of media coverage. So, yeah. I got permission, and that's why I'm here. So, you can probably guess that. So, we will talk a bit about how this thing works. Specifically, we will focus, first of all, how does this NAS, like a web server specifically, how does it handle our requests? Because this is, well, it's the software design, right? It's the cause of our issues. So, I


chunk_text:
  but on the actual device, it's owned by root. So, I looked at this interesting name, Remote Help CDI, that's cool. And I looked inside it. Specifically, I unpacked all the strings I could find in it. And I found some funny strings. So, OpenBackdoor.sh and NSA Rescue Angel. And my thought here, preparing this student presentation thing, was, well, that's suspicious. So, we did the presentation, yada yada, things were successful, and I asked my boss, like, hey, can I continue poking into this device? Because, well, it was end of life at the point, but I still wanted to dig into it, because this looked very interesting. And I happened to know that Zyxel had a couple of similar vulnerabilities with remote code execution that did get a lot of media coverage. So, yeah. I got permission, and that's why I'm here. So, you can probably guess that. So, we will talk a bit about how this thing works. Specifically, we will focus, first of all, how does this NAS, like a web server specifically, how does it handle our requests? Because this is, well, it's the software design, right? It's the cause of our issues. So, I made a pretty image with a terrible color scheme, I'm sorry. So, we got a client, they speak to an Apache server, and all of the requests will be going through an authentication module, and after that, they will be passed on to a handler, which is either a Python server or some CGI binaries. We will dig into them a little bit later on. So, we know this file, remote help CGI, it's got some funny content, right? It's got these funny strings. So, let's focus on it first, because it sounds delicious. So, what does it do? I'm trying to avoid boring you guys with code, so I will more explain about how it works, instead of showing you code and letting you read it, because this is a presentation. So, it takes strings that are the names for a list of callbacks, and if the string happens to match something in that list, it will take the callback and execute it. And it's got two interesting callbacks related to those strings that we saw, right? It's got the backdoor callback, and we can maybe guess what that thing's doing. But sadly, it's calling a SH file to


chunk_text:
  made a pretty image with a terrible color scheme, I'm sorry. So, we got a client, they speak to an Apache server, and all of the requests will be going through an authentication module, and after that, they will be passed on to a handler, which is either a Python server or some CGI binaries. We will dig into them a little bit later on. So, we know this file, remote help CGI, it's got some funny content, right? It's got these funny strings. So, let's focus on it first, because it sounds delicious. So, what does it do? I'm trying to avoid boring you guys with code, so I will more explain about how it works, instead of showing you code and letting you read it, because this is a presentation. So, it takes strings that are the names for a list of callbacks, and if the string happens to match something in that list, it will take the callback and execute it. And it's got two interesting callbacks related to those strings that we saw, right? It's got the backdoor callback, and we can maybe guess what that thing's doing. But sadly, it's calling a SH file to do its task, and that one did not exist in the latest version at the time. So, I ignored it. This was a previous vulnerability patch in 2020, we will discuss it a little bit later. But it did have one called sshd-tdc, which was new. And it was doing basically the same thing as the old SSH script, where it starts the SSH server if it's not enabled already, it's going to map port 22 to the internet using UPnP, that's where you disable UPnP on your home router, and it's also going to generate a password for that account, because we cannot give it the password ourself, and it's going to do this based on the Ethernet0 MAC address, and it will append tdp to that output, it's calculated, and then it enables the user, which by the way has root privileges, so it's pretty bad stuff. Awesome. It's my fault. This looks super cool. But it's authenticated, so that's kind of suck, because on this device, well, if you already have an account, you basically already compromised it anyways, so meh. But this device is kind of cheap, in my opinion. It's not a Cisco super expensive


chunk_text:
  do its task, and that one did not exist in the latest version at the time. So, I ignored it. This was a previous vulnerability patch in 2020, we will discuss it a little bit later. But it did have one called sshd-tdc, which was new. And it was doing basically the same thing as the old SSH script, where it starts the SSH server if it's not enabled already, it's going to map port 22 to the internet using UPnP, that's where you disable UPnP on your home router, and it's also going to generate a password for that account, because we cannot give it the password ourself, and it's going to do this based on the Ethernet0 MAC address, and it will append tdp to that output, it's calculated, and then it enables the user, which by the way has root privileges, so it's pretty bad stuff. Awesome. It's my fault. This looks super cool. But it's authenticated, so that's kind of suck, because on this device, well, if you already have an account, you basically already compromised it anyways, so meh. But this device is kind of cheap, in my opinion. It's not a Cisco super expensive thing, so I know that developers tend to like being wet. Write everything twice, and so I thought that hey, let's look into historical vulnerabilities, they might be relevant into what I should start focusing on. And yeah, I looked at the changelogs, and I'm so happy that this looks sort of readable. There's a lot of mentions about authentication bypasses, pre-authentication command injections, and other command injections. The list is long, I couldn't fit all of them into this presentation slide, so whatever. We can probably find one more, was my thought at this point. So, let's look at the authentication mechanism. IBM also describes this on that blog that they had. I do recommend reading it. I do also recommend reading my blog, obviously. It's better, but I'm biased. So, the authentication mechanism has one task, right? It's going to take a request, and it's going to categorize it into two groups. Either a request is authenticated, or it's not. It's kind of simple. The thing is doing that right, if it's an authenticated request and you have a cookie, we're happy. And if it's authenticated and you don't have a cookie, you're denied, and it's going to


chunk_text:
  thing, so I know that developers tend to like being wet. Write everything twice, and so I thought that hey, let's look into historical vulnerabilities, they might be relevant into what I should start focusing on. And yeah, I looked at the changelogs, and I'm so happy that this looks sort of readable. There's a lot of mentions about authentication bypasses, pre-authentication command injections, and other command injections. The list is long, I couldn't fit all of them into this presentation slide, so whatever. We can probably find one more, was my thought at this point. So, let's look at the authentication mechanism. IBM also describes this on that blog that they had. I do recommend reading it. I do also recommend reading my blog, obviously. It's better, but I'm biased. So, the authentication mechanism has one task, right? It's going to take a request, and it's going to categorize it into two groups. Either a request is authenticated, or it's not. It's kind of simple. The thing is doing that right, if it's an authenticated request and you have a cookie, we're happy. And if it's authenticated and you don't have a cookie, you're denied, and it's going to blast your request to hell and send you back to the login screen. The quirk here is in how this thing is checking the whitelist, and this is related to why they keep having these stupid authentication bypasses. It's looking for substrings. So, it's assuming everything is authenticated by default, and then it has a whitelist, and that's good practice, right? But, for example, we happen to have this icon in our web browser that's giving this, like, you know when you get into a website and it's going to show this icon for the website up in the corner, the favicon.ico file. That's one of the stuff you don't want authentication for, and so it's in the whitelist, and so what's going to happen now, right, is if this favicon.ico file is unauthenticated, i.e. the request is valid without a cookie, we're happy. If foo slash bar is authenticated, it's going to be invalid alone, but if we happen to add favicon.ico in the end, or in the middle, or in the beginning, it's going to be unauthenticated. Hooray! Great software design. So, and here's an interesting part, right? It's an Apache web server, and it has a lot


chunk_text:
  blast your request to hell and send you back to the login screen. The quirk here is in how this thing is checking the whitelist, and this is related to why they keep having these stupid authentication bypasses. It's looking for substrings. So, it's assuming everything is authenticated by default, and then it has a whitelist, and that's good practice, right? But, for example, we happen to have this icon in our web browser that's giving this, like, you know when you get into a website and it's going to show this icon for the website up in the corner, the favicon.ico file. That's one of the stuff you don't want authentication for, and so it's in the whitelist, and so what's going to happen now, right, is if this favicon.ico file is unauthenticated, i.e. the request is valid without a cookie, we're happy. If foo slash bar is authenticated, it's going to be invalid alone, but if we happen to add favicon.ico in the end, or in the middle, or in the beginning, it's going to be unauthenticated. Hooray! Great software design. So, and here's an interesting part, right? It's an Apache web server, and it has a lot of request handlers, like scripts and CGI binaries and whatever, and the server and also then the authentication module is not aware about what path is actually valid the moment it gets handed off to a handler. So what it means is if you have a path to a handler and appends something to the end, the authentication module doesn't know what's going on. So this means that all of the handlers, like all of the endpoints that's in a handler, it's got to then know its own path, right, because someone's requesting it, and it means then that it's got to be able to make sure that nobody is appending favicon.ico at the end. And it's also got to know then, does it require authentication? And if it does require authentication, it's got to remember how do I validate this cookie, and it's also got to remember to validate the cookie. I think we're starting to see why there's a lot of authentication bypasses here. So in my opinion, the authentication module is useless. Like, it doesn't really do anything. We can't trust it. We get a request that's been through it, it's authenticated, but we can still not


chunk_text:
  of request handlers, like scripts and CGI binaries and whatever, and the server and also then the authentication module is not aware about what path is actually valid the moment it gets handed off to a handler. So what it means is if you have a path to a handler and appends something to the end, the authentication module doesn't know what's going on. So this means that all of the handlers, like all of the endpoints that's in a handler, it's got to then know its own path, right, because someone's requesting it, and it means then that it's got to be able to make sure that nobody is appending favicon.ico at the end. And it's also got to know then, does it require authentication? And if it does require authentication, it's got to remember how do I validate this cookie, and it's also got to remember to validate the cookie. I think we're starting to see why there's a lot of authentication bypasses here. So in my opinion, the authentication module is useless. Like, it doesn't really do anything. We can't trust it. We get a request that's been through it, it's authenticated, but we can still not trust it, so it's not good. Hello? There we go. Real quick, this is how the request for the backdoor exploit looks like. I won't be deep diving into how all of these pieces, where they come from, whatever, read the blog. It's good, but still, I'm biased. There is an issue, as I mentioned, with the backdoor exploit, right? We need a password. We can't give it a password, and we do not receive it in response. So, how do we get it? I mentioned, right, it's calculated based on the Ethernet0 MAC address, and appending T-D-T on it. So, we as an attacker need to either know the MAC address of this thing, or we need to have access to a shell. So, I targeted a command injection, because I thought it was cooler, and also I happened to stumble upon it. And the Python code injection, right, the part in the Sherry Pi server, it's Python 2.7, so version ancient. And looking at the control flow of how it's doing, this is, it's great design. The endpoints is terminated, like what we're calling, by calling eval on the user input. So, this is a great design for


chunk_text:
  trust it, so it's not good. Hello? There we go. Real quick, this is how the request for the backdoor exploit looks like. I won't be deep diving into how all of these pieces, where they come from, whatever, read the blog. It's good, but still, I'm biased. There is an issue, as I mentioned, with the backdoor exploit, right? We need a password. We can't give it a password, and we do not receive it in response. So, how do we get it? I mentioned, right, it's calculated based on the Ethernet0 MAC address, and appending T-D-T on it. So, we as an attacker need to either know the MAC address of this thing, or we need to have access to a shell. So, I targeted a command injection, because I thought it was cooler, and also I happened to stumble upon it. And the Python code injection, right, the part in the Sherry Pi server, it's Python 2.7, so version ancient. And looking at the control flow of how it's doing, this is, it's great design. The endpoints is terminated, like what we're calling, by calling eval on the user input. So, this is a great design for us. So, if we request something like foobar baz, it's, specifically what it's going to do is it's going to take two first parts, shove it into an eval import controllers.foo, and call eval controller.foo.bar, and then pass it some arguments. This is the main control flow for all of our requests. It's all of our Python requests that are going to go through. So, and this is important here, that baz is not getting included into the execution. So, what IBM did back in their blog was that they appended this favicon.ico thing at the end of the path, because they targeted these endpoints, right. They didn't manage to abuse the eval, but they did find one of the controllers that called system, and they inserted backticks because they forgot to filter the user input, and it exploded. So, they patched this by restricting request path to only contain, like, the each section in the request path. So, it can only contain A to Z and underscores. So, dots are no longer allowed, so favicon.ico doesn't work anymore. They also restricted the path on these endpoints to a maximum of two directories. So, if we append, like, something at


chunk_text:
  us. So, if we request something like foobar baz, it's, specifically what it's going to do is it's going to take two first parts, shove it into an eval import controllers.foo, and call eval controller.foo.bar, and then pass it some arguments. This is the main control flow for all of our requests. It's all of our Python requests that are going to go through. So, and this is important here, that baz is not getting included into the execution. So, what IBM did back in their blog was that they appended this favicon.ico thing at the end of the path, because they targeted these endpoints, right. They didn't manage to abuse the eval, but they did find one of the controllers that called system, and they inserted backticks because they forgot to filter the user input, and it exploded. So, they patched this by restricting request path to only contain, like, the each section in the request path. So, it can only contain A to Z and underscores. So, dots are no longer allowed, so favicon.ico doesn't work anymore. They also restricted the path on these endpoints to a maximum of two directories. So, if we append, like, something at the end, well, it's not going to be valid anymore. So, the problem is to begin with this whitelist thing, right. If we don't have anything valid in the whitelist, we're still not going to be happy. So, lucky me that they had something in the whitelist that did not contain the band characters, but we could still not append it to the endpoint on this path because, as mentioned, they restricted the number of paths in it, or directories. So, how do we find an authentication bypass to this Python thing now, right? There is a limit to how to length. I present to you a new endpoint that they added in a patch. And this endpoint, we won't be reading the code, so don't look at it too much, it's ugly. It's doing this right. They didn't learn. They forgot to restrict the number of directories permitted in the path. In fact, it's not even looking at the path except for, it's banning, it's not allowing the band characters, but as long as there's no band characters in the path, we're happy. It's running eval again. And the interesting part now is that the request body is what's


chunk_text:
  the end, well, it's not going to be valid anymore. So, the problem is to begin with this whitelist thing, right. If we don't have anything valid in the whitelist, we're still not going to be happy. So, lucky me that they had something in the whitelist that did not contain the band characters, but we could still not append it to the endpoint on this path because, as mentioned, they restricted the number of paths in it, or directories. So, how do we find an authentication bypass to this Python thing now, right? There is a limit to how to length. I present to you a new endpoint that they added in a patch. And this endpoint, we won't be reading the code, so don't look at it too much, it's ugly. It's doing this right. They didn't learn. They forgot to restrict the number of directories permitted in the path. In fact, it's not even looking at the path except for, it's banning, it's not allowing the band characters, but as long as there's no band characters in the path, we're happy. It's running eval again. And the interesting part now is that the request body is what's getting called the eval, and the request body does not have the limitations of A to Z and underscores. We can put magic characters in it, with some limitations, we're not allowed to use dollar signs and backticks and whatever, because they patched IBM stuff. But the interesting part about here, right, you guys can't really, oh, you can see my mouse, perfect. The args argument here is the body that I'm sending them, and it's a string at this point. They are passing it in by value to this %s in the arguments part here. And that means it's not going to say args, it's going to be the content of args. And that's good fun. This is important, right, because if we say A equals a string 2 plus 2, eval print A is going to print 2 plus 2, because it's a string, right? But if we do the content, it's going to be 4. And that's what we're abusing. So we exported it, and essentially built a big-ass request. Once again, read the blog for the super, super details on how this thing works. But essentially, I tracked down an endpoint or a controller that does


chunk_text:
  getting called the eval, and the request body does not have the limitations of A to Z and underscores. We can put magic characters in it, with some limitations, we're not allowed to use dollar signs and backticks and whatever, because they patched IBM stuff. But the interesting part about here, right, you guys can't really, oh, you can see my mouse, perfect. The args argument here is the body that I'm sending them, and it's a string at this point. They are passing it in by value to this %s in the arguments part here. And that means it's not going to say args, it's going to be the content of args. And that's good fun. This is important, right, because if we say A equals a string 2 plus 2, eval print A is going to print 2 plus 2, because it's a string, right? But if we do the content, it's going to be 4. And that's what we're abusing. So we exported it, and essentially built a big-ass request. Once again, read the blog for the super, super details on how this thing works. But essentially, I tracked down an endpoint or a controller that does not validate the cookie, because as I mentioned, all endpoints need to validate the cookie themselves, and they happen to forget it here. So then I escaped the function call, and I added my own stuff to it. And I called a utility, executed a utility called makekey, which is what they use in the backdoor to calculate that password that you're appending. So, and this code injection happened to be reflected, so I get the output back to me as long as the handler doesn't crash. So, yeah. And a funny thing about it, then, is that they did not ban things like double ticks and parentheses and underscores, and I don't remember all of them, like commas, I think. So we can base 64 payload and set an eval around it, and set the eval inside the eval, so we can eval our eval and get requests back. Joe dog. But sadly, and this is why I'm still targeting this despite it being backdoor, right? Because this is nobody, so we don't really have any privileges as this user, but we're allowed to execute the makekey utility. So it's a little bit sad. But at this point, right,


chunk_text:
  not validate the cookie, because as I mentioned, all endpoints need to validate the cookie themselves, and they happen to forget it here. So then I escaped the function call, and I added my own stuff to it. And I called a utility, executed a utility called makekey, which is what they use in the backdoor to calculate that password that you're appending. So, and this code injection happened to be reflected, so I get the output back to me as long as the handler doesn't crash. So, yeah. And a funny thing about it, then, is that they did not ban things like double ticks and parentheses and underscores, and I don't remember all of them, like commas, I think. So we can base 64 payload and set an eval around it, and set the eval inside the eval, so we can eval our eval and get requests back. Joe dog. But sadly, and this is why I'm still targeting this despite it being backdoor, right? Because this is nobody, so we don't really have any privileges as this user, but we're allowed to execute the makekey utility. So it's a little bit sad. But at this point, right, we had everything we needed for the backdoor, so I was happy here. But then I also happened to stumble upon a couple of bonus things here, like a local privilege escalation that I mentioned. I was thinking like, oh, if only we had something like sudo, but without password. Well, lucky me, they happened to have that, because this web server needs to do some admin stuff, and obviously we had sudo without passwords. But it needs an absolute path to whatever it's executing, so slash bin sh, and now we have a sudo shell. Whoops. So how do we get here, right? It's a quick recap, in case people aren't following exactly. They have a broken authentication module looking for substrings. That means we cannot trust it anymore, so all of the endpoints after it has to do the validation themselves, everyone has to remember to do this. They fixed the off-bypass that IBM found in the cherry pie server by limiting the path and by banning certain characters, and the next time that they added an endpoint, they re-implemented it, forgot to limit the path restrictions, and they forgot to put the double quotes around the args


chunk_text:
  we had everything we needed for the backdoor, so I was happy here. But then I also happened to stumble upon a couple of bonus things here, like a local privilege escalation that I mentioned. I was thinking like, oh, if only we had something like sudo, but without password. Well, lucky me, they happened to have that, because this web server needs to do some admin stuff, and obviously we had sudo without passwords. But it needs an absolute path to whatever it's executing, so slash bin sh, and now we have a sudo shell. Whoops. So how do we get here, right? It's a quick recap, in case people aren't following exactly. They have a broken authentication module looking for substrings. That means we cannot trust it anymore, so all of the endpoints after it has to do the validation themselves, everyone has to remember to do this. They fixed the off-bypass that IBM found in the cherry pie server by limiting the path and by banning certain characters, and the next time that they added an endpoint, they re-implemented it, forgot to limit the path restrictions, and they forgot to put the double quotes around the args variable, so suddenly they did not reference it by name and it's by value instead, and now, whoops, we have another vulnerability, so it's very easy for them to re-implement the vulnerability in this device, and if you're reading through the changelogs, this is very, very noticeable. They keep patching the same thing all over again. So looking at the stuff of interest that we've discussed here, they patched a backdoor back in 2020, that's the open backdoor.sh file we talked about. Then they patched IBM's command injection in 2023, and sometime in between, they re-implemented the backdoor and added a new command injection, and doing this cheap, I call it cheap code, it's not really well thought out, maybe the argument is it's a lack of skill or maybe it's to save money and time because they don't want to waste time on this stupid device, right? But in the end, having to keep patching the same thing all over again, that costs a lot of money and a lot of time and a lot of effort and it's super annoying. The patching of the stuff I found was that they killed that new endpoint entirely, not sure why,


chunk_text:
  variable, so suddenly they did not reference it by name and it's by value instead, and now, whoops, we have another vulnerability, so it's very easy for them to re-implement the vulnerability in this device, and if you're reading through the changelogs, this is very, very noticeable. They keep patching the same thing all over again. So looking at the stuff of interest that we've discussed here, they patched a backdoor back in 2020, that's the open backdoor.sh file we talked about. Then they patched IBM's command injection in 2023, and sometime in between, they re-implemented the backdoor and added a new command injection, and doing this cheap, I call it cheap code, it's not really well thought out, maybe the argument is it's a lack of skill or maybe it's to save money and time because they don't want to waste time on this stupid device, right? But in the end, having to keep patching the same thing all over again, that costs a lot of money and a lot of time and a lot of effort and it's super annoying. The patching of the stuff I found was that they killed that new endpoint entirely, not sure why, and the backdoor function is still present on this device, but they're making it exit early, so it's present-ish. I re-decompiled it and dug through it, I think what they're doing is calling exit zero at the beginning of the function, so that's good fun. So yeah, some key takeaways from this presentation, if I wasn't clear enough about this, is that my thought and what I wanted to talk about and bring up to attention here in this presentation is that quick patches is not exactly a good way to do things, right? Because it's going to waste more time in the end having to re-do it all over again, but because I've been bashing Zyxel all over, like every time in this presentation now, they were really good to work with. Like I contacted them, told them everything and they were like, oh shit, fixed it, even though the device has been end of life for like half a year, so they did good. So that's good, and that's much better compared to some other vendors I'm dealing with right now. So yeah, an angel, Python root and config walked into a bar, if you want an easy


chunk_text:
  and the backdoor function is still present on this device, but they're making it exit early, so it's present-ish. I re-decompiled it and dug through it, I think what they're doing is calling exit zero at the beginning of the function, so that's good fun. So yeah, some key takeaways from this presentation, if I wasn't clear enough about this, is that my thought and what I wanted to talk about and bring up to attention here in this presentation is that quick patches is not exactly a good way to do things, right? Because it's going to waste more time in the end having to re-do it all over again, but because I've been bashing Zyxel all over, like every time in this presentation now, they were really good to work with. Like I contacted them, told them everything and they were like, oh shit, fixed it, even though the device has been end of life for like half a year, so they did good. So that's good, and that's much better compared to some other vendors I'm dealing with right now. So yeah, an angel, Python root and config walked into a bar, if you want an easy CVS, revisit them. Their patches is probably a good joke. That's it. Thank you very much for your talk. Are there any questions in the audience? Hi, thank you for the talk. I was wondering, I have two small questions. One... Please hold the mic closer to mouth. Oh, the code for the servers, I'm guessing they were open source, right? Yeah. And the patches for them. You mean the server that you're using? Yeah, because I saw you showed some code of the servers, and like for example, the way you saw the new endpoints. Are these your own code or you... No, they are delivering Python bytecode, so it's not really text, but Python is really nice that you can just reverse bytecode back, even to get the comments back. Oh, I see. And another small question, I was wondering, the name you found, NSA Rescue Angel, do you actually think they belong to NSA? Nah. Because, yeah, I wouldn't think they would put the same name in the... Yeah. They wouldn't self-niche on them. So NSA Rescue Angel would be too obvious, and I don't expect NSA to maybe be that obvious to begin with. But what


chunk_text:
  CVS, revisit them. Their patches is probably a good joke. That's it. Thank you very much for your talk. Are there any questions in the audience? Hi, thank you for the talk. I was wondering, I have two small questions. One... Please hold the mic closer to mouth. Oh, the code for the servers, I'm guessing they were open source, right? Yeah. And the patches for them. You mean the server that you're using? Yeah, because I saw you showed some code of the servers, and like for example, the way you saw the new endpoints. Are these your own code or you... No, they are delivering Python bytecode, so it's not really text, but Python is really nice that you can just reverse bytecode back, even to get the comments back. Oh, I see. And another small question, I was wondering, the name you found, NSA Rescue Angel, do you actually think they belong to NSA? Nah. Because, yeah, I wouldn't think they would put the same name in the... Yeah. They wouldn't self-niche on them. So NSA Rescue Angel would be too obvious, and I don't expect NSA to maybe be that obvious to begin with. But what I think is that, I think this is like a support account. It's for when granny has any internet problems and they need to fix it. I think that's the reason why they have this. I see, I see. Thank you very much. Yeah. There was a guy behind him that had a question as well. Thank you for the talk. You mentioned that this device was end of life, but is it possible that this applies to currently shipping devices as well? Did you look into that? It's been on my to-do list. So this does affect at least one more device that they themselves have confirmed. I don't remember the exact model name, NAS356 or whatever. But I would expect them to be reusing this code a little bit everywhere. Because last time something big like this happened, it did affect a lot of devices. So I'm personally planning on expanding my network stack by buying a Zyxel switch and maybe accidentally killing it. So it's on my backbone to do. Thank you. Any other questions? Yes. Hi, thanks. So you stated that the password for the National Support Agency account, you can compute it based on the


chunk_text:
  I think is that, I think this is like a support account. It's for when granny has any internet problems and they need to fix it. I think that's the reason why they have this. I see, I see. Thank you very much. Yeah. There was a guy behind him that had a question as well. Thank you for the talk. You mentioned that this device was end of life, but is it possible that this applies to currently shipping devices as well? Did you look into that? It's been on my to-do list. So this does affect at least one more device that they themselves have confirmed. I don't remember the exact model name, NAS356 or whatever. But I would expect them to be reusing this code a little bit everywhere. Because last time something big like this happened, it did affect a lot of devices. So I'm personally planning on expanding my network stack by buying a Zyxel switch and maybe accidentally killing it. So it's on my backbone to do. Thank you. Any other questions? Yes. Hi, thanks. So you stated that the password for the National Support Agency account, you can compute it based on the MAC address. Have you investigated the entropy of MAC addresses in these things? Because maybe there's only like 100,000. Yeah. I looked into the MAC address. They are assigning them themselves. And I looked into what ranges of MAC addresses they have. And I don't remember the number off the top of my head. But yeah, it's brute forcible. So that's why I mentioned there was two ways of doing calculator and find it out. Sure. Thanks. Any other questions? Yes. Thanks for the talk. Is the authentication module wrote by themselves or the open source solution? The authentication module, they coded it themselves, I think. Because the more exact name would be like zymodoff. So I'm assuming it's Zyxel. So they wrote everything by themselves. Yeah. Cool. Thank you. Any other questions? No? Okay. Well, then I'd like to thank you very much for your talk. Yeah. And thank you for listening. Thanks very much.


chunk_text:
  MAC address. Have you investigated the entropy of MAC addresses in these things? Because maybe there's only like 100,000. Yeah. I looked into the MAC address. They are assigning them themselves. And I looked into what ranges of MAC addresses they have. And I don't remember the number off the top of my head. But yeah, it's brute forcible. So that's why I mentioned there was two ways of doing calculator and find it out. Sure. Thanks. Any other questions? Yes. Thanks for the talk. Is the authentication module wrote by themselves or the open source solution? The authentication module, they coded it themselves, I think. Because the more exact name would be like zymodoff. So I'm assuming it's Zyxel. So they wrote everything by themselves. Yeah. Cool. Thank you. Any other questions? No? Okay. Well, then I'd like to thank you very much for your talk. Yeah. And thank you for listening. Thanks very much.


chunk_text:
  { "webpage_url": "https://www.youtube.com/watch?v=1jPyWXuc-pY", "title": "All Cops Are Broadcasting: Breaking TETRA After Decades In The Shadows - Wouter Bokslag", "description": "", "channel_url": "https://www.youtube.com/channel/UCgJoGNj3B2Mt2F3TUblcoOA", "duration": 1829, "channel": "OrangeCon", "uploader": "OrangeCon", "upload_date": "20240909" } This text was transcribed using whisper model: large-v2 All right. Yeah, set up almost in time. Hi, guys. Welcome to this talk. All Cops are Broadcasting Breaking Tetra After Decades in Shadows. I'm Wouter Bokslag and these are my colleagues Jos Westeros and Carlo Meijer from Midnight Blue. And you may have heard of us before. We have broken several vehicle immobilization systems, found vulnerabilities in the BlackBerry QNX operating system, have broken a hardened variant of the Mifare Classic chip, well-known from the OV chip card for the Dutchies. And we offer a variety of services ranging from threat modeling, reverse engineering, vulnerability research, but also secure software development, lifecycle consultancy, red teaming, capability development, so that red teams can use capabilities that fit their use cases and trainings. Enough with the self-plug. Let's dive into it since we only have half an hour. What is Tetra? Well, Tetra is a radio technology that's used globally. It's a trunk technology, so you have these cell towers and you have these handheld or vehicle-mounted radios. It competes with the likes of P25, DMR, and Tetrapole. And it was standardized in the late 90s, mid-90s by Etsy, which is a well-known standardization institute, also known for GSM, the various Gs. GMR also decked handheld, you know, these portable phones that your parents used to have. And it was primarily developed for voice communications, but it's also suitable for data communications, ranging from short text messages like SMS, but also you can tunnel IP over it and do machine-to-machine communications. What's interesting for us is that it relies on a secret proprietary cryptography. And it's really broadly used by police forces all over the world, with the notable exception of the United States and France, and some countries that kind of mirror their choices to these countries. This is what we could confirm based on open source intelligence. So there is definitely bound to be more, but at least these countries are using it for police use. Then there is use cases by military and intelligence. It's even harder to find out what these guys are using exactly. But for these ones, we've been able to confirm use of Tetra. And


chunk_text:
  have these handheld or vehicle-mounted radios. It competes with the likes of P25, DMR, and Tetrapole. And it was standardized in the late 90s, mid-90s by Etsy, which is a well-known standardization institute, also known for GSM, the various Gs. GMR also decked handheld, you know, these portable phones that your parents used to have. And it was primarily developed for voice communications, but it's also suitable for data communications, ranging from short text messages like SMS, but also you can tunnel IP over it and do machine-to-machine communications. What's interesting for us is that it relies on a secret proprietary cryptography. And it's really broadly used by police forces all over the world, with the notable exception of the United States and France, and some countries that kind of mirror their choices to these countries. This is what we could confirm based on open source intelligence. So there is definitely bound to be more, but at least these countries are using it for police use. Then there is use cases by military and intelligence. It's even harder to find out what these guys are using exactly. But for these ones, we've been able to confirm use of Tetra. And also quite notable is use in critical infrastructure and industry. So airports, harbors, industrial sites can use it for their security personnel, for their engineers who can then talk together. But it's also used in a data-carrying capacity, for instance, to have a SCADA telecontrol system control and monitor sites that are remote. So you can use it for pipeline control, railway signaling, stuff like that. And it's often heard that Tetra is an open standard, and that's a bit of a misconception because it's a public standard. It has been funded with public money, and it is largely open. But in the standard, you will find schematics like that. You see some key material. You see how they are being combined by various functions called, for instance, TA-12 or TB-5. But what these functions are exactly was held secret by Etsy. And you could get the actual specification of these things if you would sign an NDA. But these are only available for bona fide parties. And what bona fide is, is at the discretion of Etsy to decide. And besides that, a manufacturer that wishes to integrate the secret cryptography of Tetra into a product, they have to


chunk_text:
  also quite notable is use in critical infrastructure and industry. So airports, harbors, industrial sites can use it for their security personnel, for their engineers who can then talk together. But it's also used in a data-carrying capacity, for instance, to have a SCADA telecontrol system control and monitor sites that are remote. So you can use it for pipeline control, railway signaling, stuff like that. And it's often heard that Tetra is an open standard, and that's a bit of a misconception because it's a public standard. It has been funded with public money, and it is largely open. But in the standard, you will find schematics like that. You see some key material. You see how they are being combined by various functions called, for instance, TA-12 or TB-5. But what these functions are exactly was held secret by Etsy. And you could get the actual specification of these things if you would sign an NDA. But these are only available for bona fide parties. And what bona fide is, is at the discretion of Etsy to decide. And besides that, a manufacturer that wishes to integrate the secret cryptography of Tetra into a product, they have to protect the algorithms against exfiltration. So they can choose for a hardware implementation, which is really hard to reverse engineer. Or if they want to implement it in software, they have to take countermeasures to prevent it from being extracted from the radio. Now, the thing is that by now there is a lot of bona fide vendors out there. Basically, every geopolitical block has a manufacturer on their soil. So top tier adversaries like in intelligence agencies of serious countries, they will probably have one of these manufacturers under their sphere of influence and they can just kindly ask them to hand over the secret crypto. Or if this would not be the case, which is the case for UK, France, United States, China, Russia. But still you could try to target one of the smaller manufacturers and just hack them and maybe grab it off a SharePoint or something. So by now it's reasonable to assume that any serious adversary would have these specifications already. Now, Tetra security consists of two parts. There is the TAA1 suite, which implements authentication and key management and distribution. It also implements identity encryption so that you cannot immediately see which Tetra


chunk_text:
  protect the algorithms against exfiltration. So they can choose for a hardware implementation, which is really hard to reverse engineer. Or if they want to implement it in software, they have to take countermeasures to prevent it from being extracted from the radio. Now, the thing is that by now there is a lot of bona fide vendors out there. Basically, every geopolitical block has a manufacturer on their soil. So top tier adversaries like in intelligence agencies of serious countries, they will probably have one of these manufacturers under their sphere of influence and they can just kindly ask them to hand over the secret crypto. Or if this would not be the case, which is the case for UK, France, United States, China, Russia. But still you could try to target one of the smaller manufacturers and just hack them and maybe grab it off a SharePoint or something. So by now it's reasonable to assume that any serious adversary would have these specifications already. Now, Tetra security consists of two parts. There is the TAA1 suite, which implements authentication and key management and distribution. It also implements identity encryption so that you cannot immediately see which Tetra phone numbers are talking together at any point in time. And there is some fancy remote disable, remote wipe functionality that's also implemented here. And then there is the TEA suite of algorithms and these algorithms are used for the actual data encryption in Tetra. And there's various different flavors depending on the use case for the specific network. TEA2 is the one that was originally envisaged and was intended for use by European public safety agencies only. And TEA3 would be made available for the same use case in countries with which we have friendly relations, but outside of Europe. And then there is TEA1, which is intended to be readily exportable, which is also the only option for commercial use or infrastructure use of Tetra. And there's TEA4, which to the best of my knowledge, no one has ever used. So that's basically the cryptographic parts that exist within the Tetra standard. And with that in mind, let's discuss project ReTetra. Now, many of you will be familiar with Gekhoff's principle. It states that a crypto system should be secure if everything about the system, except for the key, is public knowledge. And already in the 19th century,


chunk_text:
  phone numbers are talking together at any point in time. And there is some fancy remote disable, remote wipe functionality that's also implemented here. And then there is the TEA suite of algorithms and these algorithms are used for the actual data encryption in Tetra. And there's various different flavors depending on the use case for the specific network. TEA2 is the one that was originally envisaged and was intended for use by European public safety agencies only. And TEA3 would be made available for the same use case in countries with which we have friendly relations, but outside of Europe. And then there is TEA1, which is intended to be readily exportable, which is also the only option for commercial use or infrastructure use of Tetra. And there's TEA4, which to the best of my knowledge, no one has ever used. So that's basically the cryptographic parts that exist within the Tetra standard. And with that in mind, let's discuss project ReTetra. Now, many of you will be familiar with Gekhoff's principle. It states that a crypto system should be secure if everything about the system, except for the key, is public knowledge. And already in the 19th century, this was found to be a very good idea. And why is it a good idea? Well, because violators of this principle generally don't fare well. On this slide, you see various cryptographic primitives that shortly or longer after their specification became public knowledge, were found to be vulnerable. And also, there's quite a few backdoors in there. Everything that's marked in orange was actually intentionally backdoored, exposing their users to dangers they were not even aware of. And in the interview with Kim Zetter from WIRED, the chair of the Tetra Technical Committee, Brian Murgatroyd, stated that in his opinion, obscurity is also a way of maintaining security. And we will see if that holds up. So, we approached the EnelNet Foundation, which is funding technology projects that are to develop open technologies or shed light on closed technologies, which was our case. And we wanted to open up Tetra for public reviews after about 25 years since its inception, in order to be able to have public reviews effective informed risk analysis by the users of these technologies and resolve any issues that we would identify. So, since we could not just get the specification from Etsy, since


chunk_text:
  this was found to be a very good idea. And why is it a good idea? Well, because violators of this principle generally don't fare well. On this slide, you see various cryptographic primitives that shortly or longer after their specification became public knowledge, were found to be vulnerable. And also, there's quite a few backdoors in there. Everything that's marked in orange was actually intentionally backdoored, exposing their users to dangers they were not even aware of. And in the interview with Kim Zetter from WIRED, the chair of the Tetra Technical Committee, Brian Murgatroyd, stated that in his opinion, obscurity is also a way of maintaining security. And we will see if that holds up. So, we approached the EnelNet Foundation, which is funding technology projects that are to develop open technologies or shed light on closed technologies, which was our case. And we wanted to open up Tetra for public reviews after about 25 years since its inception, in order to be able to have public reviews effective informed risk analysis by the users of these technologies and resolve any issues that we would identify. So, since we could not just get the specification from Etsy, since we would be signing an NDA if they would give it to us in the first place, prohibiting us from talking about the subject, we decided to try and reverse them out of a radio. And after careful deliberation, we chose the Motorola MTM5400, which is a very widely used model and commonly found online. You can just buy them off eBay. And what's interesting for us is that it has a system on a chip that was developed by Texas Instruments. And that's relevant because that means that the Tetra cryptography is likely not implemented in hardware, in silicon, which would be exceedingly hard to reverse engineer, at least with our expertise. And also, this chip has software security features that are specifically tailored to protecting pieces of intellectual property from exfiltration. It has a so-called trusted execution environment. And our guess was that this would be used to protect the secret Tetra algorithms from extraction. Now, how we did that is a whole talk of its own. And we only have 30 minutes here, so I'm going to skip over it. But what we basically did is find a modem command interface on the rear of the radio,


chunk_text:
  we would be signing an NDA if they would give it to us in the first place, prohibiting us from talking about the subject, we decided to try and reverse them out of a radio. And after careful deliberation, we chose the Motorola MTM5400, which is a very widely used model and commonly found online. You can just buy them off eBay. And what's interesting for us is that it has a system on a chip that was developed by Texas Instruments. And that's relevant because that means that the Tetra cryptography is likely not implemented in hardware, in silicon, which would be exceedingly hard to reverse engineer, at least with our expertise. And also, this chip has software security features that are specifically tailored to protecting pieces of intellectual property from exfiltration. It has a so-called trusted execution environment. And our guess was that this would be used to protect the secret Tetra algorithms from extraction. Now, how we did that is a whole talk of its own. And we only have 30 minutes here, so I'm going to skip over it. But what we basically did is find a modem command interface on the rear of the radio, which you can use to send it commands like call this number or change that in the address book. We found a format string vulnerability in there, exploited it, and got control over the application processor. From there, we jumped to the digital signal processor because they had a shared memory region, which was not protected. So we could override the programming of the DSP and get our own code to run there. And then in the DSP is this separate trusted execution environment that loaded the secret crypto, which we could not immediately read out. But we found a cache timing side channel attack on the AES decryption of the loading of such a module. So we extracted an AES key, we were able to decrypt the module, and that module implemented the secret Tetra crypto. So we reverse engineered that, and we could start doing what we actually came for. More details on this in our DEF CON talk, but let's continue for now, and discuss some of the findings that we actually found within this standard. So first, a short introduction to how a stream cipher works for those of you that may not be familiar with


chunk_text:
  which you can use to send it commands like call this number or change that in the address book. We found a format string vulnerability in there, exploited it, and got control over the application processor. From there, we jumped to the digital signal processor because they had a shared memory region, which was not protected. So we could override the programming of the DSP and get our own code to run there. And then in the DSP is this separate trusted execution environment that loaded the secret crypto, which we could not immediately read out. But we found a cache timing side channel attack on the AES decryption of the loading of such a module. So we extracted an AES key, we were able to decrypt the module, and that module implemented the secret Tetra crypto. So we reverse engineered that, and we could start doing what we actually came for. More details on this in our DEF CON talk, but let's continue for now, and discuss some of the findings that we actually found within this standard. So first, a short introduction to how a stream cipher works for those of you that may not be familiar with it. A stream cipher uses a cryptographic function, which we call the key stream generator. And this thing takes a key as an input, and an initialization value, which we will talk about later. And based on this, it generates a stream of bits of ones and zeros. And these bits are then combined with your plain text message, using the bitwise XOR function, and what you get then is your encrypted message. And on the receiving end, you can simply generate the same stream of bits, the same key stream, combine it again with the encrypted data, and recover the original plain text message. Now in Tetra, this key stream generator follows always the same kind of high-level design. Remember there's TEA 1 to 4, and they all share this outline. So you have a 10-byte, 80-bit key register at the top, which provides feedback to a state register, and out comes key stream, which is used for the encryption of the messages. We've looked at it, we're not professional cryptographers per se, but to us this seems like a fairly robust algorithm, so no immediate problem here. But this is TEA 2. And once you start looking at


chunk_text:
  it. A stream cipher uses a cryptographic function, which we call the key stream generator. And this thing takes a key as an input, and an initialization value, which we will talk about later. And based on this, it generates a stream of bits of ones and zeros. And these bits are then combined with your plain text message, using the bitwise XOR function, and what you get then is your encrypted message. And on the receiving end, you can simply generate the same stream of bits, the same key stream, combine it again with the encrypted data, and recover the original plain text message. Now in Tetra, this key stream generator follows always the same kind of high-level design. Remember there's TEA 1 to 4, and they all share this outline. So you have a 10-byte, 80-bit key register at the top, which provides feedback to a state register, and out comes key stream, which is used for the encryption of the messages. We've looked at it, we're not professional cryptographers per se, but to us this seems like a fairly robust algorithm, so no immediate problem here. But this is TEA 2. And once you start looking at TEA 1, it's immediately apparent that there is a big problem here. Now remember TEA 1, the target audience for this stuff is less friendly police forces and militaries, but also all commercial industrial use. So they cannot use TEA 2 or 3, they have to use TEA 1. And this function starts with a key initialization function, which compresses the 80-bit key into a mere 32 bits. And then based off that 32-bit derived key, it will start generating key stream. So as an attacker, you only need to brute force these 32 bits, which can be done on my 6-year-old laptop in about a minute, and you're able to start intercepting communication, decrypting communication, but you can also partake in the communication. You can start talking on talk groups, but more worrying is probably that you can inject data whenever Tetra is being used in a data-carrying capacity like SCADA telecontrol. Now in the aforementioned interview, the Etsy chair said that we use some very high-powered equipment in order to break these keys. Well, it's a 2016 graphics card for enthusiasts. And that 25 years ago, 32 bits of entropy was probably enough to withstand brute force attacks,


chunk_text:
  TEA 1, it's immediately apparent that there is a big problem here. Now remember TEA 1, the target audience for this stuff is less friendly police forces and militaries, but also all commercial industrial use. So they cannot use TEA 2 or 3, they have to use TEA 1. And this function starts with a key initialization function, which compresses the 80-bit key into a mere 32 bits. And then based off that 32-bit derived key, it will start generating key stream. So as an attacker, you only need to brute force these 32 bits, which can be done on my 6-year-old laptop in about a minute, and you're able to start intercepting communication, decrypting communication, but you can also partake in the communication. You can start talking on talk groups, but more worrying is probably that you can inject data whenever Tetra is being used in a data-carrying capacity like SCADA telecontrol. Now in the aforementioned interview, the Etsy chair said that we use some very high-powered equipment in order to break these keys. Well, it's a 2016 graphics card for enthusiasts. And that 25 years ago, 32 bits of entropy was probably enough to withstand brute force attacks, and that you need some pretty reasonable equipment in order to be able to carry out such an attack. Now I don't think I need to convince you guys that this is nonsense, but why would we make any assumptions or why would we limit ourselves to the use of very reasonable equipment? Why not just see what this bad boy can do? Hi, we're Midnight Blue. About two weeks ago, we announced the Tetra Burst vulnerabilities, consisting of five vulnerabilities in the Tetra radio standard, two of which are deemed critical. Since then, Etsy, the standardization body responsible for Tetra, has made public statements in which they downplay the seriousness of the vulnerabilities. In these statements, they resorted to a semantic discussion, not calling a spade a spade, or more specifically, not calling a backdoor a backdoor. Furthermore, they made a number of evidently false statements, such as claiming packet injection and TEA1 encrypted networks would be impossible, and that 32 bits of cryptographic strength would have been sufficient in the late 90s. To any information security expert, it's pretty clear that this is not the case. But to help remove those few remaining doubts, we decided to take


chunk_text:
  and that you need some pretty reasonable equipment in order to be able to carry out such an attack. Now I don't think I need to convince you guys that this is nonsense, but why would we make any assumptions or why would we limit ourselves to the use of very reasonable equipment? Why not just see what this bad boy can do? Hi, we're Midnight Blue. About two weeks ago, we announced the Tetra Burst vulnerabilities, consisting of five vulnerabilities in the Tetra radio standard, two of which are deemed critical. Since then, Etsy, the standardization body responsible for Tetra, has made public statements in which they downplay the seriousness of the vulnerabilities. In these statements, they resorted to a semantic discussion, not calling a spade a spade, or more specifically, not calling a backdoor a backdoor. Furthermore, they made a number of evidently false statements, such as claiming packet injection and TEA1 encrypted networks would be impossible, and that 32 bits of cryptographic strength would have been sufficient in the late 90s. To any information security expert, it's pretty clear that this is not the case. But to help remove those few remaining doubts, we decided to take on the challenge of cracking TEA1 on this beautiful machine produced in 1998, running good old Windows 95. Frankly, the hardware is so old that it wasn't easy to get our hands on. When we run the cracking tool, we see it reports that it needs about 13 hours to go through the entire search space. After 12 and a half hours, the key is found, demonstrating the feasibility of cracking TEA1 on 90s consumer hardware. Alright, Etsy, now that we've cleared up this issue, please let us know if you'd like us to demonstrate packet injection as well. Alright, so I think we got that out of the way. Now, that attack is a deliberately placed backdoor when it was designed, but there are still the other stronger algorithms left, right? There's TEA2 and TEA3. But we also found an attack on those. And in order to understand that, you need a little more information on how this encryption process actually works. So I mentioned the fact that besides a key, the keystream generator also takes an initialization value. And that is necessary because you want to generate a different keystream for each message that you want to encrypt.


chunk_text:
  on the challenge of cracking TEA1 on this beautiful machine produced in 1998, running good old Windows 95. Frankly, the hardware is so old that it wasn't easy to get our hands on. When we run the cracking tool, we see it reports that it needs about 13 hours to go through the entire search space. After 12 and a half hours, the key is found, demonstrating the feasibility of cracking TEA1 on 90s consumer hardware. Alright, Etsy, now that we've cleared up this issue, please let us know if you'd like us to demonstrate packet injection as well. Alright, so I think we got that out of the way. Now, that attack is a deliberately placed backdoor when it was designed, but there are still the other stronger algorithms left, right? There's TEA2 and TEA3. But we also found an attack on those. And in order to understand that, you need a little more information on how this encryption process actually works. So I mentioned the fact that besides a key, the keystream generator also takes an initialization value. And that is necessary because you want to generate a different keystream for each message that you want to encrypt. Because if you would use the same keystream again, you can do statistical analysis, derive what the keystream was and decrypt traffic. That's really bad. So you need a unique keystream for each message you encrypt. And in Tetra, this is done by using the network time as a fresh piece of information, as an initialization vector. And the network time is a series of numbers like the slot, the frame, the hyperframe, which designates basically the time the network is operating at. And how does a mobile station know what the time of the network is? Well, it knows because it's told. The infrastructure broadcasts sync and sysinfo frames which contain these counters very frequently so that a mobile station is aware of the network time, is aware of which IV should be used for the decryption. And it's important to note that besides the encryption on the message, there is no further integrity check, like cryptographic integrity check. So if a message would have been modified by an attacker, the radio will still just decrypt the message and see if it can be interpreted in a sensible way. So that brings us to an attack opportunity here. An


chunk_text:
  Because if you would use the same keystream again, you can do statistical analysis, derive what the keystream was and decrypt traffic. That's really bad. So you need a unique keystream for each message you encrypt. And in Tetra, this is done by using the network time as a fresh piece of information, as an initialization vector. And the network time is a series of numbers like the slot, the frame, the hyperframe, which designates basically the time the network is operating at. And how does a mobile station know what the time of the network is? Well, it knows because it's told. The infrastructure broadcasts sync and sysinfo frames which contain these counters very frequently so that a mobile station is aware of the network time, is aware of which IV should be used for the decryption. And it's important to note that besides the encryption on the message, there is no further integrity check, like cryptographic integrity check. So if a message would have been modified by an attacker, the radio will still just decrypt the message and see if it can be interpreted in a sensible way. So that brings us to an attack opportunity here. An attacker can identify a mobile station which is connected to the legitimate infrastructure and overpower the infrastructure signal. So basically taking over the link between the mobile station and the original infra. And if the attacker will then start sending spoofed sync and sysinfo frames, the mobile station will gladly oblige and start using these updated network time counters. And as such, the perception of time of the mobile station has been changed. And it will restart reusing key stream that was relevant before or that will be relevant in the future. So the attacker can now control which key streams from which time will be used by the mobile station. And this once more works for any of the of the air and interface encryption algorithms. So an outline of the attack would be that as an adversary we capture a stream of tetra traffic that's encrypted and we identify a message that we find interesting. We would like to know what's in that message. And say this message has been sent at time t. What we then do is identify another mobile station or the same, as long as they share the key material, this doesn't matter. You


chunk_text:
  attacker can identify a mobile station which is connected to the legitimate infrastructure and overpower the infrastructure signal. So basically taking over the link between the mobile station and the original infra. And if the attacker will then start sending spoofed sync and sysinfo frames, the mobile station will gladly oblige and start using these updated network time counters. And as such, the perception of time of the mobile station has been changed. And it will restart reusing key stream that was relevant before or that will be relevant in the future. So the attacker can now control which key streams from which time will be used by the mobile station. And this once more works for any of the of the air and interface encryption algorithms. So an outline of the attack would be that as an adversary we capture a stream of tetra traffic that's encrypted and we identify a message that we find interesting. We would like to know what's in that message. And say this message has been sent at time t. What we then do is identify another mobile station or the same, as long as they share the key material, this doesn't matter. You can pick one that's in a convenient location. And we overpower the legitimate signal of the infrastructure. You can do that by using a higher transmit power, by using a directional antenna, or simply by being closer to the mobile station. And what we then do is tell this mobile station that the network time is now again t. And then the mobile station will reuse key stream relevant at that time. If we can then send traffic to the mobile station and somehow recover the key stream that was that was being used back then, we can obtain the original key stream used to encrypt the message we want to know. And if we have done that, we can decrypt the message and we have won. How this works, I'm not going into that here because it'll take time and I don't have that. But you can check out one of our other talks on this subject or read the research paper. When we reported this to Etsy, they said, okay, that's a nice and valid theoretical attack. And it's true that there is some caveats to this, right? Would a radio actually accept these weird jumps in network


chunk_text:
  can pick one that's in a convenient location. And we overpower the legitimate signal of the infrastructure. You can do that by using a higher transmit power, by using a directional antenna, or simply by being closer to the mobile station. And what we then do is tell this mobile station that the network time is now again t. And then the mobile station will reuse key stream relevant at that time. If we can then send traffic to the mobile station and somehow recover the key stream that was that was being used back then, we can obtain the original key stream used to encrypt the message we want to know. And if we have done that, we can decrypt the message and we have won. How this works, I'm not going into that here because it'll take time and I don't have that. But you can check out one of our other talks on this subject or read the research paper. When we reported this to Etsy, they said, okay, that's a nice and valid theoretical attack. And it's true that there is some caveats to this, right? Would a radio actually accept these weird jumps in network time or will they just crash or will they have some safeguard against it? So we also wanted to know whether this was doable in practice. So we asked, maybe we can have a base station at our disposal that we can instrument and implement the attack on to see if this actually works in practice. And they said, well, lol, no, or something along those lines. Probably the wording was a bit different. So that left us in a bit of a tricky situation because we wanted to validate our theoretical attack. So we could implement a Tetra base station stack from scratch, which is a lot of work and not very fun to do. So instead we opted for another round, the other route, and we bought ourselves a Tetra base station. That was one on eBay. It was here in The Hague. It weighs 75 kilos and it's awesome. We found some vulnerabilities in it. We wrote a module loading framework that we patched into the firmware so that we could load modules at runtime. And we turned this thing into an attack platform to be able to assess whether our theoretical attack was actually valid in


chunk_text:
  time or will they just crash or will they have some safeguard against it? So we also wanted to know whether this was doable in practice. So we asked, maybe we can have a base station at our disposal that we can instrument and implement the attack on to see if this actually works in practice. And they said, well, lol, no, or something along those lines. Probably the wording was a bit different. So that left us in a bit of a tricky situation because we wanted to validate our theoretical attack. So we could implement a Tetra base station stack from scratch, which is a lot of work and not very fun to do. So instead we opted for another round, the other route, and we bought ourselves a Tetra base station. That was one on eBay. It was here in The Hague. It weighs 75 kilos and it's awesome. We found some vulnerabilities in it. We wrote a module loading framework that we patched into the firmware so that we could load modules at runtime. And we turned this thing into an attack platform to be able to assess whether our theoretical attack was actually valid in practice. Hi, we are Midnight Blue. We have uncovered several serious vulnerabilities in the Tetra radio standard dubbed Tetra Burst. We will first demonstrate a decryption oracle attack to recover a text message, but the attack can also be applied to voice communication and data. The demonstration takes place on our lab setup. The radio receives an encrypted message, which is also captured by the attacker. We see the message says secret. The attacker now needs to target a radio and impersonate the infrastructure and carry out the attack to decrypt the previously captured message. We have sped up this process. The attacker has now recovered all he needs to decrypt the message. This attack applies to all Tetra configurations, but can be resolved with a firmware update. All right, so it was possible after all. Now there's many more issues we uncovered along the way. I mentioned two issues in the Tetra standard. There's two more we found at the Anonymization attack, allowing you to know exactly who's talking to whom at which point in time on the network, and a session key pinning attack. Also, we found several issues in the Texas Instruments chip that this Motorola radio


chunk_text:
  practice. Hi, we are Midnight Blue. We have uncovered several serious vulnerabilities in the Tetra radio standard dubbed Tetra Burst. We will first demonstrate a decryption oracle attack to recover a text message, but the attack can also be applied to voice communication and data. The demonstration takes place on our lab setup. The radio receives an encrypted message, which is also captured by the attacker. We see the message says secret. The attacker now needs to target a radio and impersonate the infrastructure and carry out the attack to decrypt the previously captured message. We have sped up this process. The attacker has now recovered all he needs to decrypt the message. This attack applies to all Tetra configurations, but can be resolved with a firmware update. All right, so it was possible after all. Now there's many more issues we uncovered along the way. I mentioned two issues in the Tetra standard. There's two more we found at the Anonymization attack, allowing you to know exactly who's talking to whom at which point in time on the network, and a session key pinning attack. Also, we found several issues in the Texas Instruments chip that this Motorola radio was using. These are ROM level vulnerabilities, so they cannot be fixed that easily. You would have to make a new mask revision for the chip. We found four CVEs in the Motorola part of the firmware, and five CVEs in the Motorola base station firmware stack. Both of these last ones allow for key extraction and for the placement of persistent covert implants, so it's pretty serious stuff. Also, we found a backdoor password in the Motorola base station, like a secret hard-coded password that would give you an authorization level even beyond that of the system itself. So, this is a very important issue. Even beyond that of the system's owner. Very fun stuff. So, since this technology was developed in Europe, and since the TEA-1 backdoor was placed deliberately, sure, Europe at least would not be affected by this, right? The ETSI technical committee chair said that anyone who needs a lot of protection in Europe should not be using TEA-1, and he would suggest using TEA-2. The thing is that TEA-2 can only legally be used by law enforcement and emergency services, so that leaves out critical infrastructure. That's a pretty serious case, because what you


chunk_text:
  was using. These are ROM level vulnerabilities, so they cannot be fixed that easily. You would have to make a new mask revision for the chip. We found four CVEs in the Motorola part of the firmware, and five CVEs in the Motorola base station firmware stack. Both of these last ones allow for key extraction and for the placement of persistent covert implants, so it's pretty serious stuff. Also, we found a backdoor password in the Motorola base station, like a secret hard-coded password that would give you an authorization level even beyond that of the system itself. So, this is a very important issue. Even beyond that of the system's owner. Very fun stuff. So, since this technology was developed in Europe, and since the TEA-1 backdoor was placed deliberately, sure, Europe at least would not be affected by this, right? The ETSI technical committee chair said that anyone who needs a lot of protection in Europe should not be using TEA-1, and he would suggest using TEA-2. The thing is that TEA-2 can only legally be used by law enforcement and emergency services, so that leaves out critical infrastructure. That's a pretty serious case, because what you see here is a picture of how Tetra can be used in a critical infrastructure scenario. You have your SCADA telecontrol system, you have a Tetra link connecting it to a power distribution substation, and using either STS, which looks like SMS, if you will, or the packet data features of Tetra, telecontrol traffic goes back and forth between the substation and the SCADA service. So, it's really sensitive stuff, and really bad if someone can mess with this. Now, also, we found that up to very recently, we have actually been shipping backdoored TEA-1 encrypted material to European member states or candidate member states. And we found this by going through a lot of tenders and using a lot of Google Translate, but it's still being used at scale, especially in like the Eastern European countries. And that can be explained, because back in the day when these networks were founded, were built, we were a bit suspicious about these countries, and we were like, okay, have this nice backdoor, we can listen in and eavesdrop. But now that the geopolitical landscape has changed, it comes back to haunt us. So, maybe all of this is not that relevant,


chunk_text:
  see here is a picture of how Tetra can be used in a critical infrastructure scenario. You have your SCADA telecontrol system, you have a Tetra link connecting it to a power distribution substation, and using either STS, which looks like SMS, if you will, or the packet data features of Tetra, telecontrol traffic goes back and forth between the substation and the SCADA service. So, it's really sensitive stuff, and really bad if someone can mess with this. Now, also, we found that up to very recently, we have actually been shipping backdoored TEA-1 encrypted material to European member states or candidate member states. And we found this by going through a lot of tenders and using a lot of Google Translate, but it's still being used at scale, especially in like the Eastern European countries. And that can be explained, because back in the day when these networks were founded, were built, we were a bit suspicious about these countries, and we were like, okay, have this nice backdoor, we can listen in and eavesdrop. But now that the geopolitical landscape has changed, it comes back to haunt us. So, maybe all of this is not that relevant, maybe no one is actually targeting Tetra networks, or trying to listen in or trying to manipulate traffic. Well, we dug through the Snowden archives, and we found an example of Tetra being targeted for interception. For instance, during the climate change conference in Bali, the NSA and ASD had a joint operation, and they managed to recover demonstration routes and telephone number of the chief of police there. And we also found a GCHQ operation called Quito, which surrounded oil exploration rights around the Falkland Islands in a conflict with Argentina. And this is not proof that the vulnerabilities that I've been talking about have been used in the wild, but it is proof that Tetra is a legitimate target for attack and interception. Now, what's next? There are new algorithms. Regardless of our research, ETSI has been working on an update to the standard. There's now a TAA2 authentication suite, and TEA527 error interface encryption ciphers, which use longer keys. They were initially going to be secret again, but following our disclosure, they published that they will make these algorithms public. So that's a very nice thing, since in their own words, transparency is at the root of


chunk_text:
  maybe no one is actually targeting Tetra networks, or trying to listen in or trying to manipulate traffic. Well, we dug through the Snowden archives, and we found an example of Tetra being targeted for interception. For instance, during the climate change conference in Bali, the NSA and ASD had a joint operation, and they managed to recover demonstration routes and telephone number of the chief of police there. And we also found a GCHQ operation called Quito, which surrounded oil exploration rights around the Falkland Islands in a conflict with Argentina. And this is not proof that the vulnerabilities that I've been talking about have been used in the wild, but it is proof that Tetra is a legitimate target for attack and interception. Now, what's next? There are new algorithms. Regardless of our research, ETSI has been working on an update to the standard. There's now a TAA2 authentication suite, and TEA527 error interface encryption ciphers, which use longer keys. They were initially going to be secret again, but following our disclosure, they published that they will make these algorithms public. So that's a very nice thing, since in their own words, transparency is at the root of ETSI. So that's fantastic. I mean, it's a step forward. We hope they will also publish their design criteria, the reason why they would pick certain constructions, why they picked certain constants or tables. And additionally, there is a clear front door now, because they have already admitted that TEA7 will have an effective key length of 56 bits, as to make it freely exportable. And that free export thing is a bit tricky, because Wassenaar, the convention governing all of this, leaves room for strong cryptography in these kinds of use cases. We all use HTTPS without problem. There are exceptions for civil use. There are exceptions for connected civil industry applications. So at least the critical infrastructure use cases, I think, should be covered by these things. And we can just give these guys strong crypto. So will TEA7 get into critical infra again? I really don't hope so. But if it happens, at least we now know on beforehand. So in conclusion, we have published the first in-depth security analysis of Tetra. We've reverse engineered and published the secret algorithms that were being used. We found multiple vulnerabilities, including a backdoor. Patches are available for some of


chunk_text:
  ETSI. So that's fantastic. I mean, it's a step forward. We hope they will also publish their design criteria, the reason why they would pick certain constructions, why they picked certain constants or tables. And additionally, there is a clear front door now, because they have already admitted that TEA7 will have an effective key length of 56 bits, as to make it freely exportable. And that free export thing is a bit tricky, because Wassenaar, the convention governing all of this, leaves room for strong cryptography in these kinds of use cases. We all use HTTPS without problem. There are exceptions for civil use. There are exceptions for connected civil industry applications. So at least the critical infrastructure use cases, I think, should be covered by these things. And we can just give these guys strong crypto. So will TEA7 get into critical infra again? I really don't hope so. But if it happens, at least we now know on beforehand. So in conclusion, we have published the first in-depth security analysis of Tetra. We've reverse engineered and published the secret algorithms that were being used. We found multiple vulnerabilities, including a backdoor. Patches are available for some of these issues. If you want to know more about that, check out our website. There has been great progress in understanding these issues and in mitigating the issues. But there's still a lot of work to be done for asset owners. And in the broadest sense, it seems that these kind of mission-critical technologies are just not being assessed enough. And with that, I conclude this presentation, and I'd love to take any questions if there are any. Yes, thank you very much. Are there any questions in the audience? One question. Tetra is here to stay for a little while before we go over to a new system. Would it be feasible to tunnel some other protocol on top of it, which is encrypted, to overcome these hurdles? Yes, definitely. Etsy themselves, they envision a multi-decade future for Tetra. At the very least, the networks that are out there are not leaving anytime soon. So indeed, it's possible to use something like a VPN before you start sending your IP traffic over Tetra, which would be a very good idea. For existing networks, however, especially in the industrial context, due to the strictness of the acceptance testing and the


