私はコードを書いた:
// a.c
#include <stdlib.h>
int main () {
system("/bin/sh");
return 0;
}
次のコマンドを使用してコンパイルします。
gcc a.c -o a.out
setuidビットを追加しました:
sudo chown root.root a.out
sudo chmod 4755 a.out
Ubuntu 14.04では、通常のユーザーとして実行するとroot権限が得られます。
しかし、Ubuntu 16.04ではまだ現在のユーザーのシェルを取得します。
なぜ違うの?
ベストアンサー1
変更されたことは、/bin/sh
bebash
またはstay bashの動作を模倣するdash
追加のフラグがあることです。-p
-p
Bashでは、次の説明に従ってsetuid権限を放棄しないためにこのフラグが必要です。マニュアルページ:
シェルの起動時に有効なユーザー(グループ)IDが実際のユーザー(グループ)IDと同じでなく、-pオプションが指定されていない場合は起動ファイルを読み取らず、シェル機能は環境とSHELLOPTS、BASHOPTS、CDPATH、およびGLOBIGNORE変数が表示された場合は無視します。になります。有効ユーザーIDを実際のユーザーIDに設定します。。呼び出し時に-pオプションを指定した場合、起動動作は同じですが、有効なユーザーIDはリセットされません。
以前はdash
これは無視され、setuidの実行は許可されました(これを防ぐための措置は取られていませんでした)。しかし、Ubuntu 16.04dash
マンページ次のような追加オプションの説明がありますbash
。
-p priv
有効な uid が uid と一致しない場合はリセットしないでください。誤った使用を防ぐためにデフォルトでは設定されていません。system(3) または popen(3) を介した Setuid ルートプログラム。
このオプションは、次には存在しません。上流(提案されたパッチに反応しないことがあります。*)もDebian 9ではありませんが、2018年からパッチされたDebian Busterにあります。
"/bin/sh -p"
注:Stéphane Chazelasが説明したように、特定のコンテンツが実行されるため、system()
今すぐ電話するのは遅すぎます。したがって、setuidはすでに削除されています。system()
/bin/sh
ドロバート前のコードの答えは、この問題を処理する方法を説明していますsystem()
。