About

Check the flag05 home directory. You are looking for weak directory permissions

To do this level, log in as the level05 account with the password level05 . Files for this level can be found in /home/flag05.

Source code

There is no source code available for this level


이번 문제는 프로그램이 주어지지 않는다. 문제의 목적은 flag05의 쉘을 획득하는 것이지만 프로그램으로 쉘을 획득하는 것이 아니다. 일단 flag05의 디렉토리에는 다음과 같은 파일들이 존재한다.


[그림 1 - flag05 디렉토리의 하위 디렉토리와 파일 목록]


이전 디렉토리에서는 보지 못했던 ssh 디렉토리와 .backup 디렉토리가 보인다. .backup 디렉토리에는 하나의 압축 파일이 존재한다.


[그림 2 - .backup 디렉토리 목록]


일단 해당 압축 파일에 무엇이 압축되어 있는지 보기 위해 옵션을 이용해 압축 파일의 내용을 확인해 보면 다음과 같이 몇개의 키 들이 들어 있는 것을 확인 할 수 있다.


[그림 3 - backup 압축 파일 내용]


내용들을 보니 아무래도 flag05 디렉토리에 있던 .ssh 디렉토리의 압축 파일인 듯 하다. ps로 ssh 데몬을 확인해 보면 구동되는 것을 확인 할 수 있다. ssh를 이용해 flag05 계정으로 접속하기 위해서 해당 키 파일들을 level05 계정의 홈 디렉토리로 압축을 풀어놓고 접속을 시도하면 flag05 계정의 쉘이 뜨는 것을 확인 할 수 있다.


[그림 4 - 압축 해제]

[그림 5 - ssh 접속 및 쉘 획득]


 * 참고 : ssh 접속은 ssh flag05@localhost 명령을 수행하여 접속 했다.



About

This level requires you to read the token file, but the code restricts the files that can be read. Find a way to bypass it :)

To do this level, log in as the level04 account with the password level04 . Files for this level can be found in /home/flag04.

Source code

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>

int main(int argc, char **argv, char **envp)
{
char buf[1024];
int fd, rc;

if(argc == 1) {
printf("%s [file to read]\n", argv[0]);
exit(EXIT_FAILURE);
}

if(strstr(argv[1], "token") != NULL) {
printf("You may not access '%s'\n", argv[1]);
exit(EXIT_FAILURE);
}

fd = open(argv[1], O_RDONLY);
if(fd == -1) {
err(EXIT_FAILURE, "Unable to open %s", argv[1]);
}

rc = read(fd, buf, sizeof(buf));

if(rc == -1) {
err(EXIT_FAILURE, "Unable to read fd %d", fd);
}

write(1, buf, rc);
}


문제의 요점은 다음과 같다.

위 소스코드를 이용해 token 파일을 읽어라.


소스는 그렇게 길지 않다. 우리가 중요하게 봐야 할 부분은 다음과 같다.


if(strstr(argv[1], "token") != NULL) {
printf("You may not access '%s'\n", argv[1]);
exit(EXIT_FAILURE);
}


파일명에서 token 이란 글자가 있을 시 You may ~ 라는 문자열을 출력하며 프로그램이 종료 되어 버린다. 즉 목적인 token 파일을 읽을 수 없도록 해 놓은 것이다. 하지만 반대로 생각해보면 argv[1]에 들어가는 문자열에서 token이란 문자만 없으면 위 루틴은 pass 된다. 심볼릭링크를 이용하면 되는 것이다.


[그림 1 - 풀이 전체 과정]


argv[1] 에는 /tmp/shell 문자열이 들어가게 되고 해당 루틴을 pass하게 된다. 그 후 아래에 있는 open() 함수를 통해 파일을 열게 되는데 시스템은 최종적으로 /tmp/shell 이 가리키고 있는 token 파일을 열게 되어 파일 내용을 읽을 수 있는 것이다.





About

Check the home directory of flag03 and take note of the files there.

There is a crontab that is called every couple of minutes.

To do this level, log in as the level03 account with the password level03 . Files for this level can be found in /home/flag03.

Source code

There is no source code available for this level


문제의 핵심부터 살펴보자.


crontab에 설정되어 있는 문제 파일을 이용 해 쉘을 획득하라.


문제의 디렉토리로 가보면 쉘 스크립트로 보이는 파일이 하나 존재하며 소스를 보면 다음과 같이 되어 있다.


[그림 1 - 쉘 스크립트]


