
lighttpd 1.4.85 - High - Remote - Path - native Win32 GET /..%20/ がドキュメントルート外を読み取る
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · lighttpd-win32-dotdot-space
解説記事: https://abraxaslabs.tech/research/lighttpd-win32-dotdot-space
分類: ファイル読み取り 到達範囲: リモート
lighttpd 1.4.85 (4852959) - lighttpd
ネイティブ _WIN32 の staticfile は、buffer_path_simplify の後に document-root と rel_path を結合します。simplify は 3 バイト目が / の場合にのみ ../ を畳み込みます。http_response_prepare_physical はパス全体のみから末尾のスペースとドットを除去します。したがって GET /..%20/windows/win.ini は /.. /windows/win.ini のまま残ります。その後、\\?\ プレフィックスなしの _wstati64 / _wopen により、Win32 がコンポーネントごとにスペースを除去し、そのセグメントを .. として扱います。
ネイティブ Windows の lighttpd に対する未認証の GET/HEAD により、ワーカーアカウントが開ける document-root 外の通常ファイルが読み取られます。 Unix/Linux はこの残存問題には該当しません。RCE ではなくファイル読み取りです。
このラボは、それらのピン留めされた関数を再現したガジェットです。実際のネイティブ Win32 ワーカーではありません。最終行は how=gadget を使用しています。
| ID | CVE 未割当 |
| 分類 | ファイル読み取り (パストラバーサル、ネイティブ Win32 ..%20/) |
| 到達範囲 | リモート (未認証 GET/HEAD) |
| CWE | CWE-22 |
| CVSS | High: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
| 製品 | lighttpd1.4 |
| 影響を受けるバージョン | 1.4.85 (4852959e67ef51ea68084984400d3264b854c97d) ネイティブ _WIN32 |
| 認証 | なし。デフォルトの mod_staticfile |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1 のみ、how=gadget |
静的ファイルを配信するネイティブ Windows の lighttpd が必要です。ワーカーアカウントが対象の通常ファイルを開ける必要があります。
| 権限 | メソッド / シンク | ラボで実証済みか推測か |
|---|---|---|
document-root 外のファイルを読み取る | 未認証 GET /..%20/<name> | ラボで実証済み (ガジェット)。HTTP 200 のボディが親ディレクトリの秘密情報 |
最終コンポーネント以外の .. に対する他の末尾 ASCII スペース/ドットでも同分類 | URL デコード後に simplify が .. を保持 | %20 はラボで実証済み。他の末尾スペース/ドットは推測 |
| 同じパスへの HEAD | staticfile HEAD | 推測。ラボでは GET を使用 |
陰性: 実際の /../ | buffer_path_simplify が ../ を畳み込む | ラボで実証済み。404、簡略化された /windows/win.ini、証跡なし |
| 陰性: 簡略化されていない物理文字列に対する Unix POSIX open | open("/srv/htdocs/.. /windows/win.ini") | ラボで実証済み。ENOENT |
この残存問題では対象外: Unix/Linux の staticfile、Cygwin (同じ除去処理だが POSIX open)、1.4.85 の %5C parseopt、CVE-2018-19052 の別名、CVE-2014-2324 の Host。RCE ではありません。書き込みでもありません。
タグ lighttpd-1.4.85 をピン留めしました。20 回の調査を行いました。デフォルトの Unix/Linux staticfile、FastCGI、プロキシ、TLS、認証、HTTP/2、alias/rewrite は、この水準では該当なしでした。1.4.81-1.4.85 のパーサー関連の一連の問題では、すでに trailers、CGI ヘッダーの競合、不正なバックエンド Content-Length が塞がれていました。
buffer_path_simplify は walk[2] == '/' の場合にのみ ../ を畳み込みます。http_response_prepare_physical (src/response.c 334-360) における WIN32 の除去処理はパス全体の末尾に対して行われます。_wstati64 / _wopen (src/fs_win32.c 24-77) は \\?\ なしで UTF-16 を渡すため、Win32 がコンポーネントごとに末尾スペースを除去し、.. が .. になります。物理的な結合は doc_root + rel_path であり、stat 後のベースディレクトリチェックはありません。
誤った判断としてすでに記録済み: Unix の ENOENT を「バグではない」と扱ったこと(これは陰性対照である); Cygwin をネイティブ Win32 と呼んだこと; 1.4.85 の %5C がこの残存物であると主張したこと; ファイル読み取りを RCE に誇張したこと。見せかけ: リバースシェル。オラクルは document-root の親からの 200 ボディである。
python3 lighttpd-win32-dotdot-space-Abraxas-Labs.py
または
cd lab
./run.sh
ラボは、buffer_urldecode_path、buffer_path_simplify(Win32 の '\\' マップ)、response.c の末尾除去、および \\?\ なしの _wstati64 を忠実に再現したガジェットである。Unix の POSIX open がネガティブコントロールとなる。Win32 の解決は、同じコンポーネントごとの末尾スペース除去、続いて . / ..、そして解決済みパスに対する POSIX open として実装されている。ループバック HTTP は 127.0.0.1:19400。
/index.html -> 200 public-index、witness なし。/../windows/win.ini -> 404、簡略化後は /windows/win.ini。/..%20/windows/win.ini -> デコード後は /.. /windows/win.ini、簡略化でスペースが保持され、Unix では ENOENT、Win32 では /srv/windows/win.ini に解決され、200 witness。SUCCESS lighttpd-win32-dotdot-space how=gadget win32-get=200 unix-open=enoent simplify-kept-dotdot-space=yes LIGHTTPD-WIN32-DOTDOT-SPACE-WITNESS
simplify の前にパスコンポーネントごとに末尾のスペースとドットを除去するか、Win32 のオープンに \\?\ を付与し、document-root 配下に留まらない物理パスを拒否します。
4852959e67ef51ea68084984400d3264b854c97d)src/buffer.c · src/response.c · src/fs_win32.c%5C parseopt · CVE-2018-19052 alias · CVE-2014-2324 HostGNU Affero GPL v3.0。LICENSE を参照してください。ループバックラボ専用です。保証はありません。