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.
yum
and 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/*