スクリプトが自身をインタプリタとして再帰的に呼び出すことでシステムリソースを中断するサービス拒否攻撃のシナリオについて考えています。
原則は次のとおりです。
#!
スクリプトは独自のインタプリタで、最初の行にシャバン形式で独自の絶対パスを指定します。
システムカーネルは、execve
サポートに従ってシステムコール中にインタプリタを自動的に呼び出し、インタプリタを引数ベクトルの前に追加します。
{ARG_MAX}
これらの呼び出しは、システムに設定されたprogram_parameters()のサイズ制限を使い果たし、(おそらく隔離された)エラーを引き起こします。
実験
私は2つの攻撃ベクトルセットを作成しました。
最初は自分自身を呼び出します。
#!/usr/local/bin/recurse
第二に、お互いに電話してください。
#!/usr/local/bin/recurse-1
#!/usr/local/bin/recurse-2
私はmacOS Big Sur 11.5.2でこの2つの攻撃ベクトルをテストしました。終了ステータスチェックを使用すると、echo $?
プロセスが正常に完了したことを意味するゼロが表示されます。
質問。
このタイプの攻撃に対して最新のオペレーティングシステムにパッチが適用されていますか?これに関する研究論文はありますか?
答え1
Linuxでは、次のようになります。
hashbang行に存在しないインタプリタ用のスクリプトがあります(execve()
与えられたENOEXEC
):
$ cat brokenhashbang.sh
#!/bin/nonexisting
echo hello
$ ./brokenhashbang.sh
bash: ./brokenhashbang.sh: /bin/nonexisting: bad interpreter: No such file or directory
再帰的なhashbang()を使ったスクリプトELOOP
:
$ cat /tmp/recursivehashbang.sh
#!/tmp/recursivehashbang.sh
echo hello
$ /tmp/recursivehashbang.sh
bash: /tmp/recursivehashbang.sh: /tmp/recursivehashbang.sh: bad interpreter: Too many levels of symbolic links
既存ではあるが実行できないインタプリタを持つスクリプト( EACCESS
):
$ cat noexechashbang.sh
#!/etc/passwd
echo "hello?"
$ ./noexechashbang.sh
bash: ./noexechashbang.sh: /etc/passwd: bad interpreter: Permission denied
Bashだけではありません。 Dash、ksh、zsh も同様のエラーを生成します。
スクリプトにハッシュバンがない場合、またはハッシュバンが実行できない他のファイルを指している場合(1つが必要+x
ですENOEXEC
)、動作は少し異なります。 Bashはファイル自体をシェルスクリプトとして実行しますが、zshはhashbang行の内側を見てから対応するインタプリタを起動するか、または/bin/sh
.シェルに対するPOSIX指定の動作そしてexeclp()
/execvp()
機能について。
(インタプリタがなければ、Dashはdash: 1: ./brokenhashbang.sh: not found
スクリプト自体が存在しないかのように混乱しますが、基本的なシステムコールから来るのと同じエラーだと思います。
とにかく、ここで攻撃が何であるかはわかりません。彼らが選択したコマンドを実行すれば、すでに好きなように何でもできるからです。存在しないスクリプトソルバーではなく、機能するソルバーを通してです。
答え2
ノート以下はmacOS Big Sur 11.5.2でテストされました。
標準(および既存の慣行)によると、シェルexec
関数呼び出しが失敗して返された場合は、ファイルを解釈してその中のコマンドを実行しようとします。
3番目の攻撃ベクトルは次のとおりです。
#!/usr/local/bin/recurse
eval 'printf "%s\n" xxx'
ファイル名を指定し/usr/local/bin/recurse
て実行すると、文字列はxxx
標準出力に印刷されます。ただし、インタプリタループのためにコマンドを評価しないでください。
Cプログラムを使用して関数を介してスクリプトを呼び出す場合、execv
関数errno
呼び出しの設定値はですENOEXEC
。