코드 자체는 단순하다. writable.d  디렉토리의 파일 이름을 가지고 와 일정시간에 주기적으로 bash -x [writable.d의 파일명] 명령을 수행하고 명령을 수행한 파일은 삭제하는 스크립트이다. 그렇다면 우리가 실행해야 할 명령은 writable.d 디렉토리에 파일이름으로 존재해야 한다. 하지만 일반적인 명령어를 파일 이름으로 지어 저장해 둔다고 하여도 level03 쉘에는 영향을 미치지 못한다. writable.sh는 level03 쉘에서 실행되는 것이 아니기 때문이다. 쉘 스크립트를 이용해 우리가 level03 계정에서 실행해 줄 또 하나의 파일을 만들어야 한다. 이 문제는 flag03의 쉘을 획득하는 것이 목표이니 우리가 어떤 파일을 실행했을 때 flag03 계정의 쉘이 띄어지는 프로그램을 만들어 flag03의 권한으로 실행되게끔 해보도록 하자. 일단 flag03의 권한으로 설정 해 쉘을 띄어주는 프로그램의 소스이다.


[그림 2 - flag03의 쉘을 띄어줄 프로그램 코드]


이 파일을 flag03의 권한으로 컴파일하고 flag03의 SUID를 걸어주고 우리가 실행을 시킨다면 우리는 flag03의 쉘을 획득 할 수 있을 것이다. 


[그림 3 - bash 명령 파일 생성]


gcc를 직접 파일명으로 하지 않은 이유는 -o 옵션으로 인해 touch 명령이 실행되지 않기 때문에 생성이 되질 않는다. 또 bash의 -x 옵션으로 인해 명령이 확장되면서 위처럼 할 경우 bash 파일이 실행되면서 gcc 명령도 같이 실행된다.

위 코드를 간단히 설명을 하자면, writable.sh 스크립트가 실행되면서 bash -x bash 명령을 실행하게 된다. bash 파일에는 gcc 명령이 들어있고 컴파일이 완료되면 chmod로 생성된 실행파일에 SUID와 실행권한을 준다. 우리는 생성된 shell 실행 파일을 실행하면 되는 것이다.


[그림 4 - 쉘 획득]



About

There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?

To do this level, log in as the level02 account with the password level02 . Files for this level can be found in /home/flag02.

Source code

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>

int main(int argc, char **argv, char **envp)
{
char *buffer;

gid_t gid;
uid_t uid;

gid = getegid();
uid = geteuid();

setresgid(gid, gid, gid);
setresuid(uid, uid, uid);

buffer = NULL;

asprintf(&buffer, "/bin/echo %s is cool", getenv("USER"));
printf("about to call system(\"%s\")\n", buffer);

system(buffer);
}


문제의 핵심은 이전 문제와 동일하다. 문제의 소스코드를 보게 되면 이전 문제에서는 /usr/bin/env echo 형식으로 되어 있어 echo만을 심볼릭링크 걸어 문제를 풀 수 있었는데 이번에는 /bin/echo로 되어 있어 level02 계정으로는 심볼릭 링크를 걸 수 없다. 그 대신 이전 문제와는 다르게 사용자에게 입력을 받을 수 있는 부분이 추가 되었다. 바로 USER라는 환경 변수이다. 이 부분은 level02 계정으로도 충분히 수정이 가능하므로 우리가 수정한 값이 프로그램의 입력 값으로 들어가게 될 것이다. 일단 실행 화면부터 살펴보자.


[그림 1 - 프로그램 기본 실행 화면]


USER 환경 변수를 수정하지 않았을 때는 사용자 계정 명이 들어가 있는데 이를 입력 받아 소스코드에 코딩되어 있는 루틴을 통해 [그림1]과 같이 출력 되는 것을 다들 예상 할 수 있었을 것이다. 이제 flag02 계정의 쉘을 띄어야 하는데 어떤 방법으로 접근을 해야 할까? 혹시 SQL Injection 해킹기법을 아는가? SQL Injection 기법은 기본적으로 다음과 같은 원리를 이용한다.


 1. 정상적인 SQL 쿼리문

      - Select user, pass from AccountTB where user='$user' and password='$pass';


 2. 정상적이지 않은 입력 값 '1' or '1'='1 입력

      - Select user, pass from AccountTB where user=''1' or '1'='1' and password=''1' or '1'='1';


 3. 서버에서는 SQL 쿼리문을 정상으로 인식


임의로 쿼리문을 참으로 만드는 문자열을 입력 해 쿼리문을 실행 시키는 것이 SQL Injection의 기본원리이다. 여기서 이와 비슷한 방법으로 쉘을 실행 시킬 수 있다. echo는 문자열을 stdout으로 출력 시키는 행위를 하는 명령이다. 이를 리다렉션 문자로 출력 방향을 표준 출력이 아닌 파일로 출력하고 해당 파일을 실행 파일로 만들어 실행 시킨다면 어떻게 될까? 만약 리다렉션 된 문자열이 쉘이라면? 이쯤이면 어느정도 감이 왔을거라 생각이 든다. 그럼 자신이 생각한 것과 필자가 한 것이 맞는지 한번 보기 바란다. 


[그림 2 - 명령 실행]


; 문자는 리눅스에서 여려 명령을 순차적으로 자동 실행하기 위해 사용하는 문자이다. 앞의 명령이 실행되고 ; 뒤에 문자가 차례로  실행되게끔 하는 것이다. 하드코딩 되어 있던 is cool은 쉘이 실행되면서 무시가 되어 프로그램 실행에 아무런 문제를 일으키지 않는 것을 볼 수 있다. 




