Bug 1658786 (CVE-2018-19541)

Summary: CVE-2018-19541 jasper: heap-based buffer over-read of size 8 in jas_image_depalettize in libjasper/base/jas_image.c
Product: [Other] Security Response Reporter: Laura Pardo <lpardo>
Component: vulnerabilityAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED ERRATA QA Contact:
Severity: low Docs Contact:
Priority: low    
Version: unspecifiedCC: abhgupta, dbaker, jokerman, jridky, rh-spice-bugs, sthangav, trankin
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
A vulnerability was found in Jasper due to a heap-based buffer overflow caused by improper bounds checking in the jas_image_depalettize function within libjasper/base/jas_image.c, an attacker could exploit this flaw by persuading a victim to open a specially crafted file, which could overflow a buffer and potentially allow arbitrary code execution or cause the application to crash.
Story Points: ---
Clone Of: Environment:
Last Closed: 2021-10-27 03:21:53 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 1658787, 1658788, 1658789, 1660964, 1660970, 1660975    
Bug Blocks: 1658799    

Description Laura Pardo 2018-12-12 20:47:44 UTC
An issue was discovered in JasPer 2.0.14. There is a heap-based buffer over-read of size 8 in the function jas_image_depalettize in libjasper/base/jas_image.c. 


References:
https://github.com/mdadams/jasper/issues/182

Comment 1 Laura Pardo 2018-12-12 20:48:07 UTC
Created jasper tracking bugs for this issue:

Affects: fedora-all [bug 1658787]


Created mingw-jasper tracking bugs for this issue:

Affects: epel-7 [bug 1658789]
Affects: fedora-all [bug 1658788]

Comment 4 Scott Gayou 2019-02-01 16:46:07 UTC
```
==30795== Memcheck, a memory error detector
==30795== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==30795== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==30795== Command: jasper --input jasper_bug_1.jp2 --output-format mif
==30795== 
warning: number of components mismatch
==30795== Invalid read of size 8
==30795==    at 0x4E47AAE: jas_image_depalettize (jas_image.c:904)
==30795==    by 0x4E5949B: jp2_decode (jp2_dec.c:365)
==30795==    by 0x4E46337: jas_image_decode (jas_image.c:388)
==30795==    by 0x401554: main (jasper.c:229)
==30795==  Address 0x6d28668 is 8 bytes before a block of size 0 alloc'd
==30795==    at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
==30795==    by 0x4E4F0FC: jas_malloc (jas_malloc.c:109)
==30795==    by 0x4E4F21E: jas_alloc2 (jas_malloc.c:141)
==30795==    by 0x4E5936E: jp2_decode (jp2_dec.c:360)
==30795==    by 0x4E46337: jas_image_decode (jas_image.c:388)
==30795==    by 0x401554: main (jasper.c:229)
==30795==
```

Brings us here:

```c
	v = jas_image_readcmptsample(image, cmptno, i, j);
	if (v < 0) {
		v = 0;
	} else if (v >= numlutents) {
		v = numlutents - 1;
	}
	jas_image_writecmptsample(image, newcmptno, i, j,
	  lutents[v]);
}
```

In this vulnerability, numlutents can be set to 0. Thus, v = numlutents - 1 = -1. This is then indexed into the lutents[v] array read passed to jas_image_writecmtsample.

```
(gdb) print sizeof(lutents[v])                                                                                                                       
$37 = 8
(gdb) ptype lutents[v]
type = long
```

hence the read of size 8. lutents[-1] is out-of-bounds.

This value is passed into jas_image_writecmptsample.

```
if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * y + x) * cmpt->cps_, SEEK_SET) < 0) {
    	return;
    }
    t = inttobits(v, cmpt->prec_, cmpt->sgnd_);
    for (k = cmpt->cps_; k > 0; --k) {
    	c = (t >> (8 * (cmpt->cps_ - 1))) & 0xff;
    	if (jas_stream_putc(cmpt->stream_, (unsigned char) c) == EOF) {
    		return;
  	}
  	t <<= 8;
  	}
}
```

v modifies t, which is then masked to one byte, which is then written to cmpt->stream_.

Thus, it appears that this is an out-of-bounds read that may be able to leak a byte of information before the lutents array (which I presume is heap metadata based on `lutents = jas_alloc2(pclrd->numlutents, sizeof(int_fast32_t));`)

So, while it is always possibe that this could somehow lead to code execution downstream (ruling that out is vastly time consuming and often nearly impossible), it seems highly unlikely in this case. What is more likely, but still challenging, would be some sort of minor information leak.

Upgraded CVE to 4.4/CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:L because of this. Low still feels highly appropriate as I don't have any evidence of DoS or an infoleak at this point -- just theoretical.

Comment 5 Scott Gayou 2019-02-04 16:56:28 UTC
Accidentally set I:L instead of C:L. Was thinking (I)nformation leak and made a mistake last Friday. Updated.