Created attachment 525110 [details] testcase Description of problem: int off = ntohl(pe->offset); if (hdrchkData(off)) goto errxit; if (off) { size_t nb = REGION_TAG_COUNT; int32_t stei[nb]; /* XXX Hmm, why the copy? */ memcpy(&stei, dataStart + off, nb); No check for dataStart + off > dataEnd. (gdb) r --checksig rpminput.rpm [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/libthread_db.so.1". error: no dbpath has been set error: cannot open Packages database in /%{_dbpath} Program received signal SIGSEGV, Segmentation fault. memcpy () at ../sysdeps/x86_64/memcpy.S:117 117 ../sysdeps/x86_64/memcpy.S: No such file or directory. in ../sysdeps/x86_64/memcpy.S (gdb) bt #0 memcpy () at ../sysdeps/x86_64/memcpy.S:117 #1 0x00007ffff7946493 in headerLoad (uh=0x623e00) at header.c:831 #2 0x00007ffff7946af9 in headerRead (fd=0x622180, magicp=HEADER_MAGIC_YES) at header.c:994 #3 0x00007ffff79731d1 in readFile (fd=0x622180, fn=0x60a080 "rpminput.rpm", dig=0x622ab0, plbundle=0x6223b0, hdrbundle=0x622420) at rpmchecksig.c:462 #4 0x00007ffff7973c29 in rpmpkgVerifySigs (keyring=0x620ef0, flags=1572865, fd=0x622180, fn=0x60a080 "rpminput.rpm") at rpmchecksig.c:689 #5 0x00007ffff797429e in rpmcliSign (ts=0x621630, qva=0x7ffff7bab180, argv=0x609ed8) at rpmchecksig.c:824 #6 0x00000000004036e0 in main (argc=3, argv=0x7fffffffe458) at rpmqv.c:787
Created attachment 525123 [details] testcase This is probably exploitable, the same error exists in regionSwab, and allows you to damage internal structures.
Marking urgent, because I didn't realise that yum just uses librpm via a native wrapper. Also sent a mail to secalert@.
This probably affects pretty much every single rpm version ever released. I could only easily test down to rpm-4.4.x (which is certainly affected too), but this is ancient code which hasn't seen much changes in a long long time. What makes this even more "fun" is that the code path taken by regular query behaves correctly here: [pmatilai@localhost ~]$ rpm -qpi ~/Downloads/dataStart.rpm error: /home/pmatilai/Downloads/dataStart.rpm: headerRead failed: tag[0]: BAD, tag 63 type 7 offset 7540604 count 16 error: /home/pmatilai/Downloads/dataStart.rpm: not an rpm package (or package manifest)
Just FYI # yum install regionSwab.rpm Setting up Install Process *** glibc detected *** /usr/bin/python: free(): invalid pointer: 0x0ae8e8f4 *** ======= Backtrace: ========= /lib/libc.so.6[0x4d68e2b5] /usr/lib/librpmio.so.2(rfree+0x1c)[0x41010a9c] /usr/lib/librpm.so.2(headerFree+0x8a)[0x4103b92a] /usr/lib/python2.7/site-packages/rpm/_rpmmodule.so(+0x763a)[0xd8163a] /usr/lib/libpython2.7.so.1.0[0x4f7674b7] The same bug being reached via rpm-python and yum.
Yup. I initially missed the regionSwab.rpm case which is different from the others in that no existing safeguard catches that, whereas the two others (dataStart.rpm and the copyTdEntry.rpm) are cleanly caught by the "normal" code paths taken by yum, and rpm in other than --checksig modes.
In reply at comment 4 rpm --checksig dataStart.rpm error: dataStart.rpm: Header: tag[0]: BAD, tag 63 type 7 offset 7540604 count 16 [andrew@andorra rpmb]# rpm --checksig regionSwab.rpm rpm: signature.c:749: verifyRSA: Assertion `rsactx != ((void *)0)' failed. Aborted rpm --version rpm (RPM) 5.3.9 [andrew@andorra rpmb]# cat /etc/redhat-release Mandriva Linux release 2011.0 (Cooker) for x86_64 No dump here
(In reply to comment #2) > This is probably exploitable, the same error exists in regionSwab, and allows > you to damage internal structures. Tavis, can you be a little more specific what exactly you refer to here?
The second testcase I attached demonstrates it, you can see it damages a pointer and then libc complains it's invalid. Sorry I didn't give the attachment a better summary!
(In reply to comment #12) > The second testcase I attached demonstrates it, you can see it damages a > pointer and then libc complains it's invalid. This is what I see with the second test case: In headerLoad, rdl is read from the file. The value is 0, hence both rdl and ril is 0. Follows the first regionSwab call: rdlen = regionSwab(entry+1, ril-1, 0, pe+1, dataStart, dataEnd, entry->info.offset); as: regionSwab (entry=0x669a60, il=-1, dl=0, pe=0x668758, dataStart=0x668aa8 "", dataEnd=0x669a34 "", regionid=0) Negative il makes it exit immediately. Follows another call to regionSwab: /* Load dribble entries from region. */ rc = regionSwab(newEntry, ne, 0, pe+ril, dataStart, dataEnd, rid); as: regionSwab (entry=0x669a40, il=54, dl=0, pe=0x668748, dataStart=0x668aa8 "", dataEnd=0x669a34 "", regionid=1) ie.info.offset and ie.info.count comes from file and is used to compute ie.data and ie.length. The code does check that fits inside dataStart and dataEnd. Test case does not seem to bypass those checks. Then there is: if (entry) { ie.info.offset = regionid; *entry = ie; /* structure assignment */ entry++; } which is what "damages" entry->data pointer. Later on in headerFree, the check seems to distinguish cases where entry has own malloced data chunk, and data pointing to inside of some larger chunk using: } else if (!ENTRY_IN_REGION(entry)) { entry->data = _free(entry->data); which translates to: } else if (!(entry->info.offset < 0)) { and hence code is confused to free something it should not. It does not seem quite similar to the comment #0 case (i.e. not a memory corruption from buffer overflow due to missing end of buffer check, afaics), hence the question what I'm missing.
*** Bug 741612 has been marked as a duplicate of this bug. ***
Assigning CVE-2011-3378 for the issue described in bug #741612 and bug #741606 comment #2. The issue described in comment #0 does not have a security implication.
Shouldn't be more appropriate check the offset; index and data lenghts; in rpmReadSignature (or headerVerifyInfo) rather than in headerLoad and regionSwab?
Sort of yes, but the problem is with multiple levels of related historical API's, each of which do different levels of validation. While we could make rpm -K use rpmReadHeader() which does far more thorough checking on the header sanity than headerRead() does, but that would still leave headerRead() and headerLoad() (both are public API functions) open to this vulnerability. headerRead() could be made to use rpmReadHeader() internally with some twisting and turning for newer versions, in old versions its not possible. And even then headerLoad() would be vulnerable. Rpm generally expects callers to have done maximum possible pre-validation before calling headerLoad(), but there's no way to enforce that. The whole headerLoad() interface is as unsafe as they come, and there will always be ways to make it crash as long as it's exported the way it is now. And we can't very well just remove it in stable releases either. Etc. So the approach here is more of a minimal patch to plug these particular issues at the lowest level rather than attempt to cure the entire way headers get read and loaded.
(In reply to comment #15) > Assigning CVE-2011-3378 for the issue described in bug #741612 and bug #741606 > comment #2. Upstream git commit: http://rpm.org/gitweb?p=rpm.git;a=commitdiff;h=11a7e5d95a8ca8c7d4eaff179094afd8bb74fc3f > The issue described in comment #0 does not have a security implication. http://rpm.org/gitweb?p=rpm.git;a=commitdiff;h=a48f0e20cbe2ababc88b2fc52fb7a281d6fc1656
This issue has been addressed in following products: Red Hat Enterprise Linux 3 Extended Lifecycle Support Red Hat Enterprise Linux 4 Red Hat Enterprise Linux 5.3 Long Life Red Hat Enterprise Linux 5.6.Z - Server Only Red Hat Enterprise Linux 5 Red Hat Enterprise Linux 6.0.Z - Server Only Red Hat Enterprise Linux 6 Via RHSA-2011:1349 https://rhn.redhat.com/errata/RHSA-2011-1349.html
Created rpm tracking bugs for this issue Affects: fedora-all [bug 743103]
*** Bug 744263 has been marked as a duplicate of this bug. ***
rpm-4.9.1.2-1.fc16 has been pushed to the Fedora 16 stable repository. If problems still persist, please make note of it in this bug report.
rpm-4.9.1.2-1.fc15 has been pushed to the Fedora 15 stable repository. If problems still persist, please make note of it in this bug report.
rpm-4.8.1-7.fc14 has been pushed to the Fedora 14 stable repository. If problems still persist, please make note of it in this bug report.
Segmentation fault is received while trying to install the specially crafted rpm regionSwab.rpm from rpm libraries after applying the update from RHSA-2011:1349. Package version: ---------------- # rpm -qa | grep -i rpm redhat-rpm-config-8.0.45-32.el5 rpm-devel-4.4.2.3-22.el5_7.2 rpm-apidocs-4.4.2.3-22.el5_7.2 rpm-python-4.4.2.3-22.el5_7.2 rpm-4.4.2.3-22.el5_7.2 rpm-libs-4.4.2.3-22.el5_7.2 rpm-build-4.4.2.3-22.el5_7.2 # rpm -qa | grep -i popt popt-1.10.2.3-22.el5_7.2 Repro: ----- # rpm -ivh regionSwab.rpm error: regionSwab.rpm: headerRead failed: Header sanity check: OK Segmentation fault (core dumped) # gdb rpm -c core.4813 GNU gdb (GDB) Red Hat Enterprise Linux (7.0.1-37.el5) Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i386-redhat-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /bin/rpm...(no debugging symbols found)...done. [New Thread 4813] Reading symbols from /usr/lib/librpm-4.4.so...(no debugging symbols found)...done. Loaded symbols for /usr/lib/librpm-4.4.so Reading symbols from /usr/lib/librpmdb-4.4.so...(no debugging symbols found)...done. Loaded symbols for /usr/lib/librpmdb-4.4.so Reading symbols from /lib/libselinux.so.1...(no debugging symbols found)...done. Loaded symbols for /lib/libselinux.so.1 Reading symbols from /usr/lib/librpmio-4.4.so...(no debugging symbols found)...done. Loaded symbols for /usr/lib/librpmio-4.4.so Reading symbols from /usr/lib/libpopt.so.0...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libpopt.so.0 Reading symbols from /usr/lib/libsqlite3.so.0...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libsqlite3.so.0 Reading symbols from /usr/lib/libelf.so.1...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libelf.so.1 Reading symbols from /lib/libm.so.6...(no debugging symbols found)...done. Loaded symbols for /lib/libm.so.6 Reading symbols from /lib/libz.so.1...(no debugging symbols found)...done. Loaded symbols for /lib/libz.so.1 Reading symbols from /usr/lib/libnss3.so...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libnss3.so Reading symbols from /usr/lib/libnssutil3.so...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libnssutil3.so Reading symbols from /usr/lib/libplds4.so...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libplds4.so Reading symbols from /usr/lib/libplc4.so...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libplc4.so Reading symbols from /usr/lib/libnspr4.so...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libnspr4.so Reading symbols from /lib/libdl.so.2...(no debugging symbols found)...done. Loaded symbols for /lib/libdl.so.2 Reading symbols from /lib/librt.so.1...(no debugging symbols found)...done. Loaded symbols for /lib/librt.so.1 Reading symbols from /lib/libpthread.so.0...(no debugging symbols found)...done. [Thread debugging using libthread_db enabled] Loaded symbols for /lib/libpthread.so.0 Reading symbols from /usr/lib/libbz2.so.1...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libbz2.so.1 Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/libsepol.so.1...(no debugging symbols found)...done. Loaded symbols for /lib/libsepol.so.1 Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done. Loaded symbols for /lib/ld-linux.so.2 Reading symbols from /lib/libgcc_s.so.1...(no debugging symbols found)...done. Loaded symbols for /lib/libgcc_s.so.1 Reading symbols from /usr/lib/libsoftokn3.so...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libsoftokn3.so Reading symbols from /usr/lib/libfreebl3.so...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libfreebl3.so Core was generated by `rpm -ivh regionSwab.rpm'. Program terminated with signal 11, Segmentation fault. #0 0x00486e28 in ?? () from /usr/lib/librpm-4.4.so (gdb) run -ivh regionSwab.rpm No core file now. Starting program: /bin/rpm -ivh regionSwab.rpm [Thread debugging using libthread_db enabled] error: regionSwab.rpm: headerRead failed: Header sanity check: OK Program received signal SIGSEGV, Segmentation fault. 0x00486e28 in ?? () from /usr/lib/librpm-4.4.so (gdb) backtrace #0 0x00486e28 in ?? () from /usr/lib/librpm-4.4.so #1 0x00487ba9 in rpmtsAddInstallElement () from /usr/lib/librpm-4.4.so #2 0x004b1709 in rpmInstall () from /usr/lib/librpm-4.4.so #3 0x0804b824 in getStringBuf () #4 0x00a3fe9c in __libc_start_main () from /lib/libc.so.6 #5 0x0804a4e1 in getStringBuf () (gdb) frame 0 #0 0x00486e28 in ?? () from /usr/lib/librpm-4.4.so (gdb) Thanks Rajiv
(In reply to comment #29) Hello Rajiv, thank you for your report. Please note this particular (CVE-2011-3378) Red Hat Bugzilla entry is dedicated to the CVE-2011-3378 issue only. Any new issues (even related with original CVE-2011-3378 patch) should be reported as new Red Hat Bugzilla entries. We will investigate your report below and based on the results of the research, either dedicate a new Red Hat Bugzilla entry for that (if being a security flaw) or comment here to clarify, why Red Hat Security Response Team does not consider this issue to be a security flaw. For future cases like this, please consult Red Hat Security Response Team: [1] https://access.redhat.com/security/team/contact/ first, to ensure your concerns to be promptly investigated and particular resolution provided. Thank you for your understanding and cooperation. Regards, Jan. -- Jan iankko Lieskovsky / Red Hat Security Response Team > Segmentation fault is received while trying to install the specially crafted > rpm regionSwab.rpm from rpm libraries after applying the update from > RHSA-2011:1349. [..] > Thanks > Rajiv
(In reply to comment #29) > Segmentation fault is received while trying to install the specially crafted > rpm regionSwab.rpm from rpm libraries after applying the update from > RHSA-2011:1349. Patches from that erratum try to ensure that rpm does not misbehave until the moment rpm signature is successfully verified. After that point, rpm needs to be considered trusted as installation of rpm implies that, by definition, the rpm can execute arbitrary code even when it's perfectly well-formed. > # rpm -ivh regionSwab.rpm > error: regionSwab.rpm: headerRead failed: Header sanity check: OK > Segmentation fault (core dumped) rpm run this way does not abort if signature verification can not be done or if it fails. If you want to install package that way, you should first check its signature (rpm -K) and proceed if it was signed by a trusted vendor.