Level01의 문제는 다음과 같다.

About

There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?

To do this level, log in as the level01 account with the password level01 . Files for this level can be found in /home/flag01.

Source code

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>

int main(int argc, char **argv, char **envp)
{
gid_t gid;
uid_t uid;
gid = getegid();
uid = geteuid();

setresgid(gid, gid, gid);
setresuid(uid, uid, uid);

system("/usr/bin/env echo and now what?");
}


문제의 핵심은 다음과 같다.

위 소스코드로 컴파일 된 프로그램을 이용해 다른 프로그램을 실행 시킬 수 있는가?


[그림 1 - 문제 프로그램의 권한과 소유자 정보]


결국 목적은 위 프로그램의 취약한 부분을 이용 해 flag00의 쉘을 띄우는 것이다. 소스코드를 보면 정말 간단한 소스코드라는 것을 알 수 있다. 프로그램의 SUID, GUID를 얻어와 얻어온 SUID, GUID로 설정 한 후 system() 함수를 실행 시킨다. 시스템 해킹에서 자주 볼 수 있는 패턴이다. 일단 우리가 공략 할 수 있는 부분은 system() 함수 부분밖에 보이지 않을 것이다. 일단 system() 함수에 인자로 들어가 있는 명령을 일반 쉘에서 실행시켜 보자.


[그림 2 - 일반 쉘에서의 명령 실행]


정상적으로 echo 명령이 실행 되는 것을 볼 수 있다. 그럼 echo 명령이 실행 될 때 쉘을 띄어주는 /bin/bash 명령이 실행 되면 어떻게 될까? flag01 계정의 쉘이 띄어지지 않을까? 충분히 가능한 일이다. echo 명령이 실행 될 때 /bin/bash 명령을 어떻게 실행해주어야 할까? 기본적으로 생각나는 방법은 심볼릭 링크가 있다. 명령이 실행 될 때 리눅스는 기본적으로 $PATH 환경변수에 설정 된 디렉토리 경로들을 검색하여 명령을 찾아 실행한다. 이때 echo 명령에 심볼릭 링크를 걸어두고 $PATH 환경 변수에 이 명령의 디렉토리 경로를 설정해 둔다면 echo 명령을 찾고 그 심볼릭 링크를 찾아 system() 함수가 최종적으로 찾은 명령을 실행 할 것이다. 


[그림 3 - /bin/echo의 권한과 사용자 정보]


한눈에 보더라도 심볼릭 링크를 현재 상황에서는 걸어 줄 수 없다는 것을 알 수 있을 것이다. 즉 우리는 새로운 echo를 만들어야 한다. 지금의 계정이 손쉽게 접근 할 수 있는 곳은 /tmp 이다. /tmp 디렉토리는 기본적으로 누구나 접근이 가능하도록 설정 되어 있기 때문이다. /tmp 디렉토리에 가짜 echo 프로그램을 만들고 시스템이 명령을 검색 할 시 /tmp 디렉토리에 echo 프로그램이 먼저 검색되도록 $PATH 환경변수 값을 수정하도록 하자.


[그림 4 - 환경 변수 설정]


지금까지는 완벽한 것처럼 보인다. 하지만 문제를 다시보면 and now what? 이라는 문자열이 존재한다. 해당 문자열을 어떻게 처리해주어야 하는 것일까? 만약에 지금까지의 시나리오대로 문제를 진행한다면 추후 system에서 수행되는 명령은 /usr/bin/env /bin/bash and now what? 이 되어버릴 것이다. 이는 맞지 않는 명령이다. 결국 echo 안에서 /bin/bash 명령을 실행해주어야 한다. 

[그림 5 - 부정확한 명령어]


여기서 필자는 간단한 쉘프로그래밍을 이용해 우리가 사용하려하는 echo 프로그램 내에서 /bin/bash 프로그램이 실행 되도록 하였다.


[그림 6 - 쉘 프로그래밍과 권한의 적절한 사용]


echo가 실행되게 되면 /bin/bash가 실행되고 실행 된 /bin/bash는 /tmp/echo2를 실행하도록 쉘 프로그래밍을 하였다. 또 /tmp/echo2 프로그램이 /bin/bash 프로그램을 가리키도록 하여 결국 system() 함수가 최종적으로 실행하는 명령은 /bin/bash 가 된다.


[그림 7 - flag01 쉘 획득]


'[+] Hacking > [-] Challenge Report' 카테고리의 다른 글

exploit-exercises Nebula - Level03  (0) 2012.07.26
exploit-exercises Nebula - Level02  (0) 2012.07.26
exploit-exercises Nebula - Level01  (0) 2012.07.25
exploit-exercises Nebula - Level00  (0) 2012.07.25
GitS CTF Packet 200 풀이  (1) 2012.06.29

+ Recent posts