Released in September 2021, CVE-2021-30860 fixes an Xpdf integer (then heap) overflow in various Apple operating systems, documented by Apple as affecting CoreGraphics (e.g., https://support.apple.com/en-us/HT212807).
Per Google Project Zero's December 2021 write up of FORCEDENTRY:
Most of the CoreGraphics PDF decoder appears to be Apple proprietary code, but the JBIG2 implementation is from Xpdf, the source code for which is freely available.
CVE-2022-38171 is the ~upstream instance of this vulnerability in Xpdf, fixed in April 2022 in Xpdf 4.04.
Poppler forked an older version of Xpdf 2005 and may backports some changes.
Poppler is a PDF rendering library based on the xpdf-3.0 code base.
Fixed in Poppler 22.09.0 as CVE-2022-38784.
Plenty of distros include Poppler, Xpdf, and downstream packages. Notified oss-security list on 2022-09-02.
This exploit crashes Xpdf (<4.04), Poppler (<22.09.0), and other downstream software. Exploiting the vulnerability to run arbitrary code is context dependent. The Apple instance of the vulnerability (CVE-2021-30860) is used as one link in the FORCEDENTRY exploit chain, to create a weird machine used to set up the next (IMTranscoderAgent) sandbox escape.
Observations:
- The lack of sufficient CVE IDs and other documentation caused a lot of downstream Xpdf users to not notice the vulnerability or the fix.
- CVE IDs lack a formal ability to relate to each other (and to other vulnerability identifiers), see CVEProject/Board-Discussions#10.
#
# Fix for CVE-2022-38171 in Xpdf 4.04
#
cd $(mktemp -d)
wget https://dl.xpdfreader.com/xpdf-4.04.tar.gz # this will become https://dl.xpdfreader.com/old/xpdf-4.04.tar.gz
wget https://dl.xpdfreader.com/old/xpdf-4.03.tar.gz
for file in $(ls xpdf*.tar.gz); do tar xzf $file; done
diff -u xpdf-4.03/CHANGES xpdf-4.04/CHANGES | grep JBIG2
+ # Fixed an integer overflow security hole in the JBIG2 decoder.
diff -u xpdf-4.03/xpdf/JBIG2Stream.cc xpdf-4.04/xpdf/JBIG2Stream.cc
<snip>
@@ -2042,7 +2057,14 @@
for (i = 0; i < nRefSegs; ++i) {
if ((seg = findSegment(refSegs[i]))) {
if (seg->getType() == jbig2SegSymbolDict) {
- numSyms += ((JBIG2SymbolDict *)seg)->getSize();
+ Guint segSize = ((JBIG2SymbolDict *)seg)->getSize();
+ if (segSize > INT_MAX || numSyms > INT_MAX - segSize) {
+ error(errSyntaxError, getPos(),
+ "Too many symbols in JBIG2 text region");
+ delete codeTables;
+ return;
+ }
+ numSyms += segSize;
} else if (seg->getType() == jbig2SegCodeTable) {
codeTables->append(seg);
}
<snip>
Or, see this diff.