HN user

tryp

129 karma
Posts3
Comments53
View on HN
On Gravel 3 years ago

I found this an interesting look into The US Forestry service's philosophy of road management through the lens of Washington State's Olympic National Forest.

"The Forest Service – a branch of the Department of Agriculture whose original purpose was to “furnish a continuous supply of timber for the use and necessities of the people of the United States” – classifies their roads into five buckets based on their method of construction and maintenance needs. And the agency seems to be highly tuned to the lifecycle of their road infrastructure..."

(Discovered through https://kagi.com/smallweb/ featured on HN a few weeks ago)

Some folks are just not TradeMarksters. They'll teach you that Intel makes processors that implement x86 and amd64 instruction sets. You can Google things on DuckDuckGo. They'll blow their nose on the Kleenex that they bought from GenericPaperProductsCo. At some restaurants in the US South you'll have to let your server know what kind of Coke you want: cola, lemon-lime, or the Doctor one.

BIOS is often able to set mask bits in the CPU or chipset's pci bridges that prevent the devices from being reported to the OS. Before loading additional code like user DXEs or bootloader, BIOS commands a one-way sealing operation that prevents modifications until reset.

The researchers' writeup, in a very fun form, can be found at https://rol.im/securegoldenkeyboot/

With text as follows for those whom the joviality of the original presentation is undesirable:

irc.rol.im #rtchurch :: https://rol.im/chat/rtchurch

Specific Secure Boot policies, when provisioned, allow for testsigning to be enabled, on any BCD object, including {bootmgr}. This also removes the NT loader options blacklist (AFAIK). (MS16-094 / CVE-2016-3287, and MS16-100 / CVE-2016-3320)

Found by my123 (@never_released) and slipstream (@TheWack0lian) Writeup by slipstream (@TheWack0lian)

First up, "Secure Boot policies". What are they exactly?

As you know, secureboot is a part of the uefi firmware, when enabled, it only lets stuff run that's signed by a cert in db, and whose hash is not in dbx (revoked).

As you probably also know, there are devices where secure boot can NOT be disabled by the user (Windows RT, HoloLens, Windows Phone, maybe Surface Hub, and maybe some IoTCore devices if such things actually exist -- not talking about the boards themselves which are not locked down at all by default, but end devices sold that may have secureboot locked on).

But in some cases, the "shape" of secure boot needs to change a bit. For example in development, engineering, refurbishment, running flightsigned stuff (as of win10) etc. How to do that, with devices where secure boot is locked on?

Enter the Secure Boot policy.

It's a file in a binary format that's embedded within an ASN.1 blob, that is signed. It's loaded by bootmgr REALLY early into the windows boot process. It must be signed by a certificate in db. It gets loaded from a UEFI variable in the secureboot namespace (therefore, it can only be touched by boot services). There's a couple .efis signed by MS that can provision such a policy, that is, set the UEFI variable with its contents being the policy.

What can policies do, you ask?

They have two different types of rules. BCD rules, which override settings in the on-disk BCD, and registry rules, which contain configuration for the policy itself, plus configuration for other parts of boot services, etc. For example, one registry element was introduced in Windows 10 version 1607 'Redstone' which disables certificate expiry checking inside mobilestartup's .ffu flashing (ie, the "lightning bolt" windows phone flasher); and another one enables mobilestartup's USB mass storage mode. Other interesting registry rules change the shape of Code Integrity, ie, for a certain type of binary, it changes the certificates considered valid for that specific binary.

(Alex Ionescu wrote a blog post that touches on Secure Boot policies. He teased a followup post that would be all about them, but that never came.)

But, they must be signed by a cert in db. That is to say, Microsoft.

Also, there is such a thing called DeviceID. It's the first 64 bits of a salted SHA-256 hash, of some UEFI PRNG output. It's used when applying policies on Windows Phone, and on Windows RT (mobilestartup sets it on Phone, and SecureBootDebug.efi when that's launched for the first time on RT). On Phone, the policy must be located in a specific place on EFIESP partition with the filename including the hex-form of the DeviceID. (With Redstone, this got changed to UnlockID, which is set by bootmgr, and is just the raw UEFI PRNG output.)

Basically, bootmgr checks the policy when it loads, if it includes a DeviceID, which doesn't match the DeviceID of the device that bootmgr is running on, the policy will fail to load.

Any policy that allows for enabling testsigning (MS calls these Retail Device Unlock / RDU policies, and to install them is unlocking a device), is supposed to be locked to a DeviceID (UnlockID on Redstone and above). Indeed, I have several policies (signed by the Windows Phone production certificate) like this, where the only differences are the included DeviceID, and the signature.

If there is no valid policy installed, bootmgr falls back to using a default policy located in its resources. This policy is the one which blocks enabling testsigning, etc, using BCD rules.

Now, for Microsoft's screwups.

During the development of Windows 10 v1607 'Redstone', MS added a new type of secure boot policy. Namely, "supplemental" policies that are located in the EFIESP partition (rather than in a UEFI variable), and have their settings merged in, dependant on conditions (namely, that a certain "activation" policy is also in existance, and has been loaded in).

Redstone's bootmgr.efi loads "legacy" policies (namely, a policy from UEFI variables) first. At a certain time in redstone dev, it did not do any further checks beyond signature / deviceID checks. (This has now changed, but see how the change is stupid) After loading the "legacy" policy, or a base policy from EFIESP partition, it then loads, checks and merges in the supplemental policies.

See the issue here? If not, let me spell it out to you plain and clear. The "supplemental" policy contains new elements, for the merging conditions. These conditions are (well, at one time) unchecked by bootmgr when loading a legacy policy. And bootmgr of win10 v1511 and earlier certainly doesn't know about them. To those bootmgrs, it has just loaded in a perfectly valid, signed policy.

The "supplemental" policy does NOT contain a DeviceID. And, because they were meant to be merged into a base policy, they don't contain any BCD rules either, which means that if they are loaded, you can enable testsigning. Not just for windows (to load unsigned driver, ie rootkit), but for the {bootmgr} element as well, which allows bootmgr to run what is effectively an unsigned .efi (ie bootkit)!!! (In practise, the .efi file must be signed, but it can be self-signed) You can see how this is very bad!! A backdoor, which MS put in to secure boot because they decided to not let the user turn it off in certain devices, allows for secure boot to be disabled everywhere!

You can see the irony. Also the irony in that MS themselves provided us several nice "golden keys" (as the FBI would say ;) for us to use for that purpose :)

About the FBI: are you reading this? If you are, then this is a perfect real world example about why your idea of backdooring cryptosystems with a "secure golden key" is very bad! Smarter people than me have been telling this to you for so long, it seems you have your fingers in your ears. You seriously don't understand still? Microsoft implemented a "secure golden key" system. And the golden keys got released from MS own stupidity. Now, what happens if you tell everyone to make a "secure golden key" system? Hopefully you can add 2+2...

Anyway, enough about that little rant, wanted to add that to a writeup ever since this stuff was found ;)

