keepcalculator

06 Numbers and Powers

Why a clean source diff cannot stop the gnu strip trusting trust backdoor?

Card No. 06·13235 · Updated · Standard formula, shown below

A clean source diff cannot stop the GNU strip trusting-trust backdoor because the attack is not hidden in the source code you review—it is hidden in the binary toolchain that compiles, links, and strips that source. Even if you audit every line of the stripped program’s source and find nothing, the backdoor can be injected by a compromised compiler or assembler that you never inspected, and it can survive recompilation from clean source because the malicious code reproduces itself during the build process.

Background: What Is the Trusting Trust Attack?

The trusting trust attack was described by Ken Thompson in his 1984 Turing Award lecture, “Reflections on Trusting Trust.” Thompson showed that a compiler can be modified to insert a backdoor into any program it compiles, including a login program, without the backdoor ever appearing in the source code of that program. The key insight is that the compiler itself is a program, and if you modify the compiler’s source to add the backdoor, you must also modify the compiler’s binary so that the backdoor is present when the compiler runs. But Thompson went further: he showed that you can modify the compiler’s source so that when the compiler compiles itself, it inserts the backdoor into the new compiler binary—even if the source code you are looking at is completely clean. This is the “trusting trust” problem: you trust the compiler you use to build your tools, but that compiler might be betraying you.

How the Attack Works in the Context of GNU Strip

GNU strip is a utility from the GNU Binutils package that removes symbol tables, debugging information, and other metadata from executable and object files. It is a binary program, typically compiled from C source code. A trusting trust backdoor in GNU strip would work as follows:

  1. An attacker modifies the source code of the C compiler (e.g., GCC) to add a malicious routine that recognizes when it is compiling the source of GNU strip.
  2. When the compiler compiles strip.c, it inserts a backdoor into the resulting strip binary. That backdoor might, for example, cause strip to silently remove a specific piece of code from a binary it processes, or to add a hidden backdoor to a binary it strips, or to alter the binary in some other malicious way.
  3. The attacker also modifies the compiler’s source so that when the compiler compiles itself, it reproduces the same malicious routine in the new compiler binary. This ensures that the backdoor persists even if the compiler is recompiled from the modified source.
  4. Now, if you download the source code of GNU strip and review it, you see nothing suspicious. The source is clean. But when you compile it with the compromised compiler, the resulting strip binary contains the backdoor.

This is why a clean source diff cannot stop the attack: the malicious code is never in the source you are reviewing; it is in the compiler that builds the source.

Why a Clean Source Diff Is Insufficient

A source diff is a comparison between two versions of source code, typically used to identify changes. If you have a known-good version of GNU strip source and you compare it to the version you are about to build, a clean diff tells you that the source files are identical (or that the only differences are benign). However, this does not protect you because:

  • The backdoor is not in the source of strip; it is in the compiler that compiles strip. A diff of strip’s source will not show anything because the source is unchanged.
  • Even if you also diff the compiler’s source, the attacker can hide the malicious routine in the compiler’s binary, not its source. The source you diff might be clean, but the binary that actually runs is malicious.
  • Even if you recompile the compiler from clean source, the backdoor can persist if the compiler you use to compile the compiler is itself compromised. This is the recursive nature of the trusting trust attack: you need a trusted compiler to build a trusted compiler, and that chain of trust must start somewhere.

In practice, a clean source diff only proves that the source code has not been tampered with. It says nothing about the trustworthiness of the toolchain used to build that source.

Real-World Implications and Mitigations

The trusting trust attack is not just theoretical. In 2015, researchers at the University of Cambridge demonstrated a practical version of it by creating a modified compiler that could inject a backdoor into the Linux kernel, and the backdoor survived recompilation from clean source. They also showed that the attack could be carried out on the GNU Binutils package, which includes strip.

There are several ways to mitigate the risk, though none are foolproof:

  • Diverse double-compilation: Compile the compiler with a different compiler (e.g., compile GCC with Clang, or vice versa) and compare the output. If the two compilers produce identical binaries, it is likely that neither is compromised. This is a technique suggested by Thompson himself.
  • Reproducible builds: The Reproducible Builds project aims to make it possible to verify that a given binary was produced from a given source by making the build process deterministic. If you can reproduce the exact same binary from the same source on a different machine, you can have more confidence that the source is what produced the binary.
  • Trusted bootstrapping: Start with a minimal, hand-written compiler or a compiler binary that you trust, and use that to build everything else. This is difficult in practice because you need a trusted starting point.
  • Binary analysis: Analyze the binary of the compiler and the strip utility for suspicious patterns, but this is complex and not always reliable.

These mitigations are not perfect, but they raise the bar for an attacker.

Common Misconceptions

One common misconception is that if you build from source, you are safe. Building from source is safer than using a precompiled binary, but it is not safe if the compiler you use is compromised. Another misconception is that a clean source diff proves the binary is safe. As we have seen, that is not true. A third misconception is that the trusting trust attack is only relevant to compilers. In fact, it can apply to any tool that processes code, such as assemblers, linkers, and even strip itself. If an attacker can compromise the assembler, they can inject malicious code into any assembly output, and a clean source diff of the assembly source will not reveal it.

How to Choose a Trusted Build Process

When you need to build a critical tool like GNU strip, consider the following steps:

  1. Obtain the source code from a trusted source, such as the official GNU mirror, and verify its checksum.
  2. Use a compiler that you trust, ideally one that you have built yourself from source using a trusted compiler, or one that has been verified through diverse double-compilation.
  3. Use reproducible build techniques to verify that the binary you produce matches a known-good binary.
  4. Consider using a bootstrapping process that starts from a minimal, trusted compiler.

These steps are not always practical for every project, but they are essential for security-critical software.

Frequently Asked Questions

Can a clean source diff ever be enough to prove a binary is safe?

No. A clean source diff only proves that the source code has not been changed. It does not prove that the compiler used to build the source is trustworthy. The backdoor could be in the compiler, the linker, or any other tool in the build chain.

Is the trusting trust attack only a theoretical concern?

No. It has been demonstrated in practice, notably by the Cambridge researchers in 2015. They created a compiler that could inject a backdoor into the Linux kernel and the GNU Binutils, and the backdoor survived recompilation from clean source.

Does the attack require physical access to the compiler?

Not necessarily. An attacker could compromise a compiler through a supply chain attack, such as by distributing a malicious compiler binary or by modifying the compiler source in a way that is not easily detected. The attack can also be carried out remotely if the attacker can alter the build environment.

Can a clean source diff help at all in detecting a backdoor?

It can help detect if the source code itself has been tampered with, which is a common attack vector. But it is not sufficient to detect a trusting trust attack, because the malicious code is not in the source of the program being built.

What is the best way to protect against this attack?

The best practical defense is to use diverse double-compilation and reproducible builds. By compiling the compiler with two different compilers and comparing the outputs, you can detect if one of them is compromised. Reproducible builds allow you to verify that the binary you have was built from the source you have.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →