Overview
libbpg is a library for the BPG graphics format. libbpg 0.9.7 may allow a crafted file to write out-of-bounds, which may lead to denial of service or arbitrary code execution.
Tested Versions
libbpg 0.9.7
Product URLs
Details
In the build_msps function, two buffers(msps_buf and buf) will be malloced, and then in the while loop, with a crafted BPG image an attacker can controll the buf and cause an overflow in the heap, finally the vulnerability was triggered by av_free(msps_buf).
static int build_msps(uint8_t **pbuf, int *pbuf_len,
const uint8_t *input_data, int input_data_len1,
int width, int height, int chroma_format_idc,
int bit_depth)
{
int input_data_len = input_data_len1;
int idx, msps_len, ret, buf_len, i;
uint32_t len;
uint8_t *buf, *msps_buf;
*pbuf = NULL;
/* build the modified SPS header to please libavcodec */
ret = get_ue(&len, input_data, input_data_len);
int idx, msps_len, ret, buf_len, i;
uint32_t len;
uint8_t *buf, *msps_buf;
*pbuf = NULL;
/* build the modified SPS header to please libavcodec */
ret = get_ue(&len, input_data, input_data_len);
if (ret < 0)
return -1;
input_data += ret;
input_data_len -= ret;
if (len > input_data_len)
return -1;
msps_len = 1 + 4 + 4 + 1 + len;
msps_buf = av_malloc(msps_len);
idx = 0;
msps_buf[idx++] = chroma_format_idc;
msps_buf[idx++] = (width >> 24);
msps_buf[idx++] = (width >> 16);
msps_buf[idx++] = (width >> 8);
msps_buf[idx++] = (width >> 0);
msps_buf[idx++] = (height >> 24);
msps_buf[idx++] = (height >> 16);
msps_buf[idx++] = (height >> 8);
msps_buf[idx++] = (height >> 0);
msps_buf[idx++] = bit_depth - 8;
memcpy(msps_buf + idx, input_data, len);
idx += len;
assert(idx == msps_len);
input_data += len;
input_data_len -= len;
buf_len = 4 + 2 + msps_len * 2 + 4 + (input_data_len - len);
buf = av_malloc(buf_len);
idx = 0;
/* NAL header */
buf[idx++] = 0x00;
buf[idx++] = 0x00;
buf[idx++] = 0x00;
buf[idx++] = 0x01;
buf[idx++] = (48 << 1); /* application specific NAL unit type */
buf[idx++] = 1;
/* add the modified SPS with the correct escape codes */
i = 0;
while (i < msps_len) {
if ((i + 1) < msps_len && msps_buf[i] == 0 && msps_buf[i + 1] == 0) {
buf[idx++] = 0x00;
buf[idx++] = 0x00;
buf[idx++] = 0x03;
i += 2;
} else {
buf[idx++] = msps_buf[i++];
}
}
/* the last byte cannot be 0 */
if (idx == 0 || buf[idx - 1] == 0x00)
buf[idx++] = 0x80;
av_free(msps_buf);
*pbuf_len = idx;
*pbuf = buf;
return input_data_len1 - input_data_len;
}Crash Information
The output of bpgdec with address sanitizer enabled
==37020==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62300000de06 at pc 0x000000406730 bp 0x7fffffffe000 sp 0x7fffffffdff0
WRITE of size 1 at 0x62300000de06 thread T0
#0 0x40672f in build_msps /root/libbpg-0.9.7/libbpg.c:256
#1 0x40672f in hevc_decode_init1 /root/libbpg-0.9.7/libbpg.c:359
0x62300000de06 is located 0 bytes to the right of 6406-byte region [0x62300000c500,0x62300000de06)
allocated by thread T0 here:
#0 0x7ffff6f02602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
#1 0x43b568 in av_malloc libavutil/mem.c:138
SUMMARY: AddressSanitizer: heap-buffer-overflow /root/libbpg-0.9.7/libbpg.c:256 build_msps
Shadow bytes around the buggy address:
0x0c467fff9b70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c467fff9b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c467fff9b90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c467fff9ba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c467fff9bb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c467fff9bc0:[06]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c467fff9bd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c467fff9be0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c467fff9bf0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c467fff9c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c467fff9c10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
==37020==ABORTING
CREDIT
Zhao Liang, Huawei Weiran Labs