Null pointer dereference vulnerability in the function ps_exec() - abcm2ps-8.14.1
December 21, 2018
CVE Number
-
CWE
CWE-476: NULL Pointer Dereference
Product Details
abcm2ps is a C program which converts music tunes from the ABC music notation to PostScript or SVG.
URL:https://github.com/leesavide/abcm2ps.git
Vulnerable Versions
8.14.1-master
Vulnerability Details
Null Pointer Dereference vulnerability is discovered in the abcm2ps (8.14.1-master). The same can be triggered by sending a crafted abc file to the abcm2ps binary. It allows an attacker to cause Denial of Service (Segmentation fault) or possibly have unspecified other impact when a victim opens a specially crafted file.
SYNOPSIS
We observed that, the function seq_exec
is passed with a struct which is a sequence of the audio file, it also contains a switch case scenario based on the case the function ps_exec
located in svg.c
, which takes input argument type of sequence struct, now here it calls the function ps_exec()
in this function it also contains a switch case scenario based on the case the function ps_exec
, it trigerred to that case in this we can see the line gcur.font_n = strdup(fontnames[n])
, here the fontname consists of a buffer length which is 30. When we are sending a crafted audio file in the ps_exec(char *op)
function the switch case depends on n value, now here it shows the result of n value and the fontnames[n]
consists of different names, where fontnames
contains an address memory with particular names {0x5555557ddb30 "sans-serif", 0x5555557ddb50 "serif-Italic", 0x5555557ddb70 "serif", 0x5555557ddb90 "serif-Bold", 0x0 }
for the first four values of n numbers it showing some particular address memory, remaining values it contains an address of memory 0x0
. Where it contains a NULL value and we observed that n=0x4 it tries to access 0x0 which triggers a NULL pointer dereference .
Vulnerable Code
if (gcur.font_s != h || strcmp(fontnames[n], gcur.font_n) != 0)
{
free(gcur.font_n_old);
gcur.font_n_old = gcur.font_n;
gcur.font_n = strdup(fontnames[n]);
gcur.font_s = h;
}
return;
Analysis
Program received signal SIGSEGV, Segmentation fault.
[ Legend: Modified register | Code | Heap | Stack | String]
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ registers ]────
$rax : 0x0
$rbx : 0x5555557c3880 → 0x00005555557ddb30 → "sans-serif"
$rcx : 0x0
$rdx : 0x5555557d1010 → 0x0001000100000102
$rsp : 0x7fffffffd6d8 → 0x00007ffff76e39ae → lea rbx, [rax+0x1]
$rbp : 0x0
$rsi : 0x5555557d1010 → 0x0001000100000102
$rdi : 0x0
$rip : 0x7ffff76f7646 → movdqu xmm4, XMMWORD PTR [rax]
$r8 : 0x0
$r9 : 0x0
$r10 : 0x7ffff77e4cc0 → 0x0002000200020002
$r11 : 0x5555555a6c41 → add BYTE PTR [rsi+0x61], ah
$r12 : 0x5555557d13dd → 0x006864726f636361 ("accordh"?)
$r13 : 0x5555557d13e4 → 0x2e383232297c2800
$r14 : 0x61
$r15 : 0xa
$eflags: [zero CARRY parity ADJUST SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$ds: 0x0000 $cs: 0x0033 $ss: 0x002b $fs: 0x0000 $gs: 0x0000 $es: 0x0000
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ stack ]────
0x00007fffffffd6d8│+0x00: 0x00007ffff76e39ae → lea rbx, [rax+0x1] ← $rsp
0x00007fffffffd6e0│+0x08: 0x00005555557d13e4 → 0x2e383232297c2800
0x00007fffffffd6e8│+0x10: 0x00005555557c3880 → 0x00005555557ddb30 → "sans-serif"
0x00007fffffffd6f0│+0x18: 0x0000000000000000
0x00007fffffffd6f8│+0x20: 0x00005555555959da → movss xmm0, DWORD PTR [rsp]
0x00007fffffffd700│+0x28: 0x0000000000000000
0x00007fffffffd708│+0x30: 0x0000007743bd0000
0x00007fffffffd710│+0x38: 0x0000005b0000006e ("n"?)
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ code:i386:x86-64 ]────
0x7ffff76f7636 and rcx, 0xfff
0x7ffff76f763d cmp rcx, 0xfcf
0x7ffff76f7644 ja 0x7ffff76f76b0
→ 0x7ffff76f7646 movdqu xmm4, XMMWORD PTR [rax]
0x7ffff76f764a pcmpeqb xmm4, xmm0
0x7ffff76f764e pmovmskb edx, xmm4
0x7ffff76f7652 test edx, edx
0x7ffff76f7654 je 0x7ffff76f765a
0x7ffff76f7656 bsf eax, edx
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ threads ]────
[#0] Id 1, Name: "abcm2ps", stopped, reason: SIGSEGV
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ trace ]────
[#0] 0x7ffff76f7646 → Name: __strlen_sse2()
[#1] 0x7ffff76e39ae → Name: __GI___strdup(s=0x0)
[#2] 0x5555555959da → Name: ps_exec(op=)
[#3] 0x55555559f609 → Name: seq_exec(e=)
[#4] 0x555555595719 → Name: ps_exec(op=0x5555557d13dd "accordh")
[#5] 0x55555559f270 → Name: svg_write(buf=0x5555557d1260 "% --- font 20.0 F2 \n/y0{-74.0 add}!\n/yns0{-74.0 add}!\n24.0 228.1 -74.0 bar \n24.0 378.0 -74.0 bar \ndlw 378.0 0.0 -74.0 M 0 RL 378.0 0.0 -68.0 M 0 RL 378.0 0.0 -62.0 M 0 RL 378.0 0.0 -56.0 M 0 RL 378.0 0.0 -50.0 M 0 RL stroke\n12.0 F0 44.7 38.4 yns0 M (A)gcshow\n134.1 38.4 yns0 M (F)gcshow\n237.8 38.4 yns0 M (G)gcshow\n337.0 38.4 yns0 M (C)gcshow\n/y{-87.0 yns0}def 13.0 F3 378.0 0 y 2 accordh", len=0x287)
[#6] 0x55555559fcdf → Name: svg_write(buf=0x5555557d1260 "% --- font 20.0 F2 \n/y0{-74.0 add}!\n/yns0{-74.0 add}!\n24.0 228.1 -74.0 bar \n24.0 378.0 -74.0 bar \ndlw 378.0 0.0 -74.0 M 0 RL 378.0 0.0 -68.0 M 0 RL 378.0 0.0 -62.0 M 0 RL 378.0 0.0 -56.0 M 0 RL 378.0 0.0 -50.0 M 0 RL stroke\n12.0 F0 44.7 38.4 yns0 M (A)gcshow\n134.1 38.4 yns0 M (F)gcshow\n237.8 38.4 yns0 M (G)gcshow\n337.0 38.4 yns0 M (C)gcshow\n/y{-87.0 yns0}def 13.0 F3 378.0 0 y 2 accordh", len=)
[#7] 0x5555555639eb → Name: write_buffer()
[#8] 0x555555565215 → Name: write_buffer()
[#9] 0x555555565215 → Name: block_put()
gef➤ p fontnames[0x0]
$1 = 0x5555557ddb30 "sans-serif"
gef➤ p fontnames[0x1]
$2 = 0x5555557ddb50 "serif-Italic"
gef➤ p fontnames[0x2]
$3 = 0x5555557ddb70 "serif"
gef➤ p fontnames[0x3]
$4 = 0x5555557ddb90 "serif-Bold"
gef➤ p fontnames[0x9]
$5 = 0x0
gef➤ i r
rax 0x0 0x0
rbx 0x5555557c3880 0x5555557c3880
rcx 0x0 0x0
rdx 0x5555557d1010 0x5555557d1010
rsi 0x5555557d1010 0x5555557d1010
rdi 0x0 0x0
rbp 0x0 0x0
rsp 0x7fffffffd6d8 0x7fffffffd6d8
r8 0x0 0x0
r9 0x0 0x0
r10 0x7ffff77e4cc0 0x7ffff77e4cc0
r11 0x5555555a6c41 0x5555555a6c41
r12 0x5555557d13dd 0x5555557d13dd
r13 0x5555557d13e4 0x5555557d13e4
r14 0x61 0x61
r15 0xa 0xa
rip 0x7ffff76f7646 0x7ffff76f7646
eflags 0x10293 [ CF AF SF IF RF]
cs 0x33 0x33
ss 0x2b 0x2b
ds 0x0 0x0
es 0x0 0x0
fs 0x0 0x0
gs 0x0 0x0
Tested environment
64-bit ubuntu 16.04 LTS
Proof of Concept
./abcm2ps r -E -g -x -v -O fff -O = -i -k 1 $POC -s 10 -w 1 -m 100 -d 100 -a 0 -f musicfont.fmt -D Bar/ -p -l -I 500 -x -M -N 3 -1 -G -j 0 -b 1 -f -T all -c -B 10
Timeline
Vendor Disclosure: 2018-12-13
Public Disclosure:
Credit
Discovered by ACE Team - Loginsoft