<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Liam Wisehart]]></title><description><![CDATA[Notes on tech, security, AI]]></description><link>https://www.liamcvw.com</link><image><url>https://substackcdn.com/image/fetch/$s_!ZDu1!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d256547-328e-4f0c-86b7-591c7a754c64_1254x1254.png</url><title>Liam Wisehart</title><link>https://www.liamcvw.com</link></image><generator>Substack</generator><lastBuildDate>Wed, 19 Aug 2026 02:09:22 GMT</lastBuildDate><atom:link href="https://www.liamcvw.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Liam Wisehart]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[lcvw@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[lcvw@substack.com]]></itunes:email><itunes:name><![CDATA[Liam Wisehart]]></itunes:name></itunes:owner><itunes:author><![CDATA[Liam Wisehart]]></itunes:author><googleplay:owner><![CDATA[lcvw@substack.com]]></googleplay:owner><googleplay:email><![CDATA[lcvw@substack.com]]></googleplay:email><googleplay:author><![CDATA[Liam Wisehart]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Security After Remote Attestation]]></title><description><![CDATA[For what happens after boot]]></description><link>https://www.liamcvw.com/p/security-after-remote-attestation</link><guid isPermaLink="false">https://www.liamcvw.com/p/security-after-remote-attestation</guid><dc:creator><![CDATA[Liam Wisehart]]></dc:creator><pubDate>Wed, 22 Jul 2026 12:10:45 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!FaN2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d685120-c07e-49a5-90ac-b526955f2bcd_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the <a href="https://www.liamcvw.com/p/remote-attestation">previous</a> post I talked about how we can remotely attest and trust hosts. This led to a <a href="https://news.ycombinator.com/item?id=48839397">spirited discussion</a> on hacker news.</p><p>There were some good points about vendor lock in and the (supposed) death of general purpose computing. There are always tradeoffs. But the truth is that for the most part you don&#8217;t want a 100% general purpose computer. You want a device that does exactly what <strong>you</strong> want it to do, and not much else.</p><p>I don&#8217;t want my router to DDOS the internet.</p><p>I don&#8217;t want my phone or other devices to spy on me (any more then they already do!)</p><p>I don&#8217;t want my laptop to encrypt all my files and extort me for the decryption key.</p><p>And at work, I want my servers to run production workloads, not malware.</p><p>So how do we make that happen? It takes a lot more then just remote attestation. That was just the first step.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FaN2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d685120-c07e-49a5-90ac-b526955f2bcd_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FaN2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d685120-c07e-49a5-90ac-b526955f2bcd_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!FaN2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d685120-c07e-49a5-90ac-b526955f2bcd_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!FaN2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d685120-c07e-49a5-90ac-b526955f2bcd_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!FaN2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d685120-c07e-49a5-90ac-b526955f2bcd_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FaN2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d685120-c07e-49a5-90ac-b526955f2bcd_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2d685120-c07e-49a5-90ac-b526955f2bcd_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2599150,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.liamcvw.com/i/206354161?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d685120-c07e-49a5-90ac-b526955f2bcd_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!FaN2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d685120-c07e-49a5-90ac-b526955f2bcd_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!FaN2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d685120-c07e-49a5-90ac-b526955f2bcd_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!FaN2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d685120-c07e-49a5-90ac-b526955f2bcd_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!FaN2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d685120-c07e-49a5-90ac-b526955f2bcd_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p style="text-align: center;"><em>I want the train to stay on the tracks.</em></p><p>If you haven&#8217;t read the previous post about remote attestation, a lot of this post will not make sense. So go read <a href="https://www.liamcvw.com/p/remote-attestation">that</a> first.</p><p>So now that the host was booted in a way we can trust, how do we maintain that trust? How do we prove at any given moment that a host should still be trusted?</p><p><strong>We can&#8217;t.</strong></p><p>Once a computer has booted it can do more or less anything, and the problem space rapidly expands to be unmanageable. How can I scan every byte of memory, every file, every packet, and prove that a host isn&#8217;t compromised? It is an intractable problem. </p><p>I can&#8217;t just grab a host of the rack and prove that it should be trusted. But <strong>I can start a host in a way that it is significantly harder for it to go off the rails later, and then prove at boot that the host has those guardrails.</strong></p><p>Some example guardrails:</p><ul><li><p>Only trusted code can be run in the kernel (signed kernel modules)</p></li><li><p>Only trusted code can have root, or maybe only trusted code can run at all (signed binaries)</p></li><li><p>System files can&#8217;t be overwritten (immutable filesystem)</p></li><li><p>The EDR (Endpoint Detect and Respond) is running</p></li><li><p>My LSM (Linux Security Module) rules of choice are engaged</p></li><li><p>It goes on&#8230;</p></li></ul><p>If we can lock down enough of the different directions a system can go in, we make our attacker&#8217;s life that much harder. <strong>We have this one shot, at the beginning, where we have the crypto that backs up a claim about the state of the system.</strong> If that claim includes a bunch of security features, then we know that (at least at one point in time), those security features where on, and that an attacker&#8217;s life is that much harder.</p><p>Also all of our logs can be signed with the LDevID we minted as part of remote attestation, which makes them unspoofable, which is a neat property.</p><h2>dm-verity</h2><p>The best guardrail is to make things immutable. If state simply can&#8217;t be changed after boot then we have nothing to worry about. The train <strong>can&#8217;t</strong> leave the tracks.</p><p>dm-verity is kernel level block device verification, originally developed for android. It makes whatever filesystem it is applied to immutable and allows recording a hash of the filesystem contents so the kernel can detect tampering. If the filesystem is changed (even out of band, say by someone writing to the device directly) the kernel can detect that modification.</p><p>This verification is done efficiently using a <a href="https://en.wikipedia.org/wiki/Merkle_tree">Merkle tree</a>. TLDR a Merkle tree speeds up hashing by constructing a tree of blocks that contain the raw bytes of the image. Instead of a naive hash which has time complexity N with respect to the number of blocks (it has to touch each one), hashing a Merkle tree has time complexity log N to validate the contents of a block. The root hash is what we save/sign, and what will be changed if any block in the tree is modified.</p><p>The way to think about it is like this. I can&#8217;t efficiently record the hash of every block. I want just a single hash that tells me &#8220;was the filesystem changed or not.&#8221; We want a single hash for the whole filesystem. And we can&#8217;t just hash the whole filesystem on each read for obvious reasons. Instead we store the root hash of the Merkle tree, and walk the tree from leaf to root every time a block is read, and check that the root hash computes correctly.</p><p>The reason this works is that each node&#8217;s hash is the hash of child nodes. Walking up the tree from one leaf to the root, only sibling nodes need to be explored. This sounds expensive, and is by some standards (performance numbers vary heavily by workload), but the kernel caches pages in the page cache, and the tree itself, keeping things fast in most cases.</p><p>The point of this exercise is that any mutation invalidates the root hash. We can keep that root hash somewhere we attested (like the kernel command line) or sign it, if the dm-verity partition is not included in the measured boot.</p><h2>Upgrading Immutable Systems</h2><p>dm-verity makes your filesystem completely immutable. If you are using dm-verity with your root filesystem, then you can&#8217;t update it without a reboot, which also involves rolling over your boot measurements. This is unfortunate, but we can at least mitigate the issue of always needing to roll over your boot measurements to upgrade parts of the system. In modern deployments the actual product/business logic is deployed in a container, which we will ignore for now, except to state that the host can measure this container and the container can measure the host, to ensure that both sides of the equation check out. Also if a host doesn&#8217;t have valid certificates from the CA (which it needs to attest to get) the container orchestrator should refuse to schedule jobs on the host.</p><p>But how do we upgrade everything on the system (everything outside the container)? The usual solution is to have multiple dm-verity devices. The root/boot device is minimal and contains things that are rarely upgraded anyway (like systemd and glibc). Then we install additional dm-verity images. The root hash of each image is signed, with a public key we trust. So we only attested the root image and the public keys we accept. <strong>All other components are signed not attested</strong>, making life easier.</p><p>In order to have a cohesive system, each image is unpacked, then using overlayfs we layer the different dm-verity images together to create a cohesive virtual filesystem (VFS). overlayfs takes a lower and upper directory and combines them to form a virtual directory where the contents of upperdir are overlayed on lowerdir. This allows us to have, say, a single /usr/local/bin, that combines binaries from many different signed, dm-verity images.</p><p>Systemd can manage this for us (because of course it can). systemd-sysext exists to manage binary dm-verity images and systemd-confext exists to manage system configuration images (/etc). The main difference is that confext leaves /etc with a writeable overlay on top since some applications expect /etc to be writeable, whereas you don&#8217;t expect binaries to be mutable.</p><p>You still need some other mutability, usually /var and /tmp is left writeable for applications that need logging, storing certificates, tmp files, and of course containers generally need storage as well. We encrypt /var with a TPM sealed key and /tmp is ephemeral, so if boot artifacts are changed a reboot bricks the system and access to any data is blocked.</p><p>We can mount things that are mutable as NOEXEC to prevent people from circumventing this system to some degree. Ideally, we want only binaries on signed images to be executed. But an attacker can still drop scripts and execute them through an approved interpreter (say shell scripts). There is work in the kernel for a <a href="https://lwn.net/Articles/980872/">cooperative system</a> where scripting interpreters would treat scripts like binaries and use a special execveat flag to check if they can be executed. I wouldn&#8217;t rely on something like this since it is cooperative (though if you only install scripting languages that cooperate then it works). Instead, I prefer writing (arguably highly invasive) LSM rules which I&#8217;ll talk about more in later posts. SELinux in particular can be used to lock this kind of thing down effectively.</p><h2>fs-verity</h2><p>fs-verity gets an honorable mention here, since it will come up in later posts. It is the exact same idea as dm-verity but for specific files on an otherwise mutable filesystem. Not all filesystems support it, but many major ones do.</p><p>The nice thing about fs-verity is that it very quickly gives you a Merkle tree hash of a file that you can either store somewhere or sign. The built-in fs-verity signing mechanism is imperfect but works fine for many cases, it uses public keys stored in a specific keyring to validate a root hash. But when the official kernel docs <a href="https://docs.kernel.org/filesystems/fsverity.html">caution</a> you against using this signature method, you should take note. They recommend IMA or userspace validation, I personally like using eBPF LSM (yet another post there).</p><p>fs-verity is for filesystems where you can&#8217;t make the whole image immutable. You can still insist on key files being immutable and signed.</p><h2>Signed Kernel Modules</h2><p>A malicious kernel module breaks all security measures in a system instantly. Since the kernel provides many of these security primitives, a kernel module can trivially bypass such measures.</p><p>Many kernel modules are packaged in the initrd/initramfs of a system. These are attested as part of boot and we don&#8217;t have to worry about those. But often there are additional kernel modules that need to be loaded during runtime. They <a href="https://www.kernel.org/doc/html/v4.10/admin-guide/module-signing.html">can be signed</a> and you should enforce that only signed modules can be loaded.</p><h2>LSM Rules</h2><p>There are a lot of LSM things out there, and this post is starting to get long. Long story short, if you enable your LSM rules in some attested artifact, then you know they were engaged and those LSM rules can prevent themselves from being disabled. There are a couple of interesting LSMs that are commonly used:</p><ul><li><p>Lockdown &#8212; protects the kernel from many tampering avenues: kernel modules, debugging, raw memory etc.</p></li><li><p>Yama &#8212; Enforces a more restrictive hierarchy on ptrace and friends, signals, etc. Normally all processes from the same user can ptrace each other leading to excessive lateral movement.</p></li><li><p>IMA &#8212; TPM PCR measurement and immutability of chosen files and directories. As well as an immutable log of what was executed.</p></li><li><p>AppArmor &#8212; Sandboxing/privilege reduction of services based on paths. Easy to use, but has some known methods of abuse. Heavily used in Ubuntu.</p></li><li><p>Landlock &#8212; Newer, filesystem sandboxing, more features are being added all the time.</p></li><li><p>SELinux &#8212; By far the most comprehensive LSM out there (developed by the NSA). Be warned, it is extremely complicated. On one project I was on, 2 people out of a team of 15 worked more or less full time on the SELinux policy. But it allows you to express almost anything you could want in LSM rules. More associated with Redhat/CentOS.</p></li><li><p>eBPF &#8212; You can write arbitrary eBPF LSM programs. This has been my primary occupation for the last few years, so there will be a lot more on this in later posts.</p></li></ul><p>Regardless of what LSMs you are using, you are going to pick the ones that provide the properties you want and then attest that they were engaged. Once active, they provide additional guardrails to keep the system in line with what is expected.</p><p>You need to use both Mandatory Access Control (MAC) like an LSM and Discretionary Access Control (DAC) like Unix users/groups to get defense in depth on a system. I&#8217;m not touching DAC since that&#8217;s pretty well understood and a lot has been written about it. One thing that is rarely mentioned is that ephemeral users per-service or per-container can be far more effective then the usual shared user/group setup (and thus the need for an LSM for Yama).</p><h2>Wrap Up</h2><p>This is not at all a comprehensive post of immutable systems/post-attestation guardrails. But hopefully it gives an idea of what is possible. Properly constructed, you can drastically narrow the post-exploit movement of an attacker that has a foothold on a system.</p><p>I haven&#8217;t touched on networking restrictions, but those are possible as well. I also haven&#8217;t talked about EDRs (security monitoring and telemetry), most companies buy those though some open source ones like Falco are available.</p>]]></content:encoded></item><item><title><![CDATA[Remote Attestation]]></title><description><![CDATA[If it quacks like a duck...]]></description><link>https://www.liamcvw.com/p/remote-attestation</link><guid isPermaLink="false">https://www.liamcvw.com/p/remote-attestation</guid><dc:creator><![CDATA[Liam Wisehart]]></dc:creator><pubDate>Thu, 09 Jul 2026 00:31:17 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!A0EF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ab9008a-68c9-4f18-8615-2d1d4462dbcd_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A host connects to your network. It looks like part of your fleet, but is it really? It runs your software, or at least enough of it to start serving traffic. It quacks like a duck. But what&#8217;s on the inside?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!A0EF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ab9008a-68c9-4f18-8615-2d1d4462dbcd_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!A0EF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ab9008a-68c9-4f18-8615-2d1d4462dbcd_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!A0EF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ab9008a-68c9-4f18-8615-2d1d4462dbcd_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!A0EF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ab9008a-68c9-4f18-8615-2d1d4462dbcd_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!A0EF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ab9008a-68c9-4f18-8615-2d1d4462dbcd_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!A0EF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ab9008a-68c9-4f18-8615-2d1d4462dbcd_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6ab9008a-68c9-4f18-8615-2d1d4462dbcd_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2408054,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.liamcvw.com/i/206215752?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ab9008a-68c9-4f18-8615-2d1d4462dbcd_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!A0EF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ab9008a-68c9-4f18-8615-2d1d4462dbcd_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!A0EF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ab9008a-68c9-4f18-8615-2d1d4462dbcd_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!A0EF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ab9008a-68c9-4f18-8615-2d1d4462dbcd_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!A0EF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ab9008a-68c9-4f18-8615-2d1d4462dbcd_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p style="text-align: center;"><em>I&#8217;m surprised ChatGPT agreed to make that one.</em></p><p style="text-align: center;"></p><p>But seriously. How do you know that your data isn&#8217;t sitting on a compromised stack? How do you know that you aren&#8217;t trying to schedule workloads on an attacker controlled machine? How do you know any of your security controls are actually in place on a host? And once an attacker has taken over a host, there are endless places to hide and persist through upgrades and reboots.</p><p>Most setups have a lot of faith in hosts once they have been provisioned. Hosts are placed in the trust boundary and then just remain there, regardless of whatever has happened in the mean time. If they even should have been there in the first place.</p><p><strong>Enter the wonderful world of remote attestation which (mostly) solves this problem. Using a TPM, we can remotely, cryptographically prove a couple of things:</strong></p><ul><li><p>The host has the expected hardware</p></li><li><p>The host has the expected firmware</p></li><li><p>The host has the expected kernel and init image</p></li><li><p>The host has the expected root filesystem (depends on the setup)</p></li><li><p>The host passed arbitrary checks that we define</p></li></ul><p>This means that after a reboot, we know the <strong>exact state</strong> a host is in. Without extensive physical modifications and tampering, a fresh boot either puts us in a trusted state or fails and breaks trust in the host.</p><p>The measure boot cycle is different then trusted boot, it relies on <strong>signed measurements, not signed artifacts</strong> like secure boot. It offers a much bigger coverage surface at the cost of considerable complexity. Even malicious, signed, drivers and rootkits can be caught.</p><p><strong>But what&#8217;s the point of measuring if we don&#8217;t block boot like secure boot does? What does measurement get us?</strong></p><p>This gets into how you trust hosts. You can use your TPM to encrypt all or part of your root-fs (where all your keys and data are), so that a host is functionally inoperable without the measured boot succeeding. Your RA can refuse to issue certificates to a host that doesn&#8217;t provide correct measurements (you are using mTLS right?). You can even back TLS x509 certs with the TPM so an incorrectly rebooted host can&#8217;t authenticate over mTLS at all. This offers extremely strong guarantees about the initial state of hosts, so you can trust that your workloads and data are in an environment you trust.</p><p>This isn&#8217;t a perfect solution. Physical attacks (like memory taps) are still a problem. But coupled with robust EDR and a good LSM policy, you have no closed the door on a huge number of issues, in particular nasty kernel and driver supply chain attacks that bypass all of your nice userland defenses.</p><p><strong>But what about attacks after boot?</strong></p><p>That&#8217;s your EDR&#8217;s problem. Trusted boot provides the bedrock to build a bunch of other primitives on top of. Including cryptographic proof your EDR is installed and running (at boot), immutable filesystems (verified at boot), signed upgrades, confidential computing, etc. Without it you can&#8217;t trust your hosts themselves and can&#8217;t make further security guarantees. Houses built on sand and all that.</p><h2>Just use remote attestation, it is easy</h2><p>Unfortunately, remotely measuring every step of your boot process, for every host in your organization, <strong>is a tremendous undertaking</strong>. It goes into how you build and distribute firmware, init images, kernels. On the plus side, it will give you a chance to clean up a bunch of legacy cruft and also probably reveal a bunch of supply chain issues you weren&#8217;t thinking about.</p><h2>How it works</h2><p>TPM magic more or less. TPMs expose a limited interface of cryptographic operations to the host, and that interface is locked down sufficiently that it controls your access to cryptographic material. They are also resistant to physical attacks, but the main function is to mitigate software attacks, not physical. Even kernel code can&#8217;t dig into a TPM and extract private material.</p><p>The TPM comes with a set of PCRs (Platform Configuration Registers). Their only function is to store hashes. They only go forward, you can measure new hashes into a PCR and it hashes the previous value with the new one, yielding a unique result. No going backwards. Different artifacts get measured into the different PCRs during boot and init, and similar to secure boot, each phase measures the next phase. </p><p>Breaking this chain anywhere will taint the PCR values.</p><p>The TPM cares about these values. You can do a couple thing based on them:</p><ul><li><p>TPM sealing: material can be stored in the TPM and only unlocked if the PCRs (the ones you chose) check out.</p></li><li><p>TPM quotes: the values can be signed with a key resident to the TPM. Your RA knows the providence of that key (more in a moment) and this offers strong proof that the measurements are correct.</p></li></ul><p>The full ritual is outside the scope of a blog post like this (ask Claude), but it goes something like this:</p><p>When a host is first be provisioned the TPM has an Endorsement Key (EK) which is a decryption key burned in by the manufacturer. The EK comes with a x509 cert signed by the manufacture&#8217;s PKI. So the EK proves the TPM is legit.</p><p>You then mint an Attestation Key (AK), derived from the EK. The AK is a restricted signing key, it can only sign TPM quotes, nothing else (what would the point of this be if you could make your own quote and sign it) and you generally persist the AK for subsequent reboots. </p><p>But wait, how do we know that an AK is tied to an EK? The EK is a decryption key, it doesn&#8217;t sign anything. The attester just gets two public keys, the EK and AK public keys and the EK x509 leaf cert. The full answer involves more crypto math then I am comfortable trying to explain. TLDR the verifier issues a challenge: encrypting a credential with the EK public key and sending it back. The device decrypts the credential with the EK private key (which never leaves the TPM), and sends the credential to the attester, proving that it is talking to a device that has control of the EK private key.</p><p>The AK can only sign quotes, and the attester has a set of permissible PCR values for each register. So an AK proves the host booted the way we expect, the &#8220;measured boot&#8221; side of the story. But need a third key, the LDevID (Locally-scoped Device ID), which represents a node identity.</p><p>The LDevID is a child of the AK. Importantly, the LDevID can sign anything, not just quotes. Anything signed by the LDevID is proven to have been signed with this specific TPM. Importantly, since it can sign anything we need to restrict when signing can take place &#8212; otherwise an attacker can gain control of it. Frequently it is sealed to golden PCR values, so a reboot into a bad state cannot use it.</p><p>Once the whole ritual is done the host can actually prove itself to be legitimate. <strong>This does not ensure runtime security, that part is on you. </strong>This is only about boot. If this is all set up correctly, attacks will not survive a reboot. Or at least can only brick the host.</p><p>TPM sealing runs into problems with upgrades. New firmware has different measurements and will break attestation. The solution is to authorize a policy (TPM2_PolicyAuthorize), signed by an AuthKey, that authorizes the TPM to accept new PCR values. The AuthKey can be held by the node itself, in which case it needs to vet updates and determine whether or not to accept them, or an authority hold it and distributes the public key to the device/TPM. It just depends if you want to validate upgrades on device or elsewhere in your infra.</p><h2>What does this let you do?</h2><p>If your infra consistently enforces mTLS, you can <strong>reject hosts that were not attested</strong>, since the RA won&#8217;t give them certs. If you use TPM backed certs, tampered hosts naturally lose access to the rest of production.</p><p><strong>Every host has providence.</strong> Data signed by the LDevID (whether TLS or something else), you can prove is from a specific host.</p><p>Workloads can refuse to run on hosts that were not attested. <strong>Your scheduler can demand cryptographic proof before allowing jobs to run on a host.</strong> Your jobs themselves can challenge a host before pulling in data.</p><p>Like I said above, if you are confident in your boot security you can build your runtime security appropriately. In the next post I&#8217;ll get into dm-verity and immutable root images with systemd.</p>]]></content:encoded></item></channel></rss>