Anyway, MS's first patch attempt. I say "attempt" because it surely doesn't do anything useful. It blacklists (in boot.stl), most (not all!) of the policies. Now, about boot.stl. It's a file that gets cloned to a UEFI variable only boot services can touch, and only when the boot.stl signing time is later than the time this UEFI variable was set. However, this is done AFTER a secure boot policy gets loaded. Redstone's bootmgr has extra code to use the boot.stl in the UEFI variable to check policy revocation, but the bootmgrs of TH2 and earlier does NOT have such code. So, an attacker can just replace a later bootmgr with an earlier one.

Another thing: I saw some additional code in the load-legacy-policy function in redstone 14381.rs1_release. Code that wasn't there in 14361. Code that specifically checked the policy being loaded for an element that meant this was a supplemental policy, and erroring out if so. So, if a system is running Windows 10 version 1607 or above, an attacker MUST replace bootmgr with an earlier one.

On August 9th, 2016, another patch came about, this one was given the designation MS16-100 and CVE-2016-3320. This one updates dbx. The advisory says it revokes bootmgrs. The dbx update seems to add these SHA256 hashes (unless I screwed up my parsing): <snip>

I checked the hash in the signature of several bootmgrs of several architectures against this list, and found no matches. So either this revokes many "obscure" bootmgrs and bootmgfws, or I'm checking the wrong hash.

