setuidビットの動作に一貫性がないのはなぜですか?


8

私はコードを書きました:

// 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でも、現在のユーザーのシェルを取得しています。

なぜ違うのですか?

回答:


9

何が変わったことはということである/bin/shになったのどちらかbashまたは滞在しdash、追加のフラグを取得した場所-pのbashの振る舞いを模倣します。

Bashのmanページで-p説明されているように、setuid特権を削除しないようにするには、フラグが必要です

実効ユーザー(グループ)IDが実際のユーザー(グループ)IDと等しくない状態でシェルが起動され、-pオプションが指定されていない場合、起動ファイルは読み込まれず、シェル関数は環境から継承されません。SHELLOPTS 、BASHOPTS、CDPATH、およびGLOBIGNORE変数は、環境に表示されても無視され、実効ユーザーIDは実際のユーザーIDに設定されます。呼び出し時に-pオプションが指定されている場合、起動時の動作は同じですが、有効なユーザーIDはリセットされません。

以前は、dashこれを気にせず、(それを防ぐために何もしないことで)setuidの実行を許可していました。ただし、Ubuntu 16.04のdashマンページには、次のような追加のオプションが記載されていますbash

-p priv
有効なuidがuidと一致しない場合、それをリセットしようと試みません。これはデフォルトでは設定されておらず、system(3)またはpopen(3)を介したsetuid rootプログラムによる誤った使用を回避します

このオプションは上流(提案されたパッチ*に反応しない可能性がある)にもDebian 9にも存在しませんでしたが、2018年以降にパッチを入手したDebianバスターには存在します。

注:StéphaneChazelasで説明されているように、渡さ"/bin/sh -p"system()たものsystem()はすべて実行されるため、呼び出すのは遅すぎ/bin/sh、setuidはすでに削除されています。デロバートの答えは、以前のコードでこれを処理する方法を説明していますsystem()

*歴史についての詳細はこちらそこ


system("bash -p")実行sh -c "bash -p"時に特権がすでに削除bashされているので、実行されます。
ステファンChazelas

まあまあ。とりあえず、derobertの回答でより適切に処理される「解決策」の部分を削除します。
AB


Ubuntuはwily(15.10)のダッシュを修正したように見えます。bugs.launchpad.net/ubuntu/+source/dash/+bug/1215660
Mark Plotnick

1
Debianは以前とは逆の方向に進んでいたことに注意してください。特権を落とさないようにbashにパッチを当ててました。それが改善であるかどうかは議論の余地があります。さて、system()昇格された特権(当然のことながら、最初から許可されていません)でaを実行したい人setresuid()は、シェルがそれがsuidであることを認識していないので、それよりもずっと前に実行することになります。環境を信頼しないモードをアクティブにします。
ステファンChazelas

8

おそらくシェルは、何らかの理由で、起動の一部として有効なユーザーIDを実際のユーザーIDに戻しています。これを確認するには、次を追加します。

/* needs _GNU_SOURCE; non-Linux users see setregid/setreuid instead */
uid_t euid = geteuid(), egid = getegid();
setresgid(egid, egid, egid);
setresuid(euid, euid, euid);

あなたの前にsystem()。(実際には、Linuxでも、おそらく実際のものを設定するだけで済みます。保存されたものはそのままにしておいても問題ありません。これは、デバッグするためのブルートフォースです。set-idに応じて、もちろん必要になる場合があります。実際のIDもどこかに保存します。)

[また、これがsetidがどのように機能するかを学ぶだけの演習ではない場合、特にシェルを呼び出すときに、多くのセキュリティ問題が心配されます。たとえば、シェルの動作に影響を与える多くの環境変数があります。sudo可能であれば、既存のアプローチを優先してください。]


問題を回避する方法を提供しながら、変更の理由に集中しました。+1
AB

もちろん、実際のIDを保存する場所が本当に必要な場合は、保存されたIDを使用すると非常に便利です。特に、有効なIDがroot:rootでない場合。
ケビン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.