Bug 1223534 (CVE-2024-34020)

Summary: VUL-1: CVE-2024-34020: hcode: out-of-bounds write in putSDN()
Product: [openSUSE] openSUSE Tumbleweed Reporter: Wolfgang Frisch <wolfgang.frisch>
Component: SecurityAssignee: Wolfgang Frisch <wolfgang.frisch>
Status: RESOLVED FIXED QA Contact: E-mail List <qa-bugs>
Severity: Minor    
Priority: P4 - Low CC: security-team
Version: Current   
Target Milestone: ---   
Hardware: Other   
OS: Other   
See Also: https://bugzilla.suse.com/show_bug.cgi?id=1216103
Whiteboard: CVSSv3.1:SUSE:CVE-2024-34020:4.3:(AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L)
Found By: --- Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---
Attachments: POC for hcode's putSDN function
patch

Description Wolfgang Frisch 2024-04-29 13:28:09 UTC
### Vulnerability summary
A stack buffer overflow was found in the putSDN() function of hcode-2.1 [1][2] during a routine audit of packages shipped in openSUSE.

### Program description
`hcode` converts text files with legacy Korean character sets. The intended use case appears to be, among other things, converting emails in clients like Pine and Elm. That means hcode is intended to ingest arbitrary data from untrusted sources.

### Vulnerability details
The problematic function in question is putSDN() in mail.c. The static variable `cp` is used as an index for a fixed-sized buffer `ibuf`. There is a range check: `if ( cp >= HDR_BUF_LEN ) ...` but under certain circumstances, cp can be incremented beyond the buffer size, leading to a buffer overwrite here:
```
if ( (Printwc>>16) == 0x8ffb ) {
    ibuf[cp++] = (Printwc>>8)&0xff;
    ibuf[cp++] = Printwc&0xff;
}
```

The condition can be reached by supplying an input with 1023 ASCII characters followed by a valid wide-character encoding, e.g.:
```
bytes([0x20] * 1023) + bytes([0xA4, 0xA1, 0x1C])
```

```
=================================================================
==4721==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7f35ab508420 at pc 0x000000407ba0 bp 0x7ffdf1513680 sp 0x7ffdf1513678
WRITE of size 1 at 0x7f35ab508420 thread T0
    #0 0x407b9f in putSDN /home/wfrisch/audit/hcode/hcode2.1-mailpatch3/mail.c:282
    #1 0x4029ef in main /home/wfrisch/audit/hcode/hcode2.1-mailpatch3/hcode.c:114
    #2 0x7f35ad42a1ef in __libc_start_call_main (/lib64/libc.so.6+0x2a1ef) (BuildId: 96b8eb5a4407af753cc31c18e7c116279f2eab1f)
    #3 0x7f35ad42a2b8 in __libc_start_main_alias_2 (/lib64/libc.so.6+0x2a2b8) (BuildId: 96b8eb5a4407af753cc31c18e7c116279f2eab1f)
    #4 0x4022d4 in _start ../sysdeps/x86_64/start.S:115

Address 0x7f35ab508420 is located in stack of thread T0 at offset 1056 in frame
    #0 0x4074fa in putSDN /home/wfrisch/audit/hcode/hcode2.1-mailpatch3/mail.c:238

  This frame has 3 object(s):
    [32, 1056) 'ibuf' (line 240) <== Memory access at offset 1056 overflows this variable
    [1184, 2208) 'obuf' (line 240)
    [2336, 3360) 'tbuf' (line 240)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /home/wfrisch/audit/hcode/hcode2.1-mailpatch3/mail.c:282 in putSDN
Shadow bytes around the buggy address:
  0x7f35ab508180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7f35ab508200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7f35ab508280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7f35ab508300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7f35ab508380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x7f35ab508400: 00 00 00 00[f2]f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2
  0x7f35ab508480: f2 f2 f2 f2 00 00 00 00 00 00 00 00 00 00 00 00
  0x7f35ab508500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7f35ab508580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7f35ab508600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7f35ab508680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  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
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==4721==ABORTING
```

There's another branch in putSDN() that overwrites 7 bytes that could be reached with the right input, but considering the obscurity and very low usage frequency of this program, I can't justify spending more time on it.

### Impact
An attacker can supply an input file that crashes the program.

### Remediation
Fix the range check in putSDN(), e.g.:
```
if ( cp >= (HDR_BUF_LEN - 8)) { ...
```

### References
[1] http://ftp.kaist.ac.kr/hangul/code/hcode/
[2] https://build.opensuse.org/package/show/openSUSE:Factory/hcode
Comment 2 Wolfgang Frisch 2024-04-29 13:31:52 UTC
Created attachment 874559 [details]
POC for hcode's putSDN function

1. Compile with -fsanitize=address
2. ./hcode -kd hcode_putSDN_poc output
Comment 3 Wolfgang Frisch 2024-04-29 13:44:30 UTC
Upstream has abandoned this project approximately 20 years ago. Therefore it doesn't make any sense to attempt a coordinated disclosure process involving upstream.
hcode's openSUSE package maintainer also hasn't modified the package in many years.
hcode hasn't been packaged in SUSE distributions since SLE-11.

IMHO, the quickest course of action is to submit a patch for openSUSE:Factory myself and then publish the bug.
Comment 4 Wolfgang Frisch 2024-04-29 13:56:25 UTC
No upstream, no internal maintainer, not packaged by other distros -> publish.

https://build.opensuse.org/request/show/1170803
Comment 5 Wolfgang Frisch 2024-04-29 13:58:40 UTC
4.3 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L
Comment 6 Wolfgang Frisch 2024-04-29 14:10:45 UTC
I have requested a CVE from Mitre for the unlikely event that anyone is actually still using this ancient program.
Comment 7 Wolfgang Frisch 2024-04-29 14:31:05 UTC
Created attachment 874563 [details]
patch
Comment 9 Wolfgang Frisch 2024-05-02 08:06:09 UTC
Patch accepted by Factory