[Pwnable.kr Prob] cmd2

코코·2023년 3월 3일
0

Pwnable.kr

목록 보기
9/10

오늘은 cmd1에 이어, cmd2의 풀이를 적어보려한다.
생각보다 쉽지 않았다...

우선 마찬가지로 ssh를 통해 문제 서버에 접속해보자!
접속해보면, 위와 같이 cmd2 바이너리와 flag 파일을 확인할 수 있다. 또한 ./cmd2만 실행시킬 경우 Segmentation fault가 뜨는 것을 확인할 수 있다.

바로 소스코드를 확인해보자. 소스코드는 cmd1과 비슷하다.

#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;
}

우선 delete_env 함수부터 살펴보자.

extern char** environ;
void delete_env(){
	char** p;
	for(p=environ; *p; p++)	memset(*p, 0, strlen(*p));
}

이는 해당 바이너리 실행 시, 리눅의 환경변수를 가져오기 위한 코드이다.
extern char** environ이라는 전역 변수를 선언하고, 해당 변수를 통해 환경 변수 목록을 확인하는 것이다.

delete_env() 함수에서는 char **p를 다시 선언하고, environ에 들어있는 값들을 p에 넣어준 뒤, memset을 통해 해당 부분이 올라가 있는 Memory 부분을 0으로 덮어씌워준다.

즉, 환경변수의 값들이 저장된 메모리 공간을 0으로 초기화시켜, 환경변수를 사용하지 못하도록 만든 것이다!


putenv("PATH=/no_command_execution_until_you_become_a_hacker");

또한 main함수에서도 putenv를 통해 환경변수의 값들을 날려버린다.
즉, cmd1의 문제와 같이 ls명령어만 입력해서는 파일의 목록을 확인할 수 없고, /bin/ls -al과 같이 ls 명령어의 Full Path를 입력해줘야 명령어를 사용할 수 있다...


다음으로는 filter() 함수를 살펴보자.

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;
}

cmd1의 문제와 마찬가지로 사용자의 입력값을 받아, 필터링을 진행하는 함수이다.
그러나 필터링하는 문자열이 =, PATH, export, /, `, flag 등등 으로 많아졌다. cmd1 문제를 푼 것과 같이 /bin/cat은 사용할 수 없어진 것이다!



Trial


두 번째는 Shell Script를 사용해보려고 했었다...
그러나, Shell Script를 파일명만 입력해서 사용하려면, 아래와 같이 ./test.sh 혹은 . test.sh로 실행을 해보았지만, 전자의 경우는 필터링, 후자는 어째서인지 test.sh를 찾을 수 없다고만 나왔다.


Solution

계속 어떻게 할 지 고민하다가 우선, 비슷한 환경을 만들 수 있는 PATH 환경변수를 날리고 여러 Command를 날렸는데 echo와 같은 명령어는 환경변수를 날려도 정상적으로 실행이 되었다.
그 후, echo로 출력해보려고 리다이렉션 특수문자를 이용했으나, Flag를 출력하는데 실패했다.....😂

그리고 문득 든 생각이, ls, cp, mv와 같은 명령어는 PATH 환경변수를 날리면 명령어의 Full Path를 적어주지 않으면 실행이 안되는데 왜 echo는 실행이 될까.. 구글링을 통해 찾아보던 중 echo는 Built-in Command라는 것을 알게되었다...!

그래서 여기서 실마리를 잡은 것이다❗ Built-in command이다❗

💡 Built-in Command는 Shell 자체에 포함된 명령어다.

Built-In command는 Shell에 자체적으로 내장되어, 환경변수가 설정되어있지 않은 상황에서도 문제없이 사용할 수 있는 명령어이다.


화면과 같이 ls명령어는 PATH 환경변수에 /bin 디렉터리가 포함되지 않아, 실행하지 못하였고, 반면 echo는 정상적으로 실행되었다.


※ built-in 명령어인지는 type명령어를 통해 확인할 수 있다!


다시 본론으로 돌아와서, 이제 Built-in commmand를 사용하여 cat과 비슷한 명령어를 찾아봐야한다.(거의 다 왔는데 여기서 생각보다 오래걸렸다...🤣)

Built-in Command의 종류는 아래의 링크에서 확인할 수 있다.
👉 https://www.computerhope.com/unix/bash/index.html


그 중 command라는 명령어를 발견하게 되었다...!

commnad 명령어는 간단한 명령을 실행한다고 적혀있다.

Purpose : Executes a simple command.

아래의 링크를 통해 commnad 명령어에 대한 설명을 확인할 수 있다(명령어 이름이 command라 검색하기도 난감...😅)
👉 https://www.ibm.com/docs/en/aix/7.2?topic=c-command-command


위의 사이트에서 commnad 명령어에 대한 설명을 아래와 같이 하고 있다.

The command command causes the shell to treat the specified command and arguments as a simple command, suppressing shell function lookup.

Normally, when a / (slash) does not precede a command (indicating a specific path), the shell locates a command by searching the following categories:


1. special shell built-ins
2. shell functions
3. regular shell built-ins
4. PATH environment variable


For example, if there is a function with the same name as a regular built-in, the system uses the function. The command command allows you to call a command that has the same name as a function and get the simple command.

: 1, 2, 3, 4와 같은 순서로 명령어를 찾고, 간단히 실행한다고 적혀있다.

또한 -p 옵션에 대한 설명은 아래와 같다.

Performs the command search using a default value for the PATH environment variable that is finds all of the standard commands.

: PATH 환경변수의 기본값으로 명령어를 검색하는 옵션이다.

즉, -p 옵션을 통해 cat을 주면, /bin/cat를 찾을 것이다...!


🚩 Get!


생각보다 시간이 너무 오래 걸렸다😵‍💫

profile
화이팅!

0개의 댓글