Either way, it'd be impossible in practise for MS to revoke every bootmgr earlier than a certain point, as they'd break install media, recovery partitions, backups, etc.

- RoL

disclosure timeline: ~march-april 2016 - found initial policy, contacted MSRC ~april 2016 - MSRC reply: wontfix, started analysis and reversing, working on almost-silent (3 reboots needed) PoC for possible emfcamp demonstration ~june-july 2016 - MSRC reply again, finally realising: bug bounty awarded july 2016 - initial fix - fix analysed, deemed inadequate. reversed later rs1 bootmgr, noticed additional inadequate mitigation august 2016 - mini-talk about the issue at emfcamp, second fix, full writeup release

credits: my123 (@never_released) -- found initial policy set, tested on surface rt slipstream (@TheWack0lian) -- analysis of policies, reversing bootmgr/ mobilestartup/etc, found even more policies, this writeup.

tiny-tro credits: code and design: slipstream/RoL awesome chiptune: bzl/cRO <3

Toward the end of that slide deck, in the "Slowing Brute Force" section, there the following slide:

Argon2 ensures that both defenders and attackers hash passwords on the same platform (x86)

Do they simply mean that currently the most cost effective platform to deliver the necessary computation and memory is x86?

I'm having trouble believing that it is either achievable or desirable to design a password hash that's only efficient on one architecture.

A few years ago I implemented the storage system for a special-purpose diagnostic camera. The specification defined (very long) filenames for the saved images using a timestamp and some other data. I used a mostly off-the-shelf microcontroller/NAND/USB mass storage reference implementation, hooked it up a side-channel to the FPGA, and had everything working pretty nicely. Until the test harness that just continuously commanded pictures to be taken reached 105 iterations. After that, the camera timed out waiting on the storage subsystem to store the image.

The problem turned out to be the code that found the 8.3 filename: it did the longfi~1.bin, checked to see if that file existed and if so, incremented to longfi~2.bin, then checked that... but never did the checksum trick described here, just kept iterating. (bear in mind this was a tiny 8-bit microcontroller that didn't have the RAM to just read all the directory entries at once and keep them around for comparison) Finding the proper 8.3 filename this way took longer than the timeout period after 104 collisions.

Of course, we only cared about the long filename and never saw the 8.3 filename, so my fix was simply to use an appropriate hash of the long filename to ensure a good probability of uniqueness.

Why can't the HDD vendors publish a md5/sha1 hash of the firmware so we know what the value should be?

Because the only way to actually verify the hash of the firmware is to connect to the drive's controller outside of the firmware's control with something like JTAG or a direct dump of the flash. Otherwise, the PC would send a command to ask the HD firmware what it's own hash is. The compromised HD firmware can then simply respond with a published vendor hash.

(U)EFI is essentially a little OS that eventually loads the OS that runs the software you care about. Intel sponsors most of the core OS code (mirrored) at: https://github.com/tianocore/edk2

A Bios vendor takes that code, drops in a bunch of hardware init code from Intel (or AMD), adds thier own user interface, "csm16" old-school BIOS implementation, and value-adds like debugging and automation for factory test and provisioning.

In order to comprehend anything in the codebase, the first step is probably to get acquainted with the local vernacular. https://github.com/tianocore/tianocore.github.io/wiki/Acrony...

The best place to look is probably Coreboot. It's the boot firmware used by Google Chromebooks. (Github mirror links used here for politeness to the project's servers.) Taking Intel Haswell processors as an example (because I know this code path) we can sketch the general process.

Start at 0xfffffff0, the boot vector for x86, executing in 16-bit "I can run DOS 1.0" mode. https://github.com/coreboot/coreboot/blob/master/src/cpu/x86...

It just jumps to the entry to 32-bit mode https://github.com/coreboot/coreboot/blob/master/src/cpu/x86...

Turn on FPU https://github.com/coreboot/coreboot/blob/master/src/cpu/x86...

