Note: This is a public test instance of Red Hat Bugzilla. The data contained within is a snapshot of the live data so any changes you make will not be reflected in the production Bugzilla. Email is disabled so feel free to test any aspect of the site that you want. File any problems you find or give feedback at bugzilla.redhat.com.
Bug 1933867 - CVE-2021-3421 rpm: unsigned signature header leads to string injection into an rpm database [fedora-33]
Summary: CVE-2021-3421 rpm: unsigned signature header leads to string injection into a...
Keywords:
Status: ON_QA
Alias: None
Product: Fedora
Classification: Fedora
Component: rpm
Version: 33
Hardware: All
OS: All
medium
medium
Target Milestone: ---
Assignee: Packaging Maintenance Team
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2021-03-01 22:03 UTC by Demi Marie Obenour
Modified: 2021-03-30 01:10 UTC (History)
7 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed:
Type: Bug
Embargoed:


Attachments (Terms of Use)
Crafted RPM package that triggers the bug (184.97 KB, application/x-rpm)
2021-03-01 22:03 UTC, Demi Marie Obenour
no flags Details
Avoid copying unknown tags (967 bytes, patch)
2021-03-02 10:33 UTC, Panu Matilainen
no flags Details | Diff
Another crafted RPM package (184.98 KB, application/x-rpm)
2021-03-02 18:39 UTC, Demi Marie Obenour
no flags Details
A more complete, mostly backportable patch (4.80 KB, patch)
2021-03-04 13:22 UTC, Panu Matilainen
no flags Details | Diff
Further (final?) revision, now with data count checks (5.16 KB, patch)
2021-03-05 09:05 UTC, Panu Matilainen
no flags Details | Diff

Description Demi Marie Obenour 2021-03-01 22:03:51 UTC
Created attachment 1760101 [details]
Crafted RPM package that triggers the bug

Description of problem:
It is possible to maliciously modify a signed package such that it will
still pass the RPM signature check, but will corrupt the RPM database upon
installation.

Version-Release number of selected component (if applicable):
rpm-4.16.1.2-1.fc33

How reproducible:
100%

Steps to Reproduce:

1. Create a virtual machine to run the following steps, to avoid corrupting the
   host rpmdb.
2. Download the attached RPM package `bad.rpm`
3. Check its signature with
   `rpmkeys --define '_pkgverify_level all' --checksig -- bad.rpm`
4. Note that that returns `bad.rpm: digests signatures OK`
5. Install it with
   `rpm --define '_pkgverify_level all' -U --reinstall -- bad.rpm`

Actual results:
Installing the package corrupts the rpmdb.

Expected results:
RPM rejects the package.

Additional info:
Hardening patches to RPM are in the works but are blocked on upstream’s ability
to review them.

Comment 1 Panu Matilainen 2021-03-02 08:48:39 UTC
Okay so it creates an inaccessible header in the rpmdb, with indexes pointing to it:
error: rpmdbNextIterator: skipping h#       1 tag[61]: BAD, tag 261 type 6 offset 6989 count 1 len 65

Obviously this is not okay at all, but as far as database corruptions go this is relatively tame and fixing is easy: just don't copy any unexpected tag entries from the signature.

Comment 2 Panu Matilainen 2021-03-02 08:55:50 UTC
Doh, forgot to mention: getting rid of that inaccessible header is a simple matter of 'rpmdb --rebuilddb'. A header disappearing might break dependencies on the db-level etc but that's also easily fixable by just reinstalling the original package. So it's not anything like a "total data loss" corruption.

Comment 3 Panu Matilainen 2021-03-02 09:15:49 UTC
For all practical purposes, this is essentially the same as bug 1927747.

Thanks for the reproducer.

Comment 4 Panu Matilainen 2021-03-02 10:33:40 UTC
Created attachment 1760192 [details]
Avoid copying unknown tags

Unknown tags are not a legit reason for rpm to reject a package, doing so would be devastating to compatibility. However we have no legit reason to copy them either. While there are many more hardening tricks than can be done, this simple patch is enough to take off the edge and is trivially backportable throughout all rpm 4.x versions if need be.

