RPM signing is an often underestimated feature: you use official repositories, why shouldn’t you trust them? Those repositories are also probably protected with TLS encryption, so you feel safe against man-in-the-middle attacks.
But you may not be as safe as you think you are. Have you heard about that time when the repository of the windows registry cleaner tool CCleaner compromised?
The popularity of CCleaner made it a high-value target for hackers. In 2017 a Chinese hacker group penetrated CCleaner’s distribution servers, uploading a tampered version containing the malware Floxif. This trojan was used to bring in a second attack that installed a backdoor, and was aimed particularly at big companies.
In 2019, hackers again tried several times to tamper with CCleaner in a similar way, but luckily that time their actions failed.
The RPM format has an area reserved for signatures of both the header and payload, using an OpenPGP key. The signature is applied after a package is created, therefore a dedicated hardened server can be used to sign packages, while keeping the key very safe. Our signing infrastructure has been described by my colleague Andrea Avancini in its own blog post Signing NetEye RPMs.
The verification is end-to-end because the publisher can sign their RPM with a private key, and provide the user the public key to use to verify the packages. Verification can be done with the
rpm utility. Please note that
rpm has its own keyring, and therefore the
gpg utility cannot be used to verify package signature, and repository keys will not be imported into the user’s keyring.
dnf can be configured within their
.repo files, and gpg keys will be added to the
rpm databases. Package verification is performed before installation, so you may be asked to import the key if it’s the first time you’re using it.
If the verification step fails, installation will halt with an error:
The GPG keys listed for the "CentOS7-x86_64 - NetEye" repository are already installed but they are not correct for this package. Check that the correct key URLs are configured for this repository.
Enabling signature verification is very easy: you just need to enable the
gpgpcheck option and provide a
gpgpkey path or URL.
Beginning with NetEye 4.17, repository definitions will be provided with package signature verification enabled, and the public keys will be installed locally.
[neteye] name=CentOS7-x86_64 - NetEye baseurl=https://repo.wuerth-phoenix.com/centos7-x86_64/RPMS.neteye-$YUM0 gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-NETEYE
With these options set only signed packages can be installed (or even reinstalled or updated) from the neteye repository.
You can even check locally downloaded RPMs against the keys imported into your
rpm tool. This is important should you need to update a machine with no internet access: since you are not installing packages directly from a repository,
yum will not perform any signature check before installing them, and therefore you can potentially place tampered software on your NetEye.
Thanks to the
rpm utility you can check local packages against its local keyring, for example to verify all packages in a directory:
rpm --checksig ./*.rpm
In case of failure you will get an error like the following:
./cargo-1.33.0-2.el7.x86_64.rpm: RSA sha1 ((MD5) PGP) md5 NOT OK (MISSING KEYS: (MD5) PGP#d6ee560c)
You can easily handle the
rpm keyring for example listing the imported GPG keys
rpm -q gpg-pubkey
or importing new keys from the default directory where NetEye puts them
rpm --import /etc/pki/rpm-gpg/*