Turn on SSE https://github.com/coreboot/coreboot/blob/master/src/cpu/x86...

Configure the cache not to require a backing DRAM so that it can be used temporarily as RAM. https://github.com/coreboot/coreboot/blob/master/src/cpu/int...

Now that "RAM" is available for use as a stack, the next steps can be written in plain-ole C https://github.com/coreboot/coreboot/blob/master/src/cpu/int...

From there, mainboard-specific code sets up things like which SuperIO chip to configure, the i2c addresses to interrogate for information on RAM geometry and timing, and how the chipset is wired to connectors on the board. Commong chipset (northbridge and southbridge) init code is run using that configuration data. https://github.com/coreboot/coreboot/blob/master/src/mainboa...

Then DRAM is initialized (the Haswell example is a bit lame in that currently a binary blob of compiled code from Intel does this job.) The Sandybridge DDR3 init was recently reverse-engineered and re-implemented and fully exemplifies the training processes required. https://github.com/coreboot/coreboot/blob/master/src/northbr...

Now that Gigagbytes of RAM are available, another boot stage is fetched from flash. When generic framework gets back to cpu-specific stuff, power management is configured,Inter-Processor Interrupt handlers are installed, and other cores go through a quick init sequence. https://github.com/coreboot/coreboot/blob/master/src/cpu/int...

Then essentially the PCI tree is walked to setup all the chipset devices. https://github.com/coreboot/coreboot/tree/master/src/southbr...

Once hardware is running, Coreboot loads a "payload" that is in turn responsible for loading the OS.

An invalid or debug instruction causes the processor to throw an exception and jump to a specific address where "handler" code should exist. This is managed by the OS, so in this case, the OS would look up the proper thing to do as configured by the earlier ptrace calls -- probably executing your debugger code to let you inspect variables and memory. When you're done inspecting the proper instruction gets re-installed in the target process, the OS restores state saved by the exception trap, and transfers execution back to the debugged process. Most processors have a single-step flag so that the next instruction to execute and the following trigger the exception.

There is typically only one (or a small set) of hardware instruction pointer breakpoints. Every time the CPU is about to execute an instruction, it compares IP to the IP breakpoint register (or set of registers) and if they match, a debug exception is thrown. These are what you must use to debug the BIOS/bootloader executing in-place from ROM with a JTAG or XDP hardware debugger attached. Later, software can add the proper exception handler once enough of the hardware platform is configured. (Not all architectures exit power-on reset with exceptions enabled or even exception vectors mapped to a valid memory location.)

If the code you are debugging is executing out of write-able memory, then your debugger can support an effectively infinite list of breakpoints by writing some instruction that causes an exception to be thrown anywhere you want a break, then handling that exception by looking up the faulting instruction address in your breakpoint list.

Most processors also give you hardware data access breakpoints as well. These typically sit on the CPU's data bus interface and can fire when the address or data that's about to hit the bus match the respective breakpoint registers. There is usually an option to only trap reads, writes, or both. Sometimes you get interesting things like a mask register that lets you trap on a whole block of memory.

One of the most interesting hardware debug features of modern processors is the branch trace which keeps a running list of the last N branch instructions that lets you reconstruct a "how did we get here" story.

To be a bit more explicit, using a separate httpd and application server allows a division of labor between the resource-bound task of handling the request + building the response from the network-bound task of dibbling bytes back to the original requestor.

Nginx (and the general class of highly concurrent servers) is good at handling lots of connections largely because it tries to minimize the resources (memory, process scheduler time, etc) required to manage each connection as it slowly feeds the result down the wire.

The application server generally wants an instance per CPU so that it can hurry up and crank through a memory-, cpu-, or database-hungry calculation in as few microseconds as possible, hand the resulting data back to the webserver and proceed to put the memory, DB, and CPU to the task of processing the next request.

This is in contrast to the (simplified here) old-school CGI way that say ancient Apache would receive a request, then fork off a copy of PHP or Perl for each one, letting the app get blocked by writing to the stdio pipe to Apache then Apache to the requesting socket. All the while maintaining a full OS process for each request in play.

