After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 794914 - (CVE-2018-9251) DoS in libxml2 if liblzma-dev is installed (Different from Bug 757466)
(CVE-2018-9251)
DoS in libxml2 if liblzma-dev is installed (Different from Bug 757466)
Status: RESOLVED FIXED
Product: libxml2
Classification: Platform
Component: general
git master
Other Linux
: Normal normal
: ---
Assigned To: Daniel Veillard
libxml QA maintainers
Depends on:
Blocks:
 
 
Reported: 2018-04-03 00:38 UTC by Dongliang Mu
Modified: 2018-07-30 12:52 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
PoC to trigger Denial of Service (15 bytes, application/octet-stream)
2018-04-03 00:38 UTC, Dongliang Mu
Details

Description Dongliang Mu 2018-04-03 00:38:02 UTC
Created attachment 370463 [details]
PoC to trigger Denial of Service

Hi,

we found a denial of service parsing a specially crafted xml file in libxml2 if liblzma-dev package is enabled. And we have attached a poc file that never finish the parsing process. 

The reproduction is :

```
mkdir obj-native
cd obj-native/
git clone git://git.gnome.org/libxml2
env CFLAGS="-O2 -g -fstack-protector-all" ../configure --enable-static=yes --enable-shared=no
make
gdb ./xmllint
(gdb) r poc -o /tmp/null
Starting program: /tmp/libxml2/obj-native/xmllint poc -o /tmp/null
Program received signal SIGINT, Interrupt.
lzma_code (strm=strm@entry=0x761b08, action=action@entry=LZMA_FINISH) at ../../../../src/liblzma/common/common.c:247
247	../../../../src/liblzma/common/common.c: No such file or directory.
(gdb) info stack
  • #0 lzma_code
    at ../../../../src/liblzma/common/common.c line 247
  • #1 xz_decomp
    at ../xzlib.c line 577
  • #2 xz_make
    at ../xzlib.c line 652
  • #3 __libxml2_xzread
    at ../xzlib.c line 743
  • #4 xmlXzfileRead
    at ../xmlIO.c line 1344
  • #5 xmlParserInputBufferGrow
    at ../xmlIO.c line 3236
  • #6 xmlParserInputGrow
    at ../parserInternals.c line 324
  • #7 xmlGROW
    at ../parser.c line 2090
  • #8 xmlParseDocument
    at ../parser.c line 10588
  • #9 xmlDoRead
    at ../parser.c line 15191
  • #10 xmlReadFile
    at ../parser.c line 15253
  • #11 parseAndPrintFile
    at ../xmllint.c line 2390
  • #12 main
    at ../xmllint.c line 3749

Some simple analysis for the loop: 

577             ret = lzma_code(strm, action);
578	        if (ret == LZMA_MEM_ERROR) {
579	            xz_error(state, LZMA_MEM_ERROR, "out of memory");
580	            return -1;
581	        }
582	        if (ret == LZMA_DATA_ERROR) {
583	            xz_error(state, LZMA_DATA_ERROR, "compressed data error");
584	            return -1;
585	        }
(gdb) 
586	        if (ret == LZMA_PROG_ERROR) {
587	            xz_error(state, LZMA_PROG_ERROR, "compression error");
588	            return -1;
589	        }
590	    } while (strm->avail_out && ret != LZMA_STREAM_END);

The ret variable in L577 is alway set to LZMA_MEMLIMIT_ERROR and strm->avail_out is not changed. So loop condition always hold true and this loop continues.

It is not the same error with Bug 757466 or CVE-2015-8035, but similiar to it.

And the patch could be like,

+        if (ret == LZMA_MEMLIMIT_ERROR) {
+            xz_error(state, LZMA_MEMLIMIT_ERROR, "memory limit error");
+            return -1;
+        }
Comment 1 Dongliang Mu 2018-04-03 00:58:40 UTC
```
mkdir obj-native
cd obj-native/
git clone git://git.gnome.org/libxml2
```

=>

```
git clone git://git.gnome.org/libxml2
cd libxml2
mkdir obj-native
cd obj-native/
```
Comment 2 Salvatore Bonaccorso 2018-04-04 12:31:56 UTC
Doing a bisect between v2.9.4 and 7a1bd7f6497ac33a9023d556f6f47a48f01deac0 seem to indicate that the hang happens only starting with upstream commit e2a9122b8dde53d320750451e9907a7dcb2ca8bb

commit e2a9122b8dde53d320750451e9907a7dcb2ca8bb (refs/bisect/bad)
Author: Nick Wellnhofer <wellnhofer@aevum.de>
Date:   Thu Sep 7 18:36:01 2017 +0200

    Set memory limit for LZMA decompression

    Otherwise malicious LZMA compressed files could consume large amounts
    of memory when decompressed.

    According to the xz man page, files compressed with `xz -9` currently
    require 65 MB to decompress, so set the limit to 100 MB.

    Should fix bug 786696.

$ git describe --contains e2a9122b8dde53d320750451e9907a7dcb2ca8bb
v2.9.6-rc1~7
Comment 3 Salvatore Bonaccorso 2018-04-08 19:07:13 UTC
FTR, the scope of CVE-2018-9251 is 'is all builds of libxml2 in which "ret =
lzma_code(strm, action)" (shown in 794914) can return the LZMA_MEMLIMIT_ERROR value, and trigger an infinite loop.' and so 'the call to "lzma_auto_decoder(&state->strm, UINT64_MAX, 0)"
can never result in an LZMA_MEMLIMIT_ERROR outcome, because there is
no way to exceed UINT64_MAX.'

The issue fixed by e2a9122b8dde53d320750451e9907a7dcb2ca8bb itself was assigned a second CVE, namely CVE-2017-18258.
Comment 4 Nick Wellnhofer 2018-07-30 12:52:28 UTC
Fixed here: https://gitlab.gnome.org/GNOME/libxml2/commit/2240fbf5912054af025fb6e01e26375100275e74

Thanks for the report.