CTF_WRITEUPS/TryHackMe /CVE-2021-41773/
CTF_WRITEUPS/TryHackMe /CVE-2021-41773/
簡単な歴史
2021年10月5日、Apache HTTP Server v2.4.49に対するパストラバーサル攻撃を詳述したCVEが公開されました。CVE-2021-41773という番号が割り当てられ、以下の説明とともに公開されました。
Apache HTTP Server 2.4.49のパス正規化に加えられた変更に欠陥が見つかりました。攻撃者はパストラバーサル攻撃を使用して、想定されるドキュメントルート外のファイルにURLをマッピングできる可能性があります。ドキュメントルート外のファイルが「require all denied」によって保護されていない場合、これらのリクエストは成功する可能性があります。さらに (sic) この欠陥により、CGIスクリプトのような解釈されるファイルのソースが漏洩する可能性があります。この問題は実際に悪用されていることが知られています。この問題はApache 2.4.49にのみ影響し、それ以前のバージョンには影響しません。
これを分解して、これが私たちにとって実際に何を意味するのか見てみましょう。
たくさんの修正を経て...
そこでApacheはこのバグを修正し、v2.4.50をリリースしました。これで終わりですよね? いや、そうでもありません。わずか2日後の10月7日、先のCVEを引用した新しいCVEが公開されました。今回のものは、以前のパストラバーサル攻撃に対する修正が不完全であり、問題のパスがエイリアスディレクティブを使用してURLをファイルシステムにマッピングしている場合、依然としてトラバースできる可能性があると述べています。このCVEにはCVE-2021-42013という番号が割り当てられ、説明は以下のとおりです。
Apache HTTP Server 2.4.50におけるCVE-2021-41773の修正が不十分であることが判明しました。攻撃者はパストラバーサル攻撃を使用して、Alias風ディレクティブによって設定されたディレクトリの外部にあるファイルにURLをマッピングできる可能性があります。これらのディレクトリ外のファイルが通常のデフォルト設定である「require all denied」によって保護されていない場合、これらのリクエストは成功する可能性があります。これらのエイリアスパス (sic) でCGIスクリプトも有効になっている場合、リモートコード実行が可能になる可能性があります。この問題はApache 2.4.49とApache 2.4.50にのみ影響し、それ以前のバージョンには影響しません。
前回と同様に、ここからいくつかのことを学べます。
この混乱を処理している間に、次のタスクで必要な構成について見ていきます。
下の質問に答えてください
理論のちょっとした話
パストラバーサルエクスプロイトは、パス解決や正規化の欠陥を悪用して、通常はアクセスできないリソースにアクセスすることを目的とした攻撃です。通常、この種の攻撃は、.. 構文を使用して、想定されたルートを超えて後方に移動(トラバースとも呼ばれます)することで悪用します。
正規化? なんですか?
通常、コードがファイルを見つけるためのパスを提供する場合、絶対パスが必要です。これを正規パスと呼びましょう。代わりに相対パスが与えられた場合、そのパスを使用するOSライブラリが目的のリソースを見つけられるように、正規の形式に正規化する必要があります。もちろんこれは単純化しすぎですが、要点は変わりません。
URLの正規化
HTTPサーバーは、提供する正しいファイルを見つけるために、URLをファイルシステム上の正規パスに変換する必要があります。ドキュメントルートを超えてトラバースできないようにするフィルタは確かにいくつかありますが、いくつかのユースケースは簡単に見落とされる可能性があります。この場合、エクスプロイトはURLエンコーディング(これについては後で説明します)だけでなく、Aliasモジュールのパス正規化の欠陥も利用しています(おそらく)
URLエンコーディングに関する余談
RFC 3986のセクション2で定義されているURLエンコーディングは、URL内の特殊文字や予約文字をエンコードするためのスキームです。たとえば、URL内のスペースは+文字としてエンコードされます(特にクエリパラメータで)。実際のプラス記号をエンコードしたい場合は、「パーセントエンコーディング」として知られる方法でエンコードする必要があります。これは単に、文字のUS-ASCII 16進コードの前に%記号を付けるだけです。この例では、+記号は%2Bとしてエンコードできます。
任意の文字をURLエンコードでき、完全にURLエンコードされたURLは、エンコードされていないバージョンと機能的に同等です。RFCから引用:2つのURIが、パーセントエンコードされたオクテットで使用される16進数字の大文字小文字のみが異なる場合、それらは同等です。
それでApacheでは何が起こったのか?
Apacheサーバーのパス正規化モジュールに最近加えられた変更により、特別に細工されたURLがフィルタをバイパスしてドキュメントルートを越えてトラバースできるようになり、構成が許せばシステム上の任意のファイル読み取りが可能になりました。さらに、CGIモジュールが有効になっている場合は、任意のファイル実行も可能です!
下の質問に答えてください
A) サーバー上で処理される任意のリモートファイルを含める。 B) サーバー上で処理される任意のローカルファイルを含める。 C) サーバーによって任意のファイルが公開されることを許可する。 D) 上記のいずれでもない。
楽しみのためのApacheハッキング
さて、理論は終わったので、この欠陥を悪用してみましょう。まず、脆弱なバージョンのApacheが必要です。ありがたいことに、これにはdockerがあります:)```
user@machine$ docker pull httpd:2.4.49
2.4.49: Pulling from library/httpd
07aded7c29c6: Already exists
05bb40c8f148: Already exists
0827b74117da: Already exists
35a526fdcc7d: Pull complete
59fed288cd32: Pull complete
Digest: sha256:dcba0d12e2362fb0c50ec524ae8aa1cca4a4ba7216617a57e7bbca20767e79cc
Status: Downloaded newer image for httpd:2.4.49
docker.io/library/httpd:2.4.49
**設定**
このエクスプロイトを機能させるには、ドキュメントルート外のファイルへのアクセスを許可するようにApacheを設定する必要があります。特定のディレクトリを指定して正確に設定することもできますし、YOLO方式ですべてへのアクセスを許可することもできます。私たちの目的には、すべてへのアクセス許可で十分です。まず、コンテナを起動して設定を確認しましょう。これらの変更は、脆弱な両バージョンのApacheで機能することに注意してください。```
user@machine$ docker run --name vuln-httpd -p 8080:80 -d httpd:2.4.49
a4dfc0376d93dc62183982a527b0bef62543e7a91178116bb0480a42ecc0c8dd
user@machine$ docker cp vuln-httpd:/usr/local/apache2/conf/httpd.conf .
user@machine$ grep -C4 -n "Require all denied" httpd.conf
246-# <Directory> blocks below.
247-#
248-<Directory />
249- AllowOverride none
250: Require all denied
251-</Directory>
252-
253-#
254-# Note that from this point forward you must specifically allow
--
303-# The following lines prevent .htaccess and .htpasswd files from being
304-# viewed by Web clients.
305-#
306-<Files ".ht*">
307: Require all denied
308-</Files>
309-
310-#
311-# ErrorLog: The location of the error log file.
user@machine$ sed "250s/denied/granted/" httpd.conf > httpd.new.conf
user@machine$ docker cp http.new.conf vuln-httpd:/usr/local/apache2/conf/httpd.conf
user@machine docker container restart vuln-httpd
vuln-httpd
余談ですが、設定はいつでも手動で変更できます。変更したいのは、次のように書かれている部分です:``` AllowOverride none Require all denied
そして、`denied` を `granted` に置き換えます。これにより、Apache はファイルシステム全体にアクセスできるようになります(これは間違いなく良いアイデアではないので、本番環境では絶対にやらないでください。絶対に)。
**あのおいしい RCE の設定**
アクセス制御を変更するだけでは、データが露出するだけで、RCE は得られません。この小さな PoC で RCE を得るには、アクセス許可に加えて CGI モジュールを有効化するだけで済みます。これにより、CGI モジュールは、スクリプトの内容を単に表示するのではなく、呼び出したときにスクリプトを実行するようになります。CGI を有効にするには、`LoadModule` 設定をコメント解除するだけです。先ほど変更したコンテナがまだある場合は、次のようにします:```
user@machine$ docker cp vuln-httpd:/usr/local/apache2/conf/httpd.conf .
user@machine$ grep -C4 -n "mod_cgi" httpd.conf
180-#LoadModule asis_module modules/mod_asis.so
181-#LoadModule info_module modules/mod_info.so
182-#LoadModule suexec_module modules/mod_suexec.so
183-<IfModule !mpm_prefork_module>
184: #LoadModule cgid_module modules/mod_cgid.so
185-</IfModule>
186-<IfModule mpm_prefork_module>
187: #LoadModule cgi_module modules/mod_cgi.so
188-</IfModule>
189-#LoadModule dav_fs_module modules/mod_dav_fs.so
190-#LoadModule dav_lock_module modules/mod_dav_lock.so
191-#LoadModule vhost_alias_module modules/mod_vhost_alias.so
--
385-
386-<IfModule cgid_module>
387- #
388- # ScriptSock: On threaded servers, designate the path to the UNIX
389: # socket used to communicate with the CGI daemon of mod_cgid.
390- #
391- #Scriptsock cgisock
392-</IfModule>
393-
user@machine$ sed "184,187s/#//" httpd.conf > httpd.new.conf
user@machine$ docker cp http.new.conf vuln-httpd:/usr/local/apache2/conf/httpd.conf
user@machine docker container restart vuln-httpd
vuln-httpd
もちろん、利用可能なテキストエディタを使ってファイルを変更しても構いません。コンテナ内にはテキストエディタがないため、grep/sed 方式はコンテナ内のシェルで動作します。
いよいよエクスプロイトへ!
コンテナをセットアップしたので、このCVEのエクスプロイトに取り掛かることができます(ようやく)。方法は非常に簡単で、トラバース中に各URLパスセグメントの . 記号の1つをURLエンコードするというものです。また、エイリアスされたパスからトラバースする必要があります。ありがたいことに、設定ファイルを読むと cgi-bin パスがデフォルトでエイリアスされていることがわかるので、それを使いましょう! エクスプロイトはバージョン2.4.49と2.4.50で若干異なりますが、後者は前者でも動作します。
Apache 2.4.49(CGI無効)