I totally agree about micros. They are wonderfully nice and tidy for small, well defined problems. I've had extremely satisfying success using them for communications glue, motor controllers and thermoelectric cooler controllers.

I'm in a chatty mood tonight, so I hope you'll excuse my indulgence of another few 'graphs on modern memory bus stuff I think is cool that I had to learn under product ship-date duress: Dynamic Termination.

Remember the high-school physics demonstration of the "reflected wave" where you grab one end of a rope that's tied off at the other end, give it a flick, watch the wave travel from your hand to the knot, then reflect back? Well kind of the same thing happens with voltage level on high speed data signals.

If your high school was fortunate enough in these (or those) fiscally troubled times to afford the equipment, the next demonstration tied off the same rope to some sort of damping spring that absorbed your wave's energy and didn't reflect it back at you. Those springs translate to "termination impedance" in electrical circuits.

So in order to avoid reflections, the address/control/clock lines of the memory bus "fly by" each and every DRAM IC until they reach the end of their path, where they "terminate" via resistors that prevent reflection to a voltage potential (half-way between 1- or 0- value potentials so that it's no more work to drive a 1 that 0 or vice-versa).

The data lines are wired directly from the memory controller to the DRAM chips so the DRAM chips have termination built-in to absorb the energy at the end of the line and prevent reflections.

Except that maybe there's more than one DIMM. DDR3 chips let you command them to connect or disconnect their termination resistors. So when you are accessing the closer-to-the-controller DIMM, the next one that's further out can apply termination. And when addressing the one that's furthest out, you disable on-die termination and rely on the actual resistor on the motherboard at the end of the bus.

My hard-learned lesson: the signals don't so so well when you get confused about which rank of chips are closer and which are further away.

I am truly excited that there is a push to popularize FPGAs. They often allow a fundamentally different approach to problems and afford a massive improvement in efficiency and flexibility when applied to a given task. This book is a very approachable high-level answer to the question "wtf is an fpga and why do I care?" but I'm a bit disappointed that is lacks much direction on where to look next for more depth.

I'll take the liberty to suggest a couple possibilities here:

http://www.fpga4fun.com/

Fpga4Fun is pretty accessible.

http://opencores.com/

Opencores is kind of a SourceForge for FPGA stuff. There are lots of interesting components there to mix into a project.

nitpick: This is my first encounter with the ASSP (Application-Specific Standard Product) initialism. It seems like a needless distinction from ASIC to me.

Modern DDR2 SDRAM busses are a bit more involved. They use the address lines as a command word for putting the chips in the correct "link trainging" mode at startup, selecting burst access lengths, enabling self-refresh mode, setting on-die termination values, &cetera so they may not be swapped. Each "byte lane" of 8 data lines is allowed to have a different signal path length difference between clock and data (that is measured during training for compensation during operation) and signals may be swapped arbitrarily within the byte lanes.

Furthermore, the high-performance DDR3+ controllers typically hash the data word with the address so that when a repetitive data stream is transmitted it doesn't generate more EMI. (Some controllers also hash with a random seed gaining resilience against chilling the DIMMs of a running machine and reading them out on another machine in search of sensitive data.)

I find it really cool that any time you change the DIMMs in your computer, it essentially has to measure the length of the wires to the ICs on it. (I've found it less cool to have to manipulate timing values to compensate for deviation from PCB design rules, but thankful that it's possible. The fun of board bring-up.) If your BIOS has a "fast boot" option, mostly that means it remembers the wire lengths from last time so it doesn't have to do the measurement again every boot.

One point to consider is that this algorithm appears to rely on a double-precision floating-point divide at its core, so the speediness measured on a Xeon E5 may not translate to speediness on architectures with weaker floating point units.

Also, most current DDR3 controllers "scramble" which wire carries which bit based on the address. The idea is that when writing constant repeating data patterns, spreading energy among the wires reduces emitted EMI.

When you do a suspend-to-ram on a current x86 machine, it has to save the "scrambler seed" to CMOS so that it can decode the data it left stored in RAM.

I think this also helps mitigate the attack where the DRAM is chilled to make its contents less volatile, the machine is powered off, and the DRAM is then dumped in search of sensitive material.