環境変数を使用したSUIDプログラムの活用

環境変数を使用したSUIDプログラムの活用

すべてのユーザーが実行できるBobユーザーの脆弱なSUIDプログラムがあるとします。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
  const char* s = getenv("USER"); // for debugging
  printf("%s\n", s); // for debugging

  char cmd[256] = "/home/bob/hello.sh $USER"; //hello.sh prints "Hello world"
  execl("/bin/bash", "bash", "-p", "-c", cmd, NULL);

  return 0;
}

Bobだけが見ることができるファイルを読み取るために実行されるコマンドにUSER環境変数が追加されているという事実を利用したいと思います。たとえば、USERを次のように設定すると";cat /home/bob/secret-file"

env USER=";cat /home/bob/secret-file" ./program

これは実行されず、次のように返されます。

;cat /home/bob/secret-file
Hello world

USER環境変数が変更されても、2番目のコマンドは実行されません。

Cコードを編集せずにUSER環境変数を使用して "cat"などのコマンドを実行して、bobの権限で(プログラムがSUIDなので)実行してbobだけを見ることができるファイルを表示するにはどうすればよいですか?

ベストアンサー1

あなたがしたいことは不可能です。これは C または SUID とは関係ありませんが、シェルが変数を拡張する方法に関連しています。

シェルの入力を個々のシェルコマンドで解析します。今後環境変数を展開します。変数の内容はいいえシェル構文に従って解釈します(そうでなければfoo='$foo' ; : $foo無限ループになります)。これは、コマンドラインに変数を挿入する操作を別のコマンドラインに分割できないことを意味します。変数が引用されていない場合、これは単に変数の内容をスペースからコマンドの複数のパラメータに分割できることを意味します。これは悪用可能な脆弱性の種類を生成したり、生成しない可能性がありますが、直接的なシェル注入ではありません。

hello.shスクリプトを次に置き換える場合:

#!/bin/sh
i=1
for arg in "$@"; do
    echo "argument #$i: [[$arg]]"
    i="$(expr "$i" + 1)"
done

;cat最初と2番目のパラメータを使用して呼び出されることがわかります/home/bob/secret-file。シェルはこれを;コマンド区切り文字として解釈することなく単に渡します。

おすすめ記事