複数のプログラミング言語においてWindows上でコマンドインジェクションを実行可能な脆弱性(batbadbut)
概要
複数のプログラミング言語のプロセスを実行するライブラリにおいて、Windows環境でシェルのエスケープが不十分なため、意図しないコマンドを実行させることができる。
影響
影響を受ける言語
発見者が提示しているものは以下。ただし、cmd.exeの処理が複雑で完全なエスケープ処理を入れている可能性が低いため、これらの言語以外もほとんどの言語は対応されていないと考えた方が良さそう。
言語 | 対応 | 修正コミット | 補足 |
---|---|---|---|
Erlang | ドキュメント更新 | ドキュメント修正のPRが出ていた | |
Go | ドキュメント更新 | ||
Haskell | 修正する | 修正 | エスケープ処理を実施。ただし、この修正では% の処理はされていない。 % の処理を追加するPRはopenの状態 |
Java | 修正しない | ||
Node.js | 修正する | 修正 | shell:trueでない場合はバッチファイルを実行せずエラーにしている。そのため、利用アプリが動かなくなったケースもある |
PHP | 修正する | 修正 | エスケープ処理を追加している。 |
Python | ドキュメント更新 | ||
Ruby | ドキュメント更新 | ||
Rust | 修正する | 修正 | エスケープ処理を実施し、エスケープできない場合はエラーにしている |
影響を受けるアプリ
発見者のフローチャートを参考にするとよい。
Windows上で外部からの信頼できない入力をバッチファイルに渡してプロセスを実行しているアプリケーションが該当する。例えば、Webサービスなどでこのような処理を実行していると、外部からサーバ上で任意のコマンドを実行できる。
原因
詳細は発見者の記事を参照。
Windows上で外部プロセスを実行する場合、プログラミング言語のプロセス実行ライブラリはCreateProcessを利用する。CreateProcessに通常の.exeが渡されると普通に実行するのだが、.bat/.cmdのファイルが渡されると、cmd.exeがそのバッチファイルを実行する。
例えば、node.jsでバッチファイルを実行する場合、以下のようなスクリプトになる。
const { spawn } = require('child_process');
spawn('バッチファイル', ['引数1', ...]);
この場合、以下のようなコマンドラインが実行されることになる。
cmd.exe /c <バッチファイル> <引数1> ...
この時、cmd.exeは/c以降を実行するコマンド列と解釈する。
そのため、引数の部分に&calc.exe
を入力された場合、プロセスを実行するライブラリにおいて何もエスケープがされていないと
cmd.exe /c <バッチファイル> &calc.exe
が実行され、&
はコマンドの連続実行とみなされ、バッチファイル実行後にcalc.exe(電卓アプリ)が起動することになる。
コマンドを実行させないためには、引数に対してcmd.exeの特殊文字を適切にエスケープする必要がある。
node.jsでは"
と\
を\
でエスケープして、全体を""
で囲んでいたが、cmd.exeのエスケープ文字はキャレット(^
)である、cmd.exeのエスケープとしては適切ではない。
ただし、""
内部では^
はエスケープの効果を持たず、"
を二重にして無害化するしかない。
さらに%VAR%
形式の変数展開は構文解析の最初に実行されるため、"
の二重化だけでなく%
をエスケープする方法が必要である。
発見者によると、これらを考慮した適切なエスケープ処理は以下になる
-
%
を%%cd:~,%
に変換する -
"
の前の\
を\\
に変換する -
"
を""
に変換する - 改行(
\n
)を削除する - 引数全体を
""
で囲む
対策
プログラミング言語やそのライブラリで修正の出ているものは修正されたバージョンにアップデートする。しかし、対策が不十分であったり、そもそも修正をしない言語やライブラリもある。
その場合は、発見者提案のエスケープ処理をアプリ側で入れるという方法もあるが、基本的にはバッチファイルに信頼できない外部からの入力を渡さないようにするのが良い。
CVE
CVE | CVSS | 内容 |
---|---|---|
CVE-2024-1874 | 予約中 | |
CVE-2024-22423 | 8.4 | CVE-2024-3566に関連するyt-dlpの脆弱性 |
CVE-2024-24576 | 10.0 | CVE-2024-3566に関連するRustの脆弱性。Command::argやCommand::argsのエスケープ処理が不十分であるため、コマンドインジェクションが実行できてしまう。 |
CVE-2024-3566 | WindowsのCreateProcessを実行するアプリにおけるコマンドインジェクションの脆弱性 |
yt-dlpの脆弱性(CVE-2024-3566)
CVE-2024-22423やyt-dlp(Youtubeなどの動画ダウンローダ)の脆弱性である。このツールの機能として、findコマンドのようにダウンロードした動画に対して、--execオプションでコマンドの実行をすることができる。その時に%(title)qのようなテンプレートを渡すと動画のタイトルなどに変換して引数に渡してコマンド実行する。この部分で%のエスケープ処理が不十分だったため、攻撃者が特殊なタイトルで動画をYoutubeなどにアップロードして、ユーザがその動画をダウンロードすると、タイトルに書かれたコマンドが実行されるというものである。
Discussion