|
iPXE
|
iPXE is a network-capable bootloader, generally operating at ring 0 (or equivalent) with all memory protections disabled. All data originating from the network should be considered to be untrusted and potentially malicious.
Under UEFI, iPXE operates before ExitBootServices() is called. An exploit against iPXE can therefore potentially produce a Secure Boot compromise, requiring all existing binaries to be revoked (by incrementing the SBAT generation in include/ipxe/sbat.h for the official binaries that are signed via the iPXE shim).
The primary threat category is traffic originating from a network peer. All code on the receive datapath must carefully validate received lengths and contents during parsing.
iPXE includes its own cryptographic stack (covering TLS, CMS, X.509, etc). This stack is used for iPXE's own security (HTTPS connections and code-signing verification) but is entirely unrelated to UEFI Secure Boot since iPXE defers all Secure Boot decisions to the platform's own LoadImage() and StartImage() calls. A compromise within iPXE's cryptographic stack would be a compromise of iPXE's security, but would not be a Secure Boot exploit (unless it also allowed for e.g. arbitrary code execution or an out-of-bounds write).
Files may be annotated with FILE_SECBOOT() declarations to indicate whether or not they are permitted to be included in a UEFI Secure Boot build. The absence of a marker is taken to prohibit inclusion.
Exclusion from a UEFI Secure Boot build does not indicate that a file is outside the scope of the threat model, but does generally indicate that it is a lower priority.
There are some files that are explicitly marked as FORBIDDEN, for various reasons:
Malicious locally attached hardware is explicitly outside the scope of iPXE's threat model. DMA-capable hardware is assumed to have write access to all of host memory (i.e. an IOMMU is not assumed to be present). Device drivers are therefore not required to exhaustively defend against incorrect or inconsistent values written by DMA-capable hardware, since it is assumed that any such hardware could already crash the system (or overwrite iPXE's code) without any further assistance.
DMA-incapable hardware (such as USB devices) are on the edge of the threat model. It is assumed that an attacker with physical access to attach new hardware also has the ability to take full control of the system anyway (e.g. by disabling UEFI Secure Boot). That said, USB device drivers should generally guard against misbehaving USB or other DMA-incapable hardware, since that hardware would not otherwise be able to crash the system.
Under UEFI, other boot services code running on the same system is similarly on the edge of the threat model. If UEFI Secure Boot is enabled, then any other code running on the same system must itself be part of a signed binary (or be part of the platform firmware), and so is by definition already at least as privileged as iPXE itself. That said, iPXE components that interact via UEFI protocols should be written defensively, since experience shows that UEFI firmware code quality is generally quite poor, especially in closed-source vendor firmware that does not simply use the upstream EDK2 components.
Infiniband local networks are generally regarded as being within the trust boundary, not least because iPXE includes support for remote DMA access. (For this reason, Infiniband device drivers are excluded from a Secure Boot build.)
iPXE generally transfers control to whatever payload it boots at the same privilege level held by iPXE itself (i.e. ring 0 or equivalent). There are therefore some classes of defect that are simply not interesting. For example, a malformed NBI image could potentially be able to exploit a bug in arch/x86/image/nbi.c, but this would be utterly pointless since the exploit cannot do anything that a well-formed NBI image could not do simply by allowing itself to be executed.
There are several recurring patterns and helper functions used in iPXE that any security reviewer should be familiar with: