Infinite loop in function load_pnm( ) – Libsixel – 1.8.2
Loginsoft-2019-1112
8 April, 2019
CVE Number
CVE-2019-11024
CWE
CWE – 20 : Improper Input Validation
Product Details
A SIXEL encoder/decoder implementation derived from kmiya’s sixel. This package provides encoder/decoder implementation for DEC SIXEL graphics, and some converter programs.
URL: https://github.com/saitoha/libsixel
Vulnerable Versions
1.8.2
Vulnerability Details
As per our research on libsixel we found an infinite loop generating recursively at function load_pnm( ) at file frompnm.c which can lead to a denial of service attack
SYNOPSIS
During our research on libsixel we found an infinite loop generating at function load_pnm () at file frompnm.c The function load_pnm( ) which loads sixelstatus and when a crafted file is passed to the binary there is an infinite while loop generating recursively and enters into function pnm_get_line( ) at this line of code while (line[0] == ‘#’); where, the value of line[O] is 0x0 which does not satisfy the condition and recursively generates an infinite loop which can lead to a denial of service.
vulnerable Source code
while (*s == '\0') { if (p >= end) { break; } p = pnm_get_line(p, end, tmp); s = tmp; }
Analysis
DEBUG:
GDB :
Gdb: [ Legend: Modified register | Code | Heap | Stack | String ] ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ──── $rax : 0x00007fffffffd160 → 0x43434380f0314300 $rbx : 0x00007fffffffd2a0 → 0x00007fffffffd660 → 0x0000000000000000 $rcx : 0x00007fffffffd100 → 0x0000000000000000 $rdx : 0x0 $rsp : 0x00007fffffffcf50 → 0x000060400000dfd0 → 0xbebebebe00000003 $rbp : 0x00007fffffffd2c0 → 0x00007fffffffd690 → 0x00007fffffffd780 → 0x00007fffffffd7f0 → 0x00007fffffffddb0 → 0x0000000000401c00 → push r15 $rsi : 0x0 $rdi : 0x0 $rip : 0x00007ffff6c08ec1 → mov rax, QWORD PTR [rbp-0x2f0] $r8 : 0x3 $r9 : 0x184d0 $r10 : 0x2b1 $r11 : 0x00007ffff6ef6ab0 → push rbp $r12 : 0x00000ffffffff9fc → 0x0000000000000000 $r13 : 0x00007fffffffcfe0 → 0x0000000041b58ab3 $r14 : 0x00007fffffffcfe0 → 0x0000000041b58ab3 $r15 : 0x0 $eflags: [CARRY PARITY ADJUST zero SIGN trap INTERRUPT direction overflow resume virtualx86 identification] $cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000 ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ──── 0x00007fffffffcf50│+0x0000: 0x000060400000dfd0 → 0xbebebebe00000003 ← $rsp 0x00007fffffffcf58│+0x0008: 0x000060700000dfd4 → 0x0000000000000003 0x00007fffffffcf60│+0x0010: 0x000060700000dfd0 → 0x00000003ffffffff → 0x0000000000000000 0x00007fffffffcf68│+0x0018: 0x0000000000000000 0x00007fffffffcf70│+0x0020: 0x000060700000dfcc → 0xffffffff00000000 0x00007fffffffcf78│+0x0028: 0x000060700000dfc8 → 0x0000000000000000 0x00007fffffffcf80│+0x0030: 0x000060700000dfb8 → 0x000060300000efb0 → 0xffff000000000000 0x00007fffffffcf88│+0x0038: 0x000060400000dfd0 → 0xbebebebe00000003 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ──── 0x7ffff6c08eac mov QWORD PTR [rbp-0x328], rax 0x7ffff6c08eb3 lea rax, [rbx-0x140] 0x7ffff6c08eba mov QWORD PTR [rbp-0x2f0], rax → 0x7ffff6c08ec1 mov rax, QWORD PTR [rbp-0x2f0] 0x7ffff6c08ec8 mov rdx, rax 0x7ffff6c08ecb shr rdx, 0x3 0x7ffff6c08ecf add rdx, 0x7fff8000 0x7ffff6c08ed6 movzx edx, BYTE PTR [rdx] 0x7ffff6c08ed9 test dl, dl ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── source:frompnm.c+229 ──── 224 for (y = 0 ; y < height ; y++) { 225 for (x = 0 ; x < width ; x++) { 226 b = (maps == 2 ? 3 : 1); 227 for (i = 0 ; i = end) { 231 break; 232 } 233 p = pnm_get_line(p, end, tmp); 234 s = tmp; ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ──── [#0] Id 1, Name: "img2sixel", stopped, reason: SIGINT ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ──── [#0] 0x7ffff6c08ec1 → load_pnm(p=0x62d00000a427 "\027", '\276' , length=0x28, allocator=0x60400000dfd0, result=0x60700000dfb8, psx=0x60700000dfc8, psy=0x60700000dfcc, ppalette=0x0, pncolors=0x60700000dfd0, ppixelformat=0x60700000dfd4) [#1] 0x7ffff6c077b3 → load_with_builtin(pchunk=0x60300000efe0, fstatic=0x0, fuse_palette=0x0, reqcolors=0x100, bgcolor=0x0, loop_control=0x1, fn_load=0x7ffff6c16ad6 , context=0x610000007f40) [#2] 0x7ffff6c0836f → sixel_helper_load_image_file(filename=0x7fffffffe2b1 "hang10", fstatic=0x0, fuse_palette=0x0, reqcolors=0x100, bgcolor=0x0, loop_control=0x1, fn_load=0x7ffff6c16ad6 , finsecure=0x1, cancel_flag=0x606ac0 , context=0x610000007f40, allocator=0x60400000dfd0) [#3] 0x7ffff6c16f5b → sixel_encoder_encode(encoder=0x610000007f40, filename=0x7fffffffe2b1 "hang10") [#4] 0x4019ce → main(argc=0xd, argv=0x7fffffffde98)
Proof of Concept
./img2sixel -78eIkiugv -w 4 -h 8 -q auto -l force -o out $POC
Vendor Disclosure: 2019-3-28
Public Disclosure: 2019-4-9
Credit
Discovered by ACE Team – Loginsoft