
PJSIP DNS圧縮ポインタのヒープ領域外読み取り(リモートDoS)
pjlib-util/src/pjlib-util/dns.c 内の get_name_len() と get_name() は、pj_memcpy(&offset, p, 2) を使用して2バイトのDNS圧縮ポインタを読み取りますが、両バイトがパケットバッファ内にあることを確認していません。0xC0 バイト(圧縮ポインタマーカー)がDNS応答の最後のバイトである場合、memcpy はヒープ割り当て境界を1バイト超えて読み取ります。
単一の20バイトの細工されたDNS応答は、領域外読み取りを引き起こし、ネットワーク制御されたDNSサーバーを介してドメインを解決するあらゆるPJSIPアプリケーション(AsteriskやFreeSWITCHを含む)をクラッシュさせます。
ASanは get_name_len() 内で heap-buffer-overflow READ of size 2, 0 bytes after 20-byte region(サイズ2のヒープバッファオーバーフロー読み取り、20バイト領域の0バイト後)を確認しています。
これは、pjproject の dns.c における2022年以降3件目となるDNSパーサーのCVEです(CVE-2022-24793 と CVE-2023-27585 に続く)。CVE-2022-24793 の修正ではパーサー全体に長さチェックが追加されましたが、圧縮ポインタのパスが見落とされていました。
影響を受けるバージョン: pjproject <= 2.16。pjproject 2.17(コミット 5311aee)で修正済み。
# スタンドアロンASanハーネス(pjprojectのインストールは不要):
./run.sh
# または手動でビルドして実行:
gcc -fsanitize=address,undefined -g -O0 harness.c -o harness
./harness
# ネットワークPoC -- 不正なDNSサーバー:
python3 poc.py --port 5353
# その後、PJSIPアプリケーションを不正なサーバーに向ける:
# pjsua --nameserver 127.0.0.1:5353 sip:[email protected]
# Docker(ASan付きでpjproject 2.16をソースからビルド):
docker compose build
docker compose run harness
gccこのプロジェクトはGNU GPLv3の下で公開されています。
これは防御的なセキュリティ研究、教育、および許可されたテストのために提供されています。所有者から明示的な許可を得ずに、このコードをシステムやサービスに対して使用しないでください。
許可のない使用は、適用される法律に違反する可能性があります。著者は第三者システムのテストを許可しておらず、誤用について責任を負いません。
保証および責任条件については、LICENSEファイルを参照してください。
| ファイル | 説明 |
|---|
harness.c | スタンドアロンASanハーネス -- 正確なpjproject型で脆弱な get_name_len() を再実装 |
harness_pjlib.c | 実際の pj_dns_parse_packet() を呼び出す代替ハーネス(Docker用) |
poc.py | 不正なDNSサーバー -- 任意のクエリに対して細工された20バイトのパケットで応答 |
run.sh | ASanハーネスをビルドして実行 |
Dockerfile | ASan付きでpjproject 2.16をソースからビルド |
docker-compose.yml | pjlibハーネス用のDockerセットアップ |
proof_output.txt | 実機検証による完全なASan出力 |