Null pointer dereference vulnerability in the function ps_exec() – abcm2ps-8.14.1

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