Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

v2: t:utf8toUnicode drops the last hex digit of code points above U+FFFF (regression since 2.9.9)

オープン 初心者向け
#3,684 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
78/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
apache, c
領域
security

調査の方向性

バグは apache2/msc_util.c の utf8_unicode_inplace_ex() にあります。sprintf(data, "%%u%04x", d) を呼び出してから data += 6 を実行する分岐です。まずそこから始めてください。ポインタの前進は sprintf() が返す長さに従うべきで、bytes_left は残りの入力を追跡すべきです。tests/tfn/utf8toUnicode.t に4バイトシーケンスのケースを追加してください。U+1F600 が %u1f600 に変換され、既存の BMP のケースが引き続き通れば完了です。

索引モデルが issue の本文から書いたものです。

説明

Summary

In ModSecurity v2 (2.9.9 through 2.9.15, and current v2/master), t:utf8toUnicode emits only four of the five hex digits for any code point above U+FFFF (supplementary planes: emoji, CJK extensions, mathematical alphanumerics, ...). The last digit is overwritten by whatever the function writes next, or by the terminating NUL when the character is the last one in the value.

Related to #1211 (ambiguous output of this transformation), but this is a separate, newer defect: #1211 describes the 4-digit vs. 6-digit ambiguity by design; this issue is a plain truncation introduced by the refactor in #3284 (commit 907d61ad, fix for #3129), first released in 2.9.9. libModSecurity v3 is not affected (its port still writes the digits one by one), although it shares the #1211 ambiguity.

Reproduction

Output of utf8_unicode_inplace_ex() from apache2/msc_util.c at v2.9.15, compiled standalone:

Input Output Expected
U+1F600 (f0 9f 98 80) %u1f60 %u1f600
U+1F600 followed by A %u1f60A %u1f600A
a U+1F600 U+00E5 a%u1f60%u00e5 a%u1f600%u00e5
U+20AC (e2 82 ac) %u20ac %u20ac (BMP characters are fine)
Cause
if (unicode_len > 0) {
    i += unicode_len;
    sprintf(data, "%%u%04x", d);
    data += 6;          /* "%u" + 4 digits, but d > 0xFFFF prints 5 digits */
    *changed = 1;
}

Before 907d61ad the four-byte branch wrote the digits individually, so 5-digit code points were preserved.

Two adjacent problems in the same function
  • bytes_left is initialised to input_len and never decremented, so the "check we have at least N bytes" guards compare against the total length instead of the remaining length. A truncated multibyte sequence at the end of the value reads past input_len. In practice the read stops at the NUL that terminates every v2 variable value, so it is bounded to one byte, but the guard is wrong.
  • The range check only rejects lead bytes >= 0xF5; an 0xF4 lead byte with a second byte >= 0x90 encodes U+110000 and above, which is outside Unicode, and is currently accepted.
Impact

Correctness only, as far as I can tell: the output buffer is sized at ten bytes per input byte and a 4-byte sequence writes at most eight, so nothing is written outside the allocation, and the transformed string is always a superset of the ASCII input, so I could not construct a rule bypass with it. Rules that match %uXXXXX sequences for supplementary-plane characters do not work, and the transformed value is wrong in the audit log.

Proposed fix

Advance data by the value sprintf() returns instead of a constant 6, decrement bytes_left (or compare against input_len - i), reject code points above U+10FFFF, and add a four-byte sequence to tests/tfn/utf8toUnicode.t, which currently has none. PR to follow.

主要言語
C++
スター
9.8k
フォーク
1.8k
平均マージ
1日 1時間
マージ済み PR(30日)
13

環境構築

  • Dockerfile・Docker Compose ファイルなし
  • プルリクエストのテンプレートあり
  • コントリビューションガイドなし

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

owasp-modsecurity/ModSecurity のほかの issue

owasp-modsecurity/ModSecurity の issue をすべて見る

似ている issue

C++ の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。