# MediaChunks

chunk_id: 140_chunk_29
chunk_text:
1516.92s | fork that will trigger a vulnerable CI execution in the context of the target, right? We're all 1516.92s - 1523.64s | familiar with this by now. I hope so. The second bit, the lax policies, they will allow a token 1523.64s - 1529.56s | from the same, from the targeted organisation, sorry, to slip through lax policies, okay? Now 1529.60s - 1536.32s | what do I mean by that? Let's see how it plays. Demo. In order to demo that, we have to define a 1536.32s - 1540.84s | few entities, right? Let's begin with the identity federation on the resource side. So we're 1540.84s - 1546.32s | gonna set up something like this. We wanna assert that the audience equals, uh, the Amazon AWS 1546.32s - 1551.56s | thing. Um, and we wanna assert that all the identities coming in from the banana multi 1551.56s - 1557.28s | organisation are okay to go in. This is the federation. If you put it, by the way, on AWS, it's 1557.28s - 1562.60s | gonna look something like this. And although AWS did some changes in order to enforce more 1562.60s - 1569.60s | strict policies, they will allow you to do that. This is fine by AWS. Now for the git part, 1569.60s - 1575.80s | let's see what's our setup. We have this organisation called banana multi and we have two, uh, 1575.80s - 1582.32s | basically pipelines including the git repo itself. And let's explain. So the upper one, um, is a 1582.32s - 1588.20s | pipeline that is configured to connect using OIDC to an S3 role that is, uh, an admin. Um, this 1588.20s - 1594.20s | policy is the policy that we just saw, so it's lax. Um, and this is our target. The second pipeline 1594.20s - 1600.38s | is called any updateser and, uh, it contains, it's connected to a vulnerable pipeline and then 1600.38s - 1606.52s | it's using an OIDC token again to access a restricted S3, uh, uh, bucket or a role and we 1606.52s - 1613.50s | obviously cannot use that. So let's see our attack vector. Pretty simple. We're gonna fork the 1613.50s - 1620.16s | any updateser and we're gonna, uh, um, basically invoke the CI machine of the, the CI workflow, 1620.16s - 1625.34s | sorry, of, uh, and we're gonna invoke the vulnerable


chunk_id: 140_chunk_30
chunk_text:
you to do that. This is fine by AWS. Now for the git part, 1569.60s - 1575.80s | let's see what's our setup. We have this organisation called banana multi and we have two, uh, 1575.80s - 1582.32s | basically pipelines including the git repo itself. And let's explain. So the upper one, um, is a 1582.32s - 1588.20s | pipeline that is configured to connect using OIDC to an S3 role that is, uh, an admin. Um, this 1588.20s - 1594.20s | policy is the policy that we just saw, so it's lax. Um, and this is our target. The second pipeline 1594.20s - 1600.38s | is called any updateser and, uh, it contains, it's connected to a vulnerable pipeline and then 1600.38s - 1606.52s | it's using an OIDC token again to access a restricted S3, uh, uh, bucket or a role and we 1606.52s - 1613.50s | obviously cannot use that. So let's see our attack vector. Pretty simple. We're gonna fork the 1613.50s - 1620.16s | any updateser and we're gonna, uh, um, basically invoke the CI machine of the, the CI workflow, 1620.16s - 1625.34s | sorry, of, uh, and we're gonna invoke the vulnerable CI workflow and we'll try to access the 1625.34s - 1631.38s | other accounts. Um, the workflow, by the way, looks something like this. It has to react to pull 1631.38s - 1636.28s | request, maybe pull request or pull request target for the GitHub world. Um, and you have to 1636.28s - 1642.92s | specify that you want an ID token that the workflow has to say it. Um, the pipeline is gonna 1642.92s - 1646.90s | check out the fork. This is the head for the pull request. Uh, we're gonna skip the part where it 1646.90s - 1652.40s | actually assumed the AWS role. We don't, we can't use that so we don't care. And then there's an 1652.40s - 1658.08s | invocation of a file from the file system which was just cloned from the fork and yeah, we have 1658.08s - 1663.92s | RCE. So what we need to do now is make the fork pull request. This is what's called IPP, 1663.92s - 1670.72s | indirect points of pipeline execution. And this is the exploit script. Don't rush and, and, and 1670.72s - 1676.22s | take pictures. It's just chat GPT. Um, but basically


chunk_id: 140_chunk_31
chunk_text:
CI workflow and we'll try to access the 1625.34s - 1631.38s | other accounts. Um, the workflow, by the way, looks something like this. It has to react to pull 1631.38s - 1636.28s | request, maybe pull request or pull request target for the GitHub world. Um, and you have to 1636.28s - 1642.92s | specify that you want an ID token that the workflow has to say it. Um, the pipeline is gonna 1642.92s - 1646.90s | check out the fork. This is the head for the pull request. Uh, we're gonna skip the part where it 1646.90s - 1652.40s | actually assumed the AWS role. We don't, we can't use that so we don't care. And then there's an 1652.40s - 1658.08s | invocation of a file from the file system which was just cloned from the fork and yeah, we have 1658.08s - 1663.92s | RCE. So what we need to do now is make the fork pull request. This is what's called IPP, 1663.92s - 1670.72s | indirect points of pipeline execution. And this is the exploit script. Don't rush and, and, and 1670.72s - 1676.22s | take pictures. It's just chat GPT. Um, but basically all you have to do before you make this 1676.22s - 1682.56s | exploit code, you have to, uh, to do some recon and collect various id- accounts that are, are 1682.56s - 1687.40s | connected through using OIDC. Okay? I'm not gonna talk about it in stock, but this is 1687.40s - 1691.80s | something you have to do. In this example I'm having 2 roles at the top that I'm gonna try to 1691.80s - 1697.60s | exploit. Let's see it in action. So this is the prepare.sh file that is gonna be invoked at 1697.60s - 1702.60s | some point. Uh, this is my fork. Any updates sir? And I'm gonna open a pull request. So, uh, 1705.00s - 1709.32s | hello it's me. The diff is the same file, nothing but this file. And I'm gonna open the pull 1709.32s - 1717.27s | request and it's gonna invoke the CI in response to the trigger. Cool. 3 seconds from now we're 1717.29s - 1722.29s | gonna see the machine logs. 1, 2, 3, as I promised. And now in the logs we will see in the 1724.83s - 1729.89s | prepare step that it, we will


chunk_id: 140_chunk_32
chunk_text:
all you have to do before you make this 1676.22s - 1682.56s | exploit code, you have to, uh, to do some recon and collect various id- accounts that are, are 1682.56s - 1687.40s | connected through using OIDC. Okay? I'm not gonna talk about it in stock, but this is 1687.40s - 1691.80s | something you have to do. In this example I'm having 2 roles at the top that I'm gonna try to 1691.80s - 1697.60s | exploit. Let's see it in action. So this is the prepare.sh file that is gonna be invoked at 1697.60s - 1702.60s | some point. Uh, this is my fork. Any updates sir? And I'm gonna open a pull request. So, uh, 1705.00s - 1709.32s | hello it's me. The diff is the same file, nothing but this file. And I'm gonna open the pull 1709.32s - 1717.27s | request and it's gonna invoke the CI in response to the trigger. Cool. 3 seconds from now we're 1717.29s - 1722.29s | gonna see the machine logs. 1, 2, 3, as I promised. And now in the logs we will see in the 1724.83s - 1729.89s | prepare step that it, we will see the output of my script and if we're successful we'll see 1729.89s - 1735.03s | sets of credentials. And I wouldn't be here if it would work, so yeah, we have sets of 1735.03s - 1739.11s | credentials. So we were able to assume a role that was not allocated to the pipeline we were 1739.11s - 1743.71s | running at. While we were not able to assert others, but again you can just spray OIDC 1743.75s - 1748.43s | tokens. So this is a very nice technique. You can just collect tokens, find vulnerable 1748.43s - 1752.99s | pipelines and start spraying for, to find the locks policies internally, right? You're 1752.99s - 1760.14s | already past the auth end. You have the credentials. So give it a shot. 1 second. Okay, uh, 1763.36s - 1768.16s | some nice disclosure. I was able to, this is by the way from last year already and, and I was 1768.16s - 1773.00s | able to find this, uh, a month ago in Azure and this allowed to access basically all the 1773.00s - 1778.58s | identities that had Azure slash star. So yeah, nice technique. Um, the rest did not


chunk_id: 140_chunk_33
chunk_text:
see the output of my script and if we're successful we'll see 1729.89s - 1735.03s | sets of credentials. And I wouldn't be here if it would work, so yeah, we have sets of 1735.03s - 1739.11s | credentials. So we were able to assume a role that was not allocated to the pipeline we were 1739.11s - 1743.71s | running at. While we were not able to assert others, but again you can just spray OIDC 1743.75s - 1748.43s | tokens. So this is a very nice technique. You can just collect tokens, find vulnerable 1748.43s - 1752.99s | pipelines and start spraying for, to find the locks policies internally, right? You're 1752.99s - 1760.14s | already past the auth end. You have the credentials. So give it a shot. 1 second. Okay, uh, 1763.36s - 1768.16s | some nice disclosure. I was able to, this is by the way from last year already and, and I was 1768.16s - 1773.00s | able to find this, uh, a month ago in Azure and this allowed to access basically all the 1773.00s - 1778.58s | identities that had Azure slash star. So yeah, nice technique. Um, the rest did not allow 1778.58s - 1783.58s | disclosure, but you're out there. Cool. So rule of thumb in order to avoid this type of stuff, 1786.46s - 1791.46s | one is for the CI, please follow the best practices. We're at 2024. Um, we, my team, we've 1793.46s - 1799.36s | released plenty of guides on how to, uh, harden your pipelines. Please do so. The second 1799.36s - 1804.36s | thing, pursue, uh, policies that are not with wildcards as much as you can or, uh, use other 1806.56s - 1811.58s | claims that are safe in order to assert identities. Okay, this brings us to our last topic 1814.54s - 1818.38s | of the day and this is when, when the vendor misconfigures. Now that you know that the vendor, 1818.38s - 1823.46s | the CI vendor is also the identity provider, now they have to put, to give more attention to 1823.46s - 1828.32s | the details, right? They have various products at their hand now and they have to be very 1828.32s - 1833.32s | careful. So this is a disclosure for a Circle CI. Um, and basically if you're unfamiliar with 1834.92s - 1839.82s | Circle, they're


chunk_id: 140_chunk_34
chunk_text:
allow 1778.58s - 1783.58s | disclosure, but you're out there. Cool. So rule of thumb in order to avoid this type of stuff, 1786.46s - 1791.46s | one is for the CI, please follow the best practices. We're at 2024. Um, we, my team, we've 1793.46s - 1799.36s | released plenty of guides on how to, uh, harden your pipelines. Please do so. The second 1799.36s - 1804.36s | thing, pursue, uh, policies that are not with wildcards as much as you can or, uh, use other 1806.56s - 1811.58s | claims that are safe in order to assert identities. Okay, this brings us to our last topic 1814.54s - 1818.38s | of the day and this is when, when the vendor misconfigures. Now that you know that the vendor, 1818.38s - 1823.46s | the CI vendor is also the identity provider, now they have to put, to give more attention to 1823.46s - 1828.32s | the details, right? They have various products at their hand now and they have to be very 1828.32s - 1833.32s | careful. So this is a disclosure for a Circle CI. Um, and basically if you're unfamiliar with 1834.92s - 1839.82s | Circle, they're a great CI product. Um, they provide various machines, right? In order for you 1839.82s - 1845.80s | to run your workloads and they're super nice and professional folks on a personal level. Okay? 1845.80s - 1850.48s | When I looked into, oh, just to explain, uh, Circle, sorry, um, this is you, you perform Git 1850.48s - 1854.88s | push. You're all familiar with this diagram by now. Well, you notify Circle with a payload and 1854.90s - 1859.84s | they did your CI thing for you. Now when GitHub notifies Circle, by the way, they do that with 1859.84s - 1865.64s | the webhook and the payload is everything that was, that is in your Git context. So in a way, 1865.64s - 1871.02s | and just to add to the confusion, Circle can supply you with a super set of claims on top of 1871.02s - 1874.36s | GitHub's claims. If you think about it, just to add to the confusion from earlier, I see your 1874.36s - 1880.56s | faces, so yeah, it's confusing. Um, okay, so when I looked into Circle CI system state, I 1880.58s - 1884.78s | noted the following. First, pipelines reacted


chunk_id: 140_chunk_35
chunk_text:
a great CI product. Um, they provide various machines, right? In order for you 1839.82s - 1845.80s | to run your workloads and they're super nice and professional folks on a personal level. Okay? 1845.80s - 1850.48s | When I looked into, oh, just to explain, uh, Circle, sorry, um, this is you, you perform Git 1850.48s - 1854.88s | push. You're all familiar with this diagram by now. Well, you notify Circle with a payload and 1854.90s - 1859.84s | they did your CI thing for you. Now when GitHub notifies Circle, by the way, they do that with 1859.84s - 1865.64s | the webhook and the payload is everything that was, that is in your Git context. So in a way, 1865.64s - 1871.02s | and just to add to the confusion, Circle can supply you with a super set of claims on top of 1871.02s - 1874.36s | GitHub's claims. If you think about it, just to add to the confusion from earlier, I see your 1874.36s - 1880.56s | faces, so yeah, it's confusing. Um, okay, so when I looked into Circle CI system state, I 1880.58s - 1884.78s | noted the following. First, pipelines reacted to fork pull requests if and only if, there's no 1884.78s - 1889.98s | typo, uh, the project is configured to do so. Now this is actually a good limitation, right? We 1889.98s - 1894.46s | don't want anybody on the internet to run machines for us. Putting aside security, someone's 1894.46s - 1900.46s | gotta pay for that. Okay, but second thing that I noted is that pipelines were triggered, uh, on a 1900.46s - 1906.16s | workflow change, even from a fork. Okay? And this is not good. Why? This implies every pull 1906.20s - 1911.20s | request can be an RC, you can just commit, basically pull request a malicious workflow. Okay, 1913.88s - 1919.34s | doesn't look good, but the third part was the, the cherry on top. An IDC token was always 1919.34s - 1925.18s | granted to the machine regardless of anything. And this is credentials mishandle and misuse. 1925.18s - 1931.86s | Okay? So combining those, I was granted an ID token in the context of any Circle CI project 1931.86s - 1936.50s | that allowed fork pull requests. Okay, what does it imply? What does it mean? Is that I was 1936.50s


chunk_id: 140_chunk_36
chunk_text:
to fork pull requests if and only if, there's no 1884.78s - 1889.98s | typo, uh, the project is configured to do so. Now this is actually a good limitation, right? We 1889.98s - 1894.46s | don't want anybody on the internet to run machines for us. Putting aside security, someone's 1894.46s - 1900.46s | gotta pay for that. Okay, but second thing that I noted is that pipelines were triggered, uh, on a 1900.46s - 1906.16s | workflow change, even from a fork. Okay? And this is not good. Why? This implies every pull 1906.20s - 1911.20s | request can be an RC, you can just commit, basically pull request a malicious workflow. Okay, 1913.88s - 1919.34s | doesn't look good, but the third part was the, the cherry on top. An IDC token was always 1919.34s - 1925.18s | granted to the machine regardless of anything. And this is credentials mishandle and misuse. 1925.18s - 1931.86s | Okay? So combining those, I was granted an ID token in the context of any Circle CI project 1931.86s - 1936.50s | that allowed fork pull requests. Okay, what does it imply? What does it mean? Is that I was 1936.50s - 1941.80s | able to access OIDC gated resources of any Circle CI organization that allowed fork pull 1941.80s - 1947.88s | requests. Right, that's basically everybody on Circle that has pull requests and OIDC. Nice 1947.88s - 1953.02s | amount. Um, the attack flow is pretty simple, you just saw a demo of that using, uh, another 1953.02s - 1956.68s | file, right, the prepare, so I'm not gonna show the same thing, all you've, you had to do 1956.68s - 1961.16s | basically is, uh, pull request the workflow. So I'm not gonna show that, I will talk about the 1961.16s - 1966.96s | disclosure, however. So in order to show Circle CI that this was indeed a bug, I looked for 1966.96s - 1973.40s | instances in the wild to support my case. Um, it wasn't long ago until I found this file. Now, 1973.40s - 1978.38s | this was by a company called Darklang, anybody here familiar with those folks? Hands up? No? 1978.38s - 1984.28s | Okay. Um, just to explain this file, this is an identity federation for, uh, GCP, and even 1984.28s - 1988.42s | though you don't know this, this cell language,


chunk_id: 140_chunk_37
chunk_text:
- 1941.80s | able to access OIDC gated resources of any Circle CI organization that allowed fork pull 1941.80s - 1947.88s | requests. Right, that's basically everybody on Circle that has pull requests and OIDC. Nice 1947.88s - 1953.02s | amount. Um, the attack flow is pretty simple, you just saw a demo of that using, uh, another 1953.02s - 1956.68s | file, right, the prepare, so I'm not gonna show the same thing, all you've, you had to do 1956.68s - 1961.16s | basically is, uh, pull request the workflow. So I'm not gonna show that, I will talk about the 1961.16s - 1966.96s | disclosure, however. So in order to show Circle CI that this was indeed a bug, I looked for 1966.96s - 1973.40s | instances in the wild to support my case. Um, it wasn't long ago until I found this file. Now, 1973.40s - 1978.38s | this was by a company called Darklang, anybody here familiar with those folks? Hands up? No? 1978.38s - 1984.28s | Okay. Um, just to explain this file, this is an identity federation for, uh, GCP, and even 1984.28s - 1988.42s | though you don't know this, this cell language, uh, GCP's language, you can understand the 1988.42s - 1992.76s | mapping here, right? We know that CircleCI.com, we know this is the provider, and we know 1992.76s - 1997.66s | project ID is the claim, and we're gonna map it to project, audience to organization ID, and 1997.66s - 2002.60s | sub to sub, right? We now know what these claims are. Um, per the condition, the condition was 2002.60s - 2007.60s | that any one of these three project IDs is okay to access. And something that I cared, but 2010.04s - 2015.64s | then didn't care for the exploitation was that the issue URL and the allowed audience had to 2015.66s - 2020.84s | be the organization, uh, ID. Now this is fine as long as you create a pull request within the 2020.84s - 2024.64s | organization, Circle will just provide you with the ID, right? You're in the context of the 2024.64s - 2030.74s | organization, so this part is fine, we don't need to care about that. Um, so basically, a 2030.74s - 2036.28s | fork PR to any of those projects, um, which indeed they allowed fork PRs, uh, granted access 2036.28s -


chunk_id: 140_chunk_38
chunk_text:
uh, GCP's language, you can understand the 1988.42s - 1992.76s | mapping here, right? We know that CircleCI.com, we know this is the provider, and we know 1992.76s - 1997.66s | project ID is the claim, and we're gonna map it to project, audience to organization ID, and 1997.66s - 2002.60s | sub to sub, right? We now know what these claims are. Um, per the condition, the condition was 2002.60s - 2007.60s | that any one of these three project IDs is okay to access. And something that I cared, but 2010.04s - 2015.64s | then didn't care for the exploitation was that the issue URL and the allowed audience had to 2015.66s - 2020.84s | be the organization, uh, ID. Now this is fine as long as you create a pull request within the 2020.84s - 2024.64s | organization, Circle will just provide you with the ID, right? You're in the context of the 2024.64s - 2030.74s | organization, so this part is fine, we don't need to care about that. Um, so basically, a 2030.74s - 2036.28s | fork PR to any of those projects, um, which indeed they allowed fork PRs, uh, granted access 2036.28s - 2040.96s | to their clouds, that was it, as simple. Okay, just detect the misconfig, pull request, 2040.98s - 2046.68s | enjoy the cloud account. So, good summary on me, I'll disclose to the company so they can fix it, 2046.68s - 2053.06s | and meanwhile, meanwhile I'll go to Circle. I went to Darklang's, uh, Discord, asking for, uh, 2053.06s - 2059.16s | bug bounty cause I like it, and, but there was none, so I was told to DM, uh, DM someone, um, 2059.16s - 2063.60s | this is the someone, PBigger, I don't know if someone is familiar with this name, but yeah, we're 2063.60s - 2068.88s | gonna see exactly how you are familiar. But, um, yeah, he told me DM me, which I did, I sent, uh, 2069.10s - 2073.26s | I sent them everything, and I also added the line, the reason, at the bottom, sorry, the reason is 2073.26s - 2076.60s | not safe, it's not because of you, it's because of a bug in Circle, right? I mean, you're fine, 2076.60s - 2081.98s | just defend yourself, it's them, not you. Um, I also asked them to not disclose right now, I


chunk_id: 140_chunk_39
chunk_text:
2040.96s | to their clouds, that was it, as simple. Okay, just detect the misconfig, pull request, 2040.98s - 2046.68s | enjoy the cloud account. So, good summary on me, I'll disclose to the company so they can fix it, 2046.68s - 2053.06s | and meanwhile, meanwhile I'll go to Circle. I went to Darklang's, uh, Discord, asking for, uh, 2053.06s - 2059.16s | bug bounty cause I like it, and, but there was none, so I was told to DM, uh, DM someone, um, 2059.16s - 2063.60s | this is the someone, PBigger, I don't know if someone is familiar with this name, but yeah, we're 2063.60s - 2068.88s | gonna see exactly how you are familiar. But, um, yeah, he told me DM me, which I did, I sent, uh, 2069.10s - 2073.26s | I sent them everything, and I also added the line, the reason, at the bottom, sorry, the reason is 2073.26s - 2076.60s | not safe, it's not because of you, it's because of a bug in Circle, right? I mean, you're fine, 2076.60s - 2081.98s | just defend yourself, it's them, not you. Um, I also asked them to not disclose right now, I 2081.98s - 2085.74s | don't know who is aware of that, I don't want anybody to exploit, I'm, uh, white hat at that 2085.74s - 2090.88s | point, uh, I don't want anybody to exploit, um, so don't talk to anybody. Um, PBigger replied 2090.88s - 2094.82s | that he was investigating, and then he confirmed it and blocked all access. By the way, this is 2094.82s - 2101.10s | exactly where OIDC kicks in. By ticking one box, he was able to kill all the GitHub, basically 2101.10s - 2106.44s | all the, um, OIDC connections coming from Circle, okay? This is very powerful. No rotations 2106.44s - 2112.44s | needed, no credential changes, just one box. Um, he was fixing that, and we were, we 2112.44s - 2116.88s | continued chatting, later on, he said again that he was very happy to seal it, to which I 2116.88s - 2122.62s | replied, no problem. To which he replied, uh, by the way, I sent a note to the security folks 2122.62s - 2127.62s | at CircleCI, I wasn't sure if you knew, but I founded Circle. Yeah. So, just a random dude 2134.56s - 2141.58s | on Discord,


chunk_id: 140_chunk_40
chunk_text:
2081.98s - 2085.74s | don't know who is aware of that, I don't want anybody to exploit, I'm, uh, white hat at that 2085.74s - 2090.88s | point, uh, I don't want anybody to exploit, um, so don't talk to anybody. Um, PBigger replied 2090.88s - 2094.82s | that he was investigating, and then he confirmed it and blocked all access. By the way, this is 2094.82s - 2101.10s | exactly where OIDC kicks in. By ticking one box, he was able to kill all the GitHub, basically 2101.10s - 2106.44s | all the, um, OIDC connections coming from Circle, okay? This is very powerful. No rotations 2106.44s - 2112.44s | needed, no credential changes, just one box. Um, he was fixing that, and we were, we 2112.44s - 2116.88s | continued chatting, later on, he said again that he was very happy to seal it, to which I 2116.88s - 2122.62s | replied, no problem. To which he replied, uh, by the way, I sent a note to the security folks 2122.62s - 2127.62s | at CircleCI, I wasn't sure if you knew, but I founded Circle. Yeah. So, just a random dude 2134.56s - 2141.58s | on Discord, right? So, a good advice here would be to attempt to not disclose directly to the 2141.58s - 2148.34s | board member, or the CEO, it can be a bit awkward and odd. So, yeah. This was, uh, June 23, 2148.34s - 2153.20s | Circle since then fixed this bug and sealed it, and now if you look into their OIDC page, you 2153.20s - 2158.62s | see this message, what about forks, and basically, uh, you have to opt in now. Like in GitHub, I 2158.62s - 2162.88s | told you you have to set up ID token, right? This is the same thing, you have to opt in, this is 2162.88s - 2168.06s | done in a different manner, but the same idea. You have to opt in in order to provide a fork, a 2168.06s - 2174.12s | machine that is running for fork pull request, an OIDC token. Um, this changes this state, and 2174.14s - 2180.48s | now we have a proper handling. You can see that, um, part two is still there. Uh, some 2180.48s - 2185.48s | integrations in Circle still react to that, so, enjoy the misconfig. Um, and this is roughly,


chunk_id: 140_chunk_41
chunk_text:
right? So, a good advice here would be to attempt to not disclose directly to the 2141.58s - 2148.34s | board member, or the CEO, it can be a bit awkward and odd. So, yeah. This was, uh, June 23, 2148.34s - 2153.20s | Circle since then fixed this bug and sealed it, and now if you look into their OIDC page, you 2153.20s - 2158.62s | see this message, what about forks, and basically, uh, you have to opt in now. Like in GitHub, I 2158.62s - 2162.88s | told you you have to set up ID token, right? This is the same thing, you have to opt in, this is 2162.88s - 2168.06s | done in a different manner, but the same idea. You have to opt in in order to provide a fork, a 2168.06s - 2174.12s | machine that is running for fork pull request, an OIDC token. Um, this changes this state, and 2174.14s - 2180.48s | now we have a proper handling. You can see that, um, part two is still there. Uh, some 2180.48s - 2185.48s | integrations in Circle still react to that, so, enjoy the misconfig. Um, and this is roughly, 2188.16s - 2192.52s | this is our conclusions and takeaways. So, first of all, I hope that now you know what OIDC is. 2192.52s - 2197.30s | It's not that hard, right? I was talking to folks before and they were giving me weird faces, like 2197.30s - 2202.30s | yeah, I know, know OIDC, know. So, I hope you know it now, relax, it's fine, it's chill, okay? Um, 2204.40s - 2209.54s | plus you already learned OAuth, this is the big thing to, to swallow here. Um, second thing, and 2209.54s - 2215.18s | this is actual takeaways, so, for in using OIDC NCI, do the following, uh, learn the origin of 2215.18s - 2219.42s | each claims, I've provided the tool for GitHub again, but, um, learn the claims for your 2219.42s - 2225.46s | identity providers, uh, pursue policies without wildcards, and always think, always think which 2225.46s - 2230.46s | other identities can satisfy my conditions. Last bit, please harden your pipelines, sometimes 2230.70s - 2235.70s | it's too easy, that's it. So, yeah. Um, and yeah, but that's basically it, thank you very much. Um, 2241.18s - 2250.53s | yeah, I'm here for questions,


chunk_id: 140_chunk_42
chunk_text:
2188.16s - 2192.52s | this is our conclusions and takeaways. So, first of all, I hope that now you know what OIDC is. 2192.52s - 2197.30s | It's not that hard, right? I was talking to folks before and they were giving me weird faces, like 2197.30s - 2202.30s | yeah, I know, know OIDC, know. So, I hope you know it now, relax, it's fine, it's chill, okay? Um, 2204.40s - 2209.54s | plus you already learned OAuth, this is the big thing to, to swallow here. Um, second thing, and 2209.54s - 2215.18s | this is actual takeaways, so, for in using OIDC NCI, do the following, uh, learn the origin of 2215.18s - 2219.42s | each claims, I've provided the tool for GitHub again, but, um, learn the claims for your 2219.42s - 2225.46s | identity providers, uh, pursue policies without wildcards, and always think, always think which 2225.46s - 2230.46s | other identities can satisfy my conditions. Last bit, please harden your pipelines, sometimes 2230.70s - 2235.70s | it's too easy, that's it. So, yeah. Um, and yeah, but that's basically it, thank you very much. Um, 2241.18s - 2250.53s | yeah, I'm here for questions, if there are any. Questions? Beers? Shots? No? See you around.


chunk_id: 141_chunk_0
chunk_text:
{ "webpage_url": "https://www.youtube.com/watch?v=mKRS5Iyy7Qo", "title": "DEF CON 32 - MaLDAPtive: Obfuscation and De-Obfuscation - Daniel Bohannon, Sabajete Elezaj", "description": "DAP is no stranger to the security spotlight. While LDAP is a protocol (Lightweight Directory Access Protocol) and Active Directory is the most popular directory services system that supports a subset of LDAP, the terms \u201cLDAP\u201d and \u201cAD\u201d are tightly coupled when discussing the execution, detection and prevention of attacks targeting directory services data.\n\nIn the last decade the widespread offensive value of querying AD data via LDAP was cemented with the release of open-source tools such as BloodHound and PingCastle. However, proper visibility of LDAP queries mostly remains a privileged asset for those organizations with deep pockets, and the commercial security tools providing this visibility are often woefully fixated on simple signature-based detections.\n\nMaLDAPtive is the 2,000-hour (and counting) quest of offensive and defensive LDAP exploration and tool-building. This research includes mind-bending depths of obfuscation across all elements of LDAP queries (many undocumented and most never seen in the wild), all baked into an obfuscation/de-obfuscation/detection framework built upon our ground-up custom LDAP search filter tokenizer and syntax tree parser.\n\nCome witness the release of our MaLDAPtive research and open-source framework: transforming LDAP from \u201clightweight\u201d to \u201cheavyweight.\u201d", "channel_url": "https://www.youtube.com/channel/UC6Om9kAkl32dWlDSNlDS9Iw", "duration": 2802, "channel": "DEFCONConference", "uploader": "DEFCONConference", "upload_date": "20241016" } 0.00s - 12.76s | This text was transcribed using whisper model: large-v2 How's everyone doing? I'm genuinely surprised. So either 12.76s - 15.14s | y'all went to bed early or you never went to bed. So thank you 15.14s - 18.70s | so much for being here. This talk is maladaptive. It's diving 18.70s - 22.70s | really, really deep into LDAP obfuscation, deobfuscation and 22.70s - 26.62s | detection. My name is Daniel Bohannon. Everyone I know calls 26.62s - 29.78s | me Debo for short, so feel free to call me that. I'm a principal 29.78s - 32.58s | threat researcher for a startup company called Permiso Security 32.58s - 35.52s | doing cloud and identity stuff. For the last better part of a 35.52s - 39.08s | decade, I've been really focused on end point security, doing 39.08s - 42.38s | some IR and threat research at Mandiant, Microsoft. And I have 42.38s - 45.56s | a little bit of a problem with obfuscation. It's kind of an 45.56s - 48.20s | obsession of mine of taking things that look normal and 48.20s -


chunk_id: 141_chunk_1
chunk_text:
to \u201cheavyweight.\u201d", "channel_url": "https://www.youtube.com/channel/UC6Om9kAkl32dWlDSNlDS9Iw", "duration": 2802, "channel": "DEFCONConference", "uploader": "DEFCONConference", "upload_date": "20241016" } 0.00s - 12.76s | This text was transcribed using whisper model: large-v2 How's everyone doing? I'm genuinely surprised. So either 12.76s - 15.14s | y'all went to bed early or you never went to bed. So thank you 15.14s - 18.70s | so much for being here. This talk is maladaptive. It's diving 18.70s - 22.70s | really, really deep into LDAP obfuscation, deobfuscation and 22.70s - 26.62s | detection. My name is Daniel Bohannon. Everyone I know calls 26.62s - 29.78s | me Debo for short, so feel free to call me that. I'm a principal 29.78s - 32.58s | threat researcher for a startup company called Permiso Security 32.58s - 35.52s | doing cloud and identity stuff. For the last better part of a 35.52s - 39.08s | decade, I've been really focused on end point security, doing 39.08s - 42.38s | some IR and threat research at Mandiant, Microsoft. And I have 42.38s - 45.56s | a little bit of a problem with obfuscation. It's kind of an 45.56s - 48.20s | obsession of mine of taking things that look normal and 48.20s - 52.16s | making them look just absolutely crazy. And then as a defender, 52.20s - 54.90s | looking for ways to detect those things. Another thing I'm really 54.90s - 57.04s | passionate about is coffee and books and all the great 57.04s - 59.04s | conversations that happen around both of those things. 59.04s - 66.14s | Hello, everyone. So I'm Sabayita. You can call me Sabi for 66.14s - 70.34s | short. I'm originally from Albania, recently moved to 70.34s - 74.48s | Germany, Berlin, working for Solaris as a senior cyber 74.48s - 78.48s | security engineer. I'm passionate about cyber defense. 78.52s - 83.30s | Currently, I'm also working on the field, doing a little 83.30s - 86.40s | incident response detection engineering and time and time 86.42s - 90.36s | allows threat hunting. I do have also some experience in 90.36s - 94.50s | consulting and government. Love mountains. You can see even the 94.50s - 98.70s | gold there. And enjoy moving a lot at the Great Espresso. 98.70s - 103.39s | All right. So to kick things off, we're going to do a little 103.39s - 106.41s | historical lesson on Active Directory


chunk_id: 141_chunk_2
chunk_text:
52.16s | making them look just absolutely crazy. And then as a defender, 52.20s - 54.90s | looking for ways to detect those things. Another thing I'm really 54.90s - 57.04s | passionate about is coffee and books and all the great 57.04s - 59.04s | conversations that happen around both of those things. 59.04s - 66.14s | Hello, everyone. So I'm Sabayita. You can call me Sabi for 66.14s - 70.34s | short. I'm originally from Albania, recently moved to 70.34s - 74.48s | Germany, Berlin, working for Solaris as a senior cyber 74.48s - 78.48s | security engineer. I'm passionate about cyber defense. 78.52s - 83.30s | Currently, I'm also working on the field, doing a little 83.30s - 86.40s | incident response detection engineering and time and time 86.42s - 90.36s | allows threat hunting. I do have also some experience in 90.36s - 94.50s | consulting and government. Love mountains. You can see even the 94.50s - 98.70s | gold there. And enjoy moving a lot at the Great Espresso. 98.70s - 103.39s | All right. So to kick things off, we're going to do a little 103.39s - 106.41s | historical lesson on Active Directory and LDAP. And then 106.41s - 108.63s | we're going to break down kind of the components of LDAP so we 108.63s - 111.15s | know which pieces we're talking about when we get into the main 111.15s - 114.13s | piece of the talk, which is diving crazy deep into all the 114.13s - 116.77s | obfuscation. And then at the end, we'll talk more about our 116.79s - 119.73s | solution. We don't like to just create problems. We want to 119.73s - 121.33s | actually have some real solutions there so that 121.33s - 123.99s | defenders can walk away equipped with something really 123.99s - 128.47s | beneficial. And then we'll do a demo and a tool release at the 128.47s - 132.87s | end. So let's get going. We are going to go back in time to the 132.87s - 135.31s | days of disco balls and DeLoreans, talking about the 135.31s - 139.85s | 1980s. The Directory Access Protocol, or the DAP, was a 139.85s - 142.81s | directory service kind of at that time. LDAP is the 142.83s - 147.23s | lightweight version. That's the L in LDAP. Between 93 and 97, 147.23s


chunk_id: 141_chunk_3
chunk_text:
and LDAP. And then 106.41s - 108.63s | we're going to break down kind of the components of LDAP so we 108.63s - 111.15s | know which pieces we're talking about when we get into the main 111.15s - 114.13s | piece of the talk, which is diving crazy deep into all the 114.13s - 116.77s | obfuscation. And then at the end, we'll talk more about our 116.79s - 119.73s | solution. We don't like to just create problems. We want to 119.73s - 121.33s | actually have some real solutions there so that 121.33s - 123.99s | defenders can walk away equipped with something really 123.99s - 128.47s | beneficial. And then we'll do a demo and a tool release at the 128.47s - 132.87s | end. So let's get going. We are going to go back in time to the 132.87s - 135.31s | days of disco balls and DeLoreans, talking about the 135.31s - 139.85s | 1980s. The Directory Access Protocol, or the DAP, was a 139.85s - 142.81s | directory service kind of at that time. LDAP is the 142.83s - 147.23s | lightweight version. That's the L in LDAP. Between 93 and 97, 147.23s - 149.03s | you have three different versions of LDAP come onto the 149.03s - 154.17s | scene. In 1998, the Open LDAP Project released Open LDAP. And 154.17s - 156.01s | then what's important for this presentation is in the year 156.01s - 160.11s | 2000, Microsoft released Active Directory in which they kind of 160.11s - 163.75s | ensured compliance with LDAP. So it's important to remember 163.75s - 167.29s | there's a server and client side component here. So Active 167.29s - 169.99s | Directory, we chose that because it's the most popular, most 170.01s - 173.51s | widely used application service or directory service 173.51s - 176.21s | application in use. And so we wanted to make sure all the 176.21s - 179.39s | rules of obfuscation that we were discovering and building 179.39s - 183.01s | would work against an Active Directory server. So that's the 183.01s - 185.83s | server side component. You have clients that will issue LDAP 185.83s - 189.93s | queries or LDAP, what are called search filters. And then LDAP is 189.93s - 191.83s | literally the protocol that allows that exchange of 191.83s - 195.89s | information between the


chunk_id: 141_chunk_4
chunk_text:
- 149.03s | you have three different versions of LDAP come onto the 149.03s - 154.17s | scene. In 1998, the Open LDAP Project released Open LDAP. And 154.17s - 156.01s | then what's important for this presentation is in the year 156.01s - 160.11s | 2000, Microsoft released Active Directory in which they kind of 160.11s - 163.75s | ensured compliance with LDAP. So it's important to remember 163.75s - 167.29s | there's a server and client side component here. So Active 167.29s - 169.99s | Directory, we chose that because it's the most popular, most 170.01s - 173.51s | widely used application service or directory service 173.51s - 176.21s | application in use. And so we wanted to make sure all the 176.21s - 179.39s | rules of obfuscation that we were discovering and building 179.39s - 183.01s | would work against an Active Directory server. So that's the 183.01s - 185.83s | server side component. You have clients that will issue LDAP 185.83s - 189.93s | queries or LDAP, what are called search filters. And then LDAP is 189.93s - 191.83s | literally the protocol that allows that exchange of 191.83s - 195.89s | information between the client side and the server side. On the 195.93s - 200.87s | offensive side, LDAP or AD in general is quite a popular 200.87s - 203.27s | topic. And you look at open source tooling in the last 203.27s - 206.01s | decade, you have things like PowerView from the folks at 206.01s - 209.25s | SpectreOps, BloodHound, SharpHound, SoapHound, any kind 209.25s - 211.89s | of hound, right? Looking for really quick ways to get 211.89s - 214.59s | information from an offensive perspective, but also for 214.59s - 217.59s | defensive perspectives. With BloodHound and PingCastle, 217.59s - 220.63s | looking for ways to give defenders quick visibility into 220.63s - 225.63s | attack paths so that they can make better choices and 226.41s - 230.45s | increase the complexity for an attacker just to come in and get 230.45s - 233.91s | a really short path to DA or whatever else they want. So as 233.91s - 236.41s | defenders, we should then ask, okay, if attackers are using 236.41s - 240.29s | this, what are our data sources for defending? And so this is 240.29s - 243.05s | actually kind of a point of frustration for


chunk_id: 141_chunk_5
chunk_text:
client side and the server side. On the 195.93s - 200.87s | offensive side, LDAP or AD in general is quite a popular 200.87s - 203.27s | topic. And you look at open source tooling in the last 203.27s - 206.01s | decade, you have things like PowerView from the folks at 206.01s - 209.25s | SpectreOps, BloodHound, SharpHound, SoapHound, any kind 209.25s - 211.89s | of hound, right? Looking for really quick ways to get 211.89s - 214.59s | information from an offensive perspective, but also for 214.59s - 217.59s | defensive perspectives. With BloodHound and PingCastle, 217.59s - 220.63s | looking for ways to give defenders quick visibility into 220.63s - 225.63s | attack paths so that they can make better choices and 226.41s - 230.45s | increase the complexity for an attacker just to come in and get 230.45s - 233.91s | a really short path to DA or whatever else they want. So as 233.91s - 236.41s | defenders, we should then ask, okay, if attackers are using 236.41s - 240.29s | this, what are our data sources for defending? And so this is 240.29s - 243.05s | actually kind of a point of frustration for us. When we 243.05s - 245.95s | started this research, even till today, there's not that many 245.95s - 249.43s | options for production ready telemetry gathering for LDAP 249.43s - 253.49s | search filters. What we use in our lab environment was Silk ETW 253.49s - 256.53s | by Ruben Boonen, and actually one of the modules that were 256.53s - 259.79s | released with Mount Adaptive is a telemetry module to allow you 259.79s - 261.93s | to install these things, configure them, so you can have 261.93s - 264.41s | locally that client-side visibility. And then on the 264.41s - 267.41s | server side, there are options like, kind of like debug mode 267.41s - 269.57s | options, but those are not generally recommended to turn on 269.57s - 272.97s | in production. So if you want this visibility in production, 272.97s - 277.05s | the best case right now is get Microsoft Windows Defender. 277.05s - 279.45s | CrowdStrike has some stuff I've heard as well, but in terms of 279.45s - 283.15s | like, if you want to just trust the detections they have, cool. 283.15s - 286.31s | If you want to have all


chunk_id: 141_chunk_6
chunk_text:
us. When we 243.05s - 245.95s | started this research, even till today, there's not that many 245.95s - 249.43s | options for production ready telemetry gathering for LDAP 249.43s - 253.49s | search filters. What we use in our lab environment was Silk ETW 253.49s - 256.53s | by Ruben Boonen, and actually one of the modules that were 256.53s - 259.79s | released with Mount Adaptive is a telemetry module to allow you 259.79s - 261.93s | to install these things, configure them, so you can have 261.93s - 264.41s | locally that client-side visibility. And then on the 264.41s - 267.41s | server side, there are options like, kind of like debug mode 267.41s - 269.57s | options, but those are not generally recommended to turn on 269.57s - 272.97s | in production. So if you want this visibility in production, 272.97s - 277.05s | the best case right now is get Microsoft Windows Defender. 277.05s - 279.45s | CrowdStrike has some stuff I've heard as well, but in terms of 279.45s - 283.15s | like, if you want to just trust the detections they have, cool. 283.15s - 286.31s | If you want to have all the data so you can validate, then maybe 286.31s - 290.39s | explore your options a little bit. So another thing to keep in 290.39s - 292.65s | mind is there are big differences between client-side 292.65s - 296.03s | and server-side logs when it comes to LDAP. For all the 296.03s - 298.69s | hackers in the room, you're going to love client-side logs 298.69s - 302.07s | because it's basically like WYSIWYG. Like any obfuscation 302.07s - 305.13s | we're going to talk about, you put that in, that's exactly what 305.13s - 307.63s | it looks like in those client-side logs. Awesome for 307.63s - 311.27s | obfuscation evasion. With an important caveat, it depends how 311.29s - 315.47s | you're issuing that query. So a lot of the mechanisms, like the 315.47s - 321.41s | ADDZ accelerator in PowerShell, will use the WLDAP32.dll to 321.41s - 324.67s | route that request. If that's the case, then the data will show 324.67s - 327.75s | up in an ETW stream for the LDAP provider and you can scoop it 327.75s - 331.55s | out. However, some folks have noticed there are many other 331.55s - 335.15s |


chunk_id: 141_chunk_7
chunk_text:
the data so you can validate, then maybe 286.31s - 290.39s | explore your options a little bit. So another thing to keep in 290.39s - 292.65s | mind is there are big differences between client-side 292.65s - 296.03s | and server-side logs when it comes to LDAP. For all the 296.03s - 298.69s | hackers in the room, you're going to love client-side logs 298.69s - 302.07s | because it's basically like WYSIWYG. Like any obfuscation 302.07s - 305.13s | we're going to talk about, you put that in, that's exactly what 305.13s - 307.63s | it looks like in those client-side logs. Awesome for 307.63s - 311.27s | obfuscation evasion. With an important caveat, it depends how 311.29s - 315.47s | you're issuing that query. So a lot of the mechanisms, like the 315.47s - 321.41s | ADDZ accelerator in PowerShell, will use the WLDAP32.dll to 321.41s - 324.67s | route that request. If that's the case, then the data will show 324.67s - 327.75s | up in an ETW stream for the LDAP provider and you can scoop it 327.75s - 331.55s | out. However, some folks have noticed there are many other 331.55s - 335.15s | ways to talk to an Active Directory server. So Soap Hound 335.15s - 337.83s | is an example from Falcon Force where they said, hey, let's just 337.83s - 340.69s | make soap requests directly to the domain controller and avoid 340.71s - 344.75s | any kind of client-side logging. So because of this, it's still a 344.75s - 347.65s | valuable data source, but it's important to look at the server 347.65s - 352.33s | side logs as well. There is significant normalization that 352.33s - 355.59s | occurs in server-side logs. So a lot of the obfuscation we'll 355.59s - 358.53s | talk about is normalized, but there are still some interesting 358.53s - 362.27s | tricks that do persist. And yeah, that's all I'll say about 362.27s - 366.91s | that right now. So over the next 40ish minutes, we're going to be 366.91s - 370.55s | doing an absolute speed run through all of the obfuscations 370.57s - 375.05s | that we've enumerated and built out for this research. This is 375.05s - 378.95s | something we've spent over 2,000 hours of R&D on. For the record, 379.25s - 382.21s | that's too much R&D. Don't


chunk_id: 141_chunk_8
chunk_text:
ways to talk to an Active Directory server. So Soap Hound 335.15s - 337.83s | is an example from Falcon Force where they said, hey, let's just 337.83s - 340.69s | make soap requests directly to the domain controller and avoid 340.71s - 344.75s | any kind of client-side logging. So because of this, it's still a 344.75s - 347.65s | valuable data source, but it's important to look at the server 347.65s - 352.33s | side logs as well. There is significant normalization that 352.33s - 355.59s | occurs in server-side logs. So a lot of the obfuscation we'll 355.59s - 358.53s | talk about is normalized, but there are still some interesting 358.53s - 362.27s | tricks that do persist. And yeah, that's all I'll say about 362.27s - 366.91s | that right now. So over the next 40ish minutes, we're going to be 366.91s - 370.55s | doing an absolute speed run through all of the obfuscations 370.57s - 375.05s | that we've enumerated and built out for this research. This is 375.05s - 378.95s | something we've spent over 2,000 hours of R&D on. For the record, 379.25s - 382.21s | that's too much R&D. Don't recommend it to anybody. But 382.21s - 386.09s | here we are. So we're really happy to get this out there and 386.09s - 388.85s | then let our minds think about something else. And as I 388.85s - 390.73s | mentioned earlier, we're going to be doing a demo and tool 390.73s - 394.07s | release for maladaptive. And the name comes from maladaptive 394.07s - 396.37s | because typically people would think of LDAP queries as like a 396.37s - 400.31s | pretty simple, rigid kind of a language. So how flexible can it 400.33s - 402.93s | really be? And we hope to convince you pretty quickly 402.93s - 406.77s | that it can be pretty flexible. So with that, let's look at the 406.77s - 409.45s | LDAP overview so we know which pieces of an LDAP search 409.45s - 412.15s | request we're talking about for each obfuscation technique. 414.56s - 420.16s | So we're going to let's dive deep into the anatomy of an LDAP 420.16s - 424.74s | search request. We'll be looking at RFC 4511. There are many 424.74s - 428.40s | components to an LDAP search request, but we're going to


chunk_id: 141_chunk_9
chunk_text:
recommend it to anybody. But 382.21s - 386.09s | here we are. So we're really happy to get this out there and 386.09s - 388.85s | then let our minds think about something else. And as I 388.85s - 390.73s | mentioned earlier, we're going to be doing a demo and tool 390.73s - 394.07s | release for maladaptive. And the name comes from maladaptive 394.07s - 396.37s | because typically people would think of LDAP queries as like a 396.37s - 400.31s | pretty simple, rigid kind of a language. So how flexible can it 400.33s - 402.93s | really be? And we hope to convince you pretty quickly 402.93s - 406.77s | that it can be pretty flexible. So with that, let's look at the 406.77s - 409.45s | LDAP overview so we know which pieces of an LDAP search 409.45s - 412.15s | request we're talking about for each obfuscation technique. 414.56s - 420.16s | So we're going to let's dive deep into the anatomy of an LDAP 420.16s - 424.74s | search request. We'll be looking at RFC 4511. There are many 424.74s - 428.40s | components to an LDAP search request, but we're going to be 428.40s - 434.40s | focused on the four main ones, which is the base object, where 434.40s - 437.60s | in the active directory structure to start the search, 437.88s - 442.24s | the scope that says how far to let the search run, the filter, 442.28s - 445.76s | which is the logic of what to look for in the directory 445.76s - 449.04s | structure, and the attribute selection, which are the 449.08s - 454.72s | properties that we want to bring back. As defenders, most people 454.72s - 459.12s | focus on the filter for detecting malicious LDAP 459.12s - 462.84s | queries. So for this reason, it's also going to be our 462.84s - 468.72s | primary obfuscation focus. We don't want to overlook also the 468.72s - 472.20s | base object and attribute selection. So they are going to 472.20s - 477.28s | be our secondary and tertiary obfuscation focus. As filter is 477.28s - 481.08s | the main one, let's see what it's made, what makes up a 481.08s - 485.12s | filter. So well, it's made up of tokens, there are five 485.12s - 489.48s | required tokens that we have group


chunk_id: 141_chunk_10
chunk_text:
be 428.40s - 434.40s | focused on the four main ones, which is the base object, where 434.40s - 437.60s | in the active directory structure to start the search, 437.88s - 442.24s | the scope that says how far to let the search run, the filter, 442.28s - 445.76s | which is the logic of what to look for in the directory 445.76s - 449.04s | structure, and the attribute selection, which are the 449.08s - 454.72s | properties that we want to bring back. As defenders, most people 454.72s - 459.12s | focus on the filter for detecting malicious LDAP 459.12s - 462.84s | queries. So for this reason, it's also going to be our 462.84s - 468.72s | primary obfuscation focus. We don't want to overlook also the 468.72s - 472.20s | base object and attribute selection. So they are going to 472.20s - 477.28s | be our secondary and tertiary obfuscation focus. As filter is 477.28s - 481.08s | the main one, let's see what it's made, what makes up a 481.08s - 485.12s | filter. So well, it's made up of tokens, there are five 485.12s - 489.48s | required tokens that we have group start and group end, they 489.48s - 493.56s | hold in the middle the attribute and the value for it, and the 493.56s - 497.68s | comparison operator. So here, for example, we are looking, I'm 497.68s - 503.52s | looking for myself, basically. There are also two optional 503.52s - 507.44s | tokens, which is boolean operator and extensible match 507.44s - 511.56s | filter. Debo is going to talk about these in the upcoming 511.56s - 515.12s | slides. But just so you know, these are bitwise values, they 515.12s - 518.60s | have different meanings based on the attributes, and Microsoft 518.60s - 522.48s | documents all of these per attribute. So different numbers 522.48s - 529.12s | mean actually different things to different attributes. In this 529.12s - 532.00s | one, basically, we're looking for objects that are not 532.00s - 536.44s | disabled, let's say. Most people actually do not write simple 536.44s - 540.56s | filters like this, they do try to combine multiple filters, and 540.56s - 544.84s | they do that with a boolean operator to create a filter 544.84s - 552.68s | list. So it's not going to look actually as


chunk_id: 141_chunk_11
chunk_text:
start and group end, they 489.48s - 493.56s | hold in the middle the attribute and the value for it, and the 493.56s - 497.68s | comparison operator. So here, for example, we are looking, I'm 497.68s - 503.52s | looking for myself, basically. There are also two optional 503.52s - 507.44s | tokens, which is boolean operator and extensible match 507.44s - 511.56s | filter. Debo is going to talk about these in the upcoming 511.56s - 515.12s | slides. But just so you know, these are bitwise values, they 515.12s - 518.60s | have different meanings based on the attributes, and Microsoft 518.60s - 522.48s | documents all of these per attribute. So different numbers 522.48s - 529.12s | mean actually different things to different attributes. In this 529.12s - 532.00s | one, basically, we're looking for objects that are not 532.00s - 536.44s | disabled, let's say. Most people actually do not write simple 536.44s - 540.56s | filters like this, they do try to combine multiple filters, and 540.56s - 544.84s | they do that with a boolean operator to create a filter 544.84s - 552.68s | list. So it's not going to look actually as a pretty tree just 552.68s - 557.48s | like this one, but as a single row, usually. So it's going to 557.48s - 560.52s | be composed of two filters, which together they make up a 560.52s - 564.20s | filter list. And the whole string is actually called the 564.20s - 566.52s | search filter for an LDAP search request. 569.33s - 573.01s | Oh, sorry. No, we don't don't need help with PowerPoint 573.01s - 574.77s | transitions. Moving on. 578.16s - 581.36s | Hold on. It looks like you could use some help with crowd 581.36s - 586.84s | where hilarious. Oh, clippy. I have trivia and jokes. I don't 586.84s - 588.60s | know I could use that on a Sunday morning. How about y'all? 590.24s - 593.16s | What do you call the biggest LDAP search request in history? 594.08s - 599.68s | Any takers? It's pronounced 10 and a half megabytes. Because 599.68s - 603.36s | that's the limit for a search request. Now, clippy actually 603.36s - 607.16s | comes armed with sources. But just know that that's a lot of 607.16s - 609.68s | data. And keep in mind LDAP is not


chunk_id: 141_chunk_12
chunk_text:
a pretty tree just 552.68s - 557.48s | like this one, but as a single row, usually. So it's going to 557.48s - 560.52s | be composed of two filters, which together they make up a 560.52s - 564.20s | filter list. And the whole string is actually called the 564.20s - 566.52s | search filter for an LDAP search request. 569.33s - 573.01s | Oh, sorry. No, we don't don't need help with PowerPoint 573.01s - 574.77s | transitions. Moving on. 578.16s - 581.36s | Hold on. It looks like you could use some help with crowd 581.36s - 586.84s | where hilarious. Oh, clippy. I have trivia and jokes. I don't 586.84s - 588.60s | know I could use that on a Sunday morning. How about y'all? 590.24s - 593.16s | What do you call the biggest LDAP search request in history? 594.08s - 599.68s | Any takers? It's pronounced 10 and a half megabytes. Because 599.68s - 603.36s | that's the limit for a search request. Now, clippy actually 603.36s - 607.16s | comes armed with sources. But just know that that's a lot of 607.16s - 609.68s | data. And keep in mind LDAP is not just for querying 609.68s - 612.04s | information. It's also for updating records. But for the 612.04s - 615.60s | purpose of recon, I encourage anybody in this room to issue 615.60s - 618.96s | something even close to 10 and a half megs and see how much 618.96s - 623.52s | shows up in your logs. All right. Thanks, Sabi. So now that 623.52s - 625.84s | we had a good idea of the different components of LDAP 625.84s - 628.40s | that we're going to be looking at, let's actually do the fun 628.40s - 632.20s | stuff of obfuscation. For all the defenders in the room, it's 632.20s - 635.36s | going to get dark and bleak before it gets bright again. But 635.36s - 638.96s | we promise there is a light at the end of the tunnel. So as 638.96s - 641.00s | Sabi mentioned, the filter is going to be the primary 641.00s - 644.12s | obfuscation focus because it really is kind of the primary 644.12s - 647.48s | defensive detection focus today. And we're going to spend most of 647.48s - 649.92s | our time on the filter. And then a lot


chunk_id: 141_chunk_13
chunk_text:
just for querying 609.68s - 612.04s | information. It's also for updating records. But for the 612.04s - 615.60s | purpose of recon, I encourage anybody in this room to issue 615.60s - 618.96s | something even close to 10 and a half megs and see how much 618.96s - 623.52s | shows up in your logs. All right. Thanks, Sabi. So now that 623.52s - 625.84s | we had a good idea of the different components of LDAP 625.84s - 628.40s | that we're going to be looking at, let's actually do the fun 628.40s - 632.20s | stuff of obfuscation. For all the defenders in the room, it's 632.20s - 635.36s | going to get dark and bleak before it gets bright again. But 635.36s - 638.96s | we promise there is a light at the end of the tunnel. So as 638.96s - 641.00s | Sabi mentioned, the filter is going to be the primary 641.00s - 644.12s | obfuscation focus because it really is kind of the primary 644.12s - 647.48s | defensive detection focus today. And we're going to spend most of 647.48s - 649.92s | our time on the filter. And then a lot of the techniques 649.92s - 652.52s | that work on the filter will then be applied to the base 652.52s - 657.12s | object and attribute selection as well. There's a lot of things 657.12s - 660.76s | that we discovered that are not documented. Some of it was sheer 660.76s - 663.24s | luck. Some of it was brute forcing. Some of it was the fact 663.24s - 664.92s | that when you build an obfuscation framework, you're 664.92s - 667.24s | kind of defining the boundaries of a language and it's going to 667.24s - 670.56s | break out sometimes and teach you things that still work. And 670.56s - 674.12s | so we'll try to mention things that are undocumented and then 674.16s - 677.68s | also put this undocumented icon at the top. So we're going to 677.68s - 680.76s | start by looking at these five tokens and looking at 680.76s - 683.40s | obfuscation that can be applied to each, beginning with the 683.40s - 684.12s | attribute token. 687.48s - 692.60s | So let's see how what we can do to obfuscate the attribute. We 692.60s - 696.08s | can actually do casing.


chunk_id: 141_chunk_14
chunk_text:
of the techniques 649.92s - 652.52s | that work on the filter will then be applied to the base 652.52s - 657.12s | object and attribute selection as well. There's a lot of things 657.12s - 660.76s | that we discovered that are not documented. Some of it was sheer 660.76s - 663.24s | luck. Some of it was brute forcing. Some of it was the fact 663.24s - 664.92s | that when you build an obfuscation framework, you're 664.92s - 667.24s | kind of defining the boundaries of a language and it's going to 667.24s - 670.56s | break out sometimes and teach you things that still work. And 670.56s - 674.12s | so we'll try to mention things that are undocumented and then 674.16s - 677.68s | also put this undocumented icon at the top. So we're going to 677.68s - 680.76s | start by looking at these five tokens and looking at 680.76s - 683.40s | obfuscation that can be applied to each, beginning with the 683.40s - 684.12s | attribute token. 687.48s - 692.60s | So let's see how what we can do to obfuscate the attribute. We 692.60s - 696.08s | can actually do casing. It is case sensitive, so we can play 696.08s - 703.00s | with it. We can use object, our OID object identifier. OID 703.00s - 706.56s | object identifier, Microsoft defines it as a dotted string 706.56s - 710.64s | of numbers, which is actually quite true, because you can also 710.68s - 713.80s | add this OID prefix at the beginning of it, and it's still 713.80s - 718.12s | going to work, which is also case sensitive. Another thing 718.12s - 722.52s | that is really fascinating and undocumented is that we can add 722.52s - 727.44s | prefixes of zeros to each octet on this part, and it executes 727.44s - 731.00s | just fine. It will also show just like this also on client 731.00s - 736.24s | sidelocks. Another thing we can do for attribute obfuscation is 736.28s - 741.48s | ambiguous name resolution. So the same applies as above. So we 741.48s - 746.12s | can use insensitive casing and OID notation even for the ANR. 746.72s - 751.32s | But what is exactly ANR? So in case you know some name, but you 751.32s - 756.40s | don't know in which property it


chunk_id: 141_chunk_15
chunk_text:
It is case sensitive, so we can play 696.08s - 703.00s | with it. We can use object, our OID object identifier. OID 703.00s - 706.56s | object identifier, Microsoft defines it as a dotted string 706.56s - 710.64s | of numbers, which is actually quite true, because you can also 710.68s - 713.80s | add this OID prefix at the beginning of it, and it's still 713.80s - 718.12s | going to work, which is also case sensitive. Another thing 718.12s - 722.52s | that is really fascinating and undocumented is that we can add 722.52s - 727.44s | prefixes of zeros to each octet on this part, and it executes 727.44s - 731.00s | just fine. It will also show just like this also on client 731.00s - 736.24s | sidelocks. Another thing we can do for attribute obfuscation is 736.28s - 741.48s | ambiguous name resolution. So the same applies as above. So we 741.48s - 746.12s | can use insensitive casing and OID notation even for the ANR. 746.72s - 751.32s | But what is exactly ANR? So in case you know some name, but you 751.32s - 756.40s | don't know in which property it actually is, you can search and 756.40s - 759.00s | what it would actually do depending on the version of 759.00s - 762.64s | Active Directory, it will logically transform this single 762.64s - 768.04s | term into this query. So basically everything is ended in 768.04s - 771.72s | a wildcard, except for some attributes that do not support 771.72s - 776.56s | this. And in case your search actually contains a space just 776.72s - 781.28s | like us, we are looking for domain admins. Then it's going 781.28s - 785.84s | to be added another this one. So these four ones, because it 785.84s - 788.56s | will treat it as a first name, last name, last name, first 788.56s - 793.92s | name. Some nice obfuscation tricks. So we can use ANR, for 793.92s - 797.96s | example, if we're trying to search for curb TGT. And we can 797.96s - 801.68s | also use which is the second example, only the some parts of 801.68s - 805.44s | it, and it's going to be an explicit wildcard. So we'll 805.44s - 808.24s | still even on the second example, we are still going to 808.24s


chunk_id: 141_chunk_16
chunk_text:
actually is, you can search and 756.40s - 759.00s | what it would actually do depending on the version of 759.00s - 762.64s | Active Directory, it will logically transform this single 762.64s - 768.04s | term into this query. So basically everything is ended in 768.04s - 771.72s | a wildcard, except for some attributes that do not support 771.72s - 776.56s | this. And in case your search actually contains a space just 776.72s - 781.28s | like us, we are looking for domain admins. Then it's going 781.28s - 785.84s | to be added another this one. So these four ones, because it 785.84s - 788.56s | will treat it as a first name, last name, last name, first 788.56s - 793.92s | name. Some nice obfuscation tricks. So we can use ANR, for 793.92s - 797.96s | example, if we're trying to search for curb TGT. And we can 797.96s - 801.68s | also use which is the second example, only the some parts of 801.68s - 805.44s | it, and it's going to be an explicit wildcard. So we'll 805.44s - 808.24s | still even on the second example, we are still going to 808.24s - 812.80s | have the same results. And the third example, which is very 812.80s - 816.64s | nice, we actually discovered that if you add an implicit 816.64s - 822.40s | wildcard, after that, everything you add is going to be ignored. 822.96s - 826.76s | So you can play with it, but you're still going to be to get 826.76s - 834.52s | the result of ANR and return the curb TGT. And just as this also 834.52s - 838.24s | going to be handled from our detection framework. If you 838.24s - 842.60s | don't want to do all the crazy stuff with a wildcard, and just 842.60s - 846.76s | be explicit, you can actually just add an equal sign, which is 846.76s - 849.20s | document the which is the documented way to get the 849.20s - 855.16s | information. As a recap, for attribute obfuscation, we can 855.16s - 858.84s | do casing, object identifier notation, and ambiguous name 858.84s - 864.72s | resolution. Oh, sleepy again. Do you know where else ambiguous 864.72s - 869.88s | name resolution exists? We don't know Clippy where Microsoft 869.92s - 872.96s | what is more ambiguous


chunk_id: 141_chunk_17
chunk_text:
- 812.80s | have the same results. And the third example, which is very 812.80s - 816.64s | nice, we actually discovered that if you add an implicit 816.64s - 822.40s | wildcard, after that, everything you add is going to be ignored. 822.96s - 826.76s | So you can play with it, but you're still going to be to get 826.76s - 834.52s | the result of ANR and return the curb TGT. And just as this also 834.52s - 838.24s | going to be handled from our detection framework. If you 838.24s - 842.60s | don't want to do all the crazy stuff with a wildcard, and just 842.60s - 846.76s | be explicit, you can actually just add an equal sign, which is 846.76s - 849.20s | document the which is the documented way to get the 849.20s - 855.16s | information. As a recap, for attribute obfuscation, we can 855.16s - 858.84s | do casing, object identifier notation, and ambiguous name 858.84s - 864.72s | resolution. Oh, sleepy again. Do you know where else ambiguous 864.72s - 869.88s | name resolution exists? We don't know Clippy where Microsoft 869.92s - 872.96s | what is more ambiguous than resolving to rename your 872.96s - 875.52s | products every six months. Am I right? 877.40s - 880.08s | I did not know Clippy was allowed to make Microsoft burns. 880.08s - 883.96s | I don't know if that was cleared. Thanks, Clippy. So one 883.96s - 886.56s | token down, we've talked about attributes. Next, we're gonna 886.56s - 889.24s | look at the comparison operator. Most of the time, this is an 889.24s - 892.56s | equal sign. When it comes to active directories implementation 892.56s - 896.32s | of LDAP, you also have the approximately equal to because 896.32s - 899.48s | casing doesn't matter. But it does. It doesn't prevent you 899.48s - 902.32s | from using the wildcard and hex characters that we'll be talking 902.32s - 904.88s | a lot more about later. But we're really going to focus on 904.88s - 907.76s | the range operator. So greater than equal to less than equal 907.76s - 910.48s | to. So here's an example a lot of red teamers would be familiar 910.48s - 913.32s | with service principal name equal star means give us the 913.32s - 916.16s | objects that have


chunk_id: 141_chunk_18
chunk_text:
than resolving to rename your 872.96s - 875.52s | products every six months. Am I right? 877.40s - 880.08s | I did not know Clippy was allowed to make Microsoft burns. 880.08s - 883.96s | I don't know if that was cleared. Thanks, Clippy. So one 883.96s - 886.56s | token down, we've talked about attributes. Next, we're gonna 886.56s - 889.24s | look at the comparison operator. Most of the time, this is an 889.24s - 892.56s | equal sign. When it comes to active directories implementation 892.56s - 896.32s | of LDAP, you also have the approximately equal to because 896.32s - 899.48s | casing doesn't matter. But it does. It doesn't prevent you 899.48s - 902.32s | from using the wildcard and hex characters that we'll be talking 902.32s - 904.88s | a lot more about later. But we're really going to focus on 904.88s - 907.76s | the range operator. So greater than equal to less than equal 907.76s - 910.48s | to. So here's an example a lot of red teamers would be familiar 910.48s - 913.32s | with service principal name equal star means give us the 913.32s - 916.16s | objects that have an SPN, any value, I don't care, but it must 916.16s - 919.48s | be defined. Well, technically, we could rewrite this with a 919.48s - 922.84s | string operator and say, hey, make sure it's present, it has a 922.84s - 924.92s | value that is greater than or equal to the alphabetical 924.92s - 928.56s | sorting of a string that begins with equals, or the exclamation 928.56s - 932.36s | point, or is less than ZZZ. So there are other ways logically 932.36s - 935.36s | that you can accomplish this equivalence, this presence 935.36s - 939.24s | filter. One really important note, if you think about the 939.24s - 942.12s | printable range of ASCII characters, this is the proper 942.12s - 944.92s | ordering that we all know and love and have agreed upon as a 944.92s - 948.36s | standard as an industry. We do not know why, but there is an 948.36s - 952.52s | abnormal range or sorting for strings in Active Directory. 952.52s - 954.76s | Casing doesn't matter, so we get rid of those, but you have all 954.76s - 956.96s | of the digits and alpha characters at the


chunk_id: 141_chunk_19
chunk_text:
an SPN, any value, I don't care, but it must 916.16s - 919.48s | be defined. Well, technically, we could rewrite this with a 919.48s - 922.84s | string operator and say, hey, make sure it's present, it has a 922.84s - 924.92s | value that is greater than or equal to the alphabetical 924.92s - 928.56s | sorting of a string that begins with equals, or the exclamation 928.56s - 932.36s | point, or is less than ZZZ. So there are other ways logically 932.36s - 935.36s | that you can accomplish this equivalence, this presence 935.36s - 939.24s | filter. One really important note, if you think about the 939.24s - 942.12s | printable range of ASCII characters, this is the proper 942.12s - 944.92s | ordering that we all know and love and have agreed upon as a 944.92s - 948.36s | standard as an industry. We do not know why, but there is an 948.36s - 952.52s | abnormal range or sorting for strings in Active Directory. 952.52s - 954.76s | Casing doesn't matter, so we get rid of those, but you have all 954.76s - 956.96s | of the digits and alpha characters at the end. You have 956.96s - 959.92s | this very specific grouping of special characters, and then all 959.92s - 962.48s | the other characters fall right into the middle. This took us 962.48s - 965.28s | probably five days to find because it only occurred, this 965.28s - 968.64s | bug only occurred like one out of 1,000 iterations. But this 968.64s - 972.12s | is, this is the ordering. So our obfuscation framework handles 972.16s - 975.60s | that, but just know it's kind of weird. Another thing we can do 975.60s - 979.04s | is use the range filters for precise values. So SAM account 979.04s - 982.32s | type equals this number ending with 368. This is another 982.32s - 984.88s | bitwise value, but let's say that detections were looking at 984.88s - 987.36s | this. Well, you could also, instead of saying ends with 987.36s - 991.96s | 368, say greater than equals to 7, less than equal to 9, and 991.96s - 994.96s | then specifically exclude the 7 and 9, so logically you're left 994.96s - 998.64s | with an 8. If you're like me and are a more visual person, I like


chunk_id: 141_chunk_20
chunk_text:
end. You have 956.96s - 959.92s | this very specific grouping of special characters, and then all 959.92s - 962.48s | the other characters fall right into the middle. This took us 962.48s - 965.28s | probably five days to find because it only occurred, this 965.28s - 968.64s | bug only occurred like one out of 1,000 iterations. But this 968.64s - 972.12s | is, this is the ordering. So our obfuscation framework handles 972.16s - 975.60s | that, but just know it's kind of weird. Another thing we can do 975.60s - 979.04s | is use the range filters for precise values. So SAM account 979.04s - 982.32s | type equals this number ending with 368. This is another 982.32s - 984.88s | bitwise value, but let's say that detections were looking at 984.88s - 987.36s | this. Well, you could also, instead of saying ends with 987.36s - 991.96s | 368, say greater than equals to 7, less than equal to 9, and 991.96s - 994.96s | then specifically exclude the 7 and 9, so logically you're left 994.96s - 998.64s | with an 8. If you're like me and are a more visual person, I like 998.64s - 1002.00s | to think of it as a timeline. And so greater than equal to 7, 1002.00s - 1005.44s | less than equal to 9, and then let's just pop off the 7 and 9, 1005.44s - 1009.32s | so you're left with the 8. There are a lot of kind of flavors or 1009.32s - 1012.72s | recipes we built into the obfuscation module, showing a 1012.72s - 1015.28s | couple of them here. One of my favorites is actually using 1015.28s - 1018.76s | ranges for exclusions. In this last example where you can say 1018.76s - 1021.92s | give me the presence filter, but then exclude everything outward 1021.92s - 1025.40s | and inclusive of the numbers 7 and 9, so you're left with 8. So 1025.40s - 1027.44s | again, those are all random options in the obfuscation 1027.44s - 1030.88s | filter, the obfuscation module. This works for numbers. It also 1030.92s - 1033.56s | works for strings with a caveat that suffixes are a little 1033.56s - 1038.46s | tricky, but yeah, it is still quite effective for those 1038.46s - 1040.80s | things. So in review for the second token type


chunk_id: 141_chunk_21
chunk_text:
998.64s - 1002.00s | to think of it as a timeline. And so greater than equal to 7, 1002.00s - 1005.44s | less than equal to 9, and then let's just pop off the 7 and 9, 1005.44s - 1009.32s | so you're left with the 8. There are a lot of kind of flavors or 1009.32s - 1012.72s | recipes we built into the obfuscation module, showing a 1012.72s - 1015.28s | couple of them here. One of my favorites is actually using 1015.28s - 1018.76s | ranges for exclusions. In this last example where you can say 1018.76s - 1021.92s | give me the presence filter, but then exclude everything outward 1021.92s - 1025.40s | and inclusive of the numbers 7 and 9, so you're left with 8. So 1025.40s - 1027.44s | again, those are all random options in the obfuscation 1027.44s - 1030.88s | filter, the obfuscation module. This works for numbers. It also 1030.92s - 1033.56s | works for strings with a caveat that suffixes are a little 1033.56s - 1038.46s | tricky, but yeah, it is still quite effective for those 1038.46s - 1040.80s | things. So in review for the second token type of comparison 1040.80s - 1043.96s | operator, we have approximately equal to, we have the logical 1043.96s - 1046.04s | equivalence for the presence filter, and then we can use the 1046.04s - 1048.74s | range operators to do some really fun stuff for precise 1048.74s - 1051.58s | values, whether they're strings or numbers. And defenders should 1051.58s - 1054.08s | be pretty familiar with some of these we just looked at, because 1054.08s - 1058.48s | it's actually part of the sharp hound project. So that same 1058.48s - 1061.38s | account type, service principal name. So again, these are pretty 1061.38s - 1064.06s | relevant examples, and you can see that if a detection was 1064.06s - 1066.32s | looking for this, it would probably get smoked by what we 1066.32s - 1070.26s | just showed you. So the third token type is the Boolean 1070.26s - 1072.94s | operator. Mostly we think of ANDs and ORs, but when it comes 1072.94s - 1077.54s | to LDAP, the NOT is where things get really crazy really fast. So 1077.54s - 1079.54s | let's take a really practical example. Let's say you're 1079.54s - 1081.80s | looking for


chunk_id: 141_chunk_22
chunk_text:
of comparison 1040.80s - 1043.96s | operator, we have approximately equal to, we have the logical 1043.96s - 1046.04s | equivalence for the presence filter, and then we can use the 1046.04s - 1048.74s | range operators to do some really fun stuff for precise 1048.74s - 1051.58s | values, whether they're strings or numbers. And defenders should 1051.58s - 1054.08s | be pretty familiar with some of these we just looked at, because 1054.08s - 1058.48s | it's actually part of the sharp hound project. So that same 1058.48s - 1061.38s | account type, service principal name. So again, these are pretty 1061.38s - 1064.06s | relevant examples, and you can see that if a detection was 1064.06s - 1066.32s | looking for this, it would probably get smoked by what we 1066.32s - 1070.26s | just showed you. So the third token type is the Boolean 1070.26s - 1072.94s | operator. Mostly we think of ANDs and ORs, but when it comes 1072.94s - 1077.54s | to LDAP, the NOT is where things get really crazy really fast. So 1077.54s - 1079.54s | let's take a really practical example. Let's say you're 1079.54s - 1081.80s | looking for country equals Albania. You want to have all 1081.80s - 1084.34s | those objects that come out of active directory. One thing you 1084.34s - 1087.12s | can do is just throw a bunch of Boolean operators inside of it, 1087.12s - 1089.46s | and logically it doesn't matter if you AND and OR one thing, 1089.46s - 1092.12s | it's still going to be that same one thing. Additionally, you can 1092.12s - 1095.42s | also put in double negation. Again, logically this is still 1095.42s - 1098.26s | going to give you country equals Albania, the same number of 1098.26s - 1103.14s | objects. Additionally, if you wanted to do a Boolean operator, 1103.14s - 1105.54s | you can technically slide it right inside of the filter 1105.54s - 1107.74s | itself. So in this case, if we're looking for location 1107.74s - 1110.84s | equals KUKES, which is a city inside of Albania, you can see 1110.84s - 1112.88s | that bottom example, that Boolean is sitting directly 1112.88s - 1116.72s | inside of the group start, group end filters, or tokens. In our 1117.38s - 1120.22s | parser that we wrote for this research, we handle


chunk_id: 141_chunk_23
chunk_text:
country equals Albania. You want to have all 1081.80s - 1084.34s | those objects that come out of active directory. One thing you 1084.34s - 1087.12s | can do is just throw a bunch of Boolean operators inside of it, 1087.12s - 1089.46s | and logically it doesn't matter if you AND and OR one thing, 1089.46s - 1092.12s | it's still going to be that same one thing. Additionally, you can 1092.12s - 1095.42s | also put in double negation. Again, logically this is still 1095.42s - 1098.26s | going to give you country equals Albania, the same number of 1098.26s - 1103.14s | objects. Additionally, if you wanted to do a Boolean operator, 1103.14s - 1105.54s | you can technically slide it right inside of the filter 1105.54s - 1107.74s | itself. So in this case, if we're looking for location 1107.74s - 1110.84s | equals KUKES, which is a city inside of Albania, you can see 1110.84s - 1112.88s | that bottom example, that Boolean is sitting directly 1112.88s - 1116.72s | inside of the group start, group end filters, or tokens. In our 1117.38s - 1120.22s | parser that we wrote for this research, we handle this 1120.22s - 1122.42s | similarly, but do call out the distinction because it is 1122.42s - 1125.52s | extremely important for certain kinds of detections, as well as 1125.52s - 1128.72s | obfuscation and deobfuscation scenarios. Most of the time 1128.72s - 1131.12s | though, you're dealing with a slightly more complex filter 1131.12s - 1134.20s | like this. So this is saying, I want to know when the country is 1134.20s - 1139.26s | Albania, and either the location is KUKES or Tirana, two cities. 1139.26s - 1141.74s | It's important to know that the Boolean operator has kind of a 1141.74s - 1145.00s | scope of influence. So in this case there are two Booleans, and 1145.02s - 1148.12s | you can see the boxes around the filters that they affect. If we 1148.12s - 1151.20s | added in a third set, there are now three groups. And so as 1151.20s - 1153.64s | we're parsing it, we basically create a stack of Boolean 1153.64s - 1156.76s | operators to know exactly how many Booleans are affecting the 1156.76s - 1160.64s | filter that we're looking at. One really, really fun feature 1160.64s - 1163.48s | is


chunk_id: 141_chunk_24
chunk_text:
this 1120.22s - 1122.42s | similarly, but do call out the distinction because it is 1122.42s - 1125.52s | extremely important for certain kinds of detections, as well as 1125.52s - 1128.72s | obfuscation and deobfuscation scenarios. Most of the time 1128.72s - 1131.12s | though, you're dealing with a slightly more complex filter 1131.12s - 1134.20s | like this. So this is saying, I want to know when the country is 1134.20s - 1139.26s | Albania, and either the location is KUKES or Tirana, two cities. 1139.26s - 1141.74s | It's important to know that the Boolean operator has kind of a 1141.74s - 1145.00s | scope of influence. So in this case there are two Booleans, and 1145.02s - 1148.12s | you can see the boxes around the filters that they affect. If we 1148.12s - 1151.20s | added in a third set, there are now three groups. And so as 1151.20s - 1153.64s | we're parsing it, we basically create a stack of Boolean 1153.64s - 1156.76s | operators to know exactly how many Booleans are affecting the 1156.76s - 1160.64s | filter that we're looking at. One really, really fun feature 1160.64s - 1163.48s | is the not Boolean operator. So let's slide that in there. The 1163.48s - 1167.08s | not only affects the first filter, or the first Boolean 1167.08s - 1170.84s | operator that it modifies. So we can see location equals KUKES is 1170.84s - 1173.58s | modified by that not, but the filter just below it is 1173.60s - 1177.64s | completely, it doesn't modify it at all. So this is another one 1177.64s - 1180.94s | that we have to track, as well as a lot of crazy things like 1180.94s - 1183.72s | negation, traversal, because you can have lots of layers in 1183.72s - 1186.38s | between and you have to track the Booles all the way. Lots of 1186.38s - 1189.82s | fun, honestly a lot of headaches, but yeah, it's built 1189.82s - 1191.82s | into the parser so we don't have to think about that anymore, and 1191.82s - 1195.06s | we'll see that in the demos towards the end. My personal 1195.06s - 1197.86s | favorite obfuscation technique with Boolean operators is logical 1197.86s - 1200.64s | inversion. So for any math nerds in the house, this is known as 1200.66s - 1205.20s |


chunk_id: 141_chunk_25
chunk_text:
the not Boolean operator. So let's slide that in there. The 1163.48s - 1167.08s | not only affects the first filter, or the first Boolean 1167.08s - 1170.84s | operator that it modifies. So we can see location equals KUKES is 1170.84s - 1173.58s | modified by that not, but the filter just below it is 1173.60s - 1177.64s | completely, it doesn't modify it at all. So this is another one 1177.64s - 1180.94s | that we have to track, as well as a lot of crazy things like 1180.94s - 1183.72s | negation, traversal, because you can have lots of layers in 1183.72s - 1186.38s | between and you have to track the Booles all the way. Lots of 1186.38s - 1189.82s | fun, honestly a lot of headaches, but yeah, it's built 1189.82s - 1191.82s | into the parser so we don't have to think about that anymore, and 1191.82s - 1195.06s | we'll see that in the demos towards the end. My personal 1195.06s - 1197.86s | favorite obfuscation technique with Boolean operators is logical 1197.86s - 1200.64s | inversion. So for any math nerds in the house, this is known as 1200.66s - 1205.20s | De Morgan's law, but basically not A or B is the same as not A 1205.20s - 1208.20s | and not B with the inverse sitting below. So what you can 1208.20s - 1211.90s | do is take any LDAP search filter, choose a spot and negate 1211.90s - 1214.14s | it. In this case, we're going to choose the whole filter and now 1214.14s - 1216.68s | everything else kind of to the right of that is going to be in 1216.68s - 1220.58s | scope for obfuscation. So step number two is identifying within 1220.58s - 1224.22s | that in scope section, all the ands and ors and inverting them. 1224.22s - 1227.12s | And then the third step is locating all the filters and 1227.12s - 1229.42s | inverting them from a negation perspective. So none of these 1229.44s - 1232.08s | filters are negated, so we're going to add that not and those 1232.08s - 1235.54s | are now negated. Now, this is logically the same as what we 1235.54s - 1238.22s | started with. Again, this is a lot of headaches if you're 1238.22s - 1241.56s | parsing this manually, and so in the parser,


chunk_id: 141_chunk_26
chunk_text:
De Morgan's law, but basically not A or B is the same as not A 1205.20s - 1208.20s | and not B with the inverse sitting below. So what you can 1208.20s - 1211.90s | do is take any LDAP search filter, choose a spot and negate 1211.90s - 1214.14s | it. In this case, we're going to choose the whole filter and now 1214.14s - 1216.68s | everything else kind of to the right of that is going to be in 1216.68s - 1220.58s | scope for obfuscation. So step number two is identifying within 1220.58s - 1224.22s | that in scope section, all the ands and ors and inverting them. 1224.22s - 1227.12s | And then the third step is locating all the filters and 1227.12s - 1229.42s | inverting them from a negation perspective. So none of these 1229.44s - 1232.08s | filters are negated, so we're going to add that not and those 1232.08s - 1235.54s | are now negated. Now, this is logically the same as what we 1235.54s - 1238.22s | started with. Again, this is a lot of headaches if you're 1238.22s - 1241.56s | parsing this manually, and so in the parser, we basically have a 1241.56s - 1244.62s | concept of what's the logical inclusion. Is this included true 1244.62s - 1247.66s | or false? What's the logical Boolean? Is it and or? And we 1247.66s - 1250.42s | also maintain a stack of all those Boolean operator tokens 1250.42s - 1253.24s | for your convenience. So in review for the third token type 1253.24s - 1256.80s | of Boolean operator, we have the additive nature, double negation 1256.82s - 1261.72s | and then DeMorgan's laws for the Boolean operator inversion. Oh 1261.72s - 1265.92s | goodness, okay. What is my least favorite LDAP token type? I'm 1265.96s - 1268.20s | assuming Boolean operator, but let's see what happens here. 1268.92s - 1271.52s | Yep, Boolean operator because I'm afraid of getting tied up 1271.52s - 1275.74s | in knots. Oh, that's cringe, Cliffy. Cliffy's losing steam 1275.74s - 1278.24s | fast. Yeah, get that out of the way. Okay. All right, the fourth 1278.24s - 1281.28s | token type, extensible match filter. So Sabi mentioned this 1281.28s - 1284.16s | before. This is for attributes that have bitwise values. It's 1284.16s - 1288.20s | an integer, uh, number, but it


chunk_id: 141_chunk_27
chunk_text:
we basically have a 1241.56s - 1244.62s | concept of what's the logical inclusion. Is this included true 1244.62s - 1247.66s | or false? What's the logical Boolean? Is it and or? And we 1247.66s - 1250.42s | also maintain a stack of all those Boolean operator tokens 1250.42s - 1253.24s | for your convenience. So in review for the third token type 1253.24s - 1256.80s | of Boolean operator, we have the additive nature, double negation 1256.82s - 1261.72s | and then DeMorgan's laws for the Boolean operator inversion. Oh 1261.72s - 1265.92s | goodness, okay. What is my least favorite LDAP token type? I'm 1265.96s - 1268.20s | assuming Boolean operator, but let's see what happens here. 1268.92s - 1271.52s | Yep, Boolean operator because I'm afraid of getting tied up 1271.52s - 1275.74s | in knots. Oh, that's cringe, Cliffy. Cliffy's losing steam 1275.74s - 1278.24s | fast. Yeah, get that out of the way. Okay. All right, the fourth 1278.24s - 1281.28s | token type, extensible match filter. So Sabi mentioned this 1281.28s - 1284.16s | before. This is for attributes that have bitwise values. It's 1284.16s - 1288.20s | an integer, uh, number, but it actually represents a base two 1288.20s - 1291.40s | add-ins, um, for all the bitwise flags based on which attribute 1291.40s - 1296.58s | that it is. Uh, so, uh, it is, um, there are four values that 1296.58s - 1299.96s | are supported by, uh, the, by Active Directory's LDAP 1299.96s - 1302.84s | implementation. We're going to focus on the first two because 1302.84s - 1304.92s | they're the most interesting in terms of obfuscation and that's 1304.92s - 1308.12s | the and and the or. Um, for me, I remember the or because it 1308.12s - 1314.64s | ends with dot 804. So 804 is or, 803 is not or. All right. So 1314.64s - 1317.00s | here's an example. User account control, and you can see in the 1317.00s - 1319.40s | red is the extensible match filter. Um, in this case, it's 1319.40s - 1323.16s | an 803, so that's an and, and it's the number 515, which is 1323.16s - 1326.92s | the base two add-ins 1, 2, and 512. So one of the things we 1326.92s - 1329.32s | can do is what we've called bitwise breakout. So we can 1329.32s - 1333.16s


chunk_id: 141_chunk_28
chunk_text:
actually represents a base two 1288.20s - 1291.40s | add-ins, um, for all the bitwise flags based on which attribute 1291.40s - 1296.58s | that it is. Uh, so, uh, it is, um, there are four values that 1296.58s - 1299.96s | are supported by, uh, the, by Active Directory's LDAP 1299.96s - 1302.84s | implementation. We're going to focus on the first two because 1302.84s - 1304.92s | they're the most interesting in terms of obfuscation and that's 1304.92s - 1308.12s | the and and the or. Um, for me, I remember the or because it 1308.12s - 1314.64s | ends with dot 804. So 804 is or, 803 is not or. All right. So 1314.64s - 1317.00s | here's an example. User account control, and you can see in the 1317.00s - 1319.40s | red is the extensible match filter. Um, in this case, it's 1319.40s - 1323.16s | an 803, so that's an and, and it's the number 515, which is 1323.16s - 1326.92s | the base two add-ins 1, 2, and 512. So one of the things we 1326.92s - 1329.32s | can do is what we've called bitwise breakout. So we can 1329.32s - 1333.16s | break that, uh, 515 out into 1 and 514. Again, as long as we 1333.16s - 1337.00s | have the proper grouping of add-ins, we can do this. 514 is 1337.00s - 1340.44s | actually 2 and 512. So we can break that out even further. So 1340.44s - 1343.08s | from a detection perspective, we can spread our logic across many 1343.08s - 1346.88s | different filters, which is really, really complicated, but 1346.88s - 1349.92s | it's also fun. Uh, if you started with an or, the same 1349.92s - 1351.96s | trick applies. Just make sure that the Boolean operator you 1351.96s - 1354.36s | add is an or instead of an and and that it matches the 1354.36s - 1358.68s | extensible match filter. Um, this is a pretty trivial example, 1358.68s - 1361.48s | but a lot of real world examples can get pretty crazy. Like this 1361.48s - 1364.68s | is a git domain user from PowerView. Massive number. You 1364.68s - 1367.24s | can imagine all of the random groupings and regroupings of, 1367.24s - 1370.44s | uh, base two add-ins to produce the same value in your overall 1370.44s - 1375.08s


chunk_id: 141_chunk_29
chunk_text:
| break that, uh, 515 out into 1 and 514. Again, as long as we 1333.16s - 1337.00s | have the proper grouping of add-ins, we can do this. 514 is 1337.00s - 1340.44s | actually 2 and 512. So we can break that out even further. So 1340.44s - 1343.08s | from a detection perspective, we can spread our logic across many 1343.08s - 1346.88s | different filters, which is really, really complicated, but 1346.88s - 1349.92s | it's also fun. Uh, if you started with an or, the same 1349.92s - 1351.96s | trick applies. Just make sure that the Boolean operator you 1351.96s - 1354.36s | add is an or instead of an and and that it matches the 1354.36s - 1358.68s | extensible match filter. Um, this is a pretty trivial example, 1358.68s - 1361.48s | but a lot of real world examples can get pretty crazy. Like this 1361.48s - 1364.68s | is a git domain user from PowerView. Massive number. You 1364.68s - 1367.24s | can imagine all of the random groupings and regroupings of, 1367.24s - 1370.44s | uh, base two add-ins to produce the same value in your overall 1370.44s - 1375.08s | search filter. Um, so another thing we can do is if you have a 1375.08s - 1378.60s | filter that is a precise value. So this is looking for the exact 1378.60s - 1383.16s | ones and zero set to equal this number. Um, what you can do is, 1383.16s - 1385.76s | uh, use this little formula. You can and, you can add the 1385.76s - 1388.56s | extensible match filter of and for all the one bits. You can 1388.56s - 1391.40s | add the or extensible match filter for all the zero bits and 1391.40s - 1395.24s | negate it and then and both of those filters together. What's 1395.24s - 1398.28s | really cool about this is now we have extensible match filters 1398.28s - 1401.00s | and we can use the first breakout type to break those 1401.00s - 1404.20s | into smaller and smaller random groupings of those base to add 1404.20s - 1406.52s | in. So we're not going to take this further, but this could 1406.52s - 1409.80s | explode into 10, 15, 20 different filters all slammed 1409.80s - 1413.48s | together. So interview for the fourth token type of


chunk_id: 141_chunk_30
chunk_text:
| search filter. Um, so another thing we can do is if you have a 1375.08s - 1378.60s | filter that is a precise value. So this is looking for the exact 1378.60s - 1383.16s | ones and zero set to equal this number. Um, what you can do is, 1383.16s - 1385.76s | uh, use this little formula. You can and, you can add the 1385.76s - 1388.56s | extensible match filter of and for all the one bits. You can 1388.56s - 1391.40s | add the or extensible match filter for all the zero bits and 1391.40s - 1395.24s | negate it and then and both of those filters together. What's 1395.24s - 1398.28s | really cool about this is now we have extensible match filters 1398.28s - 1401.00s | and we can use the first breakout type to break those 1401.00s - 1404.20s | into smaller and smaller random groupings of those base to add 1404.20s - 1406.52s | in. So we're not going to take this further, but this could 1406.52s - 1409.80s | explode into 10, 15, 20 different filters all slammed 1409.80s - 1413.48s | together. So interview for the fourth token type of extensible 1413.48s - 1415.56s | match filter. We have the bitwise breakout with the and 1415.56s - 1418.20s | and or, and then also the precise breakout, uh, which kind 1418.20s - 1424.32s | of combines the second one, uh, with the first one. Thanks 1424.32s - 1428.88s | Debo. Let's look at what we can do to obfuscate a little, the 1428.88s - 1433.68s | value. We are still in the filter section. So excluding a 1433.68s - 1437.44s | couple of attribute types, just like seeing here, it is still 1437.44s - 1442.64s | casing doesn't matter. So it's cases sensitive and we can also 1442.64s - 1446.56s | do prepended zeros to anything that are bitwise digits or 1446.64s - 1451.44s | numbers. And we got some undocumented feature regarding 1451.44s - 1456.32s | timestamps is that we originally noticed that sometimes 1456.32s - 1460.24s | milliseconds were present, but it didn't actually seem to 1460.24s - 1464.00s | matter. If you change the millisecond seconds values or 1464.00s - 1468.32s | remove them, it turns out you can actually add literally 1468.32s - 1474.80s | anything as long as you have a capital Z in it.


chunk_id: 141_chunk_31
chunk_text:
extensible 1413.48s - 1415.56s | match filter. We have the bitwise breakout with the and 1415.56s - 1418.20s | and or, and then also the precise breakout, uh, which kind 1418.20s - 1424.32s | of combines the second one, uh, with the first one. Thanks 1424.32s - 1428.88s | Debo. Let's look at what we can do to obfuscate a little, the 1428.88s - 1433.68s | value. We are still in the filter section. So excluding a 1433.68s - 1437.44s | couple of attribute types, just like seeing here, it is still 1437.44s - 1442.64s | casing doesn't matter. So it's cases sensitive and we can also 1442.64s - 1446.56s | do prepended zeros to anything that are bitwise digits or 1446.64s - 1451.44s | numbers. And we got some undocumented feature regarding 1451.44s - 1456.32s | timestamps is that we originally noticed that sometimes 1456.32s - 1460.24s | milliseconds were present, but it didn't actually seem to 1460.24s - 1464.00s | matter. If you change the millisecond seconds values or 1464.00s - 1468.32s | remove them, it turns out you can actually add literally 1468.32s - 1474.80s | anything as long as you have a capital Z in it. So, and 1474.80s - 1478.16s | technically it is going to be treated still as a correct 1478.16s - 1482.08s | timestamp in the results. And it doesn't need to be only 1482.08s - 1486.08s | capital Z. It can also be it's hex encoding representation, 1486.72s - 1491.84s | which leads us to the next point, which is hex encoding 1491.84s - 1495.92s | for value obfuscation. And it's our favorite thing to do, to be 1495.92s - 1501.60s | honest, the hex encoding itself, it exists to be able to, to 1501.68s - 1505.20s | escape certain special characters, which Microsoft has 1505.20s - 1509.20s | detailed here very well, but you can also escape any printable 1509.20s - 1514.88s | characters that you want to as well. So you can swap these with 1514.88s - 1518.08s | the hex representations, and it's still going to be to give 1518.08s - 1521.44s | you the same results. And is going to show just like this on 1521.44s - 1526.80s | the client side logs. Again, our parser, our parser parses 1526.80s - 1530.88s | codes, decodes all the values. So it's all being handled. 1532.08s - 1536.32s |


chunk_id: 141_chunk_32
chunk_text:
So, and 1474.80s - 1478.16s | technically it is going to be treated still as a correct 1478.16s - 1482.08s | timestamp in the results. And it doesn't need to be only 1482.08s - 1486.08s | capital Z. It can also be it's hex encoding representation, 1486.72s - 1491.84s | which leads us to the next point, which is hex encoding 1491.84s - 1495.92s | for value obfuscation. And it's our favorite thing to do, to be 1495.92s - 1501.60s | honest, the hex encoding itself, it exists to be able to, to 1501.68s - 1505.20s | escape certain special characters, which Microsoft has 1505.20s - 1509.20s | detailed here very well, but you can also escape any printable 1509.20s - 1514.88s | characters that you want to as well. So you can swap these with 1514.88s - 1518.08s | the hex representations, and it's still going to be to give 1518.08s - 1521.44s | you the same results. And is going to show just like this on 1521.44s - 1526.80s | the client side logs. Again, our parser, our parser parses 1526.80s - 1530.88s | codes, decodes all the values. So it's all being handled. 1532.08s - 1536.32s | One undocumented thing is that Microsoft says that the hex 1536.32s - 1539.04s | representation should be followed by two characters, 1540.08s - 1544.64s | representative SK hex character. But that's actually not true for 1544.64s - 1548.96s | the first 16 characters, you can drop the leading zero, and it's 1548.96s - 1554.08s | still going to work. Wildcards, we mentioned a little bit, even 1554.08s - 1558.08s | the wildcards. So for example, instead of looking for the 1558.16s - 1562.48s | wildcard TGT, you can also just look for RBG and see what you 1562.48s - 1568.24s | get. These, actually, for wildcards, we are not the only 1568.24s - 1572.40s | ones who have been looking for evasion purposes. So even the 1572.40s - 1577.44s | researcher Hope Walker, these are two very well great posts, 1577.44s - 1581.20s | blog posts recent, it's a researcher at SpectreOps. And 1581.20s - 1587.52s | she outlines using wildcards for evasion purposes. As a recap, 1587.52s - 1591.20s | for value, we can do casing, we can do prepended zeros, time 1591.20s - 1596.40s | steps, hex encoding, and wildcards. The good news is, 1596.40s - 1600.16s |


chunk_id: 141_chunk_33
chunk_text:
One undocumented thing is that Microsoft says that the hex 1536.32s - 1539.04s | representation should be followed by two characters, 1540.08s - 1544.64s | representative SK hex character. But that's actually not true for 1544.64s - 1548.96s | the first 16 characters, you can drop the leading zero, and it's 1548.96s - 1554.08s | still going to work. Wildcards, we mentioned a little bit, even 1554.08s - 1558.08s | the wildcards. So for example, instead of looking for the 1558.16s - 1562.48s | wildcard TGT, you can also just look for RBG and see what you 1562.48s - 1568.24s | get. These, actually, for wildcards, we are not the only 1568.24s - 1572.40s | ones who have been looking for evasion purposes. So even the 1572.40s - 1577.44s | researcher Hope Walker, these are two very well great posts, 1577.44s - 1581.20s | blog posts recent, it's a researcher at SpectreOps. And 1581.20s - 1587.52s | she outlines using wildcards for evasion purposes. As a recap, 1587.52s - 1591.20s | for value, we can do casing, we can do prepended zeros, time 1591.20s - 1596.40s | steps, hex encoding, and wildcards. The good news is, 1596.40s - 1600.16s | that's all you can do with obfuscation. Nah, I'm lying, 1600.16s - 1604.32s | you guys, we got much more. So until now, we actually were 1604.32s - 1608.00s | looking for top and obfuscation. Let's see outside of it a 1608.00s - 1612.88s | little. And for example, for filter wide obfuscation, you can 1613.52s - 1617.68s | actually add group start and group end as long as as much as 1617.68s - 1622.40s | you want, as long as you stay until the depth of 99. You can 1622.40s - 1627.52s | also add white space all over, and it is significant. And it 1627.52s - 1634.16s | can be new line tab, etc. Garbage filters, again, need 1634.16s - 1637.84s | here, actually, you need to be careful if you're looking for if 1637.84s - 1641.76s | you're actually using logical or or logical end, because in 1641.84s - 1645.84s | case you're looking for logical end, you need to make sure the 1645.84s - 1651.68s | properties exist. But you can go crazy with ours. And lastly, 1651.68s - 1657.84s | is filter filter reordering. So until now, we only handled the 1657.84s - 1662.88s |


chunk_id: 141_chunk_34
chunk_text:
that's all you can do with obfuscation. Nah, I'm lying, 1600.16s - 1604.32s | you guys, we got much more. So until now, we actually were 1604.32s - 1608.00s | looking for top and obfuscation. Let's see outside of it a 1608.00s - 1612.88s | little. And for example, for filter wide obfuscation, you can 1613.52s - 1617.68s | actually add group start and group end as long as as much as 1617.68s - 1622.40s | you want, as long as you stay until the depth of 99. You can 1622.40s - 1627.52s | also add white space all over, and it is significant. And it 1627.52s - 1634.16s | can be new line tab, etc. Garbage filters, again, need 1634.16s - 1637.84s | here, actually, you need to be careful if you're looking for if 1637.84s - 1641.76s | you're actually using logical or or logical end, because in 1641.84s - 1645.84s | case you're looking for logical end, you need to make sure the 1645.84s - 1651.68s | properties exist. But you can go crazy with ours. And lastly, 1651.68s - 1657.84s | is filter filter reordering. So until now, we only handled the 1657.84s - 1662.88s | filter. Let's see what we can do with base object. As a 1662.88s - 1666.80s | reminder, the base object is where in the active directory 1666.80s - 1670.16s | structure, we want to see we want to start the search, there 1670.16s - 1672.96s | are some good detection opportunities that we feel 1672.96s - 1677.44s | aren't discussed as much. And for example, like some offensive 1677.44s - 1681.52s | tools, just like certify, they have a very benign common and 1681.52s - 1685.60s | super search, super common search filter. So in this case 1685.60s - 1688.88s | is the base object, and it's looking for public key services, 1689.68s - 1695.44s | we are going to focus from a syntax perspective on a simple, 1695.44s - 1699.76s | really simple object like this. All the tricks we've seen until 1699.76s - 1703.04s | now, okay, for example, they still work, which is the casing 1703.04s - 1707.44s | we can play, you can do also the hex encoding for the value 1707.44s - 1713.20s | portion, you can use the ID notation of the attributes, and 1713.20s - 1719.44s | also supports the ID prefix as


chunk_id: 141_chunk_35
chunk_text:
filter. Let's see what we can do with base object. As a 1662.88s - 1666.80s | reminder, the base object is where in the active directory 1666.80s - 1670.16s | structure, we want to see we want to start the search, there 1670.16s - 1672.96s | are some good detection opportunities that we feel 1672.96s - 1677.44s | aren't discussed as much. And for example, like some offensive 1677.44s - 1681.52s | tools, just like certify, they have a very benign common and 1681.52s - 1685.60s | super search, super common search filter. So in this case 1685.60s - 1688.88s | is the base object, and it's looking for public key services, 1689.68s - 1695.44s | we are going to focus from a syntax perspective on a simple, 1695.44s - 1699.76s | really simple object like this. All the tricks we've seen until 1699.76s - 1703.04s | now, okay, for example, they still work, which is the casing 1703.04s - 1707.44s | we can play, you can do also the hex encoding for the value 1707.44s - 1713.20s | portion, you can use the ID notation of the attributes, and 1713.20s - 1719.44s | also supports the ID prefix as well as the or prefix. And 1719.44s - 1723.84s | whitespace, it actually can be added at the end, as well as 1723.84s - 1729.20s | between the slashes of the LDAP prefix. Something interesting 1729.28s - 1733.36s | is that it's true for the base object, but not for the value in 1733.36s - 1737.60s | the filter is that as long as hex is not present, you can 1737.60s - 1740.80s | actually encapsulate it with double quotes. And it will show 1740.80s - 1745.28s | up this way in client log side logs, but it's not going to look 1745.28s - 1751.12s | like this on server side logs. Lastly, is the attribute 1751.12s - 1754.64s | selection basically is which attributes properties do you 1754.64s - 1759.36s | want to be returned in the results. And here also case in 1759.36s - 1763.68s | doesn't matter, you can substitute just like previously, 1763.68s - 1767.52s | you can also use object identifier notation also 1767.52s - 1773.20s | supports adding ID prefix and prepended zeros, add whitespace 1773.20s - 1778.08s | only after the attributes that are on the ID syntax. Not sure 1778.08s - 1782.00s


chunk_id: 141_chunk_36
chunk_text:
well as the or prefix. And 1719.44s - 1723.84s | whitespace, it actually can be added at the end, as well as 1723.84s - 1729.20s | between the slashes of the LDAP prefix. Something interesting 1729.28s - 1733.36s | is that it's true for the base object, but not for the value in 1733.36s - 1737.60s | the filter is that as long as hex is not present, you can 1737.60s - 1740.80s | actually encapsulate it with double quotes. And it will show 1740.80s - 1745.28s | up this way in client log side logs, but it's not going to look 1745.28s - 1751.12s | like this on server side logs. Lastly, is the attribute 1751.12s - 1754.64s | selection basically is which attributes properties do you 1754.64s - 1759.36s | want to be returned in the results. And here also case in 1759.36s - 1763.68s | doesn't matter, you can substitute just like previously, 1763.68s - 1767.52s | you can also use object identifier notation also 1767.52s - 1773.20s | supports adding ID prefix and prepended zeros, add whitespace 1773.20s - 1778.08s | only after the attributes that are on the ID syntax. Not sure 1778.08s - 1782.00s | why but yeah, a lot of trial and error to be honest. We have 1782.08s - 1787.04s | the option also to add duplicate attributes and garbage 1787.04s - 1791.92s | attributes, literally anything you want. And the person who's 1791.92s - 1797.60s | going to to answer about this is no one else than Clippy. Hey, 1797.60s - 1801.68s | Daniel, what do you call this character? Asterix, wildcard or 1801.68s - 1802.16s | splat? 1804.08s - 1807.52s | I think this is an ages question. But all three are 1807.52s - 1809.84s | true. But there's a lot of there's a lot of space down 1809.84s - 1813.60s | there. So let's see what Clippy has to say. F all the above. So 1813.60s - 1816.00s | two more important things here is from an input perspective and 1816.00s - 1819.04s | the attribute selection. If the only value defined is a wild 1819.04s - 1822.88s | card, it will return all the properties, even just the same 1822.88s - 1825.28s | as if you don't define any attribute selection. What's 1825.28s - 1828.32s | fascinating is that in the server side logs, that wild card 1828.32s


chunk_id: 141_chunk_37
chunk_text:
| why but yeah, a lot of trial and error to be honest. We have 1782.08s - 1787.04s | the option also to add duplicate attributes and garbage 1787.04s - 1791.92s | attributes, literally anything you want. And the person who's 1791.92s - 1797.60s | going to to answer about this is no one else than Clippy. Hey, 1797.60s - 1801.68s | Daniel, what do you call this character? Asterix, wildcard or 1801.68s - 1802.16s | splat? 1804.08s - 1807.52s | I think this is an ages question. But all three are 1807.52s - 1809.84s | true. But there's a lot of there's a lot of space down 1809.84s - 1813.60s | there. So let's see what Clippy has to say. F all the above. So 1813.60s - 1816.00s | two more important things here is from an input perspective and 1816.00s - 1819.04s | the attribute selection. If the only value defined is a wild 1819.04s - 1822.88s | card, it will return all the properties, even just the same 1822.88s - 1825.28s | as if you don't define any attribute selection. What's 1825.28s - 1828.32s | fascinating is that in the server side logs, that wild card 1828.32s - 1831.12s | is going to literally be printed as the string square brackets, 1831.12s - 1835.76s | all all all lowercase. Now, if you'll notice, he is that if you 1835.76s - 1838.96s | have a list of attributes, and any one of those is a wild card, 1838.96s - 1842.32s | then it will, the server side logs will translate that wild 1842.32s - 1846.00s | card into this other string all with list. If you are and you 1846.00s - 1848.40s | should be if you are parsing these attribute selection 1848.40s - 1852.40s | values, you need to know that this weird string is prepended 1852.40s - 1854.64s | to the first attribute. So you have to do a really specific 1854.64s - 1858.00s | split and translation that we that we do in the logging 1858.00s - 1860.00s | module. But just know there's some weirdness that goes on 1860.00s - 1864.40s | there. Thanks, Clippy. All right, now that is actually the 1864.40s - 1867.20s | end of the obfuscation portion. So we've talked about the search 1867.20s - 1869.20s | filter, we've talked about the base object, the attribute 1869.20s - 1872.80s |


chunk_id: 141_chunk_38
chunk_text:
- 1831.12s | is going to literally be printed as the string square brackets, 1831.12s - 1835.76s | all all all lowercase. Now, if you'll notice, he is that if you 1835.76s - 1838.96s | have a list of attributes, and any one of those is a wild card, 1838.96s - 1842.32s | then it will, the server side logs will translate that wild 1842.32s - 1846.00s | card into this other string all with list. If you are and you 1846.00s - 1848.40s | should be if you are parsing these attribute selection 1848.40s - 1852.40s | values, you need to know that this weird string is prepended 1852.40s - 1854.64s | to the first attribute. So you have to do a really specific 1854.64s - 1858.00s | split and translation that we that we do in the logging 1858.00s - 1860.00s | module. But just know there's some weirdness that goes on 1860.00s - 1864.40s | there. Thanks, Clippy. All right, now that is actually the 1864.40s - 1867.20s | end of the obfuscation portion. So we've talked about the search 1867.20s - 1869.20s | filter, we've talked about the base object, the attribute 1869.20s - 1872.80s | selection. So for all the defenders in the room, what now? 1872.80s - 1876.08s | So from a solution perspective, we're going to focus on three 1876.08s - 1879.76s | steps. One is parsing, two is enriching, and then three is the 1879.76s - 1882.88s | actual detection itself. So from a parsing perspective, when we 1882.88s - 1885.84s | started this research, there was no parser for LDAP search 1885.84s - 1889.36s | filters. And so we naively said, let's just build a parser. How 1889.36s - 1891.84s | hard could it be? To be honest, that was over half of the 1891.84s - 1894.64s | research, but it was one of the most interesting and 1894.64s - 1897.68s | fulfilling parts of this. And so we wrote a C sharp state 1897.68s - 1901.04s | machine parser to firstly do tokenization. So that means when 1901.04s - 1903.36s | you have a string come in, that's the entire search filter, 1903.36s - 1905.68s | let's break it into tokens. So we know which ones are 1905.68s - 1908.96s | attributes, values, comparison operator, etc. Next, you want to 1908.96s - 1911.76s | organize those tokens into a representation


chunk_id: 141_chunk_39
chunk_text:
selection. So for all the defenders in the room, what now? 1872.80s - 1876.08s | So from a solution perspective, we're going to focus on three 1876.08s - 1879.76s | steps. One is parsing, two is enriching, and then three is the 1879.76s - 1882.88s | actual detection itself. So from a parsing perspective, when we 1882.88s - 1885.84s | started this research, there was no parser for LDAP search 1885.84s - 1889.36s | filters. And so we naively said, let's just build a parser. How 1889.36s - 1891.84s | hard could it be? To be honest, that was over half of the 1891.84s - 1894.64s | research, but it was one of the most interesting and 1894.64s - 1897.68s | fulfilling parts of this. And so we wrote a C sharp state 1897.68s - 1901.04s | machine parser to firstly do tokenization. So that means when 1901.04s - 1903.36s | you have a string come in, that's the entire search filter, 1903.36s - 1905.68s | let's break it into tokens. So we know which ones are 1905.68s - 1908.96s | attributes, values, comparison operator, etc. Next, you want to 1908.96s - 1911.76s | organize those tokens into a representation that allows you 1911.76s - 1915.28s | to understand the structure of nested Boolean operators and 1915.28s - 1917.68s | filters and filter lists and all those sorts of things. And 1917.68s - 1920.16s | then you can move on to actual enrichment, which is step 1920.16s - 1923.12s | number two. So here's an example of using all the conversion 1923.20s - 1926.64s | modules within Mount Adaptive to start with a string, break it 1926.64s - 1929.68s | into tokens, and then every step of the way, we try to decode 1929.68s - 1932.48s | and enrich however much we can. So as Sabi mentioned, when 1932.48s - 1934.88s | there are hex values, we'll automatically decode them for 1934.88s - 1939.04s | you. But we leave the original syntax as well. One distinction 1939.04s - 1942.96s | between, so in our parsing, we do tokenization, and then we 1942.96s - 1946.48s | basically create a parse tree or syntax tree, which is almost 1946.48s - 1949.44s | an abstract syntax tree, but we drop the abstract part because 1949.44s - 1952.00s | abstract says, let's drop things that don't need to be there, 1952.00s - 1954.64s |


chunk_id: 141_chunk_40
chunk_text:
that allows you 1911.76s - 1915.28s | to understand the structure of nested Boolean operators and 1915.28s - 1917.68s | filters and filter lists and all those sorts of things. And 1917.68s - 1920.16s | then you can move on to actual enrichment, which is step 1920.16s - 1923.12s | number two. So here's an example of using all the conversion 1923.20s - 1926.64s | modules within Mount Adaptive to start with a string, break it 1926.64s - 1929.68s | into tokens, and then every step of the way, we try to decode 1929.68s - 1932.48s | and enrich however much we can. So as Sabi mentioned, when 1932.48s - 1934.88s | there are hex values, we'll automatically decode them for 1934.88s - 1939.04s | you. But we leave the original syntax as well. One distinction 1939.04s - 1942.96s | between, so in our parsing, we do tokenization, and then we 1942.96s - 1946.48s | basically create a parse tree or syntax tree, which is almost 1946.48s - 1949.44s | an abstract syntax tree, but we drop the abstract part because 1949.44s - 1952.00s | abstract says, let's drop things that don't need to be there, 1952.00s - 1954.64s | like insignificant white space. Well, by definition, 1954.64s - 1956.88s | obfuscation doesn't need to be there. So we actually want to 1956.88s - 1960.00s | keep all those insignificant things so we can recreate the 1960.00s - 1963.52s | input from that parse tree. And then after we break this into 1963.52s - 1965.68s | tokens and do those enrichments, we'll then group them into 1965.68s - 1968.80s | filters and branches and a tree structure to do certain kinds of 1968.80s - 1971.28s | obfuscation and detections that require that kind of tree 1972.00s - 1975.52s | grouping functionality as we go through and parse it. And then 1975.52s - 1979.12s | the final step is actually detect. So we try to make it as 1979.12s - 1981.52s | simple as possible. We wrapped all this inside of a single 1981.52s - 1984.48s | function called find evil. So you can pipe any number of 1984.48s - 1986.80s | search filters you want into find evil. And for each of those 1986.80s - 1989.36s | filters, it will parse it, do all the enrichment we just 1989.36s - 1991.60s | talked about. It will run it through all


chunk_id: 141_chunk_41
chunk_text:
like insignificant white space. Well, by definition, 1954.64s - 1956.88s | obfuscation doesn't need to be there. So we actually want to 1956.88s - 1960.00s | keep all those insignificant things so we can recreate the 1960.00s - 1963.52s | input from that parse tree. And then after we break this into 1963.52s - 1965.68s | tokens and do those enrichments, we'll then group them into 1965.68s - 1968.80s | filters and branches and a tree structure to do certain kinds of 1968.80s - 1971.28s | obfuscation and detections that require that kind of tree 1972.00s - 1975.52s | grouping functionality as we go through and parse it. And then 1975.52s - 1979.12s | the final step is actually detect. So we try to make it as 1979.12s - 1981.52s | simple as possible. We wrapped all this inside of a single 1981.52s - 1984.48s | function called find evil. So you can pipe any number of 1984.48s - 1986.80s | search filters you want into find evil. And for each of those 1986.80s - 1989.36s | filters, it will parse it, do all the enrichment we just 1989.36s - 1991.60s | talked about. It will run it through all our complete 1991.60s - 1994.24s | detection rule set, which we are releasing with maladaptive. So 1994.24s - 1997.36s | 65 rules and counting. And then for each of those detections, 1997.36s - 2000.32s | the rule carries with it a dynamic score or weight, if you 2000.32s - 2002.88s | will, as well as an explanation. So it'll give you an example of 2002.88s - 2005.12s | what kind of thing it's looking for. And then it will actually 2005.12s - 2008.32s | show you the specific part of your search filter that flagged 2008.32s - 2011.84s | on that rule, as well as in the name, you can see. It'll 2011.84s - 2014.48s | actually pull out specific values. So it should be really 2014.48s - 2017.36s | colorfully obvious, as you'll see in the demo, of exactly why 2017.36s - 2019.92s | this thing was flagged for this rule. And if you look at the 2019.92s - 2023.04s | bottom, as I said, we spent over half the time just building 2023.04s - 2026.24s | this parser. We wrote and rewrote every piece of this 2026.24s - 2029.04s | parser two to three times to make it


chunk_id: 141_chunk_42
chunk_text:
our complete 1991.60s - 1994.24s | detection rule set, which we are releasing with maladaptive. So 1994.24s - 1997.36s | 65 rules and counting. And then for each of those detections, 1997.36s - 2000.32s | the rule carries with it a dynamic score or weight, if you 2000.32s - 2002.88s | will, as well as an explanation. So it'll give you an example of 2002.88s - 2005.12s | what kind of thing it's looking for. And then it will actually 2005.12s - 2008.32s | show you the specific part of your search filter that flagged 2008.32s - 2011.84s | on that rule, as well as in the name, you can see. It'll 2011.84s - 2014.48s | actually pull out specific values. So it should be really 2014.48s - 2017.36s | colorfully obvious, as you'll see in the demo, of exactly why 2017.36s - 2019.92s | this thing was flagged for this rule. And if you look at the 2019.92s - 2023.04s | bottom, as I said, we spent over half the time just building 2023.04s - 2026.24s | this parser. We wrote and rewrote every piece of this 2026.24s - 2029.04s | parser two to three times to make it as fast as we possibly 2029.04s - 2032.24s | could. And in this example, we're parsing this search filter 2032.24s - 2036.56s | 100,000 times, doing full parsing, full detections, and 2036.64s - 2040.16s | it's clocking in at just under 4.4 seconds. And that's on a 2040.16s - 2043.28s | moderately spec laptop, because we know that the number the 2043.28s - 2045.44s | volume of search filters in production environments is 2045.44s - 2048.24s | massive. And so we wanted this to be really usable right out of 2048.24s - 2052.88s | the box. Oh, and shout out to Olaf Hartung at Falcon Force. 2052.88s - 2055.12s | He was really instrumental in taking all these rules for us 2055.12s - 2057.84s | and running them multiple times across his entire client data 2057.84s - 2060.64s | set, since we don't have that data set, and then giving us 2060.64s - 2062.96s | feedback and stats on hey, which rules need to be tuned a little 2062.96s - 2065.28s | bit. So, Olaf, if you're watching, thanks so much, buddy, 2065.28s - 2068.48s | we really appreciate it. So, instead of talking more about 2068.48s - 2070.88s |


chunk_id: 141_chunk_43
chunk_text:
as fast as we possibly 2029.04s - 2032.24s | could. And in this example, we're parsing this search filter 2032.24s - 2036.56s | 100,000 times, doing full parsing, full detections, and 2036.64s - 2040.16s | it's clocking in at just under 4.4 seconds. And that's on a 2040.16s - 2043.28s | moderately spec laptop, because we know that the number the 2043.28s - 2045.44s | volume of search filters in production environments is 2045.44s - 2048.24s | massive. And so we wanted this to be really usable right out of 2048.24s - 2052.88s | the box. Oh, and shout out to Olaf Hartung at Falcon Force. 2052.88s - 2055.12s | He was really instrumental in taking all these rules for us 2055.12s - 2057.84s | and running them multiple times across his entire client data 2057.84s - 2060.64s | set, since we don't have that data set, and then giving us 2060.64s - 2062.96s | feedback and stats on hey, which rules need to be tuned a little 2062.96s - 2065.28s | bit. So, Olaf, if you're watching, thanks so much, buddy, 2065.28s - 2068.48s | we really appreciate it. So, instead of talking more about 2068.48s - 2070.88s | the solution, let's go into the last section and actually just 2070.88s - 2073.76s | show a demo. If you haven't picked up on it by now, we 2073.76s - 2076.48s | really like to have fun. When you spend 2,000 hours on 2076.48s - 2078.88s | something, you have to trick yourself into being motivated, 2078.88s - 2082.48s | so we added colors however we can. This is our ASCII art, and 2082.48s - 2084.96s | it's actually a fully functioning LDAP query that 2084.96s - 2088.88s | will return any object that has a name property. Clippy seems 2088.88s - 2090.64s | to like it as well. I can't tell if he's hanging out or 2090.64s - 2094.00s | trying to eat the terminal or what's going on. So, in the 2094.00s - 2097.60s | first example, this is that Albania, Kukiz, Tirana filter 2097.60s - 2100.40s | example with a little bit of obfuscation. So, if we tokenize 2100.40s - 2103.44s | it, we can see it breaks out which things are attributes, 2103.44s - 2106.56s | values, et cetera. If we do the enriched tokens, we can now see 2106.56s - 2109.12s | it says hey,


chunk_id: 141_chunk_44
chunk_text:
the solution, let's go into the last section and actually just 2070.88s - 2073.76s | show a demo. If you haven't picked up on it by now, we 2073.76s - 2076.48s | really like to have fun. When you spend 2,000 hours on 2076.48s - 2078.88s | something, you have to trick yourself into being motivated, 2078.88s - 2082.48s | so we added colors however we can. This is our ASCII art, and 2082.48s - 2084.96s | it's actually a fully functioning LDAP query that 2084.96s - 2088.88s | will return any object that has a name property. Clippy seems 2088.88s - 2090.64s | to like it as well. I can't tell if he's hanging out or 2090.64s - 2094.00s | trying to eat the terminal or what's going on. So, in the 2094.00s - 2097.60s | first example, this is that Albania, Kukiz, Tirana filter 2097.60s - 2100.40s | example with a little bit of obfuscation. So, if we tokenize 2100.40s - 2103.44s | it, we can see it breaks out which things are attributes, 2103.44s - 2106.56s | values, et cetera. If we do the enriched tokens, we can now see 2106.56s - 2109.12s | it says hey, this is a defined attribute, and it translates to 2109.12s - 2112.32s | the letter L, and we have these other context objects as well. 2112.32s - 2114.64s | So, if we look at the context object, remember this is things 2114.64s - 2117.28s | like the Boolean operator. We group all these things into 2117.28s - 2120.32s | filters so that we can write detection logic against the 2120.32s - 2122.88s | entire filter. So, we can easily access the string values, but 2122.96s - 2125.36s | then we have a dictionary and list of the full token objects. 2125.36s - 2128.00s | So, all the metadata nested from tokenization we can find in 2128.00s - 2130.56s | the filter, and then if we look at the context object for the 2130.56s - 2133.84s | Boolean operator, we'll see this is a logically inclusive filter. 2133.84s - 2136.16s | This is tracking that full stack of Boolean operators that 2136.16s - 2139.12s | you still have direct access to, and then every single value 2139.12s - 2142.08s | goes through the full value parsing. So, any hex characters 2142.08s - 2144.72s | are parsed. At any time, you can


chunk_id: 141_chunk_45
chunk_text:
this is a defined attribute, and it translates to 2109.12s - 2112.32s | the letter L, and we have these other context objects as well. 2112.32s - 2114.64s | So, if we look at the context object, remember this is things 2114.64s - 2117.28s | like the Boolean operator. We group all these things into 2117.28s - 2120.32s | filters so that we can write detection logic against the 2120.32s - 2122.88s | entire filter. So, we can easily access the string values, but 2122.96s - 2125.36s | then we have a dictionary and list of the full token objects. 2125.36s - 2128.00s | So, all the metadata nested from tokenization we can find in 2128.00s - 2130.56s | the filter, and then if we look at the context object for the 2130.56s - 2133.84s | Boolean operator, we'll see this is a logically inclusive filter. 2133.84s - 2136.16s | This is tracking that full stack of Boolean operators that 2136.16s - 2139.12s | you still have direct access to, and then every single value 2139.12s - 2142.08s | goes through the full value parsing. So, any hex characters 2142.08s - 2144.72s | are parsed. At any time, you can look for the raw content or 2144.72s - 2147.44s | the decoded content. Pipe that into Find Evil, and we can see 2147.44s - 2150.08s | these are the individual rules that matched for this 2150.08s - 2152.56s | particular search filter. This is just showing a couple 2152.56s - 2155.12s | properties. In the next demos, you'll see a little better view 2155.12s - 2158.80s | of the entirety of the rules. Let's do another parsing 2158.80s - 2160.96s | example, this time using the bitwise value. So, remember all 2160.96s - 2164.88s | the bitwise breakout were like 515 can be 1, 2, 5, 12. Well, 2164.88s - 2167.28s | here's a rule that flag and says, hey, if user account 2167.28s - 2171.12s | control attribute has the flag 128 set to true, then flag this 2171.12s - 2173.04s | alert. I won't go into the details of why that's an 2173.04s - 2176.24s | interesting detection, but what we want to show you is when we 2176.24s - 2178.16s | parse this value, we automatically know this is a 2178.16s - 2181.28s | bitwise attribute, and we parse the value to get those base two 2181.28s


chunk_id: 141_chunk_46
chunk_text:
look for the raw content or 2144.72s - 2147.44s | the decoded content. Pipe that into Find Evil, and we can see 2147.44s - 2150.08s | these are the individual rules that matched for this 2150.08s - 2152.56s | particular search filter. This is just showing a couple 2152.56s - 2155.12s | properties. In the next demos, you'll see a little better view 2155.12s - 2158.80s | of the entirety of the rules. Let's do another parsing 2158.80s - 2160.96s | example, this time using the bitwise value. So, remember all 2160.96s - 2164.88s | the bitwise breakout were like 515 can be 1, 2, 5, 12. Well, 2164.88s - 2167.28s | here's a rule that flag and says, hey, if user account 2167.28s - 2171.12s | control attribute has the flag 128 set to true, then flag this 2171.12s - 2173.04s | alert. I won't go into the details of why that's an 2173.04s - 2176.24s | interesting detection, but what we want to show you is when we 2176.24s - 2178.16s | parse this value, we automatically know this is a 2178.16s - 2181.28s | bitwise attribute, and we parse the value to get those base two 2181.28s - 2184.88s | add-ins, either in a dictionary format or a list format. So, 2184.88s - 2187.68s | you can immediately write detections for combinations of 2187.68s - 2190.64s | true and false. Now, keep in mind this is per filter, so that 2190.64s - 2192.96s | breakout stuff does complicate it a bit, but you can at least 2192.96s - 2197.04s | extract the flags and aggregate it back together for your final 2197.04s - 2200.88s | detections across the entirety of the search filter. The last 2200.88s - 2204.96s | parsing example is looking for some actually kind of crazy 2204.96s - 2207.28s | stuff. So, decoding hex characters in this first 2207.28s - 2210.16s | example, that's easy sauce. So, this is trusted domain, easy 2210.16s - 2213.36s | detection, but when it's things like wildcards, they're actually 2213.36s - 2216.24s | missing characters. So, we can't precisely say what the person 2216.24s - 2219.60s | was looking for, but in our detection module, you have the 2219.60s - 2222.72s | ability to define strings of interest, like curb TGT, domain 2222.72s - 2225.36s | admins, domain controllers, and the parser and the detection 2225.36s - 2227.76s


chunk_id: 141_chunk_47
chunk_text:
- 2184.88s | add-ins, either in a dictionary format or a list format. So, 2184.88s - 2187.68s | you can immediately write detections for combinations of 2187.68s - 2190.64s | true and false. Now, keep in mind this is per filter, so that 2190.64s - 2192.96s | breakout stuff does complicate it a bit, but you can at least 2192.96s - 2197.04s | extract the flags and aggregate it back together for your final 2197.04s - 2200.88s | detections across the entirety of the search filter. The last 2200.88s - 2204.96s | parsing example is looking for some actually kind of crazy 2204.96s - 2207.28s | stuff. So, decoding hex characters in this first 2207.28s - 2210.16s | example, that's easy sauce. So, this is trusted domain, easy 2210.16s - 2213.36s | detection, but when it's things like wildcards, they're actually 2213.36s - 2216.24s | missing characters. So, we can't precisely say what the person 2216.24s - 2219.60s | was looking for, but in our detection module, you have the 2219.60s - 2222.72s | ability to define strings of interest, like curb TGT, domain 2222.72s - 2225.36s | admins, domain controllers, and the parser and the detection 2225.36s - 2227.76s | rules will go through and actually expand the wildcards 2227.76s - 2230.48s | and say, hey, does this wildcarded string match any of 2230.48s - 2233.44s | your sensitive terms? And that also handles the two ANR 2233.44s - 2235.60s | scenarios that Sabi mentioned earlier, with the implicit 2235.60s - 2239.28s | wildcard or the explicit wildcard. So, yeah, those are 2239.28s - 2241.20s | some really fun detections that go beyond just pure 2241.20s - 2244.08s | deobfuscation, but really kind of logically looking at some 2244.08s - 2245.84s | suspicious strings of interest. 2247.76s - 2252.40s | And finally, we've put all this together into a colorful 2252.40s - 2256.48s | interactive menu to make it fun to explore. We can test our 2256.48s - 2261.28s | input, the LDAP search filter, and we can explore the 2261.28s - 2265.20s | obfuscation menus for all the techniques we covered in this 2265.20s - 2272.08s | presentation. Wildcards are also supported. We can add 2272.08s - 2276.40s | obfuscation layer by layer, and we can also remove it. And if 2276.40s - 2280.32s | you're lazy, you can use all wildcards to randomly apply all 2280.32s -


chunk_id: 141_chunk_48
chunk_text:
| rules will go through and actually expand the wildcards 2227.76s - 2230.48s | and say, hey, does this wildcarded string match any of 2230.48s - 2233.44s | your sensitive terms? And that also handles the two ANR 2233.44s - 2235.60s | scenarios that Sabi mentioned earlier, with the implicit 2235.60s - 2239.28s | wildcard or the explicit wildcard. So, yeah, those are 2239.28s - 2241.20s | some really fun detections that go beyond just pure 2241.20s - 2244.08s | deobfuscation, but really kind of logically looking at some 2244.08s - 2245.84s | suspicious strings of interest. 2247.76s - 2252.40s | And finally, we've put all this together into a colorful 2252.40s - 2256.48s | interactive menu to make it fun to explore. We can test our 2256.48s - 2261.28s | input, the LDAP search filter, and we can explore the 2261.28s - 2265.20s | obfuscation menus for all the techniques we covered in this 2265.20s - 2272.08s | presentation. Wildcards are also supported. We can add 2272.08s - 2276.40s | obfuscation layer by layer, and we can also remove it. And if 2276.40s - 2280.32s | you're lazy, you can use all wildcards to randomly apply all 2280.32s - 2280.88s | the options. 2282.88s - 2288.56s | Let's test again. The search filter still works. Detection 2288.56s - 2293.12s | module is built in, and find evils shows a full summary of 2293.12s - 2297.76s | detections, scores, explanations, and more colors. 2299.52s - 2302.88s | Lastly, if you don't like interactive menus, we have full 2302.88s - 2308.32s | CLI support. So the interactive menu lets you randomly choose 2308.32s - 2313.28s | ingredients, and you can copy out the receipt for non-interactive 2313.28s - 2317.36s | user. All the functions for pretty printing and detection 2317.36s - 2320.40s | summaries are also available via CLI. 2330.00s - 2332.88s | Thank you. It's always awkward in Blue Teamer talks, and they're 2332.88s - 2336.08s | like, was that a shell? Like, do we clap or not? And so, yeah, 2336.08s - 2338.72s | our apologies for not including a dramatic pause. But yeah, 2338.72s - 2342.08s | hopefully that was really fun for everyone. So we're almost 2342.08s - 2344.32s | done here, but we just want to reiterate that Sabi and I are 2344.32s - 2346.56s | both defenders, and from the very beginning of this research,


chunk_id: 141_chunk_49
chunk_text:
2280.88s | the options. 2282.88s - 2288.56s | Let's test again. The search filter still works. Detection 2288.56s - 2293.12s | module is built in, and find evils shows a full summary of 2293.12s - 2297.76s | detections, scores, explanations, and more colors. 2299.52s - 2302.88s | Lastly, if you don't like interactive menus, we have full 2302.88s - 2308.32s | CLI support. So the interactive menu lets you randomly choose 2308.32s - 2313.28s | ingredients, and you can copy out the receipt for non-interactive 2313.28s - 2317.36s | user. All the functions for pretty printing and detection 2317.36s - 2320.40s | summaries are also available via CLI. 2330.00s - 2332.88s | Thank you. It's always awkward in Blue Teamer talks, and they're 2332.88s - 2336.08s | like, was that a shell? Like, do we clap or not? And so, yeah, 2336.08s - 2338.72s | our apologies for not including a dramatic pause. But yeah, 2338.72s - 2342.08s | hopefully that was really fun for everyone. So we're almost 2342.08s - 2344.32s | done here, but we just want to reiterate that Sabi and I are 2344.32s - 2346.56s | both defenders, and from the very beginning of this research, 2346.56s - 2349.92s | we knew that we had not seen people talking about this, and 2349.92s - 2352.48s | to be honest, attackers didn't really need this help. So why 2352.48s - 2355.44s | hand them a fully loaded machine gun when defenders still often 2355.44s - 2357.52s | don't even have the telemetry in the first place? So from the 2357.52s - 2359.60s | very beginning, we weren't strong-armed. We decided that 2359.60s - 2362.56s | we wanted to release this in a unique kind of two-stage 2362.56s - 2365.20s | approach. So today what we've released is everything we've 2365.20s - 2368.40s | talked about, minus the obfuscation module. We're 2368.40s - 2372.64s | releasing a corpus of 1,337 benign obfuscated examples, so 2372.64s - 2374.96s | you don't even have to run our code to look at examples of 2374.96s - 2378.56s | obfuscated search filters. For anyone who's really ambitious, 2378.56s - 2381.60s | you have the full parser, and the deobfuscation modules look 2381.60s - 2384.08s | suspiciously like the obfuscation ones. So if you want 2384.08s - 2386.64s | to do a little bit, go for it. But just keep in mind, we


chunk_id: 141_chunk_50
chunk_text:
2346.56s - 2349.92s | we knew that we had not seen people talking about this, and 2349.92s - 2352.48s | to be honest, attackers didn't really need this help. So why 2352.48s - 2355.44s | hand them a fully loaded machine gun when defenders still often 2355.44s - 2357.52s | don't even have the telemetry in the first place? So from the 2357.52s - 2359.60s | very beginning, we weren't strong-armed. We decided that 2359.60s - 2362.56s | we wanted to release this in a unique kind of two-stage 2362.56s - 2365.20s | approach. So today what we've released is everything we've 2365.20s - 2368.40s | talked about, minus the obfuscation module. We're 2368.40s - 2372.64s | releasing a corpus of 1,337 benign obfuscated examples, so 2372.64s - 2374.96s | you don't even have to run our code to look at examples of 2374.96s - 2378.56s | obfuscated search filters. For anyone who's really ambitious, 2378.56s - 2381.60s | you have the full parser, and the deobfuscation modules look 2381.60s - 2384.08s | suspiciously like the obfuscation ones. So if you want 2384.08s - 2386.64s | to do a little bit, go for it. But just keep in mind, we spent 2386.72s - 2389.12s | over 1,000 hours on the obfuscation module, so there is 2389.12s - 2392.24s | a heck of a lot of craziness that we put in there. Our goal, 2392.88s - 2395.76s | pending a CFP response, is hopefully by the end of this 2395.76s - 2399.12s | year to do a part two of this presentation to focus really 2399.12s - 2402.88s | deeply on all the differences in client and server-side logging, 2402.88s - 2405.44s | a lot of the weird scenarios we had to build into the parser to 2405.44s - 2408.48s | support all of this, and then at that point, releasing the 2408.48s - 2412.24s | obfuscation module. So yeah, just want to make that really 2412.24s - 2414.08s | clear. That's clear on the GitHub, which will be on the 2414.08s - 2416.96s | last slide as well. But again, as defenders, we wanted to try 2416.96s - 2419.76s | to be as creative as possible and help defenders not be 2419.76s - 2423.12s | completely throwing tomatoes at us up on the stage. And we made 2423.12s - 2425.84s | this very clear in the CFP process. Big red


chunk_id: 141_chunk_51
chunk_text:
spent 2386.72s - 2389.12s | over 1,000 hours on the obfuscation module, so there is 2389.12s - 2392.24s | a heck of a lot of craziness that we put in there. Our goal, 2392.88s - 2395.76s | pending a CFP response, is hopefully by the end of this 2395.76s - 2399.12s | year to do a part two of this presentation to focus really 2399.12s - 2402.88s | deeply on all the differences in client and server-side logging, 2402.88s - 2405.44s | a lot of the weird scenarios we had to build into the parser to 2405.44s - 2408.48s | support all of this, and then at that point, releasing the 2408.48s - 2412.24s | obfuscation module. So yeah, just want to make that really 2412.24s - 2414.08s | clear. That's clear on the GitHub, which will be on the 2414.08s - 2416.96s | last slide as well. But again, as defenders, we wanted to try 2416.96s - 2419.76s | to be as creative as possible and help defenders not be 2419.76s - 2423.12s | completely throwing tomatoes at us up on the stage. And we made 2423.12s - 2425.84s | this very clear in the CFP process. Big red text, no 2425.84s - 2429.12s | surprises. So we're really happy that there was support in us 2429.12s - 2432.96s | doing that kind of a release. So the final takeaways. LDAP is 2432.96s - 2436.80s | still widely used by attackers. It's very valuable. And in our 2436.80s - 2439.76s | opinion, defensively, it's still kind of immature in terms of 2440.56s - 2443.04s | detection. It seems to be a lot of kind of string-based 2443.04s - 2445.68s | detections. And even looking at blog posts of people doing LDAP 2445.68s - 2448.32s | hunting, there just aren't as many of them as I would like to 2448.32s - 2452.24s | see, that we would like to see. And then lastly, we released 2452.24s - 2455.68s | Maldaptive to help try to bring awareness to what can happen to 2455.68s - 2458.08s | show that we shouldn't just be doing string-based detections, 2458.08s - 2460.88s | and we're providing the parser in all of our detection modules 2460.88s - 2463.36s | so that hopefully you can right out of the gate start using it 2463.36s - 2465.52s | in your environment if you already have a mechanism to


chunk_id: 141_chunk_52
chunk_text:
text, no 2425.84s - 2429.12s | surprises. So we're really happy that there was support in us 2429.12s - 2432.96s | doing that kind of a release. So the final takeaways. LDAP is 2432.96s - 2436.80s | still widely used by attackers. It's very valuable. And in our 2436.80s - 2439.76s | opinion, defensively, it's still kind of immature in terms of 2440.56s - 2443.04s | detection. It seems to be a lot of kind of string-based 2443.04s - 2445.68s | detections. And even looking at blog posts of people doing LDAP 2445.68s - 2448.32s | hunting, there just aren't as many of them as I would like to 2448.32s - 2452.24s | see, that we would like to see. And then lastly, we released 2452.24s - 2455.68s | Maldaptive to help try to bring awareness to what can happen to 2455.68s - 2458.08s | show that we shouldn't just be doing string-based detections, 2458.08s - 2460.88s | and we're providing the parser in all of our detection modules 2460.88s - 2463.36s | so that hopefully you can right out of the gate start using it 2463.36s - 2465.52s | in your environment if you already have a mechanism to get 2465.52s - 2470.00s | all of those search filters. Our unofficial takeaway is we 2470.00s - 2471.60s | wanted to leave you with something a little different. 2472.40s - 2476.32s | And so we wanted to leave you with each of our favorite 2476.32s - 2479.04s | Albanian proverb. So I'm going to go first. I'm not a native 2479.04s - 2482.72s | speaker, so forgive my pronunciation. But mine is 2482.72s - 2486.72s | rošsa malet, which literally means live long like a mountain. 2486.72s - 2489.76s | It's kind of a blessing of well-being. I like to think of 2489.76s - 2492.00s | it in this scenario as we just climbed a crazy mountain 2492.00s - 2495.44s | together. I'm a little out of breath personally. But in this 2495.44s - 2498.24s | industry, we have to help each other out. We have to recognize 2498.24s - 2501.36s | the shoulders that we stand on. And so when you see someone else 2501.36s - 2503.20s | struggling up the mountain trying to understand what 2503.20s - 2506.16s | you're learning, help them up. Get them to the top, and then 2506.16s - 2508.00s | they'll be able


chunk_id: 141_chunk_53
chunk_text:
get 2465.52s - 2470.00s | all of those search filters. Our unofficial takeaway is we 2470.00s - 2471.60s | wanted to leave you with something a little different. 2472.40s - 2476.32s | And so we wanted to leave you with each of our favorite 2476.32s - 2479.04s | Albanian proverb. So I'm going to go first. I'm not a native 2479.04s - 2482.72s | speaker, so forgive my pronunciation. But mine is 2482.72s - 2486.72s | rošsa malet, which literally means live long like a mountain. 2486.72s - 2489.76s | It's kind of a blessing of well-being. I like to think of 2489.76s - 2492.00s | it in this scenario as we just climbed a crazy mountain 2492.00s - 2495.44s | together. I'm a little out of breath personally. But in this 2495.44s - 2498.24s | industry, we have to help each other out. We have to recognize 2498.24s - 2501.36s | the shoulders that we stand on. And so when you see someone else 2501.36s - 2503.20s | struggling up the mountain trying to understand what 2503.20s - 2506.16s | you're learning, help them up. Get them to the top, and then 2506.16s - 2508.00s | they'll be able to see the next mountain they're going to climb 2508.00s - 2509.52s | and the person they're going to bring along with them. 2511.93s - 2516.57s | And my favorite expression, and I think the audience would 2516.57s - 2521.05s | agree with me here, Diba, is to ljutem jo mokap se letraš, 2521.05s - 2524.49s | which it means please no more paperclips. 2528.09s - 2531.69s | It was fun while it lasted. All right. And with that, we just 2531.69s - 2534.41s | want to say thank you so much for your time. Thank you DefCon 2534.41s - 2537.53s | and to all the organizers. We had such a great time putting 2537.53s - 2540.17s | this research together, and we're really happy to be here. 2540.17s - 2542.97s | Here's all of our contact information. Here's the link to 2542.97s - 2545.21s | Maldaptive. Please reach out, and we'll be up here for 2545.21s - 2558.17s | questions. But thank you again for your time. Any brave souls 2558.17s - 2563.23s | for questions? Questions or criticisms, everything is 2563.23s - 2575.77s | welcome. One right here, yeah. So the question is what was our 2575.77s -


chunk_id: 141_chunk_54
chunk_text:
to see the next mountain they're going to climb 2508.00s - 2509.52s | and the person they're going to bring along with them. 2511.93s - 2516.57s | And my favorite expression, and I think the audience would 2516.57s - 2521.05s | agree with me here, Diba, is to ljutem jo mokap se letraš, 2521.05s - 2524.49s | which it means please no more paperclips. 2528.09s - 2531.69s | It was fun while it lasted. All right. And with that, we just 2531.69s - 2534.41s | want to say thank you so much for your time. Thank you DefCon 2534.41s - 2537.53s | and to all the organizers. We had such a great time putting 2537.53s - 2540.17s | this research together, and we're really happy to be here. 2540.17s - 2542.97s | Here's all of our contact information. Here's the link to 2542.97s - 2545.21s | Maldaptive. Please reach out, and we'll be up here for 2545.21s - 2558.17s | questions. But thank you again for your time. Any brave souls 2558.17s - 2563.23s | for questions? Questions or criticisms, everything is 2563.23s - 2575.77s | welcome. One right here, yeah. So the question is what was our 2575.77s - 2579.93s | process for finding all the undocumented stuff? Well, 2579.93s - 2584.25s | sometimes luck, sometimes I think the best answer that we 2584.25s - 2587.13s | can give is people ask us why do you make obfuscation 2587.13s - 2590.57s | frameworks? It's kind of a little twisted, but it's really 2590.57s - 2593.77s | a way of kind of working backwards and defining a 2593.77s - 2596.41s | grammar, because it's all a language, right? What's 2596.41s - 2599.29s | linguistically, syntactically allowed in a language, whether 2599.29s - 2602.33s | that's PowerShell or LDAP or anything else? So our 2602.33s - 2606.57s | understanding is, let's say, actually when Sabi wrote the 2606.57s - 2609.29s | hex encoding function to take values and do hex encoding, 2609.93s - 2612.01s | we wrote that function, we plugged it into our test 2612.01s - 2614.89s | harness, and one out of every 500 examples would fail. It 2614.89s - 2617.05s | wouldn't return the same results we expected. And we 2617.05s - 2619.77s | eventually realized that's because hex values or hex 2619.77s - 2623.21s | characters in the value is not allowed when the extensible 2623.21s -


chunk_id: 141_chunk_55
chunk_text:
2579.93s | process for finding all the undocumented stuff? Well, 2579.93s - 2584.25s | sometimes luck, sometimes I think the best answer that we 2584.25s - 2587.13s | can give is people ask us why do you make obfuscation 2587.13s - 2590.57s | frameworks? It's kind of a little twisted, but it's really 2590.57s - 2593.77s | a way of kind of working backwards and defining a 2593.77s - 2596.41s | grammar, because it's all a language, right? What's 2596.41s - 2599.29s | linguistically, syntactically allowed in a language, whether 2599.29s - 2602.33s | that's PowerShell or LDAP or anything else? So our 2602.33s - 2606.57s | understanding is, let's say, actually when Sabi wrote the 2606.57s - 2609.29s | hex encoding function to take values and do hex encoding, 2609.93s - 2612.01s | we wrote that function, we plugged it into our test 2612.01s - 2614.89s | harness, and one out of every 500 examples would fail. It 2614.89s - 2617.05s | wouldn't return the same results we expected. And we 2617.05s - 2619.77s | eventually realized that's because hex values or hex 2619.77s - 2623.21s | characters in the value is not allowed when the extensible 2623.21s - 2625.45s | match filter is defined, right? So that is now an 2625.45s - 2628.57s | incompatibility that no one said anywhere, but our tool 2628.57s - 2630.97s | helped us find because it found an example that broke what we'd 2630.97s - 2633.53s | expected to see. So that's how we found a lot of these 2633.53s - 2635.53s | examples. And then just some tricks you kind of learn along 2635.53s - 2637.77s | the way, like, hey, pre-pinning zeros, that seems like 2637.77s - 2639.77s | something that someone might have thought to ignore because 2639.77s - 2642.17s | it's insignificant, but it still shows up in logs, 2642.17s - 2644.57s | therefore it's meaningful to us. And so some of those tricks 2644.57s - 2646.25s | you just kind of pick up along the way and keep carrying 2646.25s - 2660.81s | forward. But yeah, great question. Thank you. Yeah. Yeah, 2660.81s - 2663.77s | good question. So the question was in our research against the 2663.77s - 2667.13s | obfuscation techniques we found, how effective was Windows 2667.13s - 2669.77s | Defender or other tools like that? We don't have access to 2669.77s - 2675.05s


chunk_id: 141_chunk_56
chunk_text:
2625.45s | match filter is defined, right? So that is now an 2625.45s - 2628.57s | incompatibility that no one said anywhere, but our tool 2628.57s - 2630.97s | helped us find because it found an example that broke what we'd 2630.97s - 2633.53s | expected to see. So that's how we found a lot of these 2633.53s - 2635.53s | examples. And then just some tricks you kind of learn along 2635.53s - 2637.77s | the way, like, hey, pre-pinning zeros, that seems like 2637.77s - 2639.77s | something that someone might have thought to ignore because 2639.77s - 2642.17s | it's insignificant, but it still shows up in logs, 2642.17s - 2644.57s | therefore it's meaningful to us. And so some of those tricks 2644.57s - 2646.25s | you just kind of pick up along the way and keep carrying 2646.25s - 2660.81s | forward. But yeah, great question. Thank you. Yeah. Yeah, 2660.81s - 2663.77s | good question. So the question was in our research against the 2663.77s - 2667.13s | obfuscation techniques we found, how effective was Windows 2667.13s - 2669.77s | Defender or other tools like that? We don't have access to 2669.77s - 2675.05s | those tools, so I actually don't know. In general, I'd say I've 2675.05s - 2677.77s | spent the last decade doing real-time detections, actually 2677.77s - 2680.33s | spending some time at Microsoft in Defender telemetry looking 2680.33s - 2683.61s | at how we detect processes and stuff like that on the 2683.61s - 2686.41s | endpoint. So what I would say that a lot of red teamers 2686.41s - 2688.89s | criticize blue teamers for is why do you make static kind of 2688.89s - 2692.41s | rigid detections? Sometimes it's out of ignorance. Sometimes 2692.41s - 2694.97s | more likely it's out of performance. So I mean, there 2694.97s - 2697.05s | are millions and millions and millions of search filters 2697.05s - 2701.29s | flying around doing crazy regexes to try to find these 2701.29s - 2703.85s | bizarre scenarios probably is going to bring down performance 2703.85s - 2706.33s | overall. So from a product's perspective, that's, I think, 2706.41s - 2708.49s | why a lot of decisions are made, but we don't have any direct 2708.49s - 2711.85s | insight into Defender or anyone else on how they're stacking up 2711.85s - 2716.01s |


chunk_id: 141_chunk_57
chunk_text:
| those tools, so I actually don't know. In general, I'd say I've 2675.05s - 2677.77s | spent the last decade doing real-time detections, actually 2677.77s - 2680.33s | spending some time at Microsoft in Defender telemetry looking 2680.33s - 2683.61s | at how we detect processes and stuff like that on the 2683.61s - 2686.41s | endpoint. So what I would say that a lot of red teamers 2686.41s - 2688.89s | criticize blue teamers for is why do you make static kind of 2688.89s - 2692.41s | rigid detections? Sometimes it's out of ignorance. Sometimes 2692.41s - 2694.97s | more likely it's out of performance. So I mean, there 2694.97s - 2697.05s | are millions and millions and millions of search filters 2697.05s - 2701.29s | flying around doing crazy regexes to try to find these 2701.29s - 2703.85s | bizarre scenarios probably is going to bring down performance 2703.85s - 2706.33s | overall. So from a product's perspective, that's, I think, 2706.41s - 2708.49s | why a lot of decisions are made, but we don't have any direct 2708.49s - 2711.85s | insight into Defender or anyone else on how they're stacking up 2711.85s - 2716.01s | against this. If anyone from Microsoft or anyone else wants 2716.01s - 2717.77s | to reach out, we'd be more than happy to share more of the 2717.77s - 2720.49s | research in detail and help if there's anything that we can do 2720.49s - 2723.85s | to protect the community in that regard. Great question. Thank 2723.85s - 2735.47s | you. Any last questions? Yes. The question was did we have 2735.47s - 2739.95s | trouble with all the colors for formatting? Trouble to who? The 2739.95s - 2756.97s | answer is yes. So we actually did, we split our programming 2756.97s - 2759.29s | actually partially. We use PowerShell core. So we did a lot 2759.29s - 2761.45s | of it in Windows, a lot of it on Mac, a little bit in Linux, 2761.45s - 2763.77s | just to test compatibility. But yeah, in terms of color 2763.77s - 2765.85s | differences, we actually stuck with the original colors, the 2765.85s - 2769.37s | original 16. We experimented with the dark colors for things 2769.37s - 2774.25s | like distinguished name values. Those are the darkened version 2774.25s - 2778.33s | of all the RDNs to represent


chunk_id: 141_chunk_58
chunk_text:
against this. If anyone from Microsoft or anyone else wants 2716.01s - 2717.77s | to reach out, we'd be more than happy to share more of the 2717.77s - 2720.49s | research in detail and help if there's anything that we can do 2720.49s - 2723.85s | to protect the community in that regard. Great question. Thank 2723.85s - 2735.47s | you. Any last questions? Yes. The question was did we have 2735.47s - 2739.95s | trouble with all the colors for formatting? Trouble to who? The 2739.95s - 2756.97s | answer is yes. So we actually did, we split our programming 2756.97s - 2759.29s | actually partially. We use PowerShell core. So we did a lot 2759.29s - 2761.45s | of it in Windows, a lot of it on Mac, a little bit in Linux, 2761.45s - 2763.77s | just to test compatibility. But yeah, in terms of color 2763.77s - 2765.85s | differences, we actually stuck with the original colors, the 2765.85s - 2769.37s | original 16. We experimented with the dark colors for things 2769.37s - 2774.25s | like distinguished name values. Those are the darkened version 2774.25s - 2778.33s | of all the RDNs to represent the overall tokens. But that 2778.33s - 2781.29s | darkness shows up better on Windows. On Mac, it actually 2781.29s - 2784.81s | doesn't quite show up as much. But yeah, so that was a factor 2784.81s - 2788.65s | we had to kind of play around with. But yeah, I like the color 2788.65s - 2793.34s | question. I've never gotten that before. So thank you. All 2793.34s - 2795.02s | right. I think with this, we're out of time. We'll be around 2795.02s - 2796.86s | front if anyone else wants to talk or ask questions. But 2796.86s - 2798.70s | again, thank you everyone for coming to the talk. Have a good 2798.70s - 2799.50s | one.


chunk_id: 141_chunk_59
chunk_text:
the overall tokens. But that 2778.33s - 2781.29s | darkness shows up better on Windows. On Mac, it actually 2781.29s - 2784.81s | doesn't quite show up as much. But yeah, so that was a factor 2784.81s - 2788.65s | we had to kind of play around with. But yeah, I like the color 2788.65s - 2793.34s | question. I've never gotten that before. So thank you. All 2793.34s - 2795.02s | right. I think with this, we're out of time. We'll be around 2795.02s - 2796.86s | front if anyone else wants to talk or ask questions. But 2796.86s - 2798.70s | again, thank you everyone for coming to the talk. Have a good 2798.70s - 2799.50s | one.


chunk_id: 142_chunk_0
chunk_text:
{ "webpage_url": "https://www.youtube.com/watch?v=GPODCSvZMyM", "title": "DEF CON 32 - Open Sesame: how vulnerable is your stuff in electronic lockers -Dennis Giese, braelynn", "description": "Physical security is often overlooked in many organizational threat models. An increasing amount of physical security devices with smart components are being introduced to the market with widespread adoption. This creates an enticing attack surface for physical red teams.\n\nLockers and cabinets equipped with electronic smart locks can be found in many places such as offices, factories, hospitals, labs, and gyms. With remote and hybrid work increasing in popularity, shared use office setups becoming the default. Co-working spaces in offices are now commonplace with lockers being installed for employee device storage. People generally trust that their belongings will be secure in these lockers and entrust the locks with sensitive information, like their personal PIN.\n\nIs there a more stealthy way to get into lockers that don't involve using a crowbar?\n\nIn this talk we will analyze the vulnerabilities affecting locks manufactured by the \"global leader in keyless lock solutions,\" Digilock and Schulte-Schlagbaum AG (SAG). Both companies have been in the physical security industry for many decades. What went wrong in the development of these devices and how can these vulnerabilities be fixed? We will also discuss several other vendors operating in this space and compare findings.\n\nWe will demonstrate practical physical and side-channel attacks targeting locks that accept a standard PIN and RFID. Learn why it is poor practice to reuse the same secret PIN for lockers and safes and devices such as mobile phones and laptops (especially if they are stored inside the lockers).", "channel_url": "https://www.youtube.com/channel/UC6Om9kAkl32dWlDSNlDS9Iw", "duration": 2408, "channel": "DEFCONConference", "uploader": "DEFCONConference", "upload_date": "20241016" } 2.22s - 7.54s | This text was transcribed using whisper model: large-v2 Hello DEF CON! Thank you for being here on a Saturday morning. I know everyone was 7.54s - 13.14s | partying yesterday until 5 a.m. probably, so I'm glad that you're here. So yeah, now 13.14s - 18.10s | we're talking about our talk, Open CSAM or how secure is your stuff in your 18.10s - 21.14s | lockers? And this is the main question, basically, which we will talk through the 21.14s - 26.10s | talk. As you might have heard, there have been some issues with the talk in the 26.10s - 32.06s | past, so I will address it later. So before we start with the topic, let me 32.06s -


chunk_id: 142_chunk_1
chunk_text:
fixed? We will also discuss several other vendors operating in this space and compare findings.\n\nWe will demonstrate practical physical and side-channel attacks targeting locks that accept a standard PIN and RFID. Learn why it is poor practice to reuse the same secret PIN for lockers and safes and devices such as mobile phones and laptops (especially if they are stored inside the lockers).", "channel_url": "https://www.youtube.com/channel/UC6Om9kAkl32dWlDSNlDS9Iw", "duration": 2408, "channel": "DEFCONConference", "uploader": "DEFCONConference", "upload_date": "20241016" } 2.22s - 7.54s | This text was transcribed using whisper model: large-v2 Hello DEF CON! Thank you for being here on a Saturday morning. I know everyone was 7.54s - 13.14s | partying yesterday until 5 a.m. probably, so I'm glad that you're here. So yeah, now 13.14s - 18.10s | we're talking about our talk, Open CSAM or how secure is your stuff in your 18.10s - 21.14s | lockers? And this is the main question, basically, which we will talk through the 21.14s - 26.10s | talk. As you might have heard, there have been some issues with the talk in the 26.10s - 32.06s | past, so I will address it later. So before we start with the topic, let me 32.06s - 36.70s | introduce myself real quick. So I'm Dennis, I'm a security researcher or also 36.70s - 41.34s | a hardware hacker, and I basically am interested in wireless and embedded 41.34s - 44.58s | security and privacy. So I take a look at all kind of interesting devices which 44.58s - 50.18s | are around me. Primarily this is vacuum robots, but I generally like look at all 50.18s - 54.98s | kind of things. That's why I call myself also a vacuum robot and IoT collector, so 54.98s - 60.14s | I have probably way over 600-700 devices and, you know, 60 or 70 vacuum robots by 60.14s - 65.66s | now. So my main goal typically is to root vacuum robots, but, you know, again I 65.66s - 68.46s | look at all the other things. And if you're interested in vacuum robots, by the 68.46s - 72.50s | way, I have a website which documents all the, you know, hardware and 72.50s - 80.78s | everything. Yeah, one thing which is kind of new in the slides, so I have been a 80.78s - 84.78s | target of a seasoned assistant at DEF CON, so I


chunk_id: 142_chunk_2
chunk_text:
36.70s | introduce myself real quick. So I'm Dennis, I'm a security researcher or also 36.70s - 41.34s | a hardware hacker, and I basically am interested in wireless and embedded 41.34s - 44.58s | security and privacy. So I take a look at all kind of interesting devices which 44.58s - 50.18s | are around me. Primarily this is vacuum robots, but I generally like look at all 50.18s - 54.98s | kind of things. That's why I call myself also a vacuum robot and IoT collector, so 54.98s - 60.14s | I have probably way over 600-700 devices and, you know, 60 or 70 vacuum robots by 60.14s - 65.66s | now. So my main goal typically is to root vacuum robots, but, you know, again I 65.66s - 68.46s | look at all the other things. And if you're interested in vacuum robots, by the 68.46s - 72.50s | way, I have a website which documents all the, you know, hardware and 72.50s - 80.78s | everything. Yeah, one thing which is kind of new in the slides, so I have been a 80.78s - 84.78s | target of a seasoned assistant at DEF CON, so I think this is like a, you know, 84.78s - 89.14s | interesting thing. Which, by the way, was withdrawn as today in the morning or at 89.14s - 98.21s | night, so yeah. And now we would like to introduce Braylyn. Cool. Hi, I am Braylyn. 98.21s - 102.41s | I hack things for the Leviathan Security Group during the day, but I'm here 102.41s - 105.73s | representing myself as an independent security researcher, and this talk does 105.73s - 110.93s | not reflect their views. My general focus has been application security and APIs, 110.93s - 116.93s | but I've started hardware hacking for fun, looking at things like robots, 117.05s - 122.85s | cameras, and smart locks. And this is my first DEF CON talk, and I was also named 122.85s - 134.41s | in the C synthesis, so that's pretty fun. All right, so let's talk about some 134.41s - 137.65s | previous work. So this is not necessarily the first lock which we took a look at. 137.65s - 142.05s | Like exactly 10 years ago, well a little bit more than 10 years ago, I was working 142.05s - 145.73s | on a group


chunk_id: 142_chunk_3
chunk_text:
think this is like a, you know, 84.78s - 89.14s | interesting thing. Which, by the way, was withdrawn as today in the morning or at 89.14s - 98.21s | night, so yeah. And now we would like to introduce Braylyn. Cool. Hi, I am Braylyn. 98.21s - 102.41s | I hack things for the Leviathan Security Group during the day, but I'm here 102.41s - 105.73s | representing myself as an independent security researcher, and this talk does 105.73s - 110.93s | not reflect their views. My general focus has been application security and APIs, 110.93s - 116.93s | but I've started hardware hacking for fun, looking at things like robots, 117.05s - 122.85s | cameras, and smart locks. And this is my first DEF CON talk, and I was also named 122.85s - 134.41s | in the C synthesis, so that's pretty fun. All right, so let's talk about some 134.41s - 137.65s | previous work. So this is not necessarily the first lock which we took a look at. 137.65s - 142.05s | Like exactly 10 years ago, well a little bit more than 10 years ago, I was working 142.05s - 145.73s | on a group which looked at Siemens and Foss door locks, and we published a paper 145.73s - 150.93s | about that. Also some while ago I was taking a look at Schlage electronic 150.93s - 154.01s | locks, which you find especially in America, like, you know, in government 154.01s - 160.77s | buildings, universities. So what are the goals of this talk? Well, first we want 160.77s - 164.41s | to give you some overview of the reverse engineering of digilock and SAG locks. 164.41s - 169.65s | We want to tell you something about vulnerabilities, and we want to show you 169.65s - 173.13s | some ideas and methods how you can extract typically firmware and 173.13s - 177.77s | configurations from that kind of devices. One thing which is the most important 177.77s - 182.25s | part of this talk is basically we want to raise awareness about pin numbers. As 182.25s - 186.37s | a general side note, we use digilock and SAG as an example, and we are not 186.37s - 189.49s | claiming that they are more or less secure than other companies. We're kind of 189.49s - 193.09s | just unlucky that they're one of


chunk_id: 142_chunk_4
chunk_text:
which looked at Siemens and Foss door locks, and we published a paper 145.73s - 150.93s | about that. Also some while ago I was taking a look at Schlage electronic 150.93s - 154.01s | locks, which you find especially in America, like, you know, in government 154.01s - 160.77s | buildings, universities. So what are the goals of this talk? Well, first we want 160.77s - 164.41s | to give you some overview of the reverse engineering of digilock and SAG locks. 164.41s - 169.65s | We want to tell you something about vulnerabilities, and we want to show you 169.65s - 173.13s | some ideas and methods how you can extract typically firmware and 173.13s - 177.77s | configurations from that kind of devices. One thing which is the most important 177.77s - 182.25s | part of this talk is basically we want to raise awareness about pin numbers. As 182.25s - 186.37s | a general side note, we use digilock and SAG as an example, and we are not 186.37s - 189.49s | claiming that they are more or less secure than other companies. We're kind of 189.49s - 193.09s | just unlucky that they're one of the market leaders and that they build good 193.09s - 197.53s | products. So yeah, so we basically have chosen them because we have a good 197.53s - 200.61s | reputation, they have a quality of products, we just might have made some 200.61s - 205.49s | mistakes. We reported the things also to the vendors, and digilock is actively 205.49s - 209.65s | working on fixing the issues, and I will tell, give you some information later on 209.65s - 215.93s | that. So about this talk, it's basically a continuation of my Nulcon talk 215.93s - 222.21s | at Nulcon Berlin 24. The focus, and this is the important part, on offline locks 222.21s - 225.37s | which are managed. So if there's like a master key or something, if you think of 225.37s - 230.49s | a gym or, you know, master keyed systems. And we do not cover a couple things. For 230.49s - 233.41s | example, we do not cover management software, we do not cover 233.41s - 237.17s | reprovisioning, so how to, you know, factory reset the lock. We also don't 237.17s - 241.13s | talk about physical attacks using magnets or destructive


chunk_id: 142_chunk_5
chunk_text:
the market leaders and that they build good 193.09s - 197.53s | products. So yeah, so we basically have chosen them because we have a good 197.53s - 200.61s | reputation, they have a quality of products, we just might have made some 200.61s - 205.49s | mistakes. We reported the things also to the vendors, and digilock is actively 205.49s - 209.65s | working on fixing the issues, and I will tell, give you some information later on 209.65s - 215.93s | that. So about this talk, it's basically a continuation of my Nulcon talk 215.93s - 222.21s | at Nulcon Berlin 24. The focus, and this is the important part, on offline locks 222.21s - 225.37s | which are managed. So if there's like a master key or something, if you think of 225.37s - 230.49s | a gym or, you know, master keyed systems. And we do not cover a couple things. For 230.49s - 233.41s | example, we do not cover management software, we do not cover 233.41s - 237.17s | reprovisioning, so how to, you know, factory reset the lock. We also don't 237.17s - 241.13s | talk about physical attacks using magnets or destructive attacks like 241.13s - 246.13s | drilling, you know, decapping, all other kinds of things. And later on, we have 246.13s - 251.17s | included a statement of digilock in regard to their cease and desist. 251.17s - 257.01s | Alright, so what is our motivation here? So generally, back then when I was, you 257.01s - 261.89s | know, looking at locks, I realized quite quickly that hacking locks is not that, 262.41s - 267.25s | you know, new. There's a lot of people who were hacking like high security locks, so 267.25s - 270.29s | a lot of researchers were kind of focusing on that, especially like safe locks, 270.29s - 275.09s | because there's probably very important stuff in there. A lot of research has 275.09s - 279.29s | been put into side channel attacks, you know, safes contain expensive things, and 279.29s - 284.53s | the impact is like very high if they're insecure. The general problem is for, you 284.53s - 287.77s | know, manufacturers or for even companies who have this kind of devices, it's very 287.81s - 292.21s | hard to defend against physical attacks and highly motivated attackers. So if I'm an


chunk_id: 142_chunk_6
chunk_text:
attacks like 241.13s - 246.13s | drilling, you know, decapping, all other kinds of things. And later on, we have 246.13s - 251.17s | included a statement of digilock in regard to their cease and desist. 251.17s - 257.01s | Alright, so what is our motivation here? So generally, back then when I was, you 257.01s - 261.89s | know, looking at locks, I realized quite quickly that hacking locks is not that, 262.41s - 267.25s | you know, new. There's a lot of people who were hacking like high security locks, so 267.25s - 270.29s | a lot of researchers were kind of focusing on that, especially like safe locks, 270.29s - 275.09s | because there's probably very important stuff in there. A lot of research has 275.09s - 279.29s | been put into side channel attacks, you know, safes contain expensive things, and 279.29s - 284.53s | the impact is like very high if they're insecure. The general problem is for, you 284.53s - 287.77s | know, manufacturers or for even companies who have this kind of devices, it's very 287.81s - 292.21s | hard to defend against physical attacks and highly motivated attackers. So if I'm an 292.21s - 295.53s | attacker, if I have unlimited time and money, then I will get into whatever it 295.53s - 300.49s | is. In regard to consumer devices, it's slightly different. So consumer locks, 300.49s - 304.81s | safes, and cabinets are known to be bad, and there's mechanical flaws, there's 304.81s - 308.53s | trivial bypasses, you know, using magnets and other things, and there's insecure 308.53s - 313.05s | software. And I have an example here from one of my favorite YouTubers, a lock 313.05s - 316.85s | picking lawyer, where he has like a, you know, gun safe kind of thing where you 316.85s - 322.13s | put the gun in, and you just pry open the plastic handle, and you can just pull 322.13s - 327.05s | the gun out, you don't care about the lock. So, you know, sometimes you don't 327.05s - 332.21s | need to even attack locks, you know, there's other ways around that. Okay, so 332.21s - 336.29s | how did we start with this particular research? So I was at Northeastern 336.29s - 340.77s | University like around 2018, and they introduced lockers in the labs. And one 340.77s


chunk_id: 142_chunk_7
chunk_text:
292.21s - 295.53s | attacker, if I have unlimited time and money, then I will get into whatever it 295.53s - 300.49s | is. In regard to consumer devices, it's slightly different. So consumer locks, 300.49s - 304.81s | safes, and cabinets are known to be bad, and there's mechanical flaws, there's 304.81s - 308.53s | trivial bypasses, you know, using magnets and other things, and there's insecure 308.53s - 313.05s | software. And I have an example here from one of my favorite YouTubers, a lock 313.05s - 316.85s | picking lawyer, where he has like a, you know, gun safe kind of thing where you 316.85s - 322.13s | put the gun in, and you just pry open the plastic handle, and you can just pull 322.13s - 327.05s | the gun out, you don't care about the lock. So, you know, sometimes you don't 327.05s - 332.21s | need to even attack locks, you know, there's other ways around that. Okay, so 332.21s - 336.29s | how did we start with this particular research? So I was at Northeastern 336.29s - 340.77s | University like around 2018, and they introduced lockers in the labs. And one 340.77s - 344.17s | of the idea was like, you know, you can put your stuff in, and you just choose 344.17s - 347.37s | your own pen, lock it, and, you know, if you come back, you unlock it again, and 347.37s - 351.37s | the next one can use it. But also when we were traveling around, we saw like these 351.37s - 355.65s | locks in many, many co-working spaces, banks, airports, hotels, gyms, so we were 355.65s - 359.37s | literally everywhere. At some point, you develop an eye for like interesting 359.37s - 364.29s | things around you. And one thing which we figured out very quickly is 364.29s - 367.81s | there's only a few widely used vendors which are out there, so there's like, you 367.81s - 370.57s | know, the groups like in the US in particular, like the DigiLock, or like 370.89s - 375.93s | in Europe, SAG, there's some very limited kind of vendors out there. And these kind 375.93s - 379.09s | of locks, they stay for a very, very long time in use, because why would you change 379.09s - 383.01s | gym lock like, you know, after five


chunk_id: 142_chunk_8
chunk_text:
- 344.17s | of the idea was like, you know, you can put your stuff in, and you just choose 344.17s - 347.37s | your own pen, lock it, and, you know, if you come back, you unlock it again, and 347.37s - 351.37s | the next one can use it. But also when we were traveling around, we saw like these 351.37s - 355.65s | locks in many, many co-working spaces, banks, airports, hotels, gyms, so we were 355.65s - 359.37s | literally everywhere. At some point, you develop an eye for like interesting 359.37s - 364.29s | things around you. And one thing which we figured out very quickly is 364.29s - 367.81s | there's only a few widely used vendors which are out there, so there's like, you 367.81s - 370.57s | know, the groups like in the US in particular, like the DigiLock, or like 370.89s - 375.93s | in Europe, SAG, there's some very limited kind of vendors out there. And these kind 375.93s - 379.09s | of locks, they stay for a very, very long time in use, because why would you change 379.09s - 383.01s | gym lock like, you know, after five years or after four years or whatever? So these 383.01s - 386.25s | things typically stay in use like for 10 years, 20 years, until they're broken 386.25s - 392.21s | basically. Okay, the question is now why do we hack cabinet lockers or lockers 392.21s - 396.49s | generally and not safes? Well, lockers and cabinets are basically everywhere, and 396.49s - 399.97s | they're used in public spaces or spaces which are accessible to the public or 400.09s - 403.65s | shared workspaces. And there might be many reasons why you want to hack them. 403.65s - 406.85s | For example, you forgot your pin, you lost your key, or you do a red team 406.85s - 410.93s | penetration test. Also, you know, sometimes the audit locks are not super 410.93s - 415.93s | correct, so you want to, you know, correct them. And they might contain a lot of 415.93s - 418.93s | interesting stuff, and including our own. And this is like what I want to say is 418.93s - 421.49s | like, I mean, one of the reasons why we do the research is because we're kind of 421.49s - 425.33s | slightly annoyed


chunk_id: 142_chunk_9
chunk_text:
years or after four years or whatever? So these 383.01s - 386.25s | things typically stay in use like for 10 years, 20 years, until they're broken 386.25s - 392.21s | basically. Okay, the question is now why do we hack cabinet lockers or lockers 392.21s - 396.49s | generally and not safes? Well, lockers and cabinets are basically everywhere, and 396.49s - 399.97s | they're used in public spaces or spaces which are accessible to the public or 400.09s - 403.65s | shared workspaces. And there might be many reasons why you want to hack them. 403.65s - 406.85s | For example, you forgot your pin, you lost your key, or you do a red team 406.85s - 410.93s | penetration test. Also, you know, sometimes the audit locks are not super 410.93s - 415.93s | correct, so you want to, you know, correct them. And they might contain a lot of 415.93s - 418.93s | interesting stuff, and including our own. And this is like what I want to say is 418.93s - 421.49s | like, I mean, one of the reasons why we do the research is because we're kind of 421.49s - 425.33s | slightly annoyed because our stuff is also that kind of lockers, so this is one 425.33s - 428.73s | big motivation from us. So what kind of things do you might store there? 429.13s - 432.89s | Well, you might store your backpack, laptop, employee ID, phone, keys, money, 432.89s - 440.37s | credit cards, USB sticks, important documents, your bitcoins, or candy. So the 440.37s - 444.81s | question is, well, did you use the same pin which you use to lock the locker also 444.81s - 454.06s | for your phone, notebook, or credit card? Quick survey, who has a friend that does 454.18s - 462.18s | this? Who reuses their pins? No, you're not supposed to admit that. 462.18s - 464.98s | To be fair, I mean, in the beginning, before I was doing the research, I caught 464.98s - 468.30s | myself using the same pin all over again. So that, you know, it gets a little bit 468.30s - 472.74s | complicated. Anyway, so what kind of attack ideas do we have and how do we do 472.74s - 477.18s | it? So what are we looking for generally in this kind of devices? Well, we try


chunk_id: 142_chunk_10
chunk_text:
because our stuff is also that kind of lockers, so this is one 425.33s - 428.73s | big motivation from us. So what kind of things do you might store there? 429.13s - 432.89s | Well, you might store your backpack, laptop, employee ID, phone, keys, money, 432.89s - 440.37s | credit cards, USB sticks, important documents, your bitcoins, or candy. So the 440.37s - 444.81s | question is, well, did you use the same pin which you use to lock the locker also 444.81s - 454.06s | for your phone, notebook, or credit card? Quick survey, who has a friend that does 454.18s - 462.18s | this? Who reuses their pins? No, you're not supposed to admit that. 462.18s - 464.98s | To be fair, I mean, in the beginning, before I was doing the research, I caught 464.98s - 468.30s | myself using the same pin all over again. So that, you know, it gets a little bit 468.30s - 472.74s | complicated. Anyway, so what kind of attack ideas do we have and how do we do 472.74s - 477.18s | it? So what are we looking for generally in this kind of devices? Well, we try to 477.18s - 480.78s | extract somehow the firmware, because firmware can give us like some secret 480.78s - 484.98s | backdoors or bugs. It helps us to understand functionality, and it can 484.98s - 488.74s | allow also an attacker to create, you know, custom firmware. You know, like 488.74s - 493.98s | basically declouding or n-certification of smart locks. The other thing is, which 493.98s - 498.34s | is obviously the crown jewels here, is the interesting data in terms of like key 498.34s - 503.58s | IDs, user pins, RFID IDs, or log files. And the other thing, if you do 503.58s - 507.50s | lockpicking, you know it, you try to find like any easy way to bypass things and 507.50s - 512.94s | to open locks. So our idea, and this is like why we want to kind of stress on 512.94s - 516.26s | that, it's not necessary, but we want to steal your stuff. But we don't want to 516.26s - 519.78s | steal your stuff anyway, but I mean, theoretically as attackers. But lateral 519.78s - 524.26s | movement, and that's the core idea of our talk. So how do we do


chunk_id: 142_chunk_11
chunk_text:
to 477.18s - 480.78s | extract somehow the firmware, because firmware can give us like some secret 480.78s - 484.98s | backdoors or bugs. It helps us to understand functionality, and it can 484.98s - 488.74s | allow also an attacker to create, you know, custom firmware. You know, like 488.74s - 493.98s | basically declouding or n-certification of smart locks. The other thing is, which 493.98s - 498.34s | is obviously the crown jewels here, is the interesting data in terms of like key 498.34s - 503.58s | IDs, user pins, RFID IDs, or log files. And the other thing, if you do 503.58s - 507.50s | lockpicking, you know it, you try to find like any easy way to bypass things and 507.50s - 512.94s | to open locks. So our idea, and this is like why we want to kind of stress on 512.94s - 516.26s | that, it's not necessary, but we want to steal your stuff. But we don't want to 516.26s - 519.78s | steal your stuff anyway, but I mean, theoretically as attackers. But lateral 519.78s - 524.26s | movement, and that's the core idea of our talk. So how do we do it? So we have, in 524.26s - 528.66s | this particular example, three cabinets. Basically one of them is open, two of them 528.66s - 531.78s | are locked. One is locked with a pin, the other one is locked with an RFID. And so 531.78s - 535.14s | what we do is, like, we try to extract a manager key from the locker which is 535.14s - 538.62s | open. As soon as we have the manager key, this is like a key which you use to kind 538.62s - 541.58s | of unlock the locker, to audit things in there, so that there's nothing, you know, 541.58s - 546.38s | like the Defcon hotel, it's like sketchy things, your flipper. And you can lock it 546.38s - 550.50s | again without resetting the pin. So by having this manager key, what we can do 550.50s - 557.38s | is basically we can unlock other lockers, and we can extract from the lockers, like 557.38s - 561.26s | with the pin, we can extract the user pin. At the same time, we can obviously 561.26s - 564.50s | access whatever is in the locker. So if you have a


chunk_id: 142_chunk_12
chunk_text:
it? So we have, in 524.26s - 528.66s | this particular example, three cabinets. Basically one of them is open, two of them 528.66s - 531.78s | are locked. One is locked with a pin, the other one is locked with an RFID. And so 531.78s - 535.14s | what we do is, like, we try to extract a manager key from the locker which is 535.14s - 538.62s | open. As soon as we have the manager key, this is like a key which you use to kind 538.62s - 541.58s | of unlock the locker, to audit things in there, so that there's nothing, you know, 541.58s - 546.38s | like the Defcon hotel, it's like sketchy things, your flipper. And you can lock it 546.38s - 550.50s | again without resetting the pin. So by having this manager key, what we can do 550.50s - 557.38s | is basically we can unlock other lockers, and we can extract from the lockers, like 557.38s - 561.26s | with the pin, we can extract the user pin. At the same time, we can obviously 561.26s - 564.50s | access whatever is in the locker. So if you have a laptop in there, and if you 564.50s - 568.34s | have your phone in there, well, we might be able to use the pin which you use to 568.34s - 572.62s | lock the locker to, you know, unlock that. But it gets even more interesting, because 572.62s - 578.50s | well, we can also extract the RFID, you know, ID or secret, in some cases, from a 578.50s - 582.46s | lock which was used to lock the locker with an RFID or employee badge. And then 582.46s - 585.66s | we can go to an interesting door, like a server room or something, and can use that 585.66s - 590.62s | to unlock that. Especially SAG, they use test fire encryption, so they store the 590.62s - 595.62s | keys, which gets very, very interesting here. All right, so how do you get that 595.62s - 600.10s | kind of locks? What's the logistics behind that? The problem is, if you do that 600.10s - 603.78s | kind of research, you need to invest a lot of time and money, and experiments 603.78s - 607.74s | typically require multiple devices. And you obviously cannot use someone else's 607.74s


chunk_id: 142_chunk_13
chunk_text:
laptop in there, and if you 564.50s - 568.34s | have your phone in there, well, we might be able to use the pin which you use to 568.34s - 572.62s | lock the locker to, you know, unlock that. But it gets even more interesting, because 572.62s - 578.50s | well, we can also extract the RFID, you know, ID or secret, in some cases, from a 578.50s - 582.46s | lock which was used to lock the locker with an RFID or employee badge. And then 582.46s - 585.66s | we can go to an interesting door, like a server room or something, and can use that 585.66s - 590.62s | to unlock that. Especially SAG, they use test fire encryption, so they store the 590.62s - 595.62s | keys, which gets very, very interesting here. All right, so how do you get that 595.62s - 600.10s | kind of locks? What's the logistics behind that? The problem is, if you do that 600.10s - 603.78s | kind of research, you need to invest a lot of time and money, and experiments 603.78s - 607.74s | typically require multiple devices. And you obviously cannot use someone else's 607.74s - 611.46s | property, because there might be one or two bricks in the process of, like, 611.46s - 616.46s | reverse engineering that. These locks are also expensive, so typically you pay 616.50s - 621.10s | between, like, more than $100 for a lock, and more than $50 for a key, or, like, way 621.10s - 625.78s | more than $50. We will talk about that later. But the good thing was, for us, 625.78s - 630.02s | there's surplus on eBay. And it's a little mean, but COVID kind of helped us a little 630.02s - 633.30s | bit, because a lot of gyms kind of got bankrupt, so they kind of offset their 633.30s - 637.46s | locks and other things on eBay. And we got a lot of, like, cheap provisioned locks, 637.46s - 640.10s | so locks which were already provisioned through some manager key or programming 640.10s - 644.74s | key, which we were able to play around with. And the other thing is, especially 644.74s - 647.90s | in Germany, we got a lot of locks from failed projects. Basically, we have been, 647.90s - 651.02s | like, a big, like, kind of


chunk_id: 142_chunk_14
chunk_text:
- 611.46s | property, because there might be one or two bricks in the process of, like, 611.46s - 616.46s | reverse engineering that. These locks are also expensive, so typically you pay 616.50s - 621.10s | between, like, more than $100 for a lock, and more than $50 for a key, or, like, way 621.10s - 625.78s | more than $50. We will talk about that later. But the good thing was, for us, 625.78s - 630.02s | there's surplus on eBay. And it's a little mean, but COVID kind of helped us a little 630.02s - 633.30s | bit, because a lot of gyms kind of got bankrupt, so they kind of offset their 633.30s - 637.46s | locks and other things on eBay. And we got a lot of, like, cheap provisioned locks, 637.46s - 640.10s | so locks which were already provisioned through some manager key or programming 640.10s - 644.74s | key, which we were able to play around with. And the other thing is, especially 644.74s - 647.90s | in Germany, we got a lot of locks from failed projects. Basically, we have been, 647.90s - 651.02s | like, a big, like, kind of gym, which kind of, you know, didn't happen. So we had, 651.02s - 653.94s | like, stacks and stacks of these locks, and we kind of sell them on eBay for a 653.94s - 659.18s | cheap price. So we spent probably more than $1,000 or $2,000 on buying random 659.18s - 665.14s | locks, which we don't even have so many lockers for. So, as mentioned, I mean, we 665.14s - 669.74s | were going on a shopping tour on eBay, and, you know, bought, like, a lot of locks. 669.74s - 673.78s | So let's talk about the DigiLock ecosystem, and this is, like, our first 673.78s - 678.76s | candidate for which devices we looked at. So DigiLock itself, we're, like, a 678.76s - 682.54s | brand of Security People Inc., which is US-based, and they are in the industry for a 682.54s - 685.10s | very, very long time. So they're very experienced, especially also with 685.10s - 688.74s | mechanical locks. They call themselves the global leader in keyless lock 688.74s - 692.14s | solutions, and they have many different bands of locks. So they have connected 692.14s - 694.94s | locks, which we're not


chunk_id: 142_chunk_15
chunk_text:
gym, which kind of, you know, didn't happen. So we had, 651.02s - 653.94s | like, stacks and stacks of these locks, and we kind of sell them on eBay for a 653.94s - 659.18s | cheap price. So we spent probably more than $1,000 or $2,000 on buying random 659.18s - 665.14s | locks, which we don't even have so many lockers for. So, as mentioned, I mean, we 665.14s - 669.74s | were going on a shopping tour on eBay, and, you know, bought, like, a lot of locks. 669.74s - 673.78s | So let's talk about the DigiLock ecosystem, and this is, like, our first 673.78s - 678.76s | candidate for which devices we looked at. So DigiLock itself, we're, like, a 678.76s - 682.54s | brand of Security People Inc., which is US-based, and they are in the industry for a 682.54s - 685.10s | very, very long time. So they're very experienced, especially also with 685.10s - 688.74s | mechanical locks. They call themselves the global leader in keyless lock 688.74s - 692.14s | solutions, and they have many different bands of locks. So they have connected 692.14s - 694.94s | locks, which we're not talking about. We have offline locks. We have mechanical 694.94s - 699.22s | locks. And as access media, you can use, like, RFIDs, the pins, key fobs, 699.22s - 703.26s | smartphones with the newest generation. And you might see them under different 703.26s - 707.50s | brands. For example, DigiLock, Nex, Numeris, so there's different ones. If you take a 707.50s - 710.14s | look at their website, I mean, they kind of say, like, they're literally in all the 710.14s - 714.18s | industries, which is, like, I mean, that's the reason why we kind of saw them in the 714.18s - 717.58s | first place, because we're, like, in education, in gyms, in some professional 717.58s - 721.78s | sports organizations, so we're literally everywhere. The way how you can typically 721.78s - 727.14s | identify them is, this is some examples right now, by the three-pin connector, 727.14s - 730.78s | which we use, like, which is very specific for DigiLock. Other lock vendors use 730.78s - 733.42s | slightly different kind of connectors, but this is, like, a thing, if you see 733.42s - 737.18s | that, it's kind of, like, you know, kind of


chunk_id: 142_chunk_16
chunk_text:
talking about. We have offline locks. We have mechanical 694.94s - 699.22s | locks. And as access media, you can use, like, RFIDs, the pins, key fobs, 699.22s - 703.26s | smartphones with the newest generation. And you might see them under different 703.26s - 707.50s | brands. For example, DigiLock, Nex, Numeris, so there's different ones. If you take a 707.50s - 710.14s | look at their website, I mean, they kind of say, like, they're literally in all the 710.14s - 714.18s | industries, which is, like, I mean, that's the reason why we kind of saw them in the 714.18s - 717.58s | first place, because we're, like, in education, in gyms, in some professional 717.58s - 721.78s | sports organizations, so we're literally everywhere. The way how you can typically 721.78s - 727.14s | identify them is, this is some examples right now, by the three-pin connector, 727.14s - 730.78s | which we use, like, which is very specific for DigiLock. Other lock vendors use 730.78s - 733.42s | slightly different kind of connectors, but this is, like, a thing, if you see 733.42s - 737.18s | that, it's kind of, like, you know, kind of know what it is. If you take a look at 737.18s - 740.80s | the lock hardware itself, the good thing for us is that they use more or less the 740.80s - 745.50s | same or very similar hardware, so they use a similar type of MCU. So if you're 745.50s - 748.66s | kind of familiar with one of them, you kind of know how the arrows work in a way. 748.66s - 753.62s | So this makes it also a great kind of thing for us as reverse engineers. And 753.62s - 757.34s | they didn't have tamper switches, so if you just assemble one, then there's 757.34s - 760.46s | nothing which triggers, which is, by the way, very, very normal for, like, you know, 760.46s - 764.78s | kind of low security or middle security locks. Only safe locks have, like, some 764.78s - 768.38s | tamper switches and other things. The lock state is controlled by the latch, 768.38s - 770.86s | which is kind of interesting for us, and we'll kind of talk about that later. 770.86s - 775.02s | And because we have so much experience with mechanical locks, we added a


chunk_id: 142_chunk_17
chunk_text:
know what it is. If you take a look at 737.18s - 740.80s | the lock hardware itself, the good thing for us is that they use more or less the 740.80s - 745.50s | same or very similar hardware, so they use a similar type of MCU. So if you're 745.50s - 748.66s | kind of familiar with one of them, you kind of know how the arrows work in a way. 748.66s - 753.62s | So this makes it also a great kind of thing for us as reverse engineers. And 753.62s - 757.34s | they didn't have tamper switches, so if you just assemble one, then there's 757.34s - 760.46s | nothing which triggers, which is, by the way, very, very normal for, like, you know, 760.46s - 764.78s | kind of low security or middle security locks. Only safe locks have, like, some 764.78s - 768.38s | tamper switches and other things. The lock state is controlled by the latch, 768.38s - 770.86s | which is kind of interesting for us, and we'll kind of talk about that later. 770.86s - 775.02s | And because we have so much experience with mechanical locks, we added a lot of 775.02s - 778.58s | mechanical protections against physical attacks. So, for example, you cannot use, 778.58s - 782.22s | like, bypassing things. We tried a couple things with needles, so there's no way to 782.22s - 786.46s | kind of, you know, bypass things. So we did a very good job there. The features 786.50s - 790.42s | which you get per lock are kind of dependent on the brand. So some of them 790.42s - 794.18s | support audit locks, so you can basically record who opened or locked the locker. 794.18s - 799.50s | And they have assigned and shared locker functionality, which means sometimes you 799.50s - 803.90s | can give an employee just one locker and only that person can use it, or you 803.90s - 807.98s | have a scenario like in the gym. If you take a look closer at the hardware, one 807.98s - 811.18s | thing which is kind of great for us is all of them have a PIC programming 811.18s - 815.62s | interface exposed. Many of them have EEPROM. We have obviously an MCU. We have a 815.62s - 820.22s | connection to the inside unit, which


chunk_id: 142_chunk_18
chunk_text:
lot of 775.02s - 778.58s | mechanical protections against physical attacks. So, for example, you cannot use, 778.58s - 782.22s | like, bypassing things. We tried a couple things with needles, so there's no way to 782.22s - 786.46s | kind of, you know, bypass things. So we did a very good job there. The features 786.50s - 790.42s | which you get per lock are kind of dependent on the brand. So some of them 790.42s - 794.18s | support audit locks, so you can basically record who opened or locked the locker. 794.18s - 799.50s | And they have assigned and shared locker functionality, which means sometimes you 799.50s - 803.90s | can give an employee just one locker and only that person can use it, or you 803.90s - 807.98s | have a scenario like in the gym. If you take a look closer at the hardware, one 807.98s - 811.18s | thing which is kind of great for us is all of them have a PIC programming 811.18s - 815.62s | interface exposed. Many of them have EEPROM. We have obviously an MCU. We have a 815.62s - 820.22s | connection to the inside unit, which kind of contains the latch and the motor, 820.22s - 824.98s | and it gets all the power from there. We have a piezo for the sound. And the most 824.98s - 828.90s | interesting thing for us was the interface. As you see, we soldered 828.90s - 834.22s | some wires to that to kind of intercept that, which is basically one wire. 834.22s - 838.38s | Hardware-wise, if you take a closer look at the microcontrollers, we use most of 838.38s - 842.26s | the time PIC18 controllers, but sometimes, especially newer models, 842.26s - 847.70s | we use PIC24s. We have EEPROM for audit locks and for credential storage in some 847.70s - 853.10s | of them devices. And if you have a device which supports RFIDs, you have an ST 853.10s - 859.06s | kind of controller for NFCs, or the newer ones have a logic IC, which is 859.06s - 863.78s | also an HSM. And from what they told us, basically in new generations of 863.78s - 867.74s | these locks, we use the HSM to store some kind of secrets, which we can 867.74s - 872.10s | confirm because it's not on eBay


chunk_id: 142_chunk_19
chunk_text:
kind of contains the latch and the motor, 820.22s - 824.98s | and it gets all the power from there. We have a piezo for the sound. And the most 824.98s - 828.90s | interesting thing for us was the interface. As you see, we soldered 828.90s - 834.22s | some wires to that to kind of intercept that, which is basically one wire. 834.22s - 838.38s | Hardware-wise, if you take a closer look at the microcontrollers, we use most of 838.38s - 842.26s | the time PIC18 controllers, but sometimes, especially newer models, 842.26s - 847.70s | we use PIC24s. We have EEPROM for audit locks and for credential storage in some 847.70s - 853.10s | of them devices. And if you have a device which supports RFIDs, you have an ST 853.10s - 859.06s | kind of controller for NFCs, or the newer ones have a logic IC, which is 859.06s - 863.78s | also an HSM. And from what they told us, basically in new generations of 863.78s - 867.74s | these locks, we use the HSM to store some kind of secrets, which we can 867.74s - 872.10s | confirm because it's not on eBay right now, so I need to wait until it shows up 872.10s - 878.30s | on eBay. So if you look inside at the locker hardware, the thing which 878.30s - 881.18s | works for me, as someone who's doing physical security for quite a while, is 881.18s - 884.94s | it's extremely well built and engineered. And what I mentioned 884.94s - 887.82s | before is that the inside lock kind of defines if it's locked and unlocked. You 887.82s - 891.50s | have some read contacts, which are kind of sensing if the latch is 891.50s - 896.90s | locked or not locked. There's also different variants of the lock, 896.90s - 901.02s | like where everything is just in the front, and we have, again, read contacts, 901.02s - 905.10s | which kind of detect a couple things. But all of the locks have some kind of 905.10s - 910.70s | debug pins. So let's talk about the keys. So there's a bunch of keys, and you see 910.70s - 914.86s | we have a stack of them because we were going on shopping trips. The most 914.86s - 918.66s | important one is the yellow key,


chunk_id: 142_chunk_20
chunk_text:
right now, so I need to wait until it shows up 872.10s - 878.30s | on eBay. So if you look inside at the locker hardware, the thing which 878.30s - 881.18s | works for me, as someone who's doing physical security for quite a while, is 881.18s - 884.94s | it's extremely well built and engineered. And what I mentioned 884.94s - 887.82s | before is that the inside lock kind of defines if it's locked and unlocked. You 887.82s - 891.50s | have some read contacts, which are kind of sensing if the latch is 891.50s - 896.90s | locked or not locked. There's also different variants of the lock, 896.90s - 901.02s | like where everything is just in the front, and we have, again, read contacts, 901.02s - 905.10s | which kind of detect a couple things. But all of the locks have some kind of 905.10s - 910.70s | debug pins. So let's talk about the keys. So there's a bunch of keys, and you see 910.70s - 914.86s | we have a stack of them because we were going on shopping trips. The most 914.86s - 918.66s | important one is the yellow key, which is the programming key. Only one of them 918.66s - 922.46s | exists in the locking system. This is basically the main provisioning key. It 922.46s - 925.66s | allows you to add manager keys, to remove them, to overwrite the lock, so if you 925.66s - 930.22s | need to open the lock. It also is used to power deadlocks, so if the battery is 930.22s - 933.34s | empty, you can use it to power jump it. And it has some additional 933.34s - 936.22s | functions like cloning functionality, audits, and some other 936.22s - 941.26s | things. Another key which is important is the black key, which is the manager key. 941.26s - 944.54s | And this is basically, typically, your administrator or whatever has it to 944.54s - 948.62s | kind of, you know, you forgot your pin, to open the locker so that you can get 948.62s - 953.50s | your stuff, or to kind of check if you have a flipper in there, a legal flipper 953.50s - 957.18s | in there. So this is kind of things which it's used for. And one thing which is 957.18s - 960.06s | very,


chunk_id: 142_chunk_21
chunk_text:
which is the programming key. Only one of them 918.66s - 922.46s | exists in the locking system. This is basically the main provisioning key. It 922.46s - 925.66s | allows you to add manager keys, to remove them, to overwrite the lock, so if you 925.66s - 930.22s | need to open the lock. It also is used to power deadlocks, so if the battery is 930.22s - 933.34s | empty, you can use it to power jump it. And it has some additional 933.34s - 936.22s | functions like cloning functionality, audits, and some other 936.22s - 941.26s | things. Another key which is important is the black key, which is the manager key. 941.26s - 944.54s | And this is basically, typically, your administrator or whatever has it to 944.54s - 948.62s | kind of, you know, you forgot your pin, to open the locker so that you can get 948.62s - 953.50s | your stuff, or to kind of check if you have a flipper in there, a legal flipper 953.50s - 957.18s | in there. So this is kind of things which it's used for. And one thing which is 957.18s - 960.06s | very, very special for Digilock, and this is like kind of, I think, one very 960.06s - 963.98s | important feature for a lot of people, is the so-called ADA key, which is in blue. 963.98s - 969.30s | And ADA means Americans with Disabilities Act. So this key allows you 969.30s - 974.78s | basically, for people who cannot enter a pin physically, you just tap the key fob, 974.78s - 980.82s | and it will kind of act as a pin, or as a key. Yeah. So if you take a look closer 980.82s - 984.18s | into these keys, well, all of them are kind of the same. So programming the 984.18s - 986.46s | manager keys, by the way, have exactly the same hardware, just the case is 986.46s - 991.70s | different, but price-wise, they are very different. They have a battery in there, 991.70s - 995.50s | they have a PIC-18, and they have, again, very nice for us, a PIC programming 995.50s - 1001.60s | interface. The ADA key is basically an I button, which will be, later, we will use 1001.60s - 1006.54s | for some things. There's one special key, which we're


chunk_id: 142_chunk_22
chunk_text:
very special for Digilock, and this is like kind of, I think, one very 960.06s - 963.98s | important feature for a lot of people, is the so-called ADA key, which is in blue. 963.98s - 969.30s | And ADA means Americans with Disabilities Act. So this key allows you 969.30s - 974.78s | basically, for people who cannot enter a pin physically, you just tap the key fob, 974.78s - 980.82s | and it will kind of act as a pin, or as a key. Yeah. So if you take a look closer 980.82s - 984.18s | into these keys, well, all of them are kind of the same. So programming the 984.18s - 986.46s | manager keys, by the way, have exactly the same hardware, just the case is 986.46s - 991.70s | different, but price-wise, they are very different. They have a battery in there, 991.70s - 995.50s | they have a PIC-18, and they have, again, very nice for us, a PIC programming 995.50s - 1001.60s | interface. The ADA key is basically an I button, which will be, later, we will use 1001.60s - 1006.54s | for some things. There's one special key, which we're not going too deep into it, 1006.54s - 1010.38s | it's a so-called data key, and what it does is, basically, it connects over USB 1010.38s - 1014.06s | to a tablet, and you can basically use it as a programming or manager key, you can 1014.06s - 1017.18s | have, you know, audit logs, you can pull things, you can clone logs, and some other 1017.18s - 1020.82s | things. So this is like an additional thing, which I think they have in their 1020.82s - 1025.70s | fifth generation or something. It's a little more expensive, but it doesn't 1025.70s - 1031.72s | matter for us. All right, so what is the key communication between, the 1031.72s - 1035.06s | communication between lock and key? And the thing here is, which you probably 1035.06s - 1038.90s | figured out very quickly already, is OneWire. And OneWire, by the way, is a 1038.90s - 1041.62s | very standard protocol. You find it in a lot of alarm systems, you find it, like, 1041.66s - 1045.22s | if you go to a restaurant, for to unlock the cash register, and some other things, 1045.22s - 1049.86s | it's a, you


chunk_id: 142_chunk_23
chunk_text:
not going too deep into it, 1006.54s - 1010.38s | it's a so-called data key, and what it does is, basically, it connects over USB 1010.38s - 1014.06s | to a tablet, and you can basically use it as a programming or manager key, you can 1014.06s - 1017.18s | have, you know, audit logs, you can pull things, you can clone logs, and some other 1017.18s - 1020.82s | things. So this is like an additional thing, which I think they have in their 1020.82s - 1025.70s | fifth generation or something. It's a little more expensive, but it doesn't 1025.70s - 1031.72s | matter for us. All right, so what is the key communication between, the 1031.72s - 1035.06s | communication between lock and key? And the thing here is, which you probably 1035.06s - 1038.90s | figured out very quickly already, is OneWire. And OneWire, by the way, is a 1038.90s - 1041.62s | very standard protocol. You find it in a lot of alarm systems, you find it, like, 1041.66s - 1045.22s | if you go to a restaurant, for to unlock the cash register, and some other things, 1045.22s - 1049.86s | it's a, you know, it's a very standard kind of thing, which makes it great to be 1049.86s - 1052.70s | intercepted with a logic analyzer. So there's some tools out there which you 1052.70s - 1057.30s | can use to kind of basically decode the stream. They use the read ROM command to 1057.30s - 1062.62s | kind of, you know, ask the key for, like, its ID, and the key returns eight bytes 1062.62s - 1067.34s | of ID to the lock, and this is, like, basically authentication. And the key 1067.38s - 1072.10s | types are identified basically by the first byte of the ID. One thing which is, 1072.10s - 1075.26s | like, important if you want to do side-channel attacks or timing attacks, the 1075.26s - 1079.50s | bus resets after every transaction. In our talk at Nulcon, we kind of described 1079.50s - 1083.58s | how, you know, you potentially could do side-channels. One key thing to take away 1083.58s - 1087.42s | here is we don't use any crypto, so we kind of rely on whatever security 1087.42s - 1094.46s | guarantees OneWire has. All right, I want to give a quick rundown of PIC MCUs


chunk_id: 142_chunk_24
chunk_text:
know, it's a very standard kind of thing, which makes it great to be 1049.86s - 1052.70s | intercepted with a logic analyzer. So there's some tools out there which you 1052.70s - 1057.30s | can use to kind of basically decode the stream. They use the read ROM command to 1057.30s - 1062.62s | kind of, you know, ask the key for, like, its ID, and the key returns eight bytes 1062.62s - 1067.34s | of ID to the lock, and this is, like, basically authentication. And the key 1067.38s - 1072.10s | types are identified basically by the first byte of the ID. One thing which is, 1072.10s - 1075.26s | like, important if you want to do side-channel attacks or timing attacks, the 1075.26s - 1079.50s | bus resets after every transaction. In our talk at Nulcon, we kind of described 1079.50s - 1083.58s | how, you know, you potentially could do side-channels. One key thing to take away 1083.58s - 1087.42s | here is we don't use any crypto, so we kind of rely on whatever security 1087.42s - 1094.46s | guarantees OneWire has. All right, I want to give a quick rundown of PIC MCUs 1094.58s - 1098.42s | because it's kind of important to understand what's going on here. So PICs 1098.42s - 1103.10s | generally are microcontrollers by microchip. They are very common in locks, so 1103.10s - 1106.18s | literally everyone is using them. Siemens of us use them, Schlage use them, 1106.18s - 1112.10s | Kitlock uses them, so everyone uses them. And they are ideal because they are 1112.10s - 1115.42s | low-power and ideal for battery operations. There's two flavors which we 1115.42s - 1119.62s | see for DigiLock in particular, or for other locks. It's a PIC18, which is 1119.62s - 1124.90s | an 8-bit MCU, which was released back in 2000, and a PIC24, which has a 16-bit 1124.90s - 1131.26s | MCU, which has no EEPROM data on board. So basically, you can flash the firmware 1131.26s - 1135.14s | onto it, but you need to store your data somewhere else. Okay, so this is an 1135.14s - 1141.26s | example of a random PIC18. So we have some SRAM, we have flash, we have EEPROM, 1141.26s - 1145.70s | as mentioned, and they have support for some protections. For example, you can 1145.70s - 1148.46s


chunk_id: 142_chunk_25
chunk_text:
1094.58s - 1098.42s | because it's kind of important to understand what's going on here. So PICs 1098.42s - 1103.10s | generally are microcontrollers by microchip. They are very common in locks, so 1103.10s - 1106.18s | literally everyone is using them. Siemens of us use them, Schlage use them, 1106.18s - 1112.10s | Kitlock uses them, so everyone uses them. And they are ideal because they are 1112.10s - 1115.42s | low-power and ideal for battery operations. There's two flavors which we 1115.42s - 1119.62s | see for DigiLock in particular, or for other locks. It's a PIC18, which is 1119.62s - 1124.90s | an 8-bit MCU, which was released back in 2000, and a PIC24, which has a 16-bit 1124.90s - 1131.26s | MCU, which has no EEPROM data on board. So basically, you can flash the firmware 1131.26s - 1135.14s | onto it, but you need to store your data somewhere else. Okay, so this is an 1135.14s - 1141.26s | example of a random PIC18. So we have some SRAM, we have flash, we have EEPROM, 1141.26s - 1145.70s | as mentioned, and they have support for some protections. For example, you can 1145.70s - 1148.46s | enable code protection, you can enable write protection, and there's also like a 1148.46s - 1152.42s | thing which is called external block table read. And on the right, you can see 1152.42s - 1157.34s | it's like consisting of multiple blocks, and at the bottom is like the EEPROM part. 1157.34s - 1161.82s | So let's talk about the code protection. Speaking of which, code protection is, I 1161.82s - 1166.06s | think, a very PIC-specific term. If you work with other processors, you might 1166.06s - 1170.14s | know it as readout protection. And the basic idea is we have here an example 1170.14s - 1173.78s | lock, which is not an example lock, just an example chip, where the first two 1173.78s - 1177.46s | blocks are protected, the data is protected, and if you connect our 1177.46s - 1181.06s | programmer to it, what will happen is we will get, for the blocks which are 1181.06s - 1186.86s | protected, all zeros, but the blocks which are not protected, we get data back. So 1186.86s - 1190.48s | write protection, similar thing. The first two blocks are protected, the last one is 1190.48s - 1195.02s


chunk_id: 142_chunk_26
chunk_text:
| enable code protection, you can enable write protection, and there's also like a 1148.46s - 1152.42s | thing which is called external block table read. And on the right, you can see 1152.42s - 1157.34s | it's like consisting of multiple blocks, and at the bottom is like the EEPROM part. 1157.34s - 1161.82s | So let's talk about the code protection. Speaking of which, code protection is, I 1161.82s - 1166.06s | think, a very PIC-specific term. If you work with other processors, you might 1166.06s - 1170.14s | know it as readout protection. And the basic idea is we have here an example 1170.14s - 1173.78s | lock, which is not an example lock, just an example chip, where the first two 1173.78s - 1177.46s | blocks are protected, the data is protected, and if you connect our 1177.46s - 1181.06s | programmer to it, what will happen is we will get, for the blocks which are 1181.06s - 1186.86s | protected, all zeros, but the blocks which are not protected, we get data back. So 1186.86s - 1190.48s | write protection, similar thing. The first two blocks are protected, the last one is 1190.48s - 1195.02s | protected. If you try to write with our programmer something to that, the 1195.02s - 1199.66s | writes will fail for them, but the other blocks are programmed. Speaking of 1199.66s - 1205.58s | security of these chips, these MCUs, they offer basically only basic protection 1205.58s - 1209.34s | against attacks, so there's many attacks which exist for these chips, even if 1209.34s - 1215.02s | protections are enabled. There's optical laser attacks back in 2002, there's UV 1215.02s - 1219.10s | erasure attacks, there's glitching, there's like overwriting of individual 1219.10s - 1222.98s | blocks, so there's a lot of attacks out there. So a lot of people kind of 1222.98s - 1228.06s | already figured out how to break these chips. Okay, let's talk about 1228.06s - 1234.10s | the attacks. So our naive approach was like, hey, what happens if you just 1234.10s - 1237.30s | connect a debugger and we do some magic with power and other things, it's not as 1237.30s - 1243.70s | terrible as it seems, and we try to dump the MCU. We had the luck that we exposed 1243.70s - 1249.26s | the data pins, both for the locks


chunk_id: 142_chunk_27
chunk_text:
| protected. If you try to write with our programmer something to that, the 1195.02s - 1199.66s | writes will fail for them, but the other blocks are programmed. Speaking of 1199.66s - 1205.58s | security of these chips, these MCUs, they offer basically only basic protection 1205.58s - 1209.34s | against attacks, so there's many attacks which exist for these chips, even if 1209.34s - 1215.02s | protections are enabled. There's optical laser attacks back in 2002, there's UV 1215.02s - 1219.10s | erasure attacks, there's glitching, there's like overwriting of individual 1219.10s - 1222.98s | blocks, so there's a lot of attacks out there. So a lot of people kind of 1222.98s - 1228.06s | already figured out how to break these chips. Okay, let's talk about 1228.06s - 1234.10s | the attacks. So our naive approach was like, hey, what happens if you just 1234.10s - 1237.30s | connect a debugger and we do some magic with power and other things, it's not as 1237.30s - 1243.70s | terrible as it seems, and we try to dump the MCU. We had the luck that we exposed 1243.70s - 1249.26s | the data pins, both for the locks and the keys, and one thing which we found is 1249.26s - 1252.30s | basically that the protection settings which we did on the locks were very 1252.30s - 1257.54s | inconsistent. So what do we mean with that? So typically, as mentioned, if readout 1257.54s - 1261.22s | protection is enabled, you get all zeros back, like on the right 1261.22s - 1265.90s | side. And one thing which we saw very quickly is that we didn't have the right 1265.90s - 1270.02s | protection enabled, which is by itself not really an issue. But the bigger thing 1270.02s - 1273.38s | was that if you use an external EEPROM, like an external chip, but it's not 1273.38s - 1277.22s | encrypted, so you can dump it basically. And this is basically the result which 1277.22s - 1280.66s | we had for the manager keys, for the data keys, and everything. One 1280.66s - 1285.30s | thing which you will see is for most locks which use more modern 1285.30s - 1290.34s | chips, they are not protecting the code, and all of them are not protecting the 1290.34s - 1294.14s | EEPROM, which is in the case of


chunk_id: 142_chunk_28
chunk_text:
and the keys, and one thing which we found is 1249.26s - 1252.30s | basically that the protection settings which we did on the locks were very 1252.30s - 1257.54s | inconsistent. So what do we mean with that? So typically, as mentioned, if readout 1257.54s - 1261.22s | protection is enabled, you get all zeros back, like on the right 1261.22s - 1265.90s | side. And one thing which we saw very quickly is that we didn't have the right 1265.90s - 1270.02s | protection enabled, which is by itself not really an issue. But the bigger thing 1270.02s - 1273.38s | was that if you use an external EEPROM, like an external chip, but it's not 1273.38s - 1277.22s | encrypted, so you can dump it basically. And this is basically the result which 1277.22s - 1280.66s | we had for the manager keys, for the data keys, and everything. One 1280.66s - 1285.30s | thing which you will see is for most locks which use more modern 1285.30s - 1290.34s | chips, they are not protecting the code, and all of them are not protecting the 1290.34s - 1294.14s | EEPROM, which is in the case of some of them doesn't matter too much, but for 1294.14s - 1302.58s | especially the locks, it matters a lot. So what are we doing? So for unprotected 1302.58s - 1306.74s | devices which don't have any code protection enabled, we can just dump the 1306.74s - 1310.26s | the code memory and the EEPROM directly. So we need a programmer, we need some 1310.26s - 1313.06s | other hardware, but generally if you work with embedded systems, you 1313.06s - 1316.14s | know how to do that. For partially protected devices, it gets a little bit 1316.14s - 1319.34s | more tricky. So this is an example for a lock which had the first three blocks 1319.34s - 1324.46s | protected, but the code was creeping into the fourth one which was not 1324.46s - 1329.66s | protected. So what we were doing is we can dump the fourth block and you can 1329.66s - 1334.50s | put a custom dumper into that block which hopefully gets hit by some code 1334.50s - 1339.38s | or branch link, and then we can dump the other ones. There's some other methods 1339.38s - 1341.90s | out there, but because we


chunk_id: 142_chunk_29
chunk_text:
some of them doesn't matter too much, but for 1294.14s - 1302.58s | especially the locks, it matters a lot. So what are we doing? So for unprotected 1302.58s - 1306.74s | devices which don't have any code protection enabled, we can just dump the 1306.74s - 1310.26s | the code memory and the EEPROM directly. So we need a programmer, we need some 1310.26s - 1313.06s | other hardware, but generally if you work with embedded systems, you 1313.06s - 1316.14s | know how to do that. For partially protected devices, it gets a little bit 1316.14s - 1319.34s | more tricky. So this is an example for a lock which had the first three blocks 1319.34s - 1324.46s | protected, but the code was creeping into the fourth one which was not 1324.46s - 1329.66s | protected. So what we were doing is we can dump the fourth block and you can 1329.66s - 1334.50s | put a custom dumper into that block which hopefully gets hit by some code 1334.50s - 1339.38s | or branch link, and then we can dump the other ones. There's some other methods 1339.38s - 1341.90s | out there, but because we kind of cash-strapped and don't want to spend 1341.90s - 1344.98s | too much time on buying more locks of the same kind of thing and 1344.98s - 1348.34s | hoping that it's the same firmware, this is basically one of the 1348.34s - 1353.26s | things you can do. Otherwise you can just access the EEPROM data directly, so 1353.26s - 1358.10s | it's the same as the other ones. We described this attack at NuCon in the 1358.10s - 1361.42s | talk, so if you're interested in that, but it's a very generic attack, it's kind of 1361.42s - 1366.78s | well-known for quite a while. So basically the firmware extraction can 1366.78s - 1371.14s | be successful for all the locks, so we can get back the firmware. You can 1371.14s - 1374.10s | analyze the firmware, you can modify it if you want, you can basically load it 1374.26s - 1379.02s | into GDRAW because it has big support. There's no real signatures, integrity 1379.02s - 1382.74s | checks, which is kind of normal for that kind of thing, and the methods are well 1382.74s - 1387.98s | established. But the thing for us is we


chunk_id: 142_chunk_30
chunk_text:
kind of cash-strapped and don't want to spend 1341.90s - 1344.98s | too much time on buying more locks of the same kind of thing and 1344.98s - 1348.34s | hoping that it's the same firmware, this is basically one of the 1348.34s - 1353.26s | things you can do. Otherwise you can just access the EEPROM data directly, so 1353.26s - 1358.10s | it's the same as the other ones. We described this attack at NuCon in the 1358.10s - 1361.42s | talk, so if you're interested in that, but it's a very generic attack, it's kind of 1361.42s - 1366.78s | well-known for quite a while. So basically the firmware extraction can 1366.78s - 1371.14s | be successful for all the locks, so we can get back the firmware. You can 1371.14s - 1374.10s | analyze the firmware, you can modify it if you want, you can basically load it 1374.26s - 1379.02s | into GDRAW because it has big support. There's no real signatures, integrity 1379.02s - 1382.74s | checks, which is kind of normal for that kind of thing, and the methods are well 1382.74s - 1387.98s | established. But the thing for us is we don't necessarily need to 1387.98s - 1390.62s | even look at the firmware if you have the data, so that's just a thing. 1390.62s - 1394.54s | So let's talk about the EEPROM contents, because that's where the cron jewels are. 1394.54s - 1398.74s | One thing is it requires quite a while and a lot of trial and error to 1398.74s - 1401.62s | figure out which data fields are for what, especially if you have only 1401.66s - 1404.22s | provisioned locks and you don't have clean locks which are provisioned, 1404.22s - 1408.34s | you kind of see what the differences are. And the data fields also differ 1408.34s - 1411.62s | slightly between lock generations and between lock types, so this is not 1411.62s - 1414.90s | accurate for other locks, it's just one example for an older fourth 1414.90s - 1418.78s | generation lock. But what we see typically is we have a partial 1418.78s - 1422.66s | programming ID, we see the amount of manager keys, we see what kind of 1422.66s - 1428.86s | manager key is provisioned on that, we see if a pin was set, ADA key ID, 1428.98s - 1435.98s


chunk_id: 142_chunk_31
chunk_text:
don't necessarily need to 1387.98s - 1390.62s | even look at the firmware if you have the data, so that's just a thing. 1390.62s - 1394.54s | So let's talk about the EEPROM contents, because that's where the cron jewels are. 1394.54s - 1398.74s | One thing is it requires quite a while and a lot of trial and error to 1398.74s - 1401.62s | figure out which data fields are for what, especially if you have only 1401.66s - 1404.22s | provisioned locks and you don't have clean locks which are provisioned, 1404.22s - 1408.34s | you kind of see what the differences are. And the data fields also differ 1408.34s - 1411.62s | slightly between lock generations and between lock types, so this is not 1411.62s - 1414.90s | accurate for other locks, it's just one example for an older fourth 1414.90s - 1418.78s | generation lock. But what we see typically is we have a partial 1418.78s - 1422.66s | programming ID, we see the amount of manager keys, we see what kind of 1422.66s - 1428.86s | manager key is provisioned on that, we see if a pin was set, ADA key ID, 1428.98s - 1435.98s | or RFID UID, so if you tap the RFID. And there's also failed pin counter, 1435.98s - 1438.66s | and for older locks, bad things might happen if you run over that. 1438.66s - 1445.06s | Just don't. As a general observation, some locks don't wipe the user pin 1445.06s - 1449.58s | or the key after it had been unlocked by the user, and some, especially 1449.58s - 1452.14s | newer versions do, so at some point I think we figured out there's a problem 1452.14s - 1454.30s | and we kind of fixed that. 1454.30s - 1457.02s | All right, so let's talk about emulation and cloning keys. 1457.34s - 1462.54s | And this kind of thing applies to both RFIDs and keys, so we only need 1462.54s - 1467.66s | the ID basically to clone the key, and we cannot extract from the key 1467.66s - 1472.18s | or the flash depending on what kind of media we have. And we can emulate 1472.18s - 1477.94s | it with an Arduino, with a Flipper Zero, or in case of RFIDs with a Proxmark. 1477.94s - 1481.02s | The thing is it looks a little bit easy,


chunk_id: 142_chunk_32
chunk_text:
| or RFID UID, so if you tap the RFID. And there's also failed pin counter, 1435.98s - 1438.66s | and for older locks, bad things might happen if you run over that. 1438.66s - 1445.06s | Just don't. As a general observation, some locks don't wipe the user pin 1445.06s - 1449.58s | or the key after it had been unlocked by the user, and some, especially 1449.58s - 1452.14s | newer versions do, so at some point I think we figured out there's a problem 1452.14s - 1454.30s | and we kind of fixed that. 1454.30s - 1457.02s | All right, so let's talk about emulation and cloning keys. 1457.34s - 1462.54s | And this kind of thing applies to both RFIDs and keys, so we only need 1462.54s - 1467.66s | the ID basically to clone the key, and we cannot extract from the key 1467.66s - 1472.18s | or the flash depending on what kind of media we have. And we can emulate 1472.18s - 1477.94s | it with an Arduino, with a Flipper Zero, or in case of RFIDs with a Proxmark. 1477.94s - 1481.02s | The thing is it looks a little bit easy, but you have to kind of build 1481.02s - 1484.98s | like a custom PCB which does a couple things to kind of wake up the lock 1484.98s - 1487.90s | in a particular way, so it's not as trivial as you can do it right now. 1487.90s - 1490.70s | You need to kind of put some effort into that, so don't go home and just 1490.70s - 1493.22s | program an Arduino. It won't work. 1493.22s - 1496.66s | All right, what kind of other ideas could you have if you want to attack them? 1496.66s - 1499.78s | Well, you could try to brute force pins and keys, which works for older locks 1499.78s - 1503.26s | very well, but for newer locks not so much. You can do side-channel attacks, 1503.26s - 1505.82s | which works for all of them as far as we know, but it's very complicated, 1505.82s - 1509.66s | takes like days. You can clone the lock configuration by one wire if you have 1509.66s - 1514.38s | a valid key, and you can try to modify the contents of EEPROMs. 1514.38s - 1517.74s | Also, you could think of like building


chunk_id: 142_chunk_33
chunk_text:
but you have to kind of build 1481.02s - 1484.98s | like a custom PCB which does a couple things to kind of wake up the lock 1484.98s - 1487.90s | in a particular way, so it's not as trivial as you can do it right now. 1487.90s - 1490.70s | You need to kind of put some effort into that, so don't go home and just 1490.70s - 1493.22s | program an Arduino. It won't work. 1493.22s - 1496.66s | All right, what kind of other ideas could you have if you want to attack them? 1496.66s - 1499.78s | Well, you could try to brute force pins and keys, which works for older locks 1499.78s - 1503.26s | very well, but for newer locks not so much. You can do side-channel attacks, 1503.26s - 1505.82s | which works for all of them as far as we know, but it's very complicated, 1505.82s - 1509.66s | takes like days. You can clone the lock configuration by one wire if you have 1509.66s - 1514.38s | a valid key, and you can try to modify the contents of EEPROMs. 1514.38s - 1517.74s | Also, you could think of like building a malicious firmware. 1517.74s - 1521.94s | We thought about that, but I mean, it's not really necessary to do. 1521.94s - 1524.66s | If you're interested in the first two attacks, you can take a look at the 1524.66s - 1529.86s | slides at NuCon. Now probably one of the reasons why you guys are here is the 1529.86s - 1534.06s | cease and desist incident. So our talk was basically meant to be on Friday 1534.06s - 1539.46s | at 11 a.m., and the day before at 2 p.m., we basically got an email, 1539.46s - 1542.42s | cease and desist, which kind of came to a couple of things, like copyright act, 1542.42s - 1546.78s | Defend Trade Secrets Act, you know, obviously other things like the Computer 1546.78s - 1551.46s | Fraud and Abuse Act and the DMCA. And the interesting thing here is, 1551.46s - 1556.66s | and I want to especially thank Corey to kind of connect us so quickly, 1556.66s - 1561.42s | who's sitting in the front. Thank you. By 3.30, basically slightly more than an 1561.42s - 1564.82s | hour later, we were sitting already in a hotel room and talking


chunk_id: 142_chunk_34
chunk_text:
a malicious firmware. 1517.74s - 1521.94s | We thought about that, but I mean, it's not really necessary to do. 1521.94s - 1524.66s | If you're interested in the first two attacks, you can take a look at the 1524.66s - 1529.86s | slides at NuCon. Now probably one of the reasons why you guys are here is the 1529.86s - 1534.06s | cease and desist incident. So our talk was basically meant to be on Friday 1534.06s - 1539.46s | at 11 a.m., and the day before at 2 p.m., we basically got an email, 1539.46s - 1542.42s | cease and desist, which kind of came to a couple of things, like copyright act, 1542.42s - 1546.78s | Defend Trade Secrets Act, you know, obviously other things like the Computer 1546.78s - 1551.46s | Fraud and Abuse Act and the DMCA. And the interesting thing here is, 1551.46s - 1556.66s | and I want to especially thank Corey to kind of connect us so quickly, 1556.66s - 1561.42s | who's sitting in the front. Thank you. By 3.30, basically slightly more than an 1561.42s - 1564.82s | hour later, we were sitting already in a hotel room and talking to lawyers from the 1564.82s - 1570.30s | EFF and also from Kurt, and we were basically figuring out what was going on. 1570.30s - 1573.66s | And so to kind of, because it was very short notice, we kind of moved the talk 1573.66s - 1576.62s | from Friday to Sunday. We probably could have given the talk on Friday, 1576.62s - 1580.46s | but we decided like, okay, it might be worth to kind of figure out what's going on. 1580.46s - 1583.62s | On Saturday, so yesterday, we had a phone call in both of everyone. 1583.62s - 1587.42s | We kind of exchanged views. We kind of resolved our differences. 1587.42s - 1590.18s | And in that call, we kind of pulled the cease and desist back. 1590.18s - 1593.18s | And officially today, shortly after midnight, we got like the withdrawal 1593.18s - 1597.70s | in writing for the cease and desist. One thing which I want to quickly say is 1597.90s - 1600.78s | there's like a kind of official response from DigiLog. 1600.78s - 1603.50s | They kind of acknowledged that we communicated with them prior to DEF CON. 1603.50s - 1607.94s |


chunk_id: 142_chunk_35
chunk_text:
to lawyers from the 1564.82s - 1570.30s | EFF and also from Kurt, and we were basically figuring out what was going on. 1570.30s - 1573.66s | And so to kind of, because it was very short notice, we kind of moved the talk 1573.66s - 1576.62s | from Friday to Sunday. We probably could have given the talk on Friday, 1576.62s - 1580.46s | but we decided like, okay, it might be worth to kind of figure out what's going on. 1580.46s - 1583.62s | On Saturday, so yesterday, we had a phone call in both of everyone. 1583.62s - 1587.42s | We kind of exchanged views. We kind of resolved our differences. 1587.42s - 1590.18s | And in that call, we kind of pulled the cease and desist back. 1590.18s - 1593.18s | And officially today, shortly after midnight, we got like the withdrawal 1593.18s - 1597.70s | in writing for the cease and desist. One thing which I want to quickly say is 1597.90s - 1600.78s | there's like a kind of official response from DigiLog. 1600.78s - 1603.50s | They kind of acknowledged that we communicated with them prior to DEF CON. 1603.50s - 1607.94s | We gave them the slides even, which was maybe a mistake, maybe not. 1607.94s - 1611.94s | They promised to do some improvements. For example, they want to enable code 1611.94s - 1615.70s | protection on their logs. For the data blocks, they want to enable 1615.70s - 1619.98s | for the firmware. They want to encrypt somehow the 1619.98s - 1625.18s | communication between the keys and the log so that you cannot clone the UID 1625.18s - 1629.02s | anymore, and they want to encrypt EEPROM data if it's external. 1629.02s - 1633.30s | They also told us that in over 32 years, we'd had no reported security incidents 1633.30s - 1636.46s | due to a hacked log, which I think, I believe. 1636.46s - 1642.14s | And they're also very committed to the security solution for their customers. 1642.14s - 1645.30s | And I put their full statement, which they sent us, on slide 70. 1645.30s - 1649.06s | So if you look later on the slides, you'll find it in the back. 1649.06s - 1652.42s | All right, that's all for DigiLog. Let's move on with the next company 1652.46s - 1656.90s | and Brayden. 1656.90s


chunk_id: 142_chunk_36
chunk_text:
We gave them the slides even, which was maybe a mistake, maybe not. 1607.94s - 1611.94s | They promised to do some improvements. For example, they want to enable code 1611.94s - 1615.70s | protection on their logs. For the data blocks, they want to enable 1615.70s - 1619.98s | for the firmware. They want to encrypt somehow the 1619.98s - 1625.18s | communication between the keys and the log so that you cannot clone the UID 1625.18s - 1629.02s | anymore, and they want to encrypt EEPROM data if it's external. 1629.02s - 1633.30s | They also told us that in over 32 years, we'd had no reported security incidents 1633.30s - 1636.46s | due to a hacked log, which I think, I believe. 1636.46s - 1642.14s | And they're also very committed to the security solution for their customers. 1642.14s - 1645.30s | And I put their full statement, which they sent us, on slide 70. 1645.30s - 1649.06s | So if you look later on the slides, you'll find it in the back. 1649.06s - 1652.42s | All right, that's all for DigiLog. Let's move on with the next company 1652.46s - 1656.90s | and Brayden. 1656.90s - 1661.58s | Cool. So let's shift gears and talk about a couple of other brands that we took 1661.58s - 1667.94s | a look at as far as logger locks go. The first one being Schulte Schlagbaum AG. 1667.94s - 1672.54s | So this is a German company. They've been in business since 1833, 1672.54s - 1676.46s | so quite an old company. These are more widely used in Europe 1676.46s - 1679.78s | and Germany. They produce both mechanic and electronic 1679.78s - 1682.42s | logger locks. We took a look at the brand called 1682.42s - 1688.98s | Safotronic. They also produce door locks, but we didn't take a look at those. 1688.98s - 1692.82s | We think they might be on the same platform, but we're not entirely sure. 1692.82s - 1700.02s | So the electronic locks accept both PIN and RFIDs or RFID plus PINs as access 1700.02s - 1704.30s | mediums, and they do provide audit log support. 1704.30s - 1709.90s | So let's talk about the LS series of locks. These are based on the STM32 MCU, 1709.90s - 1714.18s | and they also have SPI EEPROM. As for security, we found that


chunk_id: 142_chunk_37
chunk_text:
- 1661.58s | Cool. So let's shift gears and talk about a couple of other brands that we took 1661.58s - 1667.94s | a look at as far as logger locks go. The first one being Schulte Schlagbaum AG. 1667.94s - 1672.54s | So this is a German company. They've been in business since 1833, 1672.54s - 1676.46s | so quite an old company. These are more widely used in Europe 1676.46s - 1679.78s | and Germany. They produce both mechanic and electronic 1679.78s - 1682.42s | logger locks. We took a look at the brand called 1682.42s - 1688.98s | Safotronic. They also produce door locks, but we didn't take a look at those. 1688.98s - 1692.82s | We think they might be on the same platform, but we're not entirely sure. 1692.82s - 1700.02s | So the electronic locks accept both PIN and RFIDs or RFID plus PINs as access 1700.02s - 1704.30s | mediums, and they do provide audit log support. 1704.30s - 1709.90s | So let's talk about the LS series of locks. These are based on the STM32 MCU, 1709.90s - 1714.18s | and they also have SPI EEPROM. As for security, we found that SWD 1714.18s - 1719.30s | and debugging was not disabled, and their EEPROM is not encrypted. 1719.30s - 1724.10s | And we noticed a lack of physical tamper switches in the locks. 1724.10s - 1729.10s | So as you can see, these are PCBs for three different locks. 1729.10s - 1735.02s | We think that they tried to save money by using the same design for nearly a decade. 1735.02s - 1738.86s | They use the same PCB, but they leave ICs unpopulated. 1738.86s - 1745.22s | So if you buy a lock that has PIN support, you'll get an MCU for the keypad and a 1745.22s - 1752.10s | different MCU for RFID, and you'll get both for the RFID and PIN-supported locks. 1752.10s - 1757.46s | We also noted a difference in SPI EEPROM sizes. 1757.46s - 1765.58s | Okay, so let's talk about the management keys for some of the RFID SAG locks. 1765.58s - 1771.90s | So their RFID locks support MyFair Classic, MyFair DeskFire, and some ISO-compatible tags. 1771.90s - 1776.38s | For the higher-end locks, there are special RFID keys that are required for programming. 1776.38s - 1781.70s | There's a master key 1


chunk_id: 142_chunk_38
chunk_text:
SWD 1714.18s - 1719.30s | and debugging was not disabled, and their EEPROM is not encrypted. 1719.30s - 1724.10s | And we noticed a lack of physical tamper switches in the locks. 1724.10s - 1729.10s | So as you can see, these are PCBs for three different locks. 1729.10s - 1735.02s | We think that they tried to save money by using the same design for nearly a decade. 1735.02s - 1738.86s | They use the same PCB, but they leave ICs unpopulated. 1738.86s - 1745.22s | So if you buy a lock that has PIN support, you'll get an MCU for the keypad and a 1745.22s - 1752.10s | different MCU for RFID, and you'll get both for the RFID and PIN-supported locks. 1752.10s - 1757.46s | We also noted a difference in SPI EEPROM sizes. 1757.46s - 1765.58s | Okay, so let's talk about the management keys for some of the RFID SAG locks. 1765.58s - 1771.90s | So their RFID locks support MyFair Classic, MyFair DeskFire, and some ISO-compatible tags. 1771.90s - 1776.38s | For the higher-end locks, there are special RFID keys that are required for programming. 1776.38s - 1781.70s | There's a master key 1 and 2. Those are used for unlocking and relocking lockers. 1781.70s - 1786.30s | There's also a data RFID tag for data transport, if you need to, like, 1786.30s - 1791.58s | pull audit logs off of certain locks. There's also, like, a physical communicator device, 1791.58s - 1795.82s | which is, like, an advanced handheld programmer, but we didn't take a look at that. 1795.82s - 1802.86s | We tried to procure a set of these programming keys, but they were $1,400 for eight MyFair 1802.86s - 1810.74s | Classic tags, so we didn't think it was worth the money, so we didn't take a look at those. 1810.74s - 1816.98s | So just a quick overview on how we dumped EEPROM contents, just using an SOIC clip. 1816.98s - 1823.22s | We were able to interface with the EEPROM and dump the context, as you can see in the hex file. 1823.22s - 1828.98s | We were able to pull the master pin and the user set pin, so this is just totally unencrypted 1828.98s - 1835.54s | EEPROM with pins that are available for anyone who can read it to see it. 1835.54s - 1839.06s | We


chunk_id: 142_chunk_39
chunk_text:
and 2. Those are used for unlocking and relocking lockers. 1781.70s - 1786.30s | There's also a data RFID tag for data transport, if you need to, like, 1786.30s - 1791.58s | pull audit logs off of certain locks. There's also, like, a physical communicator device, 1791.58s - 1795.82s | which is, like, an advanced handheld programmer, but we didn't take a look at that. 1795.82s - 1802.86s | We tried to procure a set of these programming keys, but they were $1,400 for eight MyFair 1802.86s - 1810.74s | Classic tags, so we didn't think it was worth the money, so we didn't take a look at those. 1810.74s - 1816.98s | So just a quick overview on how we dumped EEPROM contents, just using an SOIC clip. 1816.98s - 1823.22s | We were able to interface with the EEPROM and dump the context, as you can see in the hex file. 1823.22s - 1828.98s | We were able to pull the master pin and the user set pin, so this is just totally unencrypted 1828.98s - 1835.54s | EEPROM with pins that are available for anyone who can read it to see it. 1835.54s - 1839.06s | We also found that there are audit logs on the EEPROM as well. 1839.06s - 1845.66s | There are 500 entries, including a timestamp and a status code, with the status code 50 1845.66s - 1851.62s | allowing you to see used pins and the RFID UIDs that have been used, so the last 500 1851.62s - 1856.18s | you can see, yeah, all of that. 1856.18s - 1858.14s | So how did we extract firmware? 1858.14s - 1864.50s | We noticed on the PCB there was solder mask covering the SWD, like, copper pads, so we 1864.50s - 1869.98s | scratched that off and we were able to interface with it and connect to SWD, and that allowed 1869.98s - 1874.94s | us to see that the devs didn't set the read protection byte. 1874.94s - 1880.20s | And as such, we were able to get the full firmware from these locks. 1880.20s - 1884.36s | So there are a couple of physical flaws on these locks. 1884.36s - 1889.20s | We noticed that the motor power wires and potentially debug pins are accessible from 1889.20s - 1894.68s | outside of the lock through, like, a clipped plastic cover. 1894.68s


chunk_id: 142_chunk_40
chunk_text:
also found that there are audit logs on the EEPROM as well. 1839.06s - 1845.66s | There are 500 entries, including a timestamp and a status code, with the status code 50 1845.66s - 1851.62s | allowing you to see used pins and the RFID UIDs that have been used, so the last 500 1851.62s - 1856.18s | you can see, yeah, all of that. 1856.18s - 1858.14s | So how did we extract firmware? 1858.14s - 1864.50s | We noticed on the PCB there was solder mask covering the SWD, like, copper pads, so we 1864.50s - 1869.98s | scratched that off and we were able to interface with it and connect to SWD, and that allowed 1869.98s - 1874.94s | us to see that the devs didn't set the read protection byte. 1874.94s - 1880.20s | And as such, we were able to get the full firmware from these locks. 1880.20s - 1884.36s | So there are a couple of physical flaws on these locks. 1884.36s - 1889.20s | We noticed that the motor power wires and potentially debug pins are accessible from 1889.20s - 1894.68s | outside of the lock through, like, a clipped plastic cover. 1894.68s - 1904.64s | So there's just a huge gap, as you can see, the power wires to the actual, like, motor. 1904.64s - 1909.52s | And yeah, as you can see on the right, we were able to fit a whole card under there, 1909.52s - 1917.08s | so that might allow us to tamper with the lock motor and do some physical hacking there. 1917.08s - 1923.32s | So we'll talk about a couple of other manufacturers now, one of them being Compex Security Company. 1923.32s - 1928.44s | This is a U.S. company founded in 1903, so again, another pretty old company. 1928.44s - 1930.64s | We took a look at the regulator series. 1930.64s - 1936.64s | These use the PIC-16 MCU, and these locks accept user pins, technician pins, master 1936.64s - 1941.88s | pins, and there is some audit logging support for some models. 1941.88s - 1946.44s | As for security, we found that code data and write protection were enabled on all these 1946.44s - 1949.24s | locks, so that's good for them, but not very fun for us. 1949.24s - 1954.56s | So we kind of moved on, but we took a look


chunk_id: 142_chunk_41
chunk_text:
- 1904.64s | So there's just a huge gap, as you can see, the power wires to the actual, like, motor. 1904.64s - 1909.52s | And yeah, as you can see on the right, we were able to fit a whole card under there, 1909.52s - 1917.08s | so that might allow us to tamper with the lock motor and do some physical hacking there. 1917.08s - 1923.32s | So we'll talk about a couple of other manufacturers now, one of them being Compex Security Company. 1923.32s - 1928.44s | This is a U.S. company founded in 1903, so again, another pretty old company. 1928.44s - 1930.64s | We took a look at the regulator series. 1930.64s - 1936.64s | These use the PIC-16 MCU, and these locks accept user pins, technician pins, master 1936.64s - 1941.88s | pins, and there is some audit logging support for some models. 1941.88s - 1946.44s | As for security, we found that code data and write protection were enabled on all these 1946.44s - 1949.24s | locks, so that's good for them, but not very fun for us. 1949.24s - 1954.56s | So we kind of moved on, but we took a look at their documentation and saw what they were 1954.56s - 1960.72s | using for a programming slash audit tool, an Excel spreadsheet. 1960.72s - 1965.28s | I don't know what kind of Excel macro hell is happening here. 1965.28s - 1969.96s | I'm glad I'm not the person who has to maintain this and write this, but if it works for them, 1969.96s - 1973.56s | I'm happy for them. 1973.56s - 1975.64s | So next we'll talk about Kitlock. 1975.64s - 1978.54s | This is a sub-brand of CodeLocks. 1978.54s - 1981.84s | This is a U.K.-based company founded in 1991. 1981.84s - 1988.96s | This also uses the PIC-16 MCU and again accepts user pins, technician pins, and master pins, 1988.96s - 1994.96s | and again, they had code data and write protection enabled, so good for them, not fun for us. 1994.96s - 2001.72s | So for good measure, we took a look at a couple of no-name RFID locks from Amazon and eBay. 2001.72s - 2004.44s | These are just like $20 locks, super cheap. 2004.44s - 2009.68s | We took them apart and found that they had EEPROM and some kind of mystery MCU. 2009.68s


chunk_id: 142_chunk_42
chunk_text:
at their documentation and saw what they were 1954.56s - 1960.72s | using for a programming slash audit tool, an Excel spreadsheet. 1960.72s - 1965.28s | I don't know what kind of Excel macro hell is happening here. 1965.28s - 1969.96s | I'm glad I'm not the person who has to maintain this and write this, but if it works for them, 1969.96s - 1973.56s | I'm happy for them. 1973.56s - 1975.64s | So next we'll talk about Kitlock. 1975.64s - 1978.54s | This is a sub-brand of CodeLocks. 1978.54s - 1981.84s | This is a U.K.-based company founded in 1991. 1981.84s - 1988.96s | This also uses the PIC-16 MCU and again accepts user pins, technician pins, and master pins, 1988.96s - 1994.96s | and again, they had code data and write protection enabled, so good for them, not fun for us. 1994.96s - 2001.72s | So for good measure, we took a look at a couple of no-name RFID locks from Amazon and eBay. 2001.72s - 2004.44s | These are just like $20 locks, super cheap. 2004.44s - 2009.68s | We took them apart and found that they had EEPROM and some kind of mystery MCU. 2009.68s - 2015.08s | If you like mystery MCUs and know what this is, let us know. 2015.08s - 2023.84s | Obviously, you can't really have many expectations of security on these cheap devices, so there's 2023.84s - 2031.12s | no encryption, no protection, and plain text RFID UIDs are just there for anyone to read it. 2031.20s - 2038.80s | Okay, so we're going to do a quick demo now to show how you can hack some of these locks. 2038.80s - 2044.12s | All right, due to the season, we will change the demo slightly, so usually we were kind 2044.12s - 2048.84s | of thinking of doing a whole rundown of how we can extract manager keys and other things. 2048.84s - 2053.20s | What I would do instead is I would showcase our custom PCB, which we built ourselves and 2053.20s - 2055.44s | took us some time to develop it. 2055.44s - 2059.44s | What it basically does is it emulates the same function as a manager key, so I will 2059.44s - 2060.44s | just show you. 2060.44s - 2064.84s | I locked all the lockers from DigiLock in this case, and I will just


chunk_id: 142_chunk_43
chunk_text:
- 2015.08s | If you like mystery MCUs and know what this is, let us know. 2015.08s - 2023.84s | Obviously, you can't really have many expectations of security on these cheap devices, so there's 2023.84s - 2031.12s | no encryption, no protection, and plain text RFID UIDs are just there for anyone to read it. 2031.20s - 2038.80s | Okay, so we're going to do a quick demo now to show how you can hack some of these locks. 2038.80s - 2044.12s | All right, due to the season, we will change the demo slightly, so usually we were kind 2044.12s - 2048.84s | of thinking of doing a whole rundown of how we can extract manager keys and other things. 2048.84s - 2053.20s | What I would do instead is I would showcase our custom PCB, which we built ourselves and 2053.20s - 2055.44s | took us some time to develop it. 2055.44s - 2059.44s | What it basically does is it emulates the same function as a manager key, so I will 2059.44s - 2060.44s | just show you. 2060.44s - 2064.84s | I locked all the lockers from DigiLock in this case, and I will just kind of show how 2064.84s - 2067.76s | I can hopefully open them again. 2067.76s - 2068.76s | Yeah. 2068.76s - 2075.92s | Okay, just like a quick example of a theoretical scenario, so we're going to assume that the 2075.92s - 2084.00s | attacker has access to any open locker or cabinet with the tools, the microchip picket 2084.00s - 2088.64s | three debugger, a Phillips screwdriver, and an Arduino and or flipper. 2088.64s - 2099.92s | We're using the flipper here, so our criminal has already set the key onto the flipper, 2099.92s - 2104.95s | and we are able to access the locks. 2104.95s - 2110.95s | Yeah, so to be fair, we put a lot of effort into figuring it out already, so this is like 2110.95s - 2115.77s | basically if you got access to a lock, you somehow extracted that, you built that kind 2115.77s - 2116.77s | of tool. 2116.77s - 2121.29s | It's a magic back side which we don't show. 2121.29s - 2123.33s | The attack will work very quickly after that. 2123.33s - 2126.77s | Now the obvious thing is if you want to extract secrets from these locks, you


chunk_id: 142_chunk_44
chunk_text:
kind of show how 2064.84s - 2067.76s | I can hopefully open them again. 2067.76s - 2068.76s | Yeah. 2068.76s - 2075.92s | Okay, just like a quick example of a theoretical scenario, so we're going to assume that the 2075.92s - 2084.00s | attacker has access to any open locker or cabinet with the tools, the microchip picket 2084.00s - 2088.64s | three debugger, a Phillips screwdriver, and an Arduino and or flipper. 2088.64s - 2099.92s | We're using the flipper here, so our criminal has already set the key onto the flipper, 2099.92s - 2104.95s | and we are able to access the locks. 2104.95s - 2110.95s | Yeah, so to be fair, we put a lot of effort into figuring it out already, so this is like 2110.95s - 2115.77s | basically if you got access to a lock, you somehow extracted that, you built that kind 2115.77s - 2116.77s | of tool. 2116.77s - 2121.29s | It's a magic back side which we don't show. 2121.29s - 2123.33s | The attack will work very quickly after that. 2123.33s - 2126.77s | Now the obvious thing is if you want to extract secrets from these locks, you need to kind 2126.77s - 2129.05s | of disassemble them, so you need a screwdriver. 2129.05s - 2131.81s | The locks which are kind of just having the front part are super annoying because you 2131.81s - 2137.97s | need a very special key to unscrew them, but generally, to open and relock them again without 2137.97s - 2142.49s | resetting the original pin, that's basically all you need, but this might take you some 2142.49s - 2143.49s | time to do. 2143.49s - 2144.49s | All right. 2144.49s - 2149.29s | So with that, for that, let's go to the conclusion. 2149.29s - 2150.45s | Okay. 2150.45s - 2157.45s | In summary, we were able to extract firmware and keys from these brands of locks, so access 2157.45s - 2163.49s | to one lock can give you access to all locks in one system or one location. 2163.49s - 2169.87s | Cloning and emulating keys is possible, and these attacks don't require complicated tools 2169.87s - 2172.37s | and are sometimes cheap unless you're using the flipper. 2172.37s - 2174.81s | It's a little bit more expensive, but... 2174.81s - 2178.29s | So how secure is your stuff in


chunk_id: 142_chunk_45
chunk_text:
need to kind 2126.77s - 2129.05s | of disassemble them, so you need a screwdriver. 2129.05s - 2131.81s | The locks which are kind of just having the front part are super annoying because you 2131.81s - 2137.97s | need a very special key to unscrew them, but generally, to open and relock them again without 2137.97s - 2142.49s | resetting the original pin, that's basically all you need, but this might take you some 2142.49s - 2143.49s | time to do. 2143.49s - 2144.49s | All right. 2144.49s - 2149.29s | So with that, for that, let's go to the conclusion. 2149.29s - 2150.45s | Okay. 2150.45s - 2157.45s | In summary, we were able to extract firmware and keys from these brands of locks, so access 2157.45s - 2163.49s | to one lock can give you access to all locks in one system or one location. 2163.49s - 2169.87s | Cloning and emulating keys is possible, and these attacks don't require complicated tools 2169.87s - 2172.37s | and are sometimes cheap unless you're using the flipper. 2172.37s - 2174.81s | It's a little bit more expensive, but... 2174.81s - 2178.29s | So how secure is your stuff in electronic lockers? 2178.29s - 2183.13s | Not super secure, but we need to be fair because these locks are not being sold as high-security 2183.13s - 2184.37s | devices. 2184.37s - 2187.65s | They're not promising, like, military-grade security or anything. 2187.65s - 2190.93s | These are just standard-use locks. 2190.93s - 2193.49s | So how can we fix this? 2193.49s - 2197.37s | Of course, we would recommend a security-by-design approach from the beginning. 2197.37s - 2201.85s | So enable all security features and always expect physical attacks when you're producing 2201.85s - 2203.69s | locks. 2203.69s - 2207.13s | Encrypt your secrets, store them in a secure way. 2207.13s - 2211.29s | So the best solution for vulnerable locks would be to have firmware updates for all 2211.29s - 2216.73s | of them, but depending on the age of the locks, this might not be possible, and it's... 2216.73s - 2217.73s | We... 2217.73s - 2220.03s | In our opinion, it seems unfixable. 2220.03s - 2224.47s | So the workaround could be to use a programmer to enable code protection, but this only works 2224.55s - 2228.67s | if data is stored on the MCU and not on


chunk_id: 142_chunk_46
chunk_text:
electronic lockers? 2178.29s - 2183.13s | Not super secure, but we need to be fair because these locks are not being sold as high-security 2183.13s - 2184.37s | devices. 2184.37s - 2187.65s | They're not promising, like, military-grade security or anything. 2187.65s - 2190.93s | These are just standard-use locks. 2190.93s - 2193.49s | So how can we fix this? 2193.49s - 2197.37s | Of course, we would recommend a security-by-design approach from the beginning. 2197.37s - 2201.85s | So enable all security features and always expect physical attacks when you're producing 2201.85s - 2203.69s | locks. 2203.69s - 2207.13s | Encrypt your secrets, store them in a secure way. 2207.13s - 2211.29s | So the best solution for vulnerable locks would be to have firmware updates for all 2211.29s - 2216.73s | of them, but depending on the age of the locks, this might not be possible, and it's... 2216.73s - 2217.73s | We... 2217.73s - 2220.03s | In our opinion, it seems unfixable. 2220.03s - 2224.47s | So the workaround could be to use a programmer to enable code protection, but this only works 2224.55s - 2228.67s | if data is stored on the MCU and not on an external EEPROM chip. 2228.67s - 2235.31s | So this task is kind of complicated for an average and non-tech-savvy user, so it's not 2235.31s - 2237.15s | a reasonable expectation. 2237.15s - 2241.45s | So the likely solution would be to buy new locks or just ignore the problem and hope 2241.45s - 2245.15s | it goes away. 2245.15s - 2247.43s | So takeaway lessons. 2247.43s - 2252.87s | Please don't reuse your important pins for lockers, like, public-use lockers. 2252.87s - 2257.11s | Again, don't reuse your pins for your debit cards, your phone. 2257.11s - 2258.11s | Use separate things. 2258.11s - 2259.11s | Use, like... 2259.11s - 2263.75s | We're all using separate passwords now for everything, I hope. 2263.75s - 2269.15s | So treat your pin like a password, and never loan out your electronic keys, and always 2269.15s - 2274.95s | be aware of security limitations of devices, and you cannot trust audit logs of these devices 2274.95s - 2277.27s | because they can be tampered with. 2277.27s - 2281.95s | So even experienced and big companies make mistakes, and developing stuff is way harder 2282.03s - 2288.47s | than breaking it in 90%


chunk_id: 142_chunk_47
chunk_text:
an external EEPROM chip. 2228.67s - 2235.31s | So this task is kind of complicated for an average and non-tech-savvy user, so it's not 2235.31s - 2237.15s | a reasonable expectation. 2237.15s - 2241.45s | So the likely solution would be to buy new locks or just ignore the problem and hope 2241.45s - 2245.15s | it goes away. 2245.15s - 2247.43s | So takeaway lessons. 2247.43s - 2252.87s | Please don't reuse your important pins for lockers, like, public-use lockers. 2252.87s - 2257.11s | Again, don't reuse your pins for your debit cards, your phone. 2257.11s - 2258.11s | Use separate things. 2258.11s - 2259.11s | Use, like... 2259.11s - 2263.75s | We're all using separate passwords now for everything, I hope. 2263.75s - 2269.15s | So treat your pin like a password, and never loan out your electronic keys, and always 2269.15s - 2274.95s | be aware of security limitations of devices, and you cannot trust audit logs of these devices 2274.95s - 2277.27s | because they can be tampered with. 2277.27s - 2281.95s | So even experienced and big companies make mistakes, and developing stuff is way harder 2282.03s - 2288.47s | than breaking it in 90% of cases, so be nice to developers. 2288.47s - 2291.11s | It's hard when people are attacking your stuff. 2291.11s - 2295.19s | And always remember there might be interesting cyber-physical systems around you. 2295.19s - 2298.05s | So don't forget the human factor. 2298.05s - 2302.67s | Can you just ask nicely for the manager key? 2302.67s - 2304.27s | So final notes. 2304.27s - 2306.63s | Please don't break into lockers you don't own. 2306.63s - 2312.87s | I know these systems are in a lot of places, hotels and such, but please don't. 2312.87s - 2316.91s | Anything with these locks can also permanently break them, which is kind of the standard 2316.91s - 2318.71s | expectation when you're hardware hacking. 2318.71s - 2321.27s | You can always break things quite easily. 2321.27s - 2322.27s | Be careful. 2322.27s - 2325.97s | There are more attacks that we haven't covered here. 2325.97s - 2331.47s | And other companies and products are possibly vulnerable too, and just because they claim 2331.47s - 2337.11s | that they've never been hacked doesn't mean they're unhackable, of course. 2337.11s - 2338.11s | And yeah. 2338.11s - 2339.11s | Thanks, all. 2339.39s


chunk_id: 142_chunk_48
chunk_text:
of cases, so be nice to developers. 2288.47s - 2291.11s | It's hard when people are attacking your stuff. 2291.11s - 2295.19s | And always remember there might be interesting cyber-physical systems around you. 2295.19s - 2298.05s | So don't forget the human factor. 2298.05s - 2302.67s | Can you just ask nicely for the manager key? 2302.67s - 2304.27s | So final notes. 2304.27s - 2306.63s | Please don't break into lockers you don't own. 2306.63s - 2312.87s | I know these systems are in a lot of places, hotels and such, but please don't. 2312.87s - 2316.91s | Anything with these locks can also permanently break them, which is kind of the standard 2316.91s - 2318.71s | expectation when you're hardware hacking. 2318.71s - 2321.27s | You can always break things quite easily. 2321.27s - 2322.27s | Be careful. 2322.27s - 2325.97s | There are more attacks that we haven't covered here. 2325.97s - 2331.47s | And other companies and products are possibly vulnerable too, and just because they claim 2331.47s - 2337.11s | that they've never been hacked doesn't mean they're unhackable, of course. 2337.11s - 2338.11s | And yeah. 2338.11s - 2339.11s | Thanks, all. 2339.39s - 2340.39s | Cool. 2345.69s - 2350.49s | So I would like to also give special thanks to Cori, who kind of connected us with Dolores, 2350.49s - 2356.89s | to Tara, who did that too, to our console, Hannah and Kurt, and to Andrew, and everyone 2356.89s - 2357.89s | at EFF. 2357.89s - 2364.93s | And this kind of gave me, again, a motivation to definitely donate a lot of money to EFF. 2364.93s - 2370.51s | One maybe side story is that Braylon was at B-Sides before this event and was getting 2370.51s - 2374.11s | a membership for EFF and was kind of joking, like, oh, we might need you tomorrow. 2374.11s - 2379.67s | And lo and behold, literally one day after that, on her birthday, of all the facts, both 2379.67s - 2381.59s | of us got a cease and desist letter. 2381.59s - 2384.51s | So if you have questions, we might be still around here. 2384.51s - 2388.15s | Otherwise, feel free to contact us. 2388.15s - 2390.55s | And thank you very much for being here. 2390.55s - 2391.83s | Right. 2391.83s - 2395.43s | So yeah, if you also want


chunk_id: 142_chunk_49
chunk_text:
- 2340.39s | Cool. 2345.69s - 2350.49s | So I would like to also give special thanks to Cori, who kind of connected us with Dolores, 2350.49s - 2356.89s | to Tara, who did that too, to our console, Hannah and Kurt, and to Andrew, and everyone 2356.89s - 2357.89s | at EFF. 2357.89s - 2364.93s | And this kind of gave me, again, a motivation to definitely donate a lot of money to EFF. 2364.93s - 2370.51s | One maybe side story is that Braylon was at B-Sides before this event and was getting 2370.51s - 2374.11s | a membership for EFF and was kind of joking, like, oh, we might need you tomorrow. 2374.11s - 2379.67s | And lo and behold, literally one day after that, on her birthday, of all the facts, both 2379.67s - 2381.59s | of us got a cease and desist letter. 2381.59s - 2384.51s | So if you have questions, we might be still around here. 2384.51s - 2388.15s | Otherwise, feel free to contact us. 2388.15s - 2390.55s | And thank you very much for being here. 2390.55s - 2391.83s | Right. 2391.83s - 2395.43s | So yeah, if you also want to read the statement, it will be in the slides. 2395.43s - 2398.83s | And I hope we will find a solution also to kind of fix the older locks. 2398.83s - 2402.07s | So there's probably a way we will figure it out together. 2402.07s - 2402.27s | Thank you.


chunk_id: 142_chunk_50
chunk_text:
to read the statement, it will be in the slides. 2395.43s - 2398.83s | And I hope we will find a solution also to kind of fix the older locks. 2398.83s - 2402.07s | So there's probably a way we will figure it out together. 2402.07s - 2402.27s | Thank you.


chunk_id: 143_chunk_0
chunk_text:
{ "webpage_url": "https://www.youtube.com/watch?v=4xjRgr4dbzU", "title": "DEF CON 32 - 1 for All, All for WHAD: wireless shenanigans made easy - Romain Cayre, Damien Cauquil", "description": "A lot of security research have recently focused on various wireless communication protocols, targeting smartphones, wireless mice and keyboards and even cars. In order to demonstrate these attacks, researchers developed dedicated tools that for most of them include some specialized firmware of their own but also rely on various unique custom host/device communication protocols. These tools work great but are strongly tied to some specific hardware that at some point will not be available anymore, or require hackers to buy more hardware to carry on to have fun with. Why not making these tools compatible with more hardware ? And why researchers always have to create their own host/device protocol when it comes to using a dedicated hardware ? Why not having one flexible protocol and related tools to rule them all ?\n\nWe will present in this talk WHAD, a framework that provides an extensible host/device communication protocol, dedicated protocol stacks and way more for hackers who love having fun with wireless protocols. WHAD makes interoperability possible between tools by allowing different hardware devices to be used if they provide the required capabilities, giving the opportunity to create advanced tools without having to care about the hardware and its firmware in most of the cases!", "channel_url": "https://www.youtube.com/channel/UC6Om9kAkl32dWlDSNlDS9Iw", "duration": 2680, "channel": "DEFCONConference", "uploader": "DEFCONConference", "upload_date": "20241016" } 0.05s - 6.99s | This text was transcribed using whisper model: large-v2 the way from France. One for all and all for WHD wireless shenanigans made easy. Please 6.99s - 14.08s | welcome to the stage Damian and Roman. 14.08s - 22.15s | Hello DEF CON. Ok so this is uh last talk for today on this track and we are going to 22.15s - 29.09s | present you uh something we've been working on uh since more than two years now and this 29.09s - 40.07s | is what? Oh. As usual. Ok so uh let me introduce ourselves. I'm Damian, Damian Coquille from 40.07s - 44.87s | Squawk- Squawkstab. I'm the maintainer of a tool called B-T-E-L-E-J-A-C-K or B-T-E-L-E-J-A-C-K 44.87s - 51.11s | call it what you want. Uh this is a BLE Swiss Army- Swiss Army tool and uh I love reversing 51.11s - 56.75s | stuff as well on embedded systems. And this is Roman, the


chunk_id: 143_chunk_1
chunk_text:
used if they provide the required capabilities, giving the opportunity to create advanced tools without having to care about the hardware and its firmware in most of the cases!", "channel_url": "https://www.youtube.com/channel/UC6Om9kAkl32dWlDSNlDS9Iw", "duration": 2680, "channel": "DEFCONConference", "uploader": "DEFCONConference", "upload_date": "20241016" } 0.05s - 6.99s | This text was transcribed using whisper model: large-v2 the way from France. One for all and all for WHD wireless shenanigans made easy. Please 6.99s - 14.08s | welcome to the stage Damian and Roman. 14.08s - 22.15s | Hello DEF CON. Ok so this is uh last talk for today on this track and we are going to 22.15s - 29.09s | present you uh something we've been working on uh since more than two years now and this 29.09s - 40.07s | is what? Oh. As usual. Ok so uh let me introduce ourselves. I'm Damian, Damian Coquille from 40.07s - 44.87s | Squawk- Squawkstab. I'm the maintainer of a tool called B-T-E-L-E-J-A-C-K or B-T-E-L-E-J-A-C-K 44.87s - 51.11s | call it what you want. Uh this is a BLE Swiss Army- Swiss Army tool and uh I love reversing 51.11s - 56.75s | stuff as well on embedded systems. And this is Roman, the maintainer of Mirage, another 56.75s - 62.75s | BLE Swiss Army tool but not only BLE does ZigBee and some other protocol as well. And uh he 62.75s - 67.23s | loves cross pro- cross protocol attacks and we are going to talk a bit uh about this later in 67.23s - 72.23s | the talk. So what is what and why we had to create this uh framework? So basically wireless 76.27s - 81.33s | tools are a mess. A lot of researchers did a lot of research on wireless protocols and they 81.33s - 86.35s | create a lot of tools. Different tools with different protocols and different devices and 86.35s - 91.65s | different firmwares. Uh each firmware communicates with a host or a computer with a- a 91.65s - 97.19s | specific protocol designed by uh each person. And basically everyone reverses the wheel 97.19s - 102.19s | because why not? And if you are into, yep, if you are into wireless protocol hacking, you may 105.33s - 110.71s | have to use a lot of different tools. So for BLE the classic tools B-T-E-L-E-J-A-C-K, 111.03s - 118.15s | Mirage, uh Gattacurl, SniffID, uh are the


chunk_id: 143_chunk_2
chunk_text:
maintainer of Mirage, another 56.75s - 62.75s | BLE Swiss Army tool but not only BLE does ZigBee and some other protocol as well. And uh he 62.75s - 67.23s | loves cross pro- cross protocol attacks and we are going to talk a bit uh about this later in 67.23s - 72.23s | the talk. So what is what and why we had to create this uh framework? So basically wireless 76.27s - 81.33s | tools are a mess. A lot of researchers did a lot of research on wireless protocols and they 81.33s - 86.35s | create a lot of tools. Different tools with different protocols and different devices and 86.35s - 91.65s | different firmwares. Uh each firmware communicates with a host or a computer with a- a 91.65s - 97.19s | specific protocol designed by uh each person. And basically everyone reverses the wheel 97.19s - 102.19s | because why not? And if you are into, yep, if you are into wireless protocol hacking, you may 105.33s - 110.71s | have to use a lot of different tools. So for BLE the classic tools B-T-E-L-E-J-A-C-K, 111.03s - 118.15s | Mirage, uh Gattacurl, SniffID, uh are the best way to to capture information and test some 118.15s - 123.15s | devices. And in the end you end up with a lot of devices. So if you want to be able to tackle 125.59s - 132.09s | with all these protocols, you need to buy at least all of these. And the problem is um that it 132.09s - 138.03s | takes a lot of space. It costs a lot uh as well. And most of this hardware uh can be 138.05s - 144.05s | discontinued at any time. So if you want to to hack some wireless protocol, there is this tiny 144.05s - 149.73s | hardware you didn't buy 2 years ago. And it's the only hardware that is supported for hacking 149.73s - 155.17s | this specific protocol. So that's uh that's a shame. And basically this is just a waste of 155.17s - 159.97s | time. And because uh you need to create a different uh each researcher create different 159.97s - 166.31s | firmware and uh um each researcher or each person hacking, trying to hack a wireless 166.33s - 171.63s | protocol, uh is going to face the same issues other people


chunk_id: 143_chunk_3
chunk_text:
best way to to capture information and test some 118.15s - 123.15s | devices. And in the end you end up with a lot of devices. So if you want to be able to tackle 125.59s - 132.09s | with all these protocols, you need to buy at least all of these. And the problem is um that it 132.09s - 138.03s | takes a lot of space. It costs a lot uh as well. And most of this hardware uh can be 138.05s - 144.05s | discontinued at any time. So if you want to to hack some wireless protocol, there is this tiny 144.05s - 149.73s | hardware you didn't buy 2 years ago. And it's the only hardware that is supported for hacking 149.73s - 155.17s | this specific protocol. So that's uh that's a shame. And basically this is just a waste of 155.17s - 159.97s | time. And because uh you need to create a different uh each researcher create different 159.97s - 166.31s | firmware and uh um each researcher or each person hacking, trying to hack a wireless 166.33s - 171.63s | protocol, uh is going to face the same issues other people have already had before and uh with the 171.63s - 177.51s | same solution as well. And uh all of this in fact creates fragmentation. And uh this is uh this is 177.51s - 188.07s | not good for us uh this kind of fragmentation. So we uh talked a lot together and uh we try to find 191.35s - 197.35s | a solution to solve this fragmentation issue. So uh it leads us to uh come with a solution to 199.03s - 207.03s | three main ideas. So uh the first one uh would be to design uh communication protocol for the 208.83s - 215.33s | communication between the host and uh the hardware that would be extensible. And either it is that 215.33s - 220.91s | would support multiple wireless protocols, multiple physical layers uh at the same time. And of 220.93s - 228.93s | course uh that could be open source and easy to extend. Uh the second uh big idea uh would be to 230.67s - 238.67s | create a set of libraries, a framework, and basically a wall ecosystem uh that will allow uh some 239.51s - 247.51s | reuse of uh various ready to


chunk_id: 143_chunk_4
chunk_text:
have already had before and uh with the 171.63s - 177.51s | same solution as well. And uh all of this in fact creates fragmentation. And uh this is uh this is 177.51s - 188.07s | not good for us uh this kind of fragmentation. So we uh talked a lot together and uh we try to find 191.35s - 197.35s | a solution to solve this fragmentation issue. So uh it leads us to uh come with a solution to 199.03s - 207.03s | three main ideas. So uh the first one uh would be to design uh communication protocol for the 208.83s - 215.33s | communication between the host and uh the hardware that would be extensible. And either it is that 215.33s - 220.91s | would support multiple wireless protocols, multiple physical layers uh at the same time. And of 220.93s - 228.93s | course uh that could be open source and easy to extend. Uh the second uh big idea uh would be to 230.67s - 238.67s | create a set of libraries, a framework, and basically a wall ecosystem uh that will allow uh some 239.51s - 247.51s | reuse of uh various ready to use features for different hardware, different platforms. And that 247.55s - 255.55s | be available both for the host and the firmware. And uh the third main uh idea we came with is uh that 258.47s - 266.47s | for uh these two works uh it must uh from the beginning encourage the interoperability and the 266.47s - 274.47s | collaboration between researchers. So uh it motivated us to build everything as open source software 274.55s - 282.55s | to uh easily document both the use of the tools but also uh its design. So uh here comes the main uh 288.09s - 296.09s | part uh of WAD for this project which is the WAD protocol. So we have several guidelines that have 296.67s - 302.67s | motivated uh its development. So first uh it's a standardized protocol so we properly define the 304.71s - 312.71s | it. Everything uh is uh documented and explained. It's uh generic so it covers uh a set of wireless 313.59s - 321.59s | capabilities that are uh already uh in the ecosystem. It's modular so you can support multiple uh 322.25s - 329.53s | wireless protocols. Uh and uh if you want


chunk_id: 143_chunk_5
chunk_text:
use features for different hardware, different platforms. And that 247.55s - 255.55s | be available both for the host and the firmware. And uh the third main uh idea we came with is uh that 258.47s - 266.47s | for uh these two works uh it must uh from the beginning encourage the interoperability and the 266.47s - 274.47s | collaboration between researchers. So uh it motivated us to build everything as open source software 274.55s - 282.55s | to uh easily document both the use of the tools but also uh its design. So uh here comes the main uh 288.09s - 296.09s | part uh of WAD for this project which is the WAD protocol. So we have several guidelines that have 296.67s - 302.67s | motivated uh its development. So first uh it's a standardized protocol so we properly define the 304.71s - 312.71s | it. Everything uh is uh documented and explained. It's uh generic so it covers uh a set of wireless 313.59s - 321.59s | capabilities that are uh already uh in the ecosystem. It's modular so you can support multiple uh 322.25s - 329.53s | wireless protocols. Uh and uh if you want to add more and put your own, it's a protocol which is 329.57s - 337.57s | evolutive. So the protocol has been designed to be easily extended and improved over time. And finally 337.57s - 346.55s | uh we also tried to make it as user friendly as possible. So uh we developed a set of C, C++, and 346.55s - 354.55s | Python parsing libraries uh allowing to facilitate uh its integration into uh your firmware uh and so on. 355.35s - 366.35s | So another uh key uh idea behind WAD is uh to offload most of the complexity from the firmware side to 366.35s - 374.37s | the uh outside. So of course on the firmware side we have some CPU uh some memory limitations. And so 374.37s - 384.37s | the idea was uh to keep only uh what is uh needed. So some atomic uh wireless primitives uh as basic as 384.43s - 391.43s | possible. Uh and of course the operations that are time critical and that could not be offloaded to the 391.43s - 397.91s | host. So for example the channel opening, this kind of stuff. So we keep uh a minimal


chunk_id: 143_chunk_6
chunk_text:
to add more and put your own, it's a protocol which is 329.57s - 337.57s | evolutive. So the protocol has been designed to be easily extended and improved over time. And finally 337.57s - 346.55s | uh we also tried to make it as user friendly as possible. So uh we developed a set of C, C++, and 346.55s - 354.55s | Python parsing libraries uh allowing to facilitate uh its integration into uh your firmware uh and so on. 355.35s - 366.35s | So another uh key uh idea behind WAD is uh to offload most of the complexity from the firmware side to 366.35s - 374.37s | the uh outside. So of course on the firmware side we have some CPU uh some memory limitations. And so 374.37s - 384.37s | the idea was uh to keep only uh what is uh needed. So some atomic uh wireless primitives uh as basic as 384.43s - 391.43s | possible. Uh and of course the operations that are time critical and that could not be offloaded to the 391.43s - 397.91s | host. So for example the channel opening, this kind of stuff. So we keep uh a minimal logic in the 397.91s - 404.89s | firmware and all the attack, the protocol stacks, the packet detectors and so on are implemented on the 404.89s - 415.89s | host. So finally uh WAD has been designed uh not only uh for hackers even if we are in a hacker 415.89s - 423.89s | conference. But uh also for uh everyone. So if you are a security researcher uh you can use it. If you are 423.89s - 431.91s | just a wireless uh enthusiast and you want to control uh your IoT devices. Uh or if you are just uh a 432.03s - 442.20s | curious user and you want to understand how uh your favorite wireless toy uh works. 442.20s - 448.84s | Alright so uh what is WAD in fact? Uh Romain introduced the main concepts behind this uh this 448.84s - 454.82s | framework. But in fact uh technically uh first the name. Because you know when you start a project you 454.82s - 461.06s | get you got to find a name. And it's always a pain in the ass to find something yeah meaningful. Uh so 461.10s - 466.44s | WAD stands originally for


chunk_id: 143_chunk_7
chunk_text:
logic in the 397.91s - 404.89s | firmware and all the attack, the protocol stacks, the packet detectors and so on are implemented on the 404.89s - 415.89s | host. So finally uh WAD has been designed uh not only uh for hackers even if we are in a hacker 415.89s - 423.89s | conference. But uh also for uh everyone. So if you are a security researcher uh you can use it. If you are 423.89s - 431.91s | just a wireless uh enthusiast and you want to control uh your IoT devices. Uh or if you are just uh a 432.03s - 442.20s | curious user and you want to understand how uh your favorite wireless toy uh works. 442.20s - 448.84s | Alright so uh what is WAD in fact? Uh Romain introduced the main concepts behind this uh this 448.84s - 454.82s | framework. But in fact uh technically uh first the name. Because you know when you start a project you 454.82s - 461.06s | get you got to find a name. And it's always a pain in the ass to find something yeah meaningful. Uh so 461.10s - 466.44s | WAD stands originally for Wireless Hacking Devices because it was uh supposed to support a lot of 466.44s - 473.32s | wireless uh uh so a lot of devices to hack into wireless protocols. And after having used this 473.32s - 480.72s | project uh during more than a year uh yeah wireless hacking for them is also a great name because it's 480.72s - 487.42s | uh makes things easier. And we are going to show that in multiple demos. Uh like Romain said it's 487.42s - 492.14s | more than a protocol uh because designing a protocol a communication protocol between a host and a 492.14s - 498.50s | device that's a thing. And this is something uh we we already did uh two of us uh for our respective 498.50s - 505.64s | tools. But in fact providing uh uh an ecosystem with uh the protocol all libraries in Python and in C 505.64s - 511.92s | and C++ that you can embed in your firmware and use to communicate with the host without having uh you 511.92s - 519.30s | know uh without worrying about how the data is encoded and so on. This is uh this is a lifesaver.


chunk_id: 143_chunk_8
chunk_text:
Wireless Hacking Devices because it was uh supposed to support a lot of 466.44s - 473.32s | wireless uh uh so a lot of devices to hack into wireless protocols. And after having used this 473.32s - 480.72s | project uh during more than a year uh yeah wireless hacking for them is also a great name because it's 480.72s - 487.42s | uh makes things easier. And we are going to show that in multiple demos. Uh like Romain said it's 487.42s - 492.14s | more than a protocol uh because designing a protocol a communication protocol between a host and a 492.14s - 498.50s | device that's a thing. And this is something uh we we already did uh two of us uh for our respective 498.50s - 505.64s | tools. But in fact providing uh uh an ecosystem with uh the protocol all libraries in Python and in C 505.64s - 511.92s | and C++ that you can embed in your firmware and use to communicate with the host without having uh you 511.92s - 519.30s | know uh without worrying about how the data is encoded and so on. This is uh this is a lifesaver. Uh 519.30s - 526.34s | you when you develop a firmware compatible with this uh ecosystem you the only thing you need to worry 526.34s - 533.64s | about is the specific code that runs and that handles all the radio frequency stuff. And uh also we 533.64s - 540.42s | provide a lot of tools uh command line interface tools and uh maybe some are more evolved and provide 540.42s - 546.50s | more features. But if you want to create all your own applications based on a web on this ecosystem you 546.50s - 553.64s | can do as do it as well. And you can just use the Python client library and use it uh yeah. It's very 553.64s - 559.94s | simple to to develop something. From the protocol perspective it's based on protocol buffers. So yeah 559.94s - 567.52s | no surprise here. And um the protocol has been thought uh in a way that the uh host can query the 567.52s - 574.90s | device uh about what uh the devices or capabilities are. And so basically the each device compatible 574.90s - 581.44s | device can announce itself to the uh what ecosystem


chunk_id: 143_chunk_9
chunk_text:
Uh 519.30s - 526.34s | you when you develop a firmware compatible with this uh ecosystem you the only thing you need to worry 526.34s - 533.64s | about is the specific code that runs and that handles all the radio frequency stuff. And uh also we 533.64s - 540.42s | provide a lot of tools uh command line interface tools and uh maybe some are more evolved and provide 540.42s - 546.50s | more features. But if you want to create all your own applications based on a web on this ecosystem you 546.50s - 553.64s | can do as do it as well. And you can just use the Python client library and use it uh yeah. It's very 553.64s - 559.94s | simple to to develop something. From the protocol perspective it's based on protocol buffers. So yeah 559.94s - 567.52s | no surprise here. And um the protocol has been thought uh in a way that the uh host can query the 567.52s - 574.90s | device uh about what uh the devices or capabilities are. And so basically the each device compatible 574.90s - 581.44s | device can announce itself to the uh what ecosystem and especially to the host. Telling okay I I 581.44s - 587.58s | support this protocol uh I can do this with this protocol packet injection or just sniffing scanning 587.58s - 596.16s | anything. And the host adapts uh the the tools based on the uh capabilities announced by the device. And 596.16s - 601.64s | this is a discovery protocol that has been included in WAD. And this one is mandatory for any device. Uh you 601.64s - 610.48s | can have uh uh some hardware on the ZigBee protocol and the BLE or or even just modulation modulation 610.48s - 616.68s | and demodulation as well. Uh but in fact you can have some you can have multiple protocols supported by a 616.68s - 625.12s | single device with using this uh this system. Um we created a lot of firmware uh a lot of firmware. We 625.12s - 631.46s | actually we support uh if you have a look at the top uh top half of the screen. We support basically 631.46s - 639.90s | and natively four devices. Um some of them are based on Nordic Semiconductor NRF52 uh system and 639.90s - 649.72s |


chunk_id: 143_chunk_10
chunk_text:
and especially to the host. Telling okay I I 581.44s - 587.58s | support this protocol uh I can do this with this protocol packet injection or just sniffing scanning 587.58s - 596.16s | anything. And the host adapts uh the the tools based on the uh capabilities announced by the device. And 596.16s - 601.64s | this is a discovery protocol that has been included in WAD. And this one is mandatory for any device. Uh you 601.64s - 610.48s | can have uh uh some hardware on the ZigBee protocol and the BLE or or even just modulation modulation 610.48s - 616.68s | and demodulation as well. Uh but in fact you can have some you can have multiple protocols supported by a 616.68s - 625.12s | single device with using this uh this system. Um we created a lot of firmware uh a lot of firmware. We 625.12s - 631.46s | actually we support uh if you have a look at the top uh top half of the screen. We support basically 631.46s - 639.90s | and natively four devices. Um some of them are based on Nordic Semiconductor NRF52 uh system and 639.90s - 649.72s | chips. Uh so basically the there is the ESP32WROOM from Espressif. The Nucleo WL55 which is uh uh 649.72s - 658.36s | LoRa and the Sigfox uh transceiver from STMicro uh that's supported. And uh also yeah I told you about the NRF52. 658.36s - 665.66s | But the most interesting part is that we uh managed to create some uh adaptation layer between WAD and the old 665.66s - 673.48s | tools such as the uh Yardstick one or the Herbatools. And in fact we we we can use all these old devices if you 673.48s - 680.44s | can say with WAD. And this is totally transparent for you. So it's uh just it appears like a classic WAD tool or WAD 680.44s - 689.67s | device and you can use it to do whatever you want. The WAD protocol supports a lot of uh modulations uh file 689.67s - 697.35s | layers and other protocols. So basically this is the FSK, GFSK, MSK modulation on the physical layer. Uh so you can 697.35s - 703.69s | do demodulate and modulate signals using your specific device. And uh obviously the BLE protocol ZigBee and so on 703.69s -


chunk_id: 143_chunk_11
chunk_text:
chips. Uh so basically the there is the ESP32WROOM from Espressif. The Nucleo WL55 which is uh uh 649.72s - 658.36s | LoRa and the Sigfox uh transceiver from STMicro uh that's supported. And uh also yeah I told you about the NRF52. 658.36s - 665.66s | But the most interesting part is that we uh managed to create some uh adaptation layer between WAD and the old 665.66s - 673.48s | tools such as the uh Yardstick one or the Herbatools. And in fact we we we can use all these old devices if you 673.48s - 680.44s | can say with WAD. And this is totally transparent for you. So it's uh just it appears like a classic WAD tool or WAD 680.44s - 689.67s | device and you can use it to do whatever you want. The WAD protocol supports a lot of uh modulations uh file 689.67s - 697.35s | layers and other protocols. So basically this is the FSK, GFSK, MSK modulation on the physical layer. Uh so you can 697.35s - 703.69s | do demodulate and modulate signals using your specific device. And uh obviously the BLE protocol ZigBee and so on 703.69s - 712.55s | are also supported. Uh based on some previous research we made, Romain and I, we also added into WAD the result of 712.55s - 721.03s | this research. So Romain published in uh 2021 uh the Wasabi uh attack. So basically this is an attack on uh or not an 721.03s - 731.27s | attack. This is uh just a uh a way to divert the uh radio transceiver from an NRF52 uh system and chip to to make it 731.29s - 741.99s | able to sniff and uh inject ZigBee packets. And uh last year we presented also uh some uh research at WOOD uh um which is 741.99s - 751.27s | basically how to turn an ESP32 into a uh a device uh that can sniff and inject raw PDUs in Bluetooth no NRG uh 751.27s - 758.17s | communication. So yeah this uh this is also supported in the firmware and uh in the WAD protocol. Not not WAD protocol but WAD 758.17s - 766.45s | ecosystem. Uh if you want to add new protocols to this uh like Romain said it's uh extensible. So you can uh just modify the 766.45s - 774.83s |


chunk_id: 143_chunk_12
chunk_text:
712.55s | are also supported. Uh based on some previous research we made, Romain and I, we also added into WAD the result of 712.55s - 721.03s | this research. So Romain published in uh 2021 uh the Wasabi uh attack. So basically this is an attack on uh or not an 721.03s - 731.27s | attack. This is uh just a uh a way to divert the uh radio transceiver from an NRF52 uh system and chip to to make it 731.29s - 741.99s | able to sniff and uh inject ZigBee packets. And uh last year we presented also uh some uh research at WOOD uh um which is 741.99s - 751.27s | basically how to turn an ESP32 into a uh a device uh that can sniff and inject raw PDUs in Bluetooth no NRG uh 751.27s - 758.17s | communication. So yeah this uh this is also supported in the firmware and uh in the WAD protocol. Not not WAD protocol but WAD 758.17s - 766.45s | ecosystem. Uh if you want to add new protocols to this uh like Romain said it's uh extensible. So you can uh just modify the 766.45s - 774.83s | protocol and add what you need to to implement it. All the uh uh all the translation between these messages and so on is 774.83s - 780.03s | performed by the framework. And uh the protocol is version as well. So it is backward compatible. If you have a device with 780.03s - 788.01s | version 1, protocol version 1, it will be supported uh as well as a protocol device with a protocol version 2 and so on. And 788.01s - 798.31s | uh obviously we hope that uh many hackers may want to contribute to to WAD and add new protocols we didn't think about because we 798.31s - 809.93s | maybe don't know this protocol or so on. Um we also designed our own flexible stack model. So speaking of wireless protocol, 810.33s - 819.97s | we provide a specific flexible stack model sorry uh that is easy to modify. So basically take a BLE stack. You can just swap a 819.97s - 827.81s | specific layer and replace it with your one with your own. You can develop your own stack layer and replace it in a in the stack. So 827.81s - 835.99s | basically


chunk_id: 143_chunk_13
chunk_text:
protocol and add what you need to to implement it. All the uh uh all the translation between these messages and so on is 774.83s - 780.03s | performed by the framework. And uh the protocol is version as well. So it is backward compatible. If you have a device with 780.03s - 788.01s | version 1, protocol version 1, it will be supported uh as well as a protocol device with a protocol version 2 and so on. And 788.01s - 798.31s | uh obviously we hope that uh many hackers may want to contribute to to WAD and add new protocols we didn't think about because we 798.31s - 809.93s | maybe don't know this protocol or so on. Um we also designed our own flexible stack model. So speaking of wireless protocol, 810.33s - 819.97s | we provide a specific flexible stack model sorry uh that is easy to modify. So basically take a BLE stack. You can just swap a 819.97s - 827.81s | specific layer and replace it with your one with your own. You can develop your own stack layer and replace it in a in the stack. So 827.81s - 835.99s | basically you can implement some very specific behavior if you want to test some uh unexpected uh behavior. This is a way to to do. Uh 835.99s - 843.19s | there is a complete stack snapshot that is implemented from scratch uh in the in this model. So for it, every protocol supported, 843.19s - 851.63s | every protocol stack we got in WAD, you can do at any time a snapshot of the old stack. Uh save this snapshot on the on your disk and 851.63s - 859.21s | reload this snapshot later if you want to test uh something on this uh this framework. And also this uh all uh flexible stack 859.21s - 868.91s | model uh makes uh writing unique tests very easy because you can just isolate a layer. Send inputs and check what outputs uh came and 868.91s - 879.75s | if it's uh what you are expected from this layer. And um in WAD actually we provide uh multiple protocol stack. Uh BLE for version 4, 879.97s - 889.45s | version 5 is on its way. Uh Logitech Unifying, uh NShock Burst from Nordic, Zigbee, RF um RFOC and lower one. So all these


chunk_id: 143_chunk_14
chunk_text:
you can implement some very specific behavior if you want to test some uh unexpected uh behavior. This is a way to to do. Uh 835.99s - 843.19s | there is a complete stack snapshot that is implemented from scratch uh in the in this model. So for it, every protocol supported, 843.19s - 851.63s | every protocol stack we got in WAD, you can do at any time a snapshot of the old stack. Uh save this snapshot on the on your disk and 851.63s - 859.21s | reload this snapshot later if you want to test uh something on this uh this framework. And also this uh all uh flexible stack 859.21s - 868.91s | model uh makes uh writing unique tests very easy because you can just isolate a layer. Send inputs and check what outputs uh came and 868.91s - 879.75s | if it's uh what you are expected from this layer. And um in WAD actually we provide uh multiple protocol stack. Uh BLE for version 4, 879.97s - 889.45s | version 5 is on its way. Uh Logitech Unifying, uh NShock Burst from Nordic, Zigbee, RF um RFOC and lower one. So all these stacks have 889.45s - 897.13s | been uh implemented from scratch and are flexible in a way that you can make the stack behave the way it's not really expected by the 897.13s - 905.63s | specifications. So this uh allows uh security research uh if you want to try uh unexpected ways to to go through the stack. And uh if you 905.81s - 913.59s | just want to use the protocol as well you can just use them and it works as expected. So this is uh this is why Romain said it was made for uh 913.59s - 923.97s | secure cyber security specialists, researchers and also uh just uh enthusiast, wireless protocol enthusiast or just user. Um and uh uh we also 923.97s - 933.51s | love KISS uh not the uh rug band uh obviously but the keep it simple stupid uh principle. And WAD provides a set of simple common tools and um 933.51s - 942.87s | a mean to combine them uh to combine all these tools into uh in order to create more complex tools. Uh and we also provide some 942.87s - 950.01s | full feature tools for those who want


chunk_id: 143_chunk_15
chunk_text:
stacks have 889.45s - 897.13s | been uh implemented from scratch and are flexible in a way that you can make the stack behave the way it's not really expected by the 897.13s - 905.63s | specifications. So this uh allows uh security research uh if you want to try uh unexpected ways to to go through the stack. And uh if you 905.81s - 913.59s | just want to use the protocol as well you can just use them and it works as expected. So this is uh this is why Romain said it was made for uh 913.59s - 923.97s | secure cyber security specialists, researchers and also uh just uh enthusiast, wireless protocol enthusiast or just user. Um and uh uh we also 923.97s - 933.51s | love KISS uh not the uh rug band uh obviously but the keep it simple stupid uh principle. And WAD provides a set of simple common tools and um 933.51s - 942.87s | a mean to combine them uh to combine all these tools into uh in order to create more complex tools. Uh and we also provide some 942.87s - 950.01s | full feature tools for those who want to just to experiment with uh a protocol. And um yeah if you are a newcomer in wireless protocol 950.01s - 959.27s | expectation or or just if you want to play with some protocol you we got you covered. Uh just to give you an idea of what's going on with WAD 959.27s - 968.33s | and this uh KISS principle. Um I don't know if it's really readable in the screen but uh basically we are using uh a first program called WBD 968.33s - 977.67s | Connect to initiate a BLE connection onto a device. Then there is a pipe with the WShark which is a uh wrapper for Wireshark. And then another 977.67s - 987.65s | pipe with WBD central profile and basically what this command does is just tells WAD to first initiate a connection to a device. Then to ask uh the 988.13s - 997.27s | the device it's a BLE services and characteristics or just basically an enumeration performed by the uh WBD central. And every packet sent between 997.27s - 1008.41s | the connection and the uh central which is a GATT client is monitored by Wireshark in real time. And you


chunk_id: 143_chunk_16
chunk_text:
to just to experiment with uh a protocol. And um yeah if you are a newcomer in wireless protocol 950.01s - 959.27s | expectation or or just if you want to play with some protocol you we got you covered. Uh just to give you an idea of what's going on with WAD 959.27s - 968.33s | and this uh KISS principle. Um I don't know if it's really readable in the screen but uh basically we are using uh a first program called WBD 968.33s - 977.67s | Connect to initiate a BLE connection onto a device. Then there is a pipe with the WShark which is a uh wrapper for Wireshark. And then another 977.67s - 987.65s | pipe with WBD central profile and basically what this command does is just tells WAD to first initiate a connection to a device. Then to ask uh the 988.13s - 997.27s | the device it's a BLE services and characteristics or just basically an enumeration performed by the uh WBD central. And every packet sent between 997.27s - 1008.41s | the connection and the uh central which is a GATT client is monitored by Wireshark in real time. And you can compose all the tools this way. You 1008.41s - 1019.75s | create a processing packet chain uh yeah that's it. Maybe I get it wrong. But um you create a chain of packet processing and you can do whatever you 1019.75s - 1029.43s | want. We are going to show you some other tool we developed and it allows very some yeah some a lot of flexibility you know in the what can be 1029.43s - 1038.67s | done with this uh this uh the things. And obviously we also created in the framework a lot of uh um wrappers for creating a command line 1038.67s - 1047.91s | application. So if you need to create some command line tools or do your own tools you got everything you need to um wrap the connection to the 1047.91s - 1061.95s | hardware and so on. Yep. The clicker. Yeah. So uh I'm going to start with the first demo. This is uh we got uh 13 demos to show you what WAD is 1061.95s - 1074.43s | capable of. Uh so the first one is the BLE exploring demo. So basically we are I'm going to show you the


chunk_id: 143_chunk_17
chunk_text:
can compose all the tools this way. You 1008.41s - 1019.75s | create a processing packet chain uh yeah that's it. Maybe I get it wrong. But um you create a chain of packet processing and you can do whatever you 1019.75s - 1029.43s | want. We are going to show you some other tool we developed and it allows very some yeah some a lot of flexibility you know in the what can be 1029.43s - 1038.67s | done with this uh this uh the things. And obviously we also created in the framework a lot of uh um wrappers for creating a command line 1038.67s - 1047.91s | application. So if you need to create some command line tools or do your own tools you got everything you need to um wrap the connection to the 1047.91s - 1061.95s | hardware and so on. Yep. The clicker. Yeah. So uh I'm going to start with the first demo. This is uh we got uh 13 demos to show you what WAD is 1061.95s - 1074.43s | capable of. Uh so the first one is the BLE exploring demo. So basically we are I'm going to show you the WBD central tool. So this is basically uh a 1074.49s - 1083.77s | GATT client and uh and what I'm going to do here is to scan devices, connect to the device, a specific device, innovate services, BLE services and 1083.77s - 1102.11s | characteristics and write and write some data from this. So I guess nope. Okay so the setup is just should be this one. So basically we launch a scan 1102.11s - 1112.91s | using WBD central. We are using uh an HCI adapter for BLE. We can get all the information, all the advertising records sent by the um the device. 1112.91s - 1121.65s | Once you found your your device or target device you can connect to it through the connect command. So this is an interactive shell provided by WBD central. 1121.65s - 1131.43s | Then the connection is made and we uh launch a profile command to start enumerating services and characteristics. We can find uh we have found a device 1131.43s - 1140.09s | name characteristic uh and a manufacturer name characteristics in two different services and we are going to read the content of this characteristics using 1140.09s - 1149.81s |


chunk_id: 143_chunk_18
chunk_text:
WBD central tool. So this is basically uh a 1074.49s - 1083.77s | GATT client and uh and what I'm going to do here is to scan devices, connect to the device, a specific device, innovate services, BLE services and 1083.77s - 1102.11s | characteristics and write and write some data from this. So I guess nope. Okay so the setup is just should be this one. So basically we launch a scan 1102.11s - 1112.91s | using WBD central. We are using uh an HCI adapter for BLE. We can get all the information, all the advertising records sent by the um the device. 1112.91s - 1121.65s | Once you found your your device or target device you can connect to it through the connect command. So this is an interactive shell provided by WBD central. 1121.65s - 1131.43s | Then the connection is made and we uh launch a profile command to start enumerating services and characteristics. We can find uh we have found a device 1131.43s - 1140.09s | name characteristic uh and a manufacturer name characteristics in two different services and we are going to read the content of this characteristics using 1140.09s - 1149.81s | the read command and we get everything and uh we can also write into characteristics and subscribe for notification. The basics a GATT client can do. 1149.81s - 1175.39s | Oh this is for the next demo. So basically this is just an example of a full feature tool uh in WAD and this is a very basic one. 1175.39s - 1193.39s | So uh second uh full feature tool we developed uh is a tool named uh ZigBee and device uh that will allow to interact with uh ZigBee networks uh and uh emulate basically ZigBee and device. 1193.39s - 1204.89s | So thanks to this tool you will be able to detect uh the surrounding ZigBee networks uh to join a specific network uh perform all the cryptographic operation this kind of stuff 1204.89s - 1216.97s | and get the network key uh associated with the network enumerate the devices on the network and interact uh with the various ZigBee devices. 1216.97s - 1228.67s | So uh here you have a small demo showing a small ZigBee network um on the camera and you have an example of the use of this tool. 1228.67s - 1244.49s | So


chunk_id: 143_chunk_19
chunk_text:
the read command and we get everything and uh we can also write into characteristics and subscribe for notification. The basics a GATT client can do. 1149.81s - 1175.39s | Oh this is for the next demo. So basically this is just an example of a full feature tool uh in WAD and this is a very basic one. 1175.39s - 1193.39s | So uh second uh full feature tool we developed uh is a tool named uh ZigBee and device uh that will allow to interact with uh ZigBee networks uh and uh emulate basically ZigBee and device. 1193.39s - 1204.89s | So thanks to this tool you will be able to detect uh the surrounding ZigBee networks uh to join a specific network uh perform all the cryptographic operation this kind of stuff 1204.89s - 1216.97s | and get the network key uh associated with the network enumerate the devices on the network and interact uh with the various ZigBee devices. 1216.97s - 1228.67s | So uh here you have a small demo showing a small ZigBee network um on the camera and you have an example of the use of this tool. 1228.67s - 1244.49s | So first we perform a scan operation to discover the surrounding networks. So it takes some time but uh finally uh we can see that we have one uh ZigBee network. 1244.49s - 1263.11s | So let's join uh this network and perform the association procedure so we are able to see the network key and now we are associated and we can uh interact and discover the nodes in the networks and the endpoints for every nodes. 1263.11s - 1312.78s | So then uh we have a list of clusters that allows us to uh interact with uh the nodes and we can use the cluster command to toggle uh a light bulb for example uh toggle it off and so on. 1312.78s - 1342.76s | So sorry uh we are also uh another tool named the Wadsniff which is a generic tool so it's a multi-protocol sniffing tool uh so Wadsniff uh works with all uh the protocols that are supported uh by WAD so ZigBee, BLE, RFC you can even uh directly sniff uh PHY uh so uh physical layer um configured as you want. 1342.84s - 1365.94s | Uh it provides different uh output formats so you


chunk_id: 143_chunk_20
chunk_text:
first we perform a scan operation to discover the surrounding networks. So it takes some time but uh finally uh we can see that we have one uh ZigBee network. 1244.49s - 1263.11s | So let's join uh this network and perform the association procedure so we are able to see the network key and now we are associated and we can uh interact and discover the nodes in the networks and the endpoints for every nodes. 1263.11s - 1312.78s | So then uh we have a list of clusters that allows us to uh interact with uh the nodes and we can use the cluster command to toggle uh a light bulb for example uh toggle it off and so on. 1312.78s - 1342.76s | So sorry uh we are also uh another tool named the Wadsniff which is a generic tool so it's a multi-protocol sniffing tool uh so Wadsniff uh works with all uh the protocols that are supported uh by WAD so ZigBee, BLE, RFC you can even uh directly sniff uh PHY uh so uh physical layer um configured as you want. 1342.84s - 1365.94s | Uh it provides different uh output formats so you can directly display the SCAPI packets uh with the different fields uh correctly dissected uh or directly a next dump uh version of the packet uh and it allows to uh monitor the traffic and do value stuff like exporting data to a PCAP uh monitoring uh with Wireshark. 1366.54s - 1387.62s | So here you have uh some uh basic uh use cases of uh Wadsniff so here we are going uh to uh display uh some BLE advertisements so here you can see the SCAPI uh representation. 1388.62s - 1395.62s | Then we can switch the format to Xdump and so here we have the Xdump version of our packets. 1396.62s - 1412.90s | We can uh also uh collect these uh packets using uh directly the physical uh layer of Bluetooth energy so we provide the modulation, Gaussian frequency shift gain, then the deviation. 1415.25s - 1433.25s | Uh we provide the frequency uh and uh finally the size uh of the packets and here we get a raw dump uh straight out the demodulator output so uh it can be useful for specific analysis. 1433.25s - 1458.38s | And uh finally we can also uh for


chunk_id: 143_chunk_21
chunk_text:
can directly display the SCAPI packets uh with the different fields uh correctly dissected uh or directly a next dump uh version of the packet uh and it allows to uh monitor the traffic and do value stuff like exporting data to a PCAP uh monitoring uh with Wireshark. 1366.54s - 1387.62s | So here you have uh some uh basic uh use cases of uh Wadsniff so here we are going uh to uh display uh some BLE advertisements so here you can see the SCAPI uh representation. 1388.62s - 1395.62s | Then we can switch the format to Xdump and so here we have the Xdump version of our packets. 1396.62s - 1412.90s | We can uh also uh collect these uh packets using uh directly the physical uh layer of Bluetooth energy so we provide the modulation, Gaussian frequency shift gain, then the deviation. 1415.25s - 1433.25s | Uh we provide the frequency uh and uh finally the size uh of the packets and here we get a raw dump uh straight out the demodulator output so uh it can be useful for specific analysis. 1433.25s - 1458.38s | And uh finally we can also uh for with this Wadsniff tool uh directly export the traffic to a PCAP for further analysis so here all the traffic is simultaneously displayed on the screen and exported to a PCAP. 1476.79s - 1484.79s | So an interesting uh feature of WAD is that you can combine uh several tools uh with pipes. 1485.79s - 1498.79s | So Wadsniff can be trained with uh several tools so for example you can use WADfilter that may allow to apply some filtering uh on the received packets. 1498.79s - 1518.79s | Uh you can transform uh the packets on the fly uh if it matches a specific filter or uh you can also use some tools like WADextract uh that may allow to extract uh a specific uh field uh from the packets. 1519.79s - 1522.79s | So let's go uh for an example of that. 1522.79s - 1539.79s | So here it's uh the same example with Wadsniff and uh we are going to pipe uh Wadsniff with uh WADfilter and in WADfilter we are going to provide a filter to keep only a specific kind of other types of packets. 1539.79s - 1549.79s | And finally if we want uh


chunk_id: 143_chunk_22
chunk_text:
with this Wadsniff tool uh directly export the traffic to a PCAP for further analysis so here all the traffic is simultaneously displayed on the screen and exported to a PCAP. 1476.79s - 1484.79s | So an interesting uh feature of WAD is that you can combine uh several tools uh with pipes. 1485.79s - 1498.79s | So Wadsniff can be trained with uh several tools so for example you can use WADfilter that may allow to apply some filtering uh on the received packets. 1498.79s - 1518.79s | Uh you can transform uh the packets on the fly uh if it matches a specific filter or uh you can also use some tools like WADextract uh that may allow to extract uh a specific uh field uh from the packets. 1519.79s - 1522.79s | So let's go uh for an example of that. 1522.79s - 1539.79s | So here it's uh the same example with Wadsniff and uh we are going to pipe uh Wadsniff with uh WADfilter and in WADfilter we are going to provide a filter to keep only a specific kind of other types of packets. 1539.79s - 1549.79s | And finally if we want uh to extract a specific field we can use uh WADextract. 1550.79s - 1560.79s | We provide the field we want to extract so here is the BG address and we also export a part of the metadata so the RSSI. 1561.79s - 1568.79s | And of course you can then grab this output and provide it uh to classical Unix tool. 1569.79s - 1581.79s | So uh Wadsniff uh has a lot of uh usage and it may even allow to perform uh some complex uh attacks. 1582.79s - 1591.79s | So typically uh in this demo we are going to attack an RF4C communication between a remote uh controller and a set-top box. 1591.79s - 1598.79s | So uh typically RF4C is a lightweight variant uh of ZigBee for remote controller. 1599.79s - 1605.79s | So here you have a set-top uh with the remote controller on one side and Wadsniff on the other side. 1606.79s - 1618.79s | So here we are performing a pairing with the remote controller and uh Wadsniff has been configured to automatically perform a brute force uh attack. 1619.79s - 1632.79s | And so in the input you can notice that the key


chunk_id: 143_chunk_23
chunk_text:
to extract a specific field we can use uh WADextract. 1550.79s - 1560.79s | We provide the field we want to extract so here is the BG address and we also export a part of the metadata so the RSSI. 1561.79s - 1568.79s | And of course you can then grab this output and provide it uh to classical Unix tool. 1569.79s - 1581.79s | So uh Wadsniff uh has a lot of uh usage and it may even allow to perform uh some complex uh attacks. 1582.79s - 1591.79s | So typically uh in this demo we are going to attack an RF4C communication between a remote uh controller and a set-top box. 1591.79s - 1598.79s | So uh typically RF4C is a lightweight variant uh of ZigBee for remote controller. 1599.79s - 1605.79s | So here you have a set-top uh with the remote controller on one side and Wadsniff on the other side. 1606.79s - 1618.79s | So here we are performing a pairing with the remote controller and uh Wadsniff has been configured to automatically perform a brute force uh attack. 1619.79s - 1632.79s | And so in the input you can notice that the key uh has been uh automatically uh derived and extracted from the communication. 1633.79s - 1640.79s | And the packet which is uh normally encrypted can be decrypted uh on the fly. 1640.79s - 1648.79s | So it allows to sniff the various buttons that are pressed on the remote control. 1649.79s - 1665.55s | And it uh can also sniff the audio stream which can be transmitted uh using the mic of the remote controller. 1666.55s - 1683.96s | And uh we can even export uh the voice command to a bad WAV file but yeah it's working. 1689.82s - 1693.82s | So uh next demonstration is about uh using Wireshark to sniff uh some traffic. 1694.82s - 1700.82s | So basically uh we showed this uh a bit earlier but uh we are going to go a bit deeper in this demo. 1701.82s - 1703.82s | So uh you can monitor everything with WShark. 1704.82s - 1717.82s | So this example is about BLE but it could be ZigBee or even your if you are trying to demodulate packets through the file layer you can get it in Wireshark in real time and you can monitor everything you are


chunk_id: 143_chunk_24
chunk_text:
uh has been uh automatically uh derived and extracted from the communication. 1633.79s - 1640.79s | And the packet which is uh normally encrypted can be decrypted uh on the fly. 1640.79s - 1648.79s | So it allows to sniff the various buttons that are pressed on the remote control. 1649.79s - 1665.55s | And it uh can also sniff the audio stream which can be transmitted uh using the mic of the remote controller. 1666.55s - 1683.96s | And uh we can even export uh the voice command to a bad WAV file but yeah it's working. 1689.82s - 1693.82s | So uh next demonstration is about uh using Wireshark to sniff uh some traffic. 1694.82s - 1700.82s | So basically uh we showed this uh a bit earlier but uh we are going to go a bit deeper in this demo. 1701.82s - 1703.82s | So uh you can monitor everything with WShark. 1704.82s - 1717.82s | So this example is about BLE but it could be ZigBee or even your if you are trying to demodulate packets through the file layer you can get it in Wireshark in real time and you can monitor everything you are working on. 1718.82s - 1725.82s | If you use WFilter to modify your packet on the fly you can see the result in real time with the WShark. 1726.82s - 1728.82s | So uh the demo is the following. 1729.82s - 1731.82s | I'm going to be very quick about this one. 1732.82s - 1743.82s | Yeah so basically we are again connecting to a device and so on and performing uh um uh services and characteristics in emulation. 1744.82s - 1752.82s | And everything uh can be monitored uh in Wireshark while the terminal shows you the results of this uh of this operation. 1752.82s - 1756.82s | So this is basically uh what WShark can do. 1757.82s - 1763.82s | And the most interesting thing is that uh we talked about uh Gatacore and BTLEJuice at the beginning of the talk. 1764.82s - 1772.82s | So basically these tools are based on not on some Node.js uh library uh which are not no more maintained at the moment. 1773.82s - 1780.82s | So if you want to perform a man-in-the-middle attack on BLE with WAD this is very simple. 1780.82s - 1788.82s | Because you can combine tools


chunk_id: 143_chunk_25
chunk_text:
working on. 1718.82s - 1725.82s | If you use WFilter to modify your packet on the fly you can see the result in real time with the WShark. 1726.82s - 1728.82s | So uh the demo is the following. 1729.82s - 1731.82s | I'm going to be very quick about this one. 1732.82s - 1743.82s | Yeah so basically we are again connecting to a device and so on and performing uh um uh services and characteristics in emulation. 1744.82s - 1752.82s | And everything uh can be monitored uh in Wireshark while the terminal shows you the results of this uh of this operation. 1752.82s - 1756.82s | So this is basically uh what WShark can do. 1757.82s - 1763.82s | And the most interesting thing is that uh we talked about uh Gatacore and BTLEJuice at the beginning of the talk. 1764.82s - 1772.82s | So basically these tools are based on not on some Node.js uh library uh which are not no more maintained at the moment. 1773.82s - 1780.82s | So if you want to perform a man-in-the-middle attack on BLE with WAD this is very simple. 1780.82s - 1788.82s | Because you can combine tools you can create for instance if you want to you know set up a man-in-the-middle attack on a device uh like Gatacore. 1789.82s - 1798.82s | You uh just create a command line starting with WBAD-spawn that will spawn a device with uh corresponding parameters that will mimic the target device. 1799.82s - 1806.82s | And then you can pipe all the packets that will go uh from the this uh fake device or spoof device into Wireshark. 1807.82s - 1814.82s | You can so you can monitor in real time what's going on and then uh once the smartphone for instance is uh is connected onto the spoof device. 1815.82s - 1819.82s | Uh then you are going to initiate a connection into the target device. 1820.82s - 1829.82s | And every packet sent by the smartphone uh or the target or the target device will be uh just forwarded as uh uh as it goes. 1830.82s - 1831.82s | And you can monitor everything in WShark. 1832.82s - 1834.82s | So this is uh the next demo I'm going to show you. 1834.82s - 1848.82s | Uh here so we are setting up uh Gatacore like man-in-the-middle attack


chunk_id: 143_chunk_26
chunk_text:
you can create for instance if you want to you know set up a man-in-the-middle attack on a device uh like Gatacore. 1789.82s - 1798.82s | You uh just create a command line starting with WBAD-spawn that will spawn a device with uh corresponding parameters that will mimic the target device. 1799.82s - 1806.82s | And then you can pipe all the packets that will go uh from the this uh fake device or spoof device into Wireshark. 1807.82s - 1814.82s | You can so you can monitor in real time what's going on and then uh once the smartphone for instance is uh is connected onto the spoof device. 1815.82s - 1819.82s | Uh then you are going to initiate a connection into the target device. 1820.82s - 1829.82s | And every packet sent by the smartphone uh or the target or the target device will be uh just forwarded as uh uh as it goes. 1830.82s - 1831.82s | And you can monitor everything in WShark. 1832.82s - 1834.82s | So this is uh the next demo I'm going to show you. 1834.82s - 1848.82s | Uh here so we are setting up uh Gatacore like man-in-the-middle attack using uh WAD using simple tools again WBAD-spawn this is very small tool like WBAD-connect. 1849.82s - 1858.82s | And uh we first the system is going to spawn a spoof device that just advertise itself like the target device. 1859.82s - 1862.82s | And the smartphone uh here is going to detect this device. 1862.82s - 1871.82s | When we initiate the connect when we push the connect button on the on the smartphone then the connection to the our spoof device is uh initiated. 1872.82s - 1874.82s | We can see on Wireshark what's going on with the BLE PDUs. 1875.82s - 1884.82s | And if you really try to read the characteristics for instance then all the PDUs are directly forwarded to the target device and back and forth and we can monitor everything. 1885.82s - 1886.82s | With Wireshark you can see what's going on. 1886.82s - 1887.82s | You can save it as a pick up. 1888.82s - 1898.82s | And what we do here with Wireshark you can do it with any other generic tool we develop such as WFilter or WX not WX type WFilter. 1899.82s - 1904.82s | And you can if


chunk_id: 143_chunk_27
chunk_text:
using uh WAD using simple tools again WBAD-spawn this is very small tool like WBAD-connect. 1849.82s - 1858.82s | And uh we first the system is going to spawn a spoof device that just advertise itself like the target device. 1859.82s - 1862.82s | And the smartphone uh here is going to detect this device. 1862.82s - 1871.82s | When we initiate the connect when we push the connect button on the on the smartphone then the connection to the our spoof device is uh initiated. 1872.82s - 1874.82s | We can see on Wireshark what's going on with the BLE PDUs. 1875.82s - 1884.82s | And if you really try to read the characteristics for instance then all the PDUs are directly forwarded to the target device and back and forth and we can monitor everything. 1885.82s - 1886.82s | With Wireshark you can see what's going on. 1886.82s - 1887.82s | You can save it as a pick up. 1888.82s - 1898.82s | And what we do here with Wireshark you can do it with any other generic tool we develop such as WFilter or WX not WX type WFilter. 1899.82s - 1904.82s | And you can if you want make some changes into the packets using some specific filters. 1905.82s - 1912.82s | If you want to modify the answer uh the um response uh from a read operation on the characteristics you can do it on the fly. 1912.82s - 1917.82s | And you can also monitor what's going on because you can pipe WFilter with WShark as well. 1918.82s - 1923.82s | So this this is powerful even if this demo is not uh really powerful but yeah. 1924.82s - 1925.82s | Anyway. 1926.82s - 1931.82s | And if you want to emulate a BLE peripheral you can you can use uh the full feature of WBLE peripheral. 1932.82s - 1933.82s | Uh so basically it goes like this. 1934.82s - 1941.82s | This is a command line tool you can use to just uh spawn a BLE device and populate the device with whatever you want. 1942.82s - 1946.82s | So basically you can change the name of the device and say that I'm going to create a device called Defcon32. 1947.82s - 1950.82s | Uh add a service and a characteristic to the device. 1951.82s - 1955.82s | Um I'm going to write


chunk_id: 143_chunk_28
chunk_text:
you want make some changes into the packets using some specific filters. 1905.82s - 1912.82s | If you want to modify the answer uh the um response uh from a read operation on the characteristics you can do it on the fly. 1912.82s - 1917.82s | And you can also monitor what's going on because you can pipe WFilter with WShark as well. 1918.82s - 1923.82s | So this this is powerful even if this demo is not uh really powerful but yeah. 1924.82s - 1925.82s | Anyway. 1926.82s - 1931.82s | And if you want to emulate a BLE peripheral you can you can use uh the full feature of WBLE peripheral. 1932.82s - 1933.82s | Uh so basically it goes like this. 1934.82s - 1941.82s | This is a command line tool you can use to just uh spawn a BLE device and populate the device with whatever you want. 1942.82s - 1946.82s | So basically you can change the name of the device and say that I'm going to create a device called Defcon32. 1947.82s - 1950.82s | Uh add a service and a characteristic to the device. 1951.82s - 1955.82s | Um I'm going to write the value of this characteristic as well. 1956.82s - 1957.82s | It should be Defcon32 I guess. 1957.82s - 1962.82s | And then uh I'm going to start the device on the uh right hand side of the screen. 1963.82s - 1965.82s | You got the uh screen of the smartphone. 1966.82s - 1970.82s | So let's start this uh spoof device or emulated device to be more precise. 1971.82s - 1973.82s | Uh yeah come on. 1974.82s - 1980.82s | Okay so it will pop on uh the um smartphone and we can connect to it. 1981.82s - 1985.82s | Um it will start the discovery process of services and characteristics. 1985.82s - 1988.82s | There is a single service with a single characteristic. 1989.82s - 1991.82s | And we can read the content. 1992.82s - 1997.82s | Each time we read from the smartphone the content of this characteristic this is caught by the BLE PRF uh tool. 1998.82s - 2004.82s | And uh if uh the smartphone subscribe to notification then it got notified by the uh the system and so on. 2005.82s - 2011.82s | So this is a good way to play with uh uh


chunk_id: 143_chunk_29
chunk_text:
the value of this characteristic as well. 1956.82s - 1957.82s | It should be Defcon32 I guess. 1957.82s - 1962.82s | And then uh I'm going to start the device on the uh right hand side of the screen. 1963.82s - 1965.82s | You got the uh screen of the smartphone. 1966.82s - 1970.82s | So let's start this uh spoof device or emulated device to be more precise. 1971.82s - 1973.82s | Uh yeah come on. 1974.82s - 1980.82s | Okay so it will pop on uh the um smartphone and we can connect to it. 1981.82s - 1985.82s | Um it will start the discovery process of services and characteristics. 1985.82s - 1988.82s | There is a single service with a single characteristic. 1989.82s - 1991.82s | And we can read the content. 1992.82s - 1997.82s | Each time we read from the smartphone the content of this characteristic this is caught by the BLE PRF uh tool. 1998.82s - 2004.82s | And uh if uh the smartphone subscribe to notification then it got notified by the uh the system and so on. 2005.82s - 2011.82s | So this is a good way to play with uh uh applications and BLE applications to mimic some device. 2011.82s - 2017.82s | If you want to see what happens when you are modifying some uh some properties of this uh of this device. 2018.82s - 2029.82s | Uh in practical situation this is not what we are going to use because it's uh you know just a uh interesting way we want to play with uh a device. 2030.82s - 2032.82s | But uh a more interesting use is the following. 2033.82s - 2038.82s | Uh if you want to implement a very specific device with specific services and characteristic with a specific behavior for the characteristics. 2039.82s - 2040.82s | Here a small example. 2041.82s - 2044.82s | We are going to create a battery device exposing your battery service with a battery level. 2045.82s - 2050.82s | Except that each time we are going to read the battery level we will decrease the level by 10%. 2051.82s - 2055.82s | And goes like this when you emulate this uh peripheral. 2056.82s - 2061.82s | So basically uh we start the Python script that uh instruments everything. 2062.82s - 2063.82s | The device appears on the screen. 2063.82s -


chunk_id: 143_chunk_30
chunk_text:
applications and BLE applications to mimic some device. 2011.82s - 2017.82s | If you want to see what happens when you are modifying some uh some properties of this uh of this device. 2018.82s - 2029.82s | Uh in practical situation this is not what we are going to use because it's uh you know just a uh interesting way we want to play with uh a device. 2030.82s - 2032.82s | But uh a more interesting use is the following. 2033.82s - 2038.82s | Uh if you want to implement a very specific device with specific services and characteristic with a specific behavior for the characteristics. 2039.82s - 2040.82s | Here a small example. 2041.82s - 2044.82s | We are going to create a battery device exposing your battery service with a battery level. 2045.82s - 2050.82s | Except that each time we are going to read the battery level we will decrease the level by 10%. 2051.82s - 2055.82s | And goes like this when you emulate this uh peripheral. 2056.82s - 2061.82s | So basically uh we start the Python script that uh instruments everything. 2062.82s - 2063.82s | The device appears on the screen. 2063.82s - 2064.82s | So there is a battery device. 2065.82s - 2070.82s | When the discovery goes with the services and characteristic we get one service with one battery level characteristics. 2071.82s - 2078.82s | And each time I read the characteristic value getting the percentage of uh battery level percentage then it is decreased. 2079.82s - 2081.82s | So this is just 10 lines of Python to do this. 2082.82s - 2091.06s | And uh we did the same with other protocols because we are talking a lot about BLE. 2092.06s - 2094.06s | Uh we got a LoRaWAN gateway implemented in WAD. 2094.06s - 2103.06s | So if you want to create a LoRaWAN network and get some device uh to associate with this uh with this um fake network. 2104.06s - 2105.06s | You can do it and it works pretty well. 2106.06s - 2108.06s | Uh I guess the demo will be a nightmare on the screens. 2109.06s - 2110.06s | So I will skip it. 2111.06s - 2116.06s | Um but the media server of DEF CON has this demo. 2117.06s - 2118.06s | So if you want to have a look at it. 2119.06s -


chunk_id: 143_chunk_31
chunk_text:
2064.82s | So there is a battery device. 2065.82s - 2070.82s | When the discovery goes with the services and characteristic we get one service with one battery level characteristics. 2071.82s - 2078.82s | And each time I read the characteristic value getting the percentage of uh battery level percentage then it is decreased. 2079.82s - 2081.82s | So this is just 10 lines of Python to do this. 2082.82s - 2091.06s | And uh we did the same with other protocols because we are talking a lot about BLE. 2092.06s - 2094.06s | Uh we got a LoRaWAN gateway implemented in WAD. 2094.06s - 2103.06s | So if you want to create a LoRaWAN network and get some device uh to associate with this uh with this um fake network. 2104.06s - 2105.06s | You can do it and it works pretty well. 2106.06s - 2108.06s | Uh I guess the demo will be a nightmare on the screens. 2109.06s - 2110.06s | So I will skip it. 2111.06s - 2116.06s | Um but the media server of DEF CON has this demo. 2117.06s - 2118.06s | So if you want to have a look at it. 2119.06s - 2120.06s | Uh please do. 2121.06s - 2122.06s | But uh I am going to still skip this one. 2122.06s - 2124.06s | Uh and let Romain explain the rest. 2125.06s - 2126.06s | Yeah. 2127.06s - 2138.06s | So uh another uh example of what you can do uh with uh WAD is uh the emulation of various uh devices. 2139.06s - 2143.06s | And for example uh you can take a proprietary protocol like Logitech Unifying. 2144.06s - 2146.06s | And you have a protocol stack which is implemented. 2146.06s - 2156.06s | And various tools that will allow to uh perform uh keyboard emulation, mouse emulation uh for Logitech Unifying devices. 2157.06s - 2164.06s | So typically here we are going to use it to perform a scan operation of surrounding Unifying devices. 2165.06s - 2169.06s | Uh spoof uh the address of uh mouse. 2170.06s - 2180.06s | And then we are going to emulate the keyboard with this address to reproduce a vulnerability uh from mouse jack to inject an encrypted keystrokes to the computer. 2181.06s - 2191.20s | So here we start by uh using a small command line tool to perform a scan


chunk_id: 143_chunk_32
chunk_text:
2120.06s | Uh please do. 2121.06s - 2122.06s | But uh I am going to still skip this one. 2122.06s - 2124.06s | Uh and let Romain explain the rest. 2125.06s - 2126.06s | Yeah. 2127.06s - 2138.06s | So uh another uh example of what you can do uh with uh WAD is uh the emulation of various uh devices. 2139.06s - 2143.06s | And for example uh you can take a proprietary protocol like Logitech Unifying. 2144.06s - 2146.06s | And you have a protocol stack which is implemented. 2146.06s - 2156.06s | And various tools that will allow to uh perform uh keyboard emulation, mouse emulation uh for Logitech Unifying devices. 2157.06s - 2164.06s | So typically here we are going to use it to perform a scan operation of surrounding Unifying devices. 2165.06s - 2169.06s | Uh spoof uh the address of uh mouse. 2170.06s - 2180.06s | And then we are going to emulate the keyboard with this address to reproduce a vulnerability uh from mouse jack to inject an encrypted keystrokes to the computer. 2181.06s - 2191.20s | So here we start by uh using a small command line tool to perform a scan operation. 2192.20s - 2195.20s | It allows us to get the address of a mouse. 2195.20s - 2203.20s | And we provide it uh in uh as argument of a Python script that will perform the injection. 2204.20s - 2210.20s | And as you can see uh we have a keystroke injection uh performed and fully emulated by WAD. 2211.20s - 2214.73s | Yeah. 2214.73s - 2215.73s | So you can see hello Defcon. 2216.73s - 2217.73s | Sorry. 2220.73s - 2228.77s | So uh we can uh emulate uh Logitech Unifying keyboard. 2228.77s - 2232.77s | We can also emulate a Logitech Unifying uh dongle. 2233.77s - 2241.77s | Uh and uh on the other side on BLE we are able to emulate a peripheral. 2242.77s - 2253.77s | So here comes uh very useless idea which is to uh create a bridge uh which is cross protocol between uh Logitech Unifying uh keyboard for example. 2254.77s - 2260.77s | And a smartphone uh that will be connected to an emulated uh BLE keyboard. 2261.77s - 2263.77s | So uh we have a small script. 2264.77s - 2266.77s | You can see the screen uh of the smartphone. 2267.77s


chunk_id: 143_chunk_33
chunk_text:
operation. 2192.20s - 2195.20s | It allows us to get the address of a mouse. 2195.20s - 2203.20s | And we provide it uh in uh as argument of a Python script that will perform the injection. 2204.20s - 2210.20s | And as you can see uh we have a keystroke injection uh performed and fully emulated by WAD. 2211.20s - 2214.73s | Yeah. 2214.73s - 2215.73s | So you can see hello Defcon. 2216.73s - 2217.73s | Sorry. 2220.73s - 2228.77s | So uh we can uh emulate uh Logitech Unifying keyboard. 2228.77s - 2232.77s | We can also emulate a Logitech Unifying uh dongle. 2233.77s - 2241.77s | Uh and uh on the other side on BLE we are able to emulate a peripheral. 2242.77s - 2253.77s | So here comes uh very useless idea which is to uh create a bridge uh which is cross protocol between uh Logitech Unifying uh keyboard for example. 2254.77s - 2260.77s | And a smartphone uh that will be connected to an emulated uh BLE keyboard. 2261.77s - 2263.77s | So uh we have a small script. 2264.77s - 2266.77s | You can see the screen uh of the smartphone. 2267.77s - 2274.77s | And uh you can see uh a video with the keyboard uh at the bottom. 2275.77s - 2278.77s | So first we connect uh we emulate the BLE keyboard. 2279.77s - 2284.77s | We connect and pair the smartphone uh with this uh emulated BLE keyboard. 2285.77s - 2294.38s | And once the pairing uh is uh successful. 2295.38s - 2309.38s | Now we can just press some key on the Logitech Unifying keyboard and it will be forwarded uh through the uh BLE emulated keyboard to the smartphone. 2310.38s - 2311.38s | So yeah. 2312.38s - 2314.38s | Completely useless but funny. 2314.38s - 2333.85s | And finally our last demo uh is uh uh based on the idea that it's uh cool that what allow to uh access various hardware uh perform uh different operations. 2334.85s - 2339.85s | Uh but it would be even cooler if you could access it over internet. 2339.85s - 2347.85s | So uh we wrote a what server that will allow you to expose a what device uh over TCP. 2348.85s - 2359.85s | And so uh with any tool, any script, you will be able to connect uh


chunk_id: 143_chunk_34
chunk_text:
- 2274.77s | And uh you can see uh a video with the keyboard uh at the bottom. 2275.77s - 2278.77s | So first we connect uh we emulate the BLE keyboard. 2279.77s - 2284.77s | We connect and pair the smartphone uh with this uh emulated BLE keyboard. 2285.77s - 2294.38s | And once the pairing uh is uh successful. 2295.38s - 2309.38s | Now we can just press some key on the Logitech Unifying keyboard and it will be forwarded uh through the uh BLE emulated keyboard to the smartphone. 2310.38s - 2311.38s | So yeah. 2312.38s - 2314.38s | Completely useless but funny. 2314.38s - 2333.85s | And finally our last demo uh is uh uh based on the idea that it's uh cool that what allow to uh access various hardware uh perform uh different operations. 2334.85s - 2339.85s | Uh but it would be even cooler if you could access it over internet. 2339.85s - 2347.85s | So uh we wrote a what server that will allow you to expose a what device uh over TCP. 2348.85s - 2359.85s | And so uh with any tool, any script, you will be able to connect uh to this what uh TCP server uh like if it was a local device. 2360.85s - 2366.85s | And uh for example it can be useful to build relay attacks and that kind of stuff. 2366.85s - 2375.85s | So uh in this next demo, so we are in two different uh cities in France. 2376.85s - 2383.85s | And I'm exposing uh my uh Bluetooth dongle uh using what server. 2384.85s - 2392.85s | Damien will use uh BLE central to connect to uh this uh remote devices. 2392.85s - 2396.85s | And he's able to connect to the light bulb next to me. 2397.85s - 2400.85s | Perform a profile uh discovery. 2401.85s - 2416.92s | And uh now he will be able to uh turn the light bulb on, turn the light bulb off, and modify uh the color. 2417.92s - 2423.92s | So typically uh it's interesting uh for building relay attacks. 2424.92s - 2428.92s | It can be interesting in uh various experiment uh setups. 2429.92s - 2430.92s | So Sky is the limit here. 2431.92s - 2437.92s | Yeah uh and the interesting part here is yeah again we show it with BLE but


chunk_id: 143_chunk_35
chunk_text:
to this what uh TCP server uh like if it was a local device. 2360.85s - 2366.85s | And uh for example it can be useful to build relay attacks and that kind of stuff. 2366.85s - 2375.85s | So uh in this next demo, so we are in two different uh cities in France. 2376.85s - 2383.85s | And I'm exposing uh my uh Bluetooth dongle uh using what server. 2384.85s - 2392.85s | Damien will use uh BLE central to connect to uh this uh remote devices. 2392.85s - 2396.85s | And he's able to connect to the light bulb next to me. 2397.85s - 2400.85s | Perform a profile uh discovery. 2401.85s - 2416.92s | And uh now he will be able to uh turn the light bulb on, turn the light bulb off, and modify uh the color. 2417.92s - 2423.92s | So typically uh it's interesting uh for building relay attacks. 2424.92s - 2428.92s | It can be interesting in uh various experiment uh setups. 2429.92s - 2430.92s | So Sky is the limit here. 2431.92s - 2437.92s | Yeah uh and the interesting part here is yeah again we show it with BLE but it can be done with any protocol as well. 2437.92s - 2445.92s | You can uh accept the Logitech unifying because you have some keep-alives that are messed up with the network. 2446.92s - 2450.92s | But in fact you can once you are connected to a device you can just discover everything. 2451.92s - 2456.92s | And yeah just like uh it's the same if you connect the device on your computer. 2457.92s - 2460.92s | So basically it opens a wide range of possibility. 2461.92s - 2473.92s | So uh we are developing this project uh since uh a few years now. 2474.92s - 2483.92s | And uh it has been used uh internally uh so in Damien's company uh and uh in my research lab. 2483.92s - 2495.92s | So for example uh one uh intern uh at Quark's lab uh Batiboye uh developed uh BLE GAT fuzzer uh using uh WAD. 2496.92s - 2504.92s | That leads to a CV uh linked to the expressive controller uh expressive uh BLE stack sorry. 2504.92s - 2514.92s | Uh and uh we also uh used it in a research project uh to evaluate the screaming channel attacks. 2515.92s


chunk_id: 143_chunk_36
chunk_text:
it can be done with any protocol as well. 2437.92s - 2445.92s | You can uh accept the Logitech unifying because you have some keep-alives that are messed up with the network. 2446.92s - 2450.92s | But in fact you can once you are connected to a device you can just discover everything. 2451.92s - 2456.92s | And yeah just like uh it's the same if you connect the device on your computer. 2457.92s - 2460.92s | So basically it opens a wide range of possibility. 2461.92s - 2473.92s | So uh we are developing this project uh since uh a few years now. 2474.92s - 2483.92s | And uh it has been used uh internally uh so in Damien's company uh and uh in my research lab. 2483.92s - 2495.92s | So for example uh one uh intern uh at Quark's lab uh Batiboye uh developed uh BLE GAT fuzzer uh using uh WAD. 2496.92s - 2504.92s | That leads to a CV uh linked to the expressive controller uh expressive uh BLE stack sorry. 2504.92s - 2514.92s | Uh and uh we also uh used it in a research project uh to evaluate the screaming channel attacks. 2515.92s - 2522.92s | So we told us to uh instrument uh the BLE protocol uh with uh custom uh link layer traffic. 2523.92s - 2530.92s | Uh it's also a project which is uh already uh easily used in uh some other LCTF. 2530.92s - 2535.92s | So for example uh this year uh edition of other I.O. 2536.92s - 2540.92s | Uh all the BLE challenges were fully emulated uh with WAD. 2541.92s - 2547.92s | And WAD has also been used in a lower one challenge to emulate a lower one gateway. 2548.92s - 2557.92s | So to conclude this talk uh we uh are releasing today uh publicly uh this project. 2557.92s - 2560.92s | So uh it's available uh on pip. 2561.92s - 2564.92s | The documentation is available uh on read.docs. 2565.92s - 2571.92s | So we are going to improve uh the documentation and the project over time. 2572.92s - 2574.92s | Uh feel free to contribute to it. 2575.92s - 2583.92s | We have also uh the firmware files that are available uh on GitHub in uh some sub repositories. 2583.92s - 2589.92s | And globally all the code uh is available uh


chunk_id: 143_chunk_37
chunk_text:
- 2522.92s | So we told us to uh instrument uh the BLE protocol uh with uh custom uh link layer traffic. 2523.92s - 2530.92s | Uh it's also a project which is uh already uh easily used in uh some other LCTF. 2530.92s - 2535.92s | So for example uh this year uh edition of other I.O. 2536.92s - 2540.92s | Uh all the BLE challenges were fully emulated uh with WAD. 2541.92s - 2547.92s | And WAD has also been used in a lower one challenge to emulate a lower one gateway. 2548.92s - 2557.92s | So to conclude this talk uh we uh are releasing today uh publicly uh this project. 2557.92s - 2560.92s | So uh it's available uh on pip. 2561.92s - 2564.92s | The documentation is available uh on read.docs. 2565.92s - 2571.92s | So we are going to improve uh the documentation and the project over time. 2572.92s - 2574.92s | Uh feel free to contribute to it. 2575.92s - 2583.92s | We have also uh the firmware files that are available uh on GitHub in uh some sub repositories. 2583.92s - 2589.92s | And globally all the code uh is available uh on GitHub under MIT license. 2590.92s - 2598.92s | So uh of course uh we are we also uh are making a call for contributors. 2599.92s - 2606.92s | So uh feel free to uh create compatible firmwares for uh your preferred hardware. 2607.92s - 2611.92s | To report any bugs, any issues you would encounter uh on GitHub. 2611.92s - 2617.92s | And if you want to help uh us by writing some documentation, 2618.92s - 2621.92s | by adding support for other protocols or other devices, 2622.92s - 2624.92s | uh we would be uh happy to have contributors. 2625.92s - 2629.92s | And if you like it uh spread the word and tell your friends. 2630.92s - 2632.92s | So uh two last words. 2633.92s - 2637.92s | So this is uh a work we initiated two years ago. 2637.92s - 2641.92s | Uh and uh here it was a very high level uh presentation. 2642.92s - 2646.92s | Uh so we only scratched the surface of what WAD is capable uh of. 2647.92s - 2651.92s | And uh we also want to uh warmly thank uh the many researchers 2652.92s - 2655.92s | that have uh


chunk_id: 143_chunk_38
chunk_text:
on GitHub under MIT license. 2590.92s - 2598.92s | So uh of course uh we are we also uh are making a call for contributors. 2599.92s - 2606.92s | So uh feel free to uh create compatible firmwares for uh your preferred hardware. 2607.92s - 2611.92s | To report any bugs, any issues you would encounter uh on GitHub. 2611.92s - 2617.92s | And if you want to help uh us by writing some documentation, 2618.92s - 2621.92s | by adding support for other protocols or other devices, 2622.92s - 2624.92s | uh we would be uh happy to have contributors. 2625.92s - 2629.92s | And if you like it uh spread the word and tell your friends. 2630.92s - 2632.92s | So uh two last words. 2633.92s - 2637.92s | So this is uh a work we initiated two years ago. 2637.92s - 2641.92s | Uh and uh here it was a very high level uh presentation. 2642.92s - 2646.92s | Uh so we only scratched the surface of what WAD is capable uh of. 2647.92s - 2651.92s | And uh we also want to uh warmly thank uh the many researchers 2652.92s - 2655.92s | that have uh better access uh to this project. 2656.92s - 2661.92s | And that uh helped us and provided some feedback uh on it. 2662.92s - 2664.92s | So I won't name them all but uh they know. 2665.92s - 2666.92s | Thank you very much. 2667.92s - 2670.92s | Uh and uh sorry for the small technical issues. 2671.92s - 2673.92s | We are ready if you have any question.


chunk_id: 143_chunk_39
chunk_text:
better access uh to this project. 2656.92s - 2661.92s | And that uh helped us and provided some feedback uh on it. 2662.92s - 2664.92s | So I won't name them all but uh they know. 2665.92s - 2666.92s | Thank you very much. 2667.92s - 2670.92s | Uh and uh sorry for the small technical issues. 2671.92s - 2673.92s | We are ready if you have any question.


chunk_id: 144_chunk_0
chunk_text:
{ "webpage_url": "https://www.youtube.com/watch?v=I1RqhGGRmHY", "title": "DEF CON 32 - Your AI Assistant has a Big Mouth: A New Side Channel Attack - Yisroel Mirsky", "description": "AI assistants like ChatGPT are changing how we interact with technology. But what if someone could read your confidential chats? Imagine awkwardly asking your AI about a strange rash, or to edit an email, only to have that conversation exposed to someone on the net. In this talk we'll unveil a novel side-channel vulnerability in popular AI assistants and demonstrate how it can be used to read encrypted messages sent from AI Assistants.\n\nBefore our disclosure, major players like OpenAI, Microsoft, Cloudflare, Quora, and Notion were at risk. We'll reveal the technical details of this exploit and show real-world examples of intercepted conversations. This talk isn't just about the problem \u2013 learn how to identify this vulnerability in other AI assistants as well! We'll dissect network traffic, discuss attack models, and explore the far-reaching consequences of this discovery.", "channel_url": "https://www.youtube.com/channel/UC6Om9kAkl32dWlDSNlDS9Iw", "duration": 2398, "channel": "DEFCONConference", "uploader": "DEFCONConference", "upload_date": "20241016" } 0.37s - 6.13s | This text was transcribed using whisper model: large-v2 Hello DEF CON! Thank you so much for being here. It's like the second-to-last 6.13s - 10.93s | talk. There's a great turnout. I'm very honored to be here. My name is Yusriel 10.93s - 16.05s | Emerski. I'm a Zuckerman Faculty Scholar at Ben-Gurion University and head of the 16.05s - 21.09s | Offensive AI Research Lab there. And with me here today are my brilliant graduate 21.09s - 24.57s | students who will be coming up on stage also to present. They did all the hard 24.57s - 30.13s | work. There's Daniel Eisenstein and Roy Weiss in collaboration with Guy Amit 30.13s - 36.53s | who couldn't make it. Okay, so today we're going to talk about a new side-channel 36.53s - 41.61s | attack against AI assistants that enables adversaries to read encrypted 41.61s - 50.65s | response traffic, such as responses from chat GPT. Okay, so I'm not going to go 50.65s - 53.69s | into, you know, what are AI assistants. You guys all know this very well. You have 53.69s - 59.05s | OpenAI's chat GPT, you have Google's Gemini, you have Microsoft Copilot, and 59.05s - 63.89s | the list goes on and on. And these AI assistants are integrated throughout 63.89s - 68.25s | industry in all


chunk_id: 144_chunk_1
chunk_text:
10.93s | talk. There's a great turnout. I'm very honored to be here. My name is Yusriel 10.93s - 16.05s | Emerski. I'm a Zuckerman Faculty Scholar at Ben-Gurion University and head of the 16.05s - 21.09s | Offensive AI Research Lab there. And with me here today are my brilliant graduate 21.09s - 24.57s | students who will be coming up on stage also to present. They did all the hard 24.57s - 30.13s | work. There's Daniel Eisenstein and Roy Weiss in collaboration with Guy Amit 30.13s - 36.53s | who couldn't make it. Okay, so today we're going to talk about a new side-channel 36.53s - 41.61s | attack against AI assistants that enables adversaries to read encrypted 41.61s - 50.65s | response traffic, such as responses from chat GPT. Okay, so I'm not going to go 50.65s - 53.69s | into, you know, what are AI assistants. You guys all know this very well. You have 53.69s - 59.05s | OpenAI's chat GPT, you have Google's Gemini, you have Microsoft Copilot, and 59.05s - 63.89s | the list goes on and on. And these AI assistants are integrated throughout 63.89s - 68.25s | industry in all different kinds of use cases. What's more interesting to me is 68.25s - 73.65s | the use cases of the personal level, right? A lot of users are using these AI 73.65s - 79.09s | assistants, such as chat GPT, to get personal advice. So, for example, you may 79.09s - 83.45s | ask it some medical questions, like, why do I have a rash on my back, right? And 83.45s - 86.93s | chat GPT will get back to you and say, oh, I'm sorry to hear you have a 86.93s - 91.33s | rash on your back. Let me give some tips how to take care of that. Or maybe 91.33s - 96.29s | you may ask chat GPT for some relationship advice. What are the signs 96.29s - 102.21s | I'm having, my wife is having an affair, right? And get some good tips on there. Or 102.21s - 105.29s | maybe you're getting into hacking and you're gonna ask chat GPT how to get 105.29s - 110.29s | into your neighbor's Wi-Fi, right? Lots of good use cases. Or my favorite, a lot of 110.29s - 115.25s | people are using chat GPT to edit their


chunk_id: 144_chunk_2
chunk_text:
different kinds of use cases. What's more interesting to me is 68.25s - 73.65s | the use cases of the personal level, right? A lot of users are using these AI 73.65s - 79.09s | assistants, such as chat GPT, to get personal advice. So, for example, you may 79.09s - 83.45s | ask it some medical questions, like, why do I have a rash on my back, right? And 83.45s - 86.93s | chat GPT will get back to you and say, oh, I'm sorry to hear you have a 86.93s - 91.33s | rash on your back. Let me give some tips how to take care of that. Or maybe 91.33s - 96.29s | you may ask chat GPT for some relationship advice. What are the signs 96.29s - 102.21s | I'm having, my wife is having an affair, right? And get some good tips on there. Or 102.21s - 105.29s | maybe you're getting into hacking and you're gonna ask chat GPT how to get 105.29s - 110.29s | into your neighbor's Wi-Fi, right? Lots of good use cases. Or my favorite, a lot of 110.29s - 115.25s | people are using chat GPT to edit their documents. They'll take whole documents 115.25s - 120.17s | or emails, dump it into chat GPT and say, hey, make it better. Or, you know, finish 120.17s - 124.13s | this paragraph, or what have you. And these are all very good and legitimate 124.13s - 128.17s | use cases. We're actually very productive for our society to help us, you know, 128.17s - 133.65s | progress and automate things. But the problem is that what happens if these 133.65s - 138.41s | chats aren't actually private? What happens if somebody could read these 138.45s - 144.17s | chats beyond, for example, OpenAI? Right, so this would be a huge breach in 144.17s - 152.09s | privacy. So, in truth, we know they're encrypted, right? So, you know, OpenAI is 152.09s - 157.05s | encrypting all the traffic going between the client and the servers. But is that 157.05s - 162.49s | enough? You know, maybe a little foreshadowing. So, let me go back to the 162.49s - 167.17s | beginning of this story here. So, several months ago, you know, late at night, I was 167.17s - 172.17s | using chat GPT for very important stuff, such as trying


chunk_id: 144_chunk_3
chunk_text:
documents. They'll take whole documents 115.25s - 120.17s | or emails, dump it into chat GPT and say, hey, make it better. Or, you know, finish 120.17s - 124.13s | this paragraph, or what have you. And these are all very good and legitimate 124.13s - 128.17s | use cases. We're actually very productive for our society to help us, you know, 128.17s - 133.65s | progress and automate things. But the problem is that what happens if these 133.65s - 138.41s | chats aren't actually private? What happens if somebody could read these 138.45s - 144.17s | chats beyond, for example, OpenAI? Right, so this would be a huge breach in 144.17s - 152.09s | privacy. So, in truth, we know they're encrypted, right? So, you know, OpenAI is 152.09s - 157.05s | encrypting all the traffic going between the client and the servers. But is that 157.05s - 162.49s | enough? You know, maybe a little foreshadowing. So, let me go back to the 162.49s - 167.17s | beginning of this story here. So, several months ago, you know, late at night, I was 167.17s - 172.17s | using chat GPT for very important stuff, such as trying to figure out, you know, 172.17s - 177.01s | what would the world be like if the entire, every country had ninjas, but 177.01s - 183.45s | Japan had the worst ninjas, right? So, as I'm looking at the text glide across the 183.45s - 188.01s | screen and looking at this very insightful and thoughtful response, it 188.01s - 194.25s | kind of hits me. Wait a second. Could it possibly be that OpenAI is sending 194.29s - 200.25s | every single word as a separate packet? And could it be that every single packet 200.25s - 208.01s | has no padding, so I can count the number of characters in each of these words? Hmm. 208.01s - 213.45s | So, I open up Wireshark, and sure enough, what do I see? For every single word 213.45s - 218.53s | that's being sent from the AI assistant, I see another packet, and the size of 218.53s - 223.41s | that packet increases. And if I take the Delta between these packets, I know 223.53s - 228.25s | exactly how many characters in every single word. And I could use this, for 228.25s - 234.73s | example, to try and


chunk_id: 144_chunk_4
chunk_text:
to figure out, you know, 172.17s - 177.01s | what would the world be like if the entire, every country had ninjas, but 177.01s - 183.45s | Japan had the worst ninjas, right? So, as I'm looking at the text glide across the 183.45s - 188.01s | screen and looking at this very insightful and thoughtful response, it 188.01s - 194.25s | kind of hits me. Wait a second. Could it possibly be that OpenAI is sending 194.29s - 200.25s | every single word as a separate packet? And could it be that every single packet 200.25s - 208.01s | has no padding, so I can count the number of characters in each of these words? Hmm. 208.01s - 213.45s | So, I open up Wireshark, and sure enough, what do I see? For every single word 213.45s - 218.53s | that's being sent from the AI assistant, I see another packet, and the size of 218.53s - 223.41s | that packet increases. And if I take the Delta between these packets, I know 223.53s - 228.25s | exactly how many characters in every single word. And I could use this, for 228.25s - 234.73s | example, to try and guess what those words are and potentially learn or 234.73s - 241.05s | identify what is being said in those responses. Now, before I go on to explain 241.05s - 244.21s | how we figured out what those words are, I need to take a little bit of a 244.21s - 248.89s | technical aside and clarify something. That what chat GPT and all these 248.89s - 253.05s | different AI services are sending are not exactly words, but rather something 253.05s - 259.97s | called tokens. What tokens are, are basically the basic building block of AI 259.97s - 265.29s | language models. When you give text to a language model, it's going to first parse 265.29s - 269.69s | it down into these tokens, and then each token goes to the model, and the model 269.69s - 275.69s | generates text using these tokens as well. So, in general, these tokens more or less 275.69s - 279.97s | correlate directly to words, but there are some cases where these tokens won't. 280.13s - 284.53s | So, for example, here, Lama's tokenizer will split the word cream into two 284.53s - 290.61s | separate tokens. But what's important to


chunk_id: 144_chunk_5
chunk_text:
guess what those words are and potentially learn or 234.73s - 241.05s | identify what is being said in those responses. Now, before I go on to explain 241.05s - 244.21s | how we figured out what those words are, I need to take a little bit of a 244.21s - 248.89s | technical aside and clarify something. That what chat GPT and all these 248.89s - 253.05s | different AI services are sending are not exactly words, but rather something 253.05s - 259.97s | called tokens. What tokens are, are basically the basic building block of AI 259.97s - 265.29s | language models. When you give text to a language model, it's going to first parse 265.29s - 269.69s | it down into these tokens, and then each token goes to the model, and the model 269.69s - 275.69s | generates text using these tokens as well. So, in general, these tokens more or less 275.69s - 279.97s | correlate directly to words, but there are some cases where these tokens won't. 280.13s - 284.53s | So, for example, here, Lama's tokenizer will split the word cream into two 284.53s - 290.61s | separate tokens. But what's important to note is that although there's not a 290.61s - 295.41s | direct correlation from token to word, these tokenizers are public information. 295.41s - 299.89s | It doesn't matter if it's open AIs, if it's metas, you can go through the entire 299.89s - 304.25s | list, you can get the tokenizer, you can learn the exact mappings. So, for all 304.25s - 307.65s | intensive purposes, these are words, and we're trying to guess what these words 307.65s - 317.47s | are. So, what's the threat model? So, the victim types some private chat into his 317.47s - 323.95s | web browser, hits enter, and that encrypted text goes across the wire. Now, 323.95s - 326.27s | we're not gonna be able to figure out what that prompt was, because that's just 326.27s - 331.27s | one big block of encrypted text. But what happens after that is the AI assistant 331.27s - 336.59s | starts responding token by token by token back, and we can count exactly how 336.59s - 339.71s | many characters are in each of these tokens. And once again, if we can guess 339.71s - 346.15s | what those words are, then boom, we


chunk_id: 144_chunk_6
chunk_text:
note is that although there's not a 290.61s - 295.41s | direct correlation from token to word, these tokenizers are public information. 295.41s - 299.89s | It doesn't matter if it's open AIs, if it's metas, you can go through the entire 299.89s - 304.25s | list, you can get the tokenizer, you can learn the exact mappings. So, for all 304.25s - 307.65s | intensive purposes, these are words, and we're trying to guess what these words 307.65s - 317.47s | are. So, what's the threat model? So, the victim types some private chat into his 317.47s - 323.95s | web browser, hits enter, and that encrypted text goes across the wire. Now, 323.95s - 326.27s | we're not gonna be able to figure out what that prompt was, because that's just 326.27s - 331.27s | one big block of encrypted text. But what happens after that is the AI assistant 331.27s - 336.59s | starts responding token by token by token back, and we can count exactly how 336.59s - 339.71s | many characters are in each of these tokens. And once again, if we can guess 339.71s - 346.15s | what those words are, then boom, we know exactly what the response was. So, why do 346.15s - 349.99s | we care? I mean, I can't figure out what the prompt was, I can't figure out what 349.99s - 356.79s | the exact question was, but it turns out that a lot of information is 356.79s - 361.55s | leaked by the response itself. So, imagine I read one of the responses off the 361.55s - 366.39s | network that somebody was receiving, and it said, I'm sorry to hear that you have 366.39s - 371.23s | a rash, right? I think it's pretty clear we know exactly what that user was 371.23s - 377.75s | asking for. So, basically this boils down to a big Wheel of Fortune game, right, 377.75s - 382.63s | where I have to start guessing what those words are. And this can be a 382.63s - 385.75s | particularly challenging problem, because, you know, there's many different ways you 385.75s - 390.11s | can solve this puzzle. But it gets even more challenging when you think about 390.11s - 394.19s | real responses from these AI assistants, right? They're not just one sentence, they 394.19s - 398.39s | typically hold paragraphs


chunk_id: 144_chunk_7
chunk_text:
know exactly what the response was. So, why do 346.15s - 349.99s | we care? I mean, I can't figure out what the prompt was, I can't figure out what 349.99s - 356.79s | the exact question was, but it turns out that a lot of information is 356.79s - 361.55s | leaked by the response itself. So, imagine I read one of the responses off the 361.55s - 366.39s | network that somebody was receiving, and it said, I'm sorry to hear that you have 366.39s - 371.23s | a rash, right? I think it's pretty clear we know exactly what that user was 371.23s - 377.75s | asking for. So, basically this boils down to a big Wheel of Fortune game, right, 377.75s - 382.63s | where I have to start guessing what those words are. And this can be a 382.63s - 385.75s | particularly challenging problem, because, you know, there's many different ways you 385.75s - 390.11s | can solve this puzzle. But it gets even more challenging when you think about 390.11s - 394.19s | real responses from these AI assistants, right? They're not just one sentence, they 394.19s - 398.39s | typically hold paragraphs with hundreds of words. So, how do we solve this 398.39s - 404.31s | problem? So, we turn to the age-old solution, which is AI, and we look towards 404.31s - 409.15s | a task which is very popular, which is language translation, right? But here, 409.15s - 414.59s | instead of going from a language such as French to English, we're gonna go from 414.59s - 420.83s | token length sequences to plain text English. And what we'll do is we'll train 420.83s - 427.07s | an AI with lots and lots of examples of these token lengths to real English, and 427.07s - 432.67s | we'll be able to translate them very effectively. In our case, we used a 432.67s - 437.99s | state-of-the-art model called a Large Language Model, or LLM, and this is the 437.99s - 443.23s | exact same technology that's being used in AI assistants such as ChatGPT. I'm 443.23s - 446.63s | not gonna go too much into detail how it works, leave that for other YouTube 446.63s - 450.91s | videos. Alright, so what's the entire attack end-to-end? How does it look like? 450.91s - 454.03s | So, the attacker is looking


chunk_id: 144_chunk_8
chunk_text:
with hundreds of words. So, how do we solve this 398.39s - 404.31s | problem? So, we turn to the age-old solution, which is AI, and we look towards 404.31s - 409.15s | a task which is very popular, which is language translation, right? But here, 409.15s - 414.59s | instead of going from a language such as French to English, we're gonna go from 414.59s - 420.83s | token length sequences to plain text English. And what we'll do is we'll train 420.83s - 427.07s | an AI with lots and lots of examples of these token lengths to real English, and 427.07s - 432.67s | we'll be able to translate them very effectively. In our case, we used a 432.67s - 437.99s | state-of-the-art model called a Large Language Model, or LLM, and this is the 437.99s - 443.23s | exact same technology that's being used in AI assistants such as ChatGPT. I'm 443.23s - 446.63s | not gonna go too much into detail how it works, leave that for other YouTube 446.63s - 450.91s | videos. Alright, so what's the entire attack end-to-end? How does it look like? 450.91s - 454.03s | So, the attacker is looking through the network, looking for responses from a 454.03s - 458.59s | particular AI service such as ChatGPT, sees the traffic going across the 458.59s - 463.19s | network, and records down the token length sequence from those packets. It 463.19s - 467.75s | then passes that token length sequence to his trained model, which has seen lots 467.75s - 471.87s | and lots of examples, and it predicts what it thinks the original plain text 471.87s - 478.91s | was. So, there's something else we can do to make this even better. So, if we just, 478.91s - 484.11s | you know, give our model random arbitrary text, it's gonna do so-so. It's not gonna 484.11s - 486.75s | do so great, because as I said, you know, there's lots of ways we can solve that 486.75s - 492.39s | puzzle. But as it turns out, AI assistants have a very specific style of speaking, 492.39s - 495.63s | right? They're not just gonna respond with some arbitrary sentence, they 495.63s - 499.23s | typically start with something like, oh sure, yeah, I can give you a recipe for 499.23s - 503.99s | tomato soup, right? So, there's a


chunk_id: 144_chunk_9
chunk_text:
through the network, looking for responses from a 454.03s - 458.59s | particular AI service such as ChatGPT, sees the traffic going across the 458.59s - 463.19s | network, and records down the token length sequence from those packets. It 463.19s - 467.75s | then passes that token length sequence to his trained model, which has seen lots 467.75s - 471.87s | and lots of examples, and it predicts what it thinks the original plain text 471.87s - 478.91s | was. So, there's something else we can do to make this even better. So, if we just, 478.91s - 484.11s | you know, give our model random arbitrary text, it's gonna do so-so. It's not gonna 484.11s - 486.75s | do so great, because as I said, you know, there's lots of ways we can solve that 486.75s - 492.39s | puzzle. But as it turns out, AI assistants have a very specific style of speaking, 492.39s - 495.63s | right? They're not just gonna respond with some arbitrary sentence, they 495.63s - 499.23s | typically start with something like, oh sure, yeah, I can give you a recipe for 499.23s - 503.99s | tomato soup, right? So, there's a certain style that's intrinsically in those 503.99s - 508.75s | responses. So, what I can do is, if I'm, let's say I'm trying to target Microsoft 508.75s - 514.59s | Copilot, I can send lots and lots of prompts to Microsoft Copilot and build a 514.59s - 520.11s | huge data set of responses. And those responses capture the style of that 520.11s - 525.11s | particular AI service. And once I have that, I can fine-tune my model on that, 525.11s - 530.07s | I'll get much, much better results. And as it turns out, I can get something 530.07s - 535.15s | around 55% attack success rate. So, more than half of the responses that we 535.15s - 540.87s | receive, if we see in the encrypted traffic, we can decipher. Okay, so let's 540.87s - 545.63s | look at some examples. So, on the screen here is the first sentences that we're 545.63s - 550.23s | trying to decipher. The first line is the original text that is being sent from 550.27s - 555.39s | the AI assistant. And the second line is our prediction. So, sometimes you can see 555.39s - 559.27s | in the first


chunk_id: 144_chunk_10
chunk_text:
certain style that's intrinsically in those 503.99s - 508.75s | responses. So, what I can do is, if I'm, let's say I'm trying to target Microsoft 508.75s - 514.59s | Copilot, I can send lots and lots of prompts to Microsoft Copilot and build a 514.59s - 520.11s | huge data set of responses. And those responses capture the style of that 520.11s - 525.11s | particular AI service. And once I have that, I can fine-tune my model on that, 525.11s - 530.07s | I'll get much, much better results. And as it turns out, I can get something 530.07s - 535.15s | around 55% attack success rate. So, more than half of the responses that we 535.15s - 540.87s | receive, if we see in the encrypted traffic, we can decipher. Okay, so let's 540.87s - 545.63s | look at some examples. So, on the screen here is the first sentences that we're 545.63s - 550.23s | trying to decipher. The first line is the original text that is being sent from 550.27s - 555.39s | the AI assistant. And the second line is our prediction. So, sometimes you can see 555.39s - 559.27s | in the first example there, we get it right on the first go. And sometimes we 559.27s - 565.15s | make some mistakes. So, for example, in the bottom there, the original response 565.15s - 570.03s | was, yes, there are several important legal considerations that couples should 570.03s - 575.91s | be aware of when considering a divorce. And then, if we look at the inferred 575.99s - 581.91s | response, we got, yes, there are several potential legal considerations that 581.91s - 585.59s | someone should be aware of when considering a divorce. So, even though we 585.59s - 590.19s | had some mistakes in the words, we're still, it's very, very clear what was the 590.19s - 598.35s | topic that the user was trying to ask the AI assistant. And then, if we move 598.35s - 603.11s | over to entire paragraphs, we get something around a 35% attack success 603.11s - 608.07s | rate, which is also very significant, considering how hard it is to try and 608.07s - 613.27s | guess what all these words are. And since we're using AI models, this isn't a 613.27s - 616.99s | perfect science. You know, we're using a lot


chunk_id: 144_chunk_11
chunk_text:
example there, we get it right on the first go. And sometimes we 559.27s - 565.15s | make some mistakes. So, for example, in the bottom there, the original response 565.15s - 570.03s | was, yes, there are several important legal considerations that couples should 570.03s - 575.91s | be aware of when considering a divorce. And then, if we look at the inferred 575.99s - 581.91s | response, we got, yes, there are several potential legal considerations that 581.91s - 585.59s | someone should be aware of when considering a divorce. So, even though we 585.59s - 590.19s | had some mistakes in the words, we're still, it's very, very clear what was the 590.19s - 598.35s | topic that the user was trying to ask the AI assistant. And then, if we move 598.35s - 603.11s | over to entire paragraphs, we get something around a 35% attack success 603.11s - 608.07s | rate, which is also very significant, considering how hard it is to try and 608.07s - 613.27s | guess what all these words are. And since we're using AI models, this isn't a 613.27s - 616.99s | perfect science. You know, we're using a lot of heuristics here. So, we sometimes 616.99s - 621.79s | get it wrong. So, here's some fails. So, in the ground truth, it was something 621.79s - 624.59s | like, I would like to suggest some following strategies for team leaders to 624.59s - 628.79s | balance the needs of individual team members with the needs of the team as a 628.79s - 634.03s | whole. And we inferred it as, I would suggest the following strategies, so far 634.03s - 639.07s | so good, but then for film studios to balance the needs of production, so on 639.07s - 642.39s | and so forth. Something that's completely unrelated. And sometimes it gets even 642.39s - 646.27s | worse, right? So, here's a case where the response has something to do with apple 646.27s - 650.39s | cider, and we thought it had to do with coral bleaching. Okay, so it's not a 650.39s - 653.99s | perfect science, but what's interesting to note is that because we're using 653.99s - 657.99s | machine learning model, the model also gives us a confidence score. How 657.99s - 663.59s | confident it is that this prediction is correct, right? So, what


chunk_id: 144_chunk_12
chunk_text:
of heuristics here. So, we sometimes 616.99s - 621.79s | get it wrong. So, here's some fails. So, in the ground truth, it was something 621.79s - 624.59s | like, I would like to suggest some following strategies for team leaders to 624.59s - 628.79s | balance the needs of individual team members with the needs of the team as a 628.79s - 634.03s | whole. And we inferred it as, I would suggest the following strategies, so far 634.03s - 639.07s | so good, but then for film studios to balance the needs of production, so on 639.07s - 642.39s | and so forth. Something that's completely unrelated. And sometimes it gets even 642.39s - 646.27s | worse, right? So, here's a case where the response has something to do with apple 646.27s - 650.39s | cider, and we thought it had to do with coral bleaching. Okay, so it's not a 650.39s - 653.99s | perfect science, but what's interesting to note is that because we're using 653.99s - 657.99s | machine learning model, the model also gives us a confidence score. How 657.99s - 663.59s | confident it is that this prediction is correct, right? So, what we can do is we can 663.59s - 666.99s | look, and we're trying to attack a particular, you know, token-linked 666.99s - 670.11s | sequence that we see in the network. We can try to look at the confidence of the 670.11s - 676.89s | model and say whether or not we should trust this inference or not. Alright, so 676.89s - 683.61s | how common is this vulnerability? So, you know, around the time of our disclosure, 683.61s - 688.89s | or prior to our disclosure around February 2024, nearly every major AI 688.89s - 693.33s | vendor out there had this vulnerability. And, you know, when you start wondering 693.33s - 697.37s | why is that the case? How do they overlook the seemingly obvious side 697.37s - 702.45s | channel? And there's a few reasons that might come to mind. First, you know, they 702.45s - 705.65s | might, perhaps they didn't think that token links the same as word links, so 705.65s - 709.65s | maybe there was just a simple blunder. Or maybe they thought there's no way that 709.65s - 713.93s | an adversary can guess entire paragraphs of text. That's just too


chunk_id: 144_chunk_13
chunk_text:
we can do is we can 663.59s - 666.99s | look, and we're trying to attack a particular, you know, token-linked 666.99s - 670.11s | sequence that we see in the network. We can try to look at the confidence of the 670.11s - 676.89s | model and say whether or not we should trust this inference or not. Alright, so 676.89s - 683.61s | how common is this vulnerability? So, you know, around the time of our disclosure, 683.61s - 688.89s | or prior to our disclosure around February 2024, nearly every major AI 688.89s - 693.33s | vendor out there had this vulnerability. And, you know, when you start wondering 693.33s - 697.37s | why is that the case? How do they overlook the seemingly obvious side 697.37s - 702.45s | channel? And there's a few reasons that might come to mind. First, you know, they 702.45s - 705.65s | might, perhaps they didn't think that token links the same as word links, so 705.65s - 709.65s | maybe there was just a simple blunder. Or maybe they thought there's no way that 709.65s - 713.93s | an adversary can guess entire paragraphs of text. That's just too hard of a 713.93s - 717.85s | problem. But what I think is more likely the case is that it has something to do 717.85s - 722.65s | with the big AI gold rush, right? There's so many industries that are jumping on 722.65s - 726.97s | the AI chatbot idea and throwing it into services willy-nilly, and they don't 726.97s - 729.93s | really think about security by design. They're saying, you know, the text is 729.93s - 735.33s | encrypted, not a big deal, let's move on, right? So this is probably more likely 735.33s - 741.13s | what happened there until they, of course, patched it after the fact. So why are 741.13s - 745.73s | they even sending, you know, text to streaming, or token streaming across the 745.73s - 750.97s | network? Why don't they just send as one big batch, right? So for example, Google's 750.97s - 755.81s | Gemini does this already. When you get a response from Google Gemini, it's not 755.81s - 759.57s | sending a token, token, token, it sends as one big block, and therefore they're not 759.57s - 762.57s | vulnerable to the side channel attack. So why


chunk_id: 144_chunk_14
chunk_text:
hard of a 713.93s - 717.85s | problem. But what I think is more likely the case is that it has something to do 717.85s - 722.65s | with the big AI gold rush, right? There's so many industries that are jumping on 722.65s - 726.97s | the AI chatbot idea and throwing it into services willy-nilly, and they don't 726.97s - 729.93s | really think about security by design. They're saying, you know, the text is 729.93s - 735.33s | encrypted, not a big deal, let's move on, right? So this is probably more likely 735.33s - 741.13s | what happened there until they, of course, patched it after the fact. So why are 741.13s - 745.73s | they even sending, you know, text to streaming, or token streaming across the 745.73s - 750.97s | network? Why don't they just send as one big batch, right? So for example, Google's 750.97s - 755.81s | Gemini does this already. When you get a response from Google Gemini, it's not 755.81s - 759.57s | sending a token, token, token, it sends as one big block, and therefore they're not 759.57s - 762.57s | vulnerable to the side channel attack. So why aren't the other vendors doing this? 762.57s - 767.37s | So there's a simple answer for that, and the answer is that, you know, these AI 767.37s - 771.93s | models are actually incredibly complex, and it takes a lot of effort to execute 771.97s - 775.97s | them. So instead of having the user wait there for, you know, a good, you know, 30 775.97s - 780.21s | seconds for this loading screen to go by to get their response, it makes perfect 780.21s - 785.13s | sense to send those words or tokens one at a time in real time, so they can read 785.13s - 791.61s | it as it's being generated. All right, so to recap so far, what we've accomplished 791.61s - 796.09s | here is that we've discovered a novel side channel attack, which we call the 796.09s - 801.29s | token length side channel, and we found it's common in LLM services all over. And 801.29s - 807.77s | we've also found a way to exploit that side channel to read the hidden 807.77s - 813.05s | information behind it directly using AI, and improve that performance using a 813.05s - 819.58s |


chunk_id: 144_chunk_15
chunk_text:
aren't the other vendors doing this? 762.57s - 767.37s | So there's a simple answer for that, and the answer is that, you know, these AI 767.37s - 771.93s | models are actually incredibly complex, and it takes a lot of effort to execute 771.97s - 775.97s | them. So instead of having the user wait there for, you know, a good, you know, 30 775.97s - 780.21s | seconds for this loading screen to go by to get their response, it makes perfect 780.21s - 785.13s | sense to send those words or tokens one at a time in real time, so they can read 785.13s - 791.61s | it as it's being generated. All right, so to recap so far, what we've accomplished 791.61s - 796.09s | here is that we've discovered a novel side channel attack, which we call the 796.09s - 801.29s | token length side channel, and we found it's common in LLM services all over. And 801.29s - 807.77s | we've also found a way to exploit that side channel to read the hidden 807.77s - 813.05s | information behind it directly using AI, and improve that performance using a 813.05s - 819.58s | known plaintext attack. Okay, so for the rest of this talk, we're going to get 819.58s - 823.10s | down into the nitty-gritty details, and first we're going to talk about how we 823.10s - 829.02s | identified response traffic inside network traffic, and how we then extract 829.02s - 832.94s | the token length sequences from there, and after that we'll talk a little bit 832.94s - 838.54s | about how we train AI models, and our specific RAI model, and finally we'll end 838.54s - 841.90s | off with some demos, defenses, and we'll talk about some bug bounties that we got 841.90s - 846.02s | along the way. So with that I'm going to hand it off to Daniel, who's going to 846.02s - 857.62s | take it from here. Thanks Israel. So let's jump to the nitty-gritty details. So we 857.62s - 861.18s | will talk about how to find the sign channel, and how to extract the token 861.18s - 869.77s | length sequence. So the first thing we'll have to do is to capture the traffic 869.81s - 874.17s | containing the response from the assistant. So we'll need to be positioned 874.17s -


chunk_id: 144_chunk_16
chunk_text:
known plaintext attack. Okay, so for the rest of this talk, we're going to get 819.58s - 823.10s | down into the nitty-gritty details, and first we're going to talk about how we 823.10s - 829.02s | identified response traffic inside network traffic, and how we then extract 829.02s - 832.94s | the token length sequences from there, and after that we'll talk a little bit 832.94s - 838.54s | about how we train AI models, and our specific RAI model, and finally we'll end 838.54s - 841.90s | off with some demos, defenses, and we'll talk about some bug bounties that we got 841.90s - 846.02s | along the way. So with that I'm going to hand it off to Daniel, who's going to 846.02s - 857.62s | take it from here. Thanks Israel. So let's jump to the nitty-gritty details. So we 857.62s - 861.18s | will talk about how to find the sign channel, and how to extract the token 861.18s - 869.77s | length sequence. So the first thing we'll have to do is to capture the traffic 869.81s - 874.17s | containing the response from the assistant. So we'll need to be positioned 874.17s - 879.69s | between the victim and the assistant. Or we can be in the same local network as 879.69s - 885.73s | the victim, for example sitting in the same cafe using WiFi. So we collected a lot 885.73s - 890.61s | of traffic, and not all of it containing our response data from the AI assistant. 890.61s - 894.81s | So we'll need to filter the traffic. We can do that by filtering by the IP 894.81s - 900.35s | address of the assistant. Uh that information can be collected by OSINT, or by 900.35s - 905.09s | connecting as a legitimate client to the assistant server for through different times 905.09s - 911.13s | a day, from different locations, and making our own data set of those IP addresses, and 911.13s - 918.01s | basically filtering by those. Also what we can do is filter by the protocol. So every uh 918.01s - 923.31s | vendor is using different protocol. For example ChetGPT is using quick protocol, so we 923.31s - 929.45s | would like to search for UDP packets that are coming from port 443. And again, every 929.45s - 934.39s | vendor is using different protocol,


chunk_id: 144_chunk_17
chunk_text:
879.69s | between the victim and the assistant. Or we can be in the same local network as 879.69s - 885.73s | the victim, for example sitting in the same cafe using WiFi. So we collected a lot 885.73s - 890.61s | of traffic, and not all of it containing our response data from the AI assistant. 890.61s - 894.81s | So we'll need to filter the traffic. We can do that by filtering by the IP 894.81s - 900.35s | address of the assistant. Uh that information can be collected by OSINT, or by 900.35s - 905.09s | connecting as a legitimate client to the assistant server for through different times 905.09s - 911.13s | a day, from different locations, and making our own data set of those IP addresses, and 911.13s - 918.01s | basically filtering by those. Also what we can do is filter by the protocol. So every uh 918.01s - 923.31s | vendor is using different protocol. For example ChetGPT is using quick protocol, so we 923.31s - 929.45s | would like to search for UDP packets that are coming from port 443. And again, every 929.45s - 934.39s | vendor is using different protocol, so we'll need to account for that. And also there is a 934.39s - 939.09s | slight problem because it will add us more complexity when we will try to extract the token 939.09s - 944.43s | length uh sequence, because again, every protocol looks differently on the wire, and it 944.43s - 952.45s | has its own metadata. So we captured the traffic, we filtered out most of the traffic 952.45s - 957.25s | that don't contain our tokens, we have the traffic that contains the response from the 957.25s - 964.72s | assistant, let's extract the token length sequence. So our objective is to find the token 964.72s - 970.16s | lengths. We need to remember that the traffic is encrypted, so we can't really see where are 970.16s - 976.16s | the tokens, and what packets contain them. But what we can see is the bandwidth patterns, 976.16s - 994.34s | basically the packet sizes. I'm sorry. So we found that there is two main ways that the 994.34s - 999.78s | vendors are using to send their tokens. The first way is base plus next token. Basically 999.78s - 1005.88s | each token is sent in


chunk_id: 144_chunk_18
chunk_text:
so we'll need to account for that. And also there is a 934.39s - 939.09s | slight problem because it will add us more complexity when we will try to extract the token 939.09s - 944.43s | length uh sequence, because again, every protocol looks differently on the wire, and it 944.43s - 952.45s | has its own metadata. So we captured the traffic, we filtered out most of the traffic 952.45s - 957.25s | that don't contain our tokens, we have the traffic that contains the response from the 957.25s - 964.72s | assistant, let's extract the token length sequence. So our objective is to find the token 964.72s - 970.16s | lengths. We need to remember that the traffic is encrypted, so we can't really see where are 970.16s - 976.16s | the tokens, and what packets contain them. But what we can see is the bandwidth patterns, 976.16s - 994.34s | basically the packet sizes. I'm sorry. So we found that there is two main ways that the 994.34s - 999.78s | vendors are using to send their tokens. The first way is base plus next token. Basically 999.78s - 1005.88s | each token is sent in a separate packet by itself, so we can infer the size of the token by 1005.88s - 1011.72s | just analyzing the size of the packet. The second way is token accumulation. Basically the 1011.72s - 1017.16s | tokens accumulate. We are sending each time the token with all of the tokens that were 1017.16s - 1022.84s | previously sent, so the packets are increasing in size. In the next slides we'll talk more 1022.84s - 1028.74s | about token accumulation, because this is the way uh that Microsoft and OpenAI are using, so 1028.74s - 1033.74s | basically our tar- main target was JGPT, so we'll talk about this more. So to simplify the 1036.02s - 1042.18s | problem, we'll first try to identify which uh messages, which packets are containing the 1042.18s - 1047.20s | response. So to simplify it, let's try to find the start and the end. So again we can analyze 1047.56s - 1052.56s | the bandwidth patterns and we found out that at the beginning, at the end of the response, we 1055.50s - 1060.84s | saw uh bumps like increases in the packet sizes. That's because at the beginning you have 1060.84s -


chunk_id: 144_chunk_19
chunk_text:
a separate packet by itself, so we can infer the size of the token by 1005.88s - 1011.72s | just analyzing the size of the packet. The second way is token accumulation. Basically the 1011.72s - 1017.16s | tokens accumulate. We are sending each time the token with all of the tokens that were 1017.16s - 1022.84s | previously sent, so the packets are increasing in size. In the next slides we'll talk more 1022.84s - 1028.74s | about token accumulation, because this is the way uh that Microsoft and OpenAI are using, so 1028.74s - 1033.74s | basically our tar- main target was JGPT, so we'll talk about this more. So to simplify the 1036.02s - 1042.18s | problem, we'll first try to identify which uh messages, which packets are containing the 1042.18s - 1047.20s | response. So to simplify it, let's try to find the start and the end. So again we can analyze 1047.56s - 1052.56s | the bandwidth patterns and we found out that at the beginning, at the end of the response, we 1055.50s - 1060.84s | saw uh bumps like increases in the packet sizes. That's because at the beginning you have 1060.84s - 1065.94s | this all of those handshakes and establishing of the new channel and at the end you have 1065.94s - 1071.58s | those uh communication of the end of the response. So you have those increases and we can 1071.60s - 1077.28s | basically find the start and the end. Between those two points, the start and the end, we'll 1077.28s - 1084.13s | try to search for this incremental pattern, the red line that you see. The packets that 1084.13s - 1089.77s | follow this trend contain our tokens, but sometimes we have packets that don't follow this 1089.77s - 1095.51s | trend. Those are sometimes control packets that do not have our tokens, so we'll filter those 1095.51s - 1102.51s | out and we will be left after that filtering with a nice and smooth incremental pattern from 1102.53s - 1107.53s | which we can extract our token links by calculating the delta as Israel said. So it sounds 1110.87s - 1115.87s | pretty simple and some would say even easy and too good to be true and in reality it's really 1118.21s - 1124.35s | the case so we have more challenges. The first challenge is


chunk_id: 144_chunk_20
chunk_text:
1065.94s | this all of those handshakes and establishing of the new channel and at the end you have 1065.94s - 1071.58s | those uh communication of the end of the response. So you have those increases and we can 1071.60s - 1077.28s | basically find the start and the end. Between those two points, the start and the end, we'll 1077.28s - 1084.13s | try to search for this incremental pattern, the red line that you see. The packets that 1084.13s - 1089.77s | follow this trend contain our tokens, but sometimes we have packets that don't follow this 1089.77s - 1095.51s | trend. Those are sometimes control packets that do not have our tokens, so we'll filter those 1095.51s - 1102.51s | out and we will be left after that filtering with a nice and smooth incremental pattern from 1102.53s - 1107.53s | which we can extract our token links by calculating the delta as Israel said. So it sounds 1110.87s - 1115.87s | pretty simple and some would say even easy and too good to be true and in reality it's really 1118.21s - 1124.35s | the case so we have more challenges. The first challenge is message size limits and the 1124.35s - 1129.61s | second one is message buffering uh that will cause message groupings. So let's talk about 1129.65s - 1135.63s | that. Message size limits. In the internet we have this thing called MTU, Maximum 1135.63s - 1140.97s | Transmission Units. Basically a maximum size that the packet can have and if we go above this 1140.97s - 1145.97s | value we we can be fragmented on the IP layer. And what we found is ChetGPT over QUIC has even 1148.91s - 1153.91s | a lower maximum size uh of 1,200 bytes. And as you remember ChetGPT is accumulating its 1153.91s - 1158.93s | tokens so at certain point it will reach this maximum size. So what will happen is basically 1163.83s - 1169.93s | that the payload will overflow to the next packet. So now we have two packets that are sending 1169.93s - 1175.33s | this token because our payload is just too big. And what will happen is basically the sort of 1175.33s - 1181.47s | pattern that you see now and also as the conversation grows and goes deeper and deeper and 1181.47s - 1186.05s | makes it more


