Null pointer dereference vulnerability in the function show( ) – abc2mps 8.14.1

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

December 26, 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

As per our research we observed that the vulnerability exists in show() located in file svg.c. The function user_ps_write gives user defined postscript sequences then invokes the function svg_write, which writes string length to buffer and goes to ps_exec. when a crafted file is passed to binary abcm2ps, in function show which is triggered by ps_exec, at condition if (stack->type == STR) ,we observed that stack is a structure and has the value NULL in it ,which triggered a null pointer dereference vulnerability.

Vulnerable code
-> if (stack->type == STR) {
s = pop_free_str();
if (!s || s[0] != '(') {
fprintf(stderr, "svg: No string\n");
ps_error = 1;
return;
}
p = s + 1;           
}
Analysis

 

0x00000000004dbda8 in show (type=0x73) at svg.c:1697
1697            if (stack->type == STR) {
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ registers ]────
$rax   : 0x0               
$rbx   : 0x7fffffffcd60      →  0x0000000041b58ab3
$rcx   : 0x8               
$rdx   : 0x0               
$rsp   : 0x7fffffffcd20      →  0x000000000040647f  →   mov ecx, 0x0
$rbp   : 0x7fffffffcde0      →  0x00007fffffffd020  →  0x00007fffffffd280  →  0x00007fffffffd530  →  0x00007fffffffd570  →  0x00007fffffffd860  →  0x00007fffffffd870  →  0x00007fffffffd8b0
$rsi   : 0x755900            →  0x000000003f333333 ("333?"?)
$rdi   : 0x755888            →  0x0000000000000000
$rip   : 0x4dbda8            →   movzx eax, BYTE PTR [rax+0x8]
$r8    : 0x800e2b18          →  0x0000000000000000
$r9    : 0x800e2b29          →  0x00f9f9f9f9f9f9f9
$r10   : 0x39a             
$r11   : 0x7ffff5a5ff90      →  0xfffda370fffda09f
$r12   : 0x7fffffffcdc0      →  0x00007fffffffcff0  →  0x00007fffffffd020  →  0x00007fffffffd280  →  0x00007fffffffd530  →  0x00007fffffffd570  →  0x00007fffffffd860  →  0x00007fffffffd870
$r13   : 0xffffffff9ac       →  0x0000000000000000
$r14   : 0x7fffffffcd60      →  0x0000000041b58ab3
$r15   : 0x7fffffffd5d0      →  0x0000000041b58ab3
$eflags: [carry PARITY adjust ZERO sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$es: 0x0000  $gs: 0x0000  $fs: 0x0000  $ds: 0x0000  $ss: 0x002b  $cs: 0x0033  
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ stack ]────
0x00007fffffffcd20│+0x00: 0x000000000040647f  →   mov ecx, 0x0     ← $rsp
0x00007fffffffcd28│+0x08: 0x00007f73f58eb830
0x00007fffffffcd30│+0x10: 0x0000000000000000
0x00007fffffffcd38│+0x18: 0x00000000f5a5973b  →  0x0000000000000000
0x00007fffffffcd40│+0x20: 0x0000000000000000
0x00007fffffffcd48│+0x28: 0x54fc41fbea02f700
0x00007fffffffcd50│+0x30: 0x0000000000000000
0x00007fffffffcd58│+0x38: 0x00007fffffffcff0  →  0x00007fffffffd020  →  0x00007fffffffd280  →  0x00007fffffffd530  →  0x00007fffffffd570  →  0x00007fffffffd860  →  0x00007fffffffd870
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ code:i386:x86-64 ]────
     0x4dbd9e        je     0x4dbda8 
     0x4dbda0        mov    rdi, rcx
     0x4dbda3        call   0x402e20 
 →   0x4dbda8        movzx  eax, BYTE PTR [rax+0x8]
     0x4dbdac        cmp    al, 0x1
     0x4dbdae        jne    0x4dbe7a 
     0x4dbdb4        call   0x4d7f1b 
     0x4dbdb9        mov    QWORD PTR [rbp-0x98], rax
     0x4dbdc0        cmp    QWORD PTR [rbp-0x98], 0x0
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ source:svg.c+1697 ]────
   1692             p = tmp;
   1693             tmp[0] = '\0';
   1694             s = NULL;
   1695             break;
   1696         default:
        // type=0x73
 → 1697             if (stack->type == STR) {
   1698                 s = pop_free_str();
   1699                 if (!s || s[0] != '(') {
   1700                     fprintf(stderr, "svg: No string\n");
   1701                     ps_error = 1;
   1702                     return;
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ threads ]────
[#0] Id 1, Name: "abcm2ps", stopped, reason: SIGSEGV
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ trace ]────
[#0] 0x4dbda8 → Name: show(type=0x73)
[#1] 0x4e13d9 → Name: ps_exec(op=0x6230000014c8 "gcshow")
[#2] 0x4eb574 → Name: svg_write(buf=0x623000000109 "/octava{\t% usage: w x y octava\n\texch -10 add exch 2 copy\n\tM 0 10 RM /Times-Roman 16 selectfont(8)show\n\t/Times-Roman 12 selectfont(va)show\n\tM 0 6 RL currentpoint stroke M\n\t[6] 0 setdash 30 add 0 RL currentpoint stroke M\n\t[] 0 setdash 0 -6 RL stroke}!\n/octavab{\t% usage: w x y octavab\n\texch -14 add exch 2 copy \n\tM 0 2 RM /Times-Roman 16 selectfont(8)show\n\t/Times-Roman 12 selectfont(va basso)show\n\t22 add M 0 -6 RL currentpoint stroke M\n\t[6] 0 setdash 30 add 0 RL stroke\n\t[] 0 setdash}!\n/bigl{\t\t% usage: str x y bigl\n\t/Times-Bold 26 selectfont\n\t4 add M showc\n\t1 SLW 1 -2 RM \n\t0 22 RL -22 0 RL\n\t0 -22 RL 22 0 RL stroke}!\n/biglc{\t\t% usage: str x y biglc\n\t2 copy 5 2 roll /Times-Bold 22 selectfont\n\t6 add M showc\n\t1 SLW 13 add newpath\n\t12 0 360 arc stroke}!\n/ped{\t\t% usage: str x y ped\n\tgsave 4 add exch -10 add exch T 26 dup scale\n\t0.368 0.074 moveto\n\t0.341 0.121 0.335 0.147 0.371 0.203 curveto\n\t0.435 0.289 0.531 0.243 0.488 0.155 curveto\n\t0.472 0.117 0.434 0.096 0.414 0.080 curveto\n\t0.429 0.038 0.494 -0.006 0.541 0.075 curveto\n\t0.559 0.123 0.558 0.224 0.663 0.252 curveto\n\t0.603 0.354 0.449 0.393 0.461 0.405 curveto\n\t0.902 0.262 0.705 -0.124 0.555 0.046 curveto\n\t0.488 -0.032 0.417 0.021 0.389 0.055 curveto\n\t0.303 -0.018 0.303 -0.020 0.248 0.040 curveto\n\t0.218 0.108 0.191 0.062 0.164 0.047 curveto\n\t0.010 -0.056 0.032 0.019 0.124 0.062 curveto\n\t0.229 0.117 0.200 0.091 0.228 0.195 curveto\n\t0.240 0.241 0.149 0.250 0.166 0.311 curveto\n\t0.207 0.493 lineto\n\t-0.041 0.441 0.049 0.261 0.126 0.387 curveto\n\t0.138 0.381 lineto\n\t-0.020 0.119 -0.100 0.472 0.220 0.507 curveto\n\t0.548 0.486 0.399 0.171 0.254 0.374 curveto\n\t0.264 0.384 lineto\n\t0.338 0.259 0.521 0.449 0.228 0.488 curveto\n\t0.198 0.356 lineto\n\t0.181 0.304 0.273 0.294 0.262 0.241 curveto\n\t0.229 0.101 lineto\n\t0.273 0.070 0.282 -0.038 0.368 0.074 curveto\n\t0.391 0.094 moveto\n\t0.456 0.130 0.476 0.171 0.468 0.213 curveto\n\t0.452 0.276 0.333 0.171 0.391 0.094 curveto\n\t0.627 0.019 moveto\n\t0.533 0.041 0.586 0.228 0.678 0.229 curveto\n\t0.729 0.170 0.712 0.025 0.627 0.019 curveto\n\teofill\n\t0.8 0.04 0.04 0 360 newpath arc fill\n\tpop grestore}!\n/pedoff{\t% usage: str x y pedoff\n\tgsave 4 add exch -5 add exch T 26 dup scale\n\t0.219 0.198 moveto\n\t0.231 0.172 0.195 0.138 0.162 0.173 curveto\n\t0.149 0.219 0.206 0.231 0.219 0.198 curveto\n\t0.144 0.242 moveto\n\t0.166 0.223 0.193 0.230 0.181 0.267 curveto\n\t0.178 0.306 0.144 0.302 0.151 0.335 curveto\n\t0.160 0.381 0.225 0.377 0.224 0.330 curveto\n\t0.228 0.302 0.198 0.306 0.197 0.267 curveto\n\t0.194 0.237 0.213 0.222 0.237 0.247 curveto\n\t0.263 0.276 0.234 0.297 0.268 0.322 curveto\n\t0.314 0.347 0.354 0.297 0.316 0.259 curveto\n\t0.296 0.237 0.273 0.266 0.246 0.237 curveto\n\t0.223 0.217 0.232 0.194 0.266 0.197 curveto\n\t0.303 0.202 0.302 0.232 0.332 0.228 curveto\n\t0.381 0.232 0.388 0.156 0.332 0.152 curveto\n\t0.302 0.148 0.302 0.185 0.266 0.183 curveto\n\t0.231 0.186 0.228 0.169 0.245 0.143 curveto\n\t0.273 0.116 0.297 0.141 0.316 0.117 curveto\n\t0.350 0.075 0.303 0.029 0.258 0.062 curveto\n\t0.237 0.082 0.261 0.102 0.233 0.133 curveto\n\t0.212 0.151 0.194 0.147 0.197 0.113 curveto\n\t0.203 0.075 0.232 0.075 0.230 0.043 curveto\n\t0.223 -0.004 0.159 -0.002 0.152 0.042 curveto\n\t0.148 0.075 0.185 0.076 0.183 0.113 curveto\n\t0.183 0.147 0.163 0.150 0.141 0.133 curveto\n\t0.113 0.104 0.140 0.079 0.113 0.059 curveto\n\t0.069 0.037 0.033 0.077 0.063 0.117 curveto\n\t0.082 0.141 0.104 0.117 0.132 0.142 curveto\n\t0.153 0.163 0.144 0.188 0.113 0.182 curveto\n\t0.073 0.182 0.075 0.147 0.046 0.152 curveto\n\t-0.003 0.152 -0.003 0.227 0.048 0.227 curveto\n\t0.075 0.231 0.075 0.198 0.113 0.196 curveto\n\t0.141 0.197 0.147 0.207 0.133 0.237 curveto\n\t0.102 0.264 0.082 0.237 0.062 0.261 curveto\n\t0.028 0.302 0.077 0.347 0.118 0.318 curveto\n\t0.138 0.297 0.116 0.275 0.144 0.242 curveto\n\tfill pop grestore}!\n/glissup{\t% usage: x y glissup\n\tgsave T 5 0 T\n\t25 rotate 10 0 T 0 0 M\n\t0 8 8{\n\t\t2 -1.15 2.30 150 30 arcn 4 0 T\n\t\t2 1.15 2.30 -150 -30 arc 4 0 T pop\n\t}for\n\t1 SLW stroke grestore}!\n/tr3{\t\t% usage: x y tr3 - mordent with 3 peeks\n\tM 2.2 2.2 RL 2.1 -2.9 RL 0.7 0.7 RL\n\t2.2 2.2 RL 2.1 -2.9 RL 0.7 0.7 RL\n\t2.2 2.2 RL 2.1 -2.9 RL 0.7 0.7 RL\n\t-2.2 -2.2 RL -2.1 2.9 RL -0.7 -0.7 RL\n\t-2.2 -2.2 RL -2.1 2.9 RL -0.7 -0.7 RL\n\t-2.2 -2.2 RL -2.1 2.9 RL -0.7 -0.7 RL fill}!\n/t2ub{\t\t% usage: x y t2ub - mordent ending with an upper bar\n\t2 copy umrd 0.6 SLW\n\tM 5 4 RM 0 6 RL stroke}!\n/t3tab{\t\t% usage: x y t3tab - mordent + upper turn and bar\n\t4 add 2 copy exch 7.5 sub exch tr3 exch 7.5 add exch\n\t2 copy 0.6 SLW M 2 6 14 6 16 0 RC\n\tM 8 1 RM 0 6 RL stroke}!\n/ubt3ta{\t% usage: x y ubt3ta - up bar + mordent + upper turn\n\t4 add 2 copy 0.6 SLW\n\tM -7.5 0 RM 0 6 RL stroke\n\t2 copy exch 7.5 sub exch tr3\n\tM 7.5 0 RM 2 6 14 6 16 0 RC stroke}!\n/tbt3{\t\t% usage: x y tbt3 - low turn + long mordent\n\texch 10 sub exch 6 add 2 copy 0.6 SLW\n\tM -8 0 RM 2 -6 14 -6 16 0 RC stroke\n\texch 8 add exch tr3}!\n/t2ta{\t\t% usage: x y t2ta - mordent + upper turn\n\t2 copy umrd\n\tM 5 4 RM 1 5 9 5 10 0 RC stroke}!\n/t3b{\t\t% usage: x y t3b - upper + lower mordent\n\t2 copy exch -7.5 add exch 4 add tr3 0.6 SLW\n\tM 2.5 0 RM 0 8 RL stroke}!\n gcshow", len=0x6c7)
[#3] 0x4d697d → Name: user_ps_write()
[#4] 0x41c747 → Name: init_page()
[#5] 0x41e58a → Name: write_buffer()
[#6] 0x4200c8 → Name: check_buffer()
[#7] 0x49a25c → Name: output_music()
[#8] 0x4a1368 → Name: generate()
[#9] 0x4a16eb → Name: gen_ly(eob=0x0)
gef➤  p stack
$1 = (struct elt_s *) 0x0
gef➤  p *stack
Cannot access memory at address 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