Comment 5 Demi Marie Obenour 2021-03-02 17:45:15 UTC
(In reply to Panu Matilainen from comment #3)
> For all practical purposes, this is essentially the same as bug 1927747.
> 
> Thanks for the reproducer.

You’re welcome!

(In reply to Panu Matilainen from comment #4)

> Created attachment 1760192 [details]
> Avoid copying unknown tags
> 
> Unknown tags are not a legit reason for rpm to reject a package, doing so
> would be devastating to compatibility. However we have no legit reason to
> copy them either. While there are many more hardening tricks than can be
> done, this simple patch is enough to take off the edge and is trivially
> backportable throughout all rpm 4.x versions if need be.

I will test locally and make sure this fixes it.  Thanks for the quick
response!

Comment 6 Demi Marie Obenour 2021-03-02 18:39:10 UTC
Created attachment 1760275 [details]
Another crafted RPM package

This also triggers the bug.

Comment 7 Demi Marie Obenour 2021-03-02 19:01:00 UTC
(In reply to Demi Marie Obenour from comment #5)
> (In reply to Panu Matilainen from comment #3)
> > For all practical purposes, this is essentially the same as bug 1927747.
> > 
> > Thanks for the reproducer.
> 
> You’re welcome!
> 
> (In reply to Panu Matilainen from comment #4)
> 
> > Created attachment 1760192 [details]
> > Avoid copying unknown tags
> > 
> > Unknown tags are not a legit reason for rpm to reject a package, doing so
> > would be devastating to compatibility. However we have no legit reason to
> > copy them either. While there are many more hardening tricks than can be
> > done, this simple patch is enough to take off the edge and is trivially
> > backportable throughout all rpm 4.x versions if need be.
> 
> I will test locally and make sure this fixes it.  Thanks for the quick
> response!

The original reproducer no longer works, but I was able to craft a different
package that exhibits the same symptoms.  I suspect that the culprit is that
we don’t type- or length- check unverified entries in the signature header.

BTW, there is another security bug in RPM: if any trusted key signs a package
with a name starting with `gpg-pubkey`, anyone can use the RPMTAG_PUBKEYS
header to inject arbitrary trusted GPG keys into the database.  Your first
patch fixes that bug, too, but I will still file a separate report.

Comment 8 Panu Matilainen 2021-03-03 08:23:41 UTC
(In reply to Demi Marie Obenour from comment #7)
> The original reproducer no longer works, but I was able to craft a different
> package that exhibits the same symptoms.  I suspect that the culprit is that
> we don’t type- or length- check unverified entries in the signature header.

Please include any such reproducers you come up with, they're very valuable material.

And yes, it's by no means a complete fix, like said it merely takes off the edge (by limiting the surface to known tags). I'm still contemplating on how to best deal with this from the perspective that in the worst case we might need to backport to some *very* old and ugly rpm versions.

> but I will still file a separate report.

Please do, discussing multiple issues in a single report makes it impossible to keep track. As a rule of thumb, it's better to open a new bug at once if there's a reason to believe it's a separate issue. Closing bugs as duplicates if it turns out that way is far easier and the lesser evil compared to discussing/tracking multiple issues in one bug.

Comment 9 Panu Matilainen 2021-03-03 08:25:59 UTC
> Please include any such reproducers you come up with, they're very valuable material.

Doh, never mind - you already did. Thanks!

/me needs more coffee...

Comment 10 Panu Matilainen 2021-03-04 09:33:10 UTC
This is actually a pretty funny case in that it's the newly added "security" checks in rpm >= 4.14 that cause it to fail to reload a header it just produced. Older rpm versions just shrug and move on, but that in turn can lead to different kind of problems.

Comment 11 Panu Matilainen 2021-03-04 13:22:12 UTC
Created attachment 1760682 [details]
A more complete, mostly backportable patch

Only look for known tags, and ensure correct type before copying.
While at it, ensure none of these tags exist in the main header,
which would confuse us greatly.

In other words, close the gaping hole between the signature and main header.
This is the minimal backport effort approach, upstream can look to do more once all the surrounding embargoes are cleared some day.

Fixes: RhBug:1935049, RhBug:1933867, RhBug:1935035, RhBug:1934125, ...
Fixes: CVE-2021-3421, ...

Comment 12 Panu Matilainen 2021-03-05 09:05:59 UTC
Created attachment 1760843 [details]
Further (final?) revision, now with data count checks

A further revision (hopefully final) which includes additional checks for exact data counts for the items where it's possible. Upstream could do more, but this is optimized for backporting.

Comment 13 Demi Marie Obenour 2021-03-05 19:16:51 UTC
(In reply to Panu Matilainen from comment #12)
> Created attachment 1760843 [details]
> Further (final?) revision, now with data count checks
> 
> A further revision (hopefully final) which includes additional checks for
> exact data counts for the items where it's possible. Upstream could do more,
> but this is optimized for backporting.

Thank you!  Trivial nit: right now, if I understand correctly, this will cause
the header to be re-sorted several times.  Not sure if that matters, though.
RPMSIGTAG_PGP5 could also cause problems; should we just reject it in the
main header?

This does not fix bug 1915990, as DNF is still vulnerable if a package
does not have payload digests in the main header, or if `%_pkgverify_level`
is set to `none`.

Comment 14 Panu Matilainen 2021-03-08 10:45:20 UTC
(In reply to Demi Marie Obenour from comment #13)
> Trivial nit: right now, if I understand correctly, this will cause
> the header to be re-sorted several times. 

Why would it do that?

> RPMSIGTAG_PGP5 could also cause problems; should we just reject it in the
> main header?

Rpm does not use the tag for anything, and we dont even carry a type for it. Seems pretty harmless to me.

> 
> This does not fix bug 1915990, as DNF is still vulnerable if a package
> does not have payload digests in the main header, or if `%_pkgverify_level`
> is set to `none`.

This makes the reproducer package in bug 1915990 unreadable regardless of all verification switches, so yes it does fix it.

Comment 15 Panu Matilainen 2021-03-08 11:27:53 UTC
(In reply to Demi Marie Obenour from comment #13)
> Trivial nit: right now, if I understand correctly, this will cause
> the header to be re-sorted several times. 

Actually - it does get re-sorted several times, but that's not introduced in this patch. It always did headerIsEntry() on the main header which interleaved with headerPut()'s.

Comment 16 Demi Marie Obenour 2021-03-09 19:22:15 UTC
(In reply to Panu Matilainen from comment #14)
> > RPMSIGTAG_PGP5 could also cause problems; should we just reject it in the
> > main header?
> 
> Rpm does not use the tag for anything, and we dont even carry a type for it.
> Seems pretty harmless to me.

My worry is old 3rd-party code that queries for it.

> > This does not fix bug 1915990, as DNF is still vulnerable if a package
> > does not have payload digests in the main header, or if `%_pkgverify_level`
> > is set to `none`.
> 
> This makes the reproducer package in bug 1915990 unreadable regardless of
> all verification switches, so yes it does fix it.

Yes and no.  It is still possible to fool DNF if there is a signed package
with no payload digests in the main header, as rpmReadPackageFile() doesn’t
check the header+payload signature or the payload digests.  But that is a
separate bug.

Comment 17 Todd Cullum 2021-03-09 19:35:43 UTC
*** Bug 1935049 has been marked as a duplicate of this bug. ***

Comment 18 Todd Cullum 2021-03-09 20:31:51 UTC
*** Bug 1935035 has been marked as a duplicate of this bug. ***

Comment 19 Panu Matilainen 2021-03-10 07:25:26 UTC
Argh. Please do not mix up issues! Throwing "but it doesn't fix" claims on something entirely different is really quite harmful to getting these processed up.

Comment 20 Panu Matilainen 2021-03-10 07:29:24 UTC
> My worry is old 3rd-party code that queries for it.

They don't. That tag is some 20 years unused.

Comment 21 Fedora Update System 2021-03-22 12:15:44 UTC
FEDORA-2021-8d52a8a999 has been submitted as an update to Fedora 33. https://bodhi.fedoraproject.org/updates/FEDORA-2021-8d52a8a999

Comment 22 Fedora Update System 2021-03-23 02:05:13 UTC
FEDORA-2021-8d52a8a999 has been pushed to the Fedora 33 testing repository.
Soon you'll be able to install the update with the following command:
`sudo dnf upgrade --enablerepo=updates-testing --advisory=FEDORA-2021-8d52a8a999`
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2021-8d52a8a999

See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.

Comment 23 Fedora Update System 2021-03-30 01:10:17 UTC
FEDORA-2021-8d52a8a999 has been pushed to the Fedora 33 stable repository.
If problem still persists, please make note of it in this bug report.


Note You need to log in before you can comment on or make changes to this bug.