level2를 풀고 얻은 password를 가지고 로그인을 하면 역시나 hint가 보입니다.

당연히 hint를 확인 해주어야겠죠.


힌트가 뭔가 길어졌습니다.

단순히 문장 한줄이었던 예전과 다르게 이번엔 autodig의 소스코드가 주어졌네요.

일단 소스코드를 분석해 봅시다.


우선 argc란 프로그램을 실행할 때 넘겨주는 인자의 개수를 말합니다.
$ ls -s / 라고 프로그램을 실행하였다면 총 3개의 인자값을 가지게 됩니다.
argc[0] = ls
argc[1] = -s
argc[2] = /
이렇게 총 3개의 인자값을 갖게 되죠. argc[0]는 항상 프로그램 자기자신을 가르킵니다.

소스를 보면 if( argc!=2 )가 보입니다.
argc의 개수가 2가 아니라면 if문 내부를 실행하는 것이죠.
if문 내부에 exit(0);가 보이는 것으로 보아 if문은 실행하면 안될 것 같습니다.

if문 이후를 보면 strcpy이 나오고, strcat2개가 나오고 system(cmd)가 보입니다.

strcpy의 형태는
char* strcpy(char * dest, cont shar * src)인데
이함수는 src의 문자열을 dest로 복사하는 것입니다.
즉, strcpy( cmd, "dig @" );는 "dig @"문자열을 cmd에 복사하는 것이 되겠습니다.

다음 나오는 strcat의 형태는
char * strcat( char * dest, const char * src)인데
이 함수는 src의 문자열을 dest에 담겨있는 문자열 뒤에 붙이는 것입니다.
즉 strcat( cmd, argv[1] ); 이므로 cmd는 "dig @argv[1]"라는 문자열이 담기게 되는것입니다.

다음 strcat( cmd, " version.bind chaos txt")까지 실행하게 되면,
cmd안에는 "dig @argv[1] version.bind chaos txt"라는 문자열이 담기게 되는것입니다.

그리고 그 다음 system( cmd ); 함수를 통해 cmd안에 담긴 문자열을 쉘에서 명령어로 입력하게 됩니다.
즉, $ dig @argv[1] version.bind chaos txt가 되는 것이죠.


여기서 잠깐 dig함수에 대해 알아보고 가면(사실 dig함수는 문제를 푸는데는 큰 의미는 없습니다만.. 일단 나왔으니...)

dig란 Domain Information Groper의 약자로 dns 진단용 유틸리티입니다.

dig 명령어는 기본적으로 다음과 같은 문법 형식을 갖고 있습니다.

$ dig @ [서버] [도메인] [쿼리형태]


쿼리형태

a : 네트워크 주소

any : 특정 도메인에 대한 모든 정보

mx : 도메인의 메일 교환

ns : 네임서버

soa : Zone파일 상단의 authority 레코드

hinfo : 호스트 정보

axfr : Zone 파일 교환(transfer)

txt : txt


$ dig를 실행하면 윗 사진과 같이 나오는데 각 필드의 뜻은 다음과 같습니다.

;; QUESTION SECTION:
- DNS 질의 내용을 표시

;; ANSWER SECTION:
- DNS 질의 사항에 대한 DNS 응답 RR(Resource Record)을 표시

;; AUTHORITY SECTION:
- DNS 응답 RR이 속한 도메인 존의 NS RR 정보

;; ADDITIONAL SECTION:
- 부가적인 RR 정보를 표시

;; Query time:
- DNS 질의 메시지 발송시점에서 응답시점까지의 소요시간

;; SERVER:
- DNS 응답 메시지를 보내온 질의응답 네임서버

;; WHEN:
- DNS 응답 메시지를 받은 시점의 date & time

;; MSG SIZE rcvd:
- 응답받은 DNS 메시지의 size표시 (byte단위)
IP TCP/UDP 헤더는 제외된 size

autodig를 통해 만들어진 명령어(dig @argv[1] servion.bind chaos txt]는 dns의 bind 버전을 알아내는데 사용되는 명령어입니다.


다시 문제풀이로 돌아가 소스의 추가 힌트 2개를 보겠습니다.
추가 힌트는
- 동시에 여러 명령어를 사용하려면?
- 문자열 형태로 명령어를 전달하려면?
입니다.

- 동시에 여러 명령어를 사용하려면?
동시에 여러 명령어를 사용하려면 명령어 사이에 ;를 넣으면 됩니다.
$ sh; ls이런식인것이죠.
이렇게 하면 sh실행이 종료된후 ls를 실행하게 됩니다.

- 문자열 형태로 명령어를 전달하려면?
문자열 형태로 명령어를 전달하려면 명령어를 큰따옴표("")로 묶어주면 됩니다.


그럼 autodig에 인자를 넘겨줘 봅시다.

$ autodig "168.126.63.1;my-pass"라 입력하겠습니다.


이렇게 하면 autodig 168.126.63.1이 실행된후 my-pass가 실행 되겠죠.

빙고 암호가 나왔습니다.

암호는 suck my brain입니다.


level3의 암호가 나올 거라 예상했는데 level4의 암호가 나온것으로 보아 autodig는 level4로 setUID가 되어 있나봅니다.
한번 확인해 보겠습니다.

확인 결과 예상대로 autodig는 level4에 setUID가 걸려 있음을 확인할 수 있었습니다.


Level1을 클리어 하고 얻은 password를 가지고 level2를 접속했더니 level1과 마찬가지로 hint가 보이는군요.
친절하게 hint를 제공해주셨기에 당연하게 열어보겠습니다.


"텍스트 파일 편집 중 쉘의 명령을 실행시킬 수 있다는데...."라는 힌트가 제공되는군요.


여기서 말하는 텍스트 파일 편집은 vi를 생각하시면 됩니다.
vi(vim)이란 리눅스에서 제일 기본이 되는 텍스트 편집기입니다. 윈도우의 메모장(notepad)와 같은 역할을 하신다고 보시면 됩니다.

GUI기반인 메모장과 달리 CLI기반인 vi는 크게 3가지의 모드가 있습니다.
1. 입력모드 : i, e, o, I, A, O를 누른후 텍스트를 입력할수 있는 상태
2. 명령모드 : esc키를 누른 상태
3. 콜론(ex)모드 : 명령모드 상태에서  :(콜론)을 입력한 상태

그리고 이러한 기본적인 모드들을 메모장의 기능과 비교해보면 다음과 같습니다.
1. 입력모드 : 타이핑을 하여 파일의 내용을 입력하는 모드
2. 명령모드 : 편집 메뉴에서 제공하는 복사, 붙이기, 삭제 등의 편집기능을 활용하는 모드
3. 콜론(ex)모드 : 다른 편집기의 파일 메뉴에서 수행하는 열기, 저장, 다른 이름으로 저장 등의 명령 수행
각 모드의 자세한 사용법은 vi 위키 참고(http://ko.wikipedia.org/wiki/Vi)


여기서 문제를 푸는데 핵심인 모드는 콜론(ex)모드입니다.
클론모드의 핵심중 하나는 :sh를 입력할 경우 쉘 창을 띄워 리눅스 명령어를 입력 할 수 있다는 것인데요.
이때 쉘의 권한은 vi를 실행할때 사용자 권한과 같이 갑니다.


그럼 한번 해보도록 하죠.
$ vi를 입력해 vi창을 띄운후 콜론모드에서 sh를 입력해 쉘을 띄우겠습니다.


아래를 보시면 쉘이 띄워짐을 알수 있습니다.


whoami 명령어를 통해 현재 사용자가 누구인지 한번 보도록 하겠습니다.


확인 결과 현재 사용자는 whoami로 나왔습니다. level2사용자로 로그인해 실행하였기 때문에 당연한 결과입니다. 
하지만 vi에 setUID가 설정되어 있었다면 setUID가 설정된 계정의 권한으로 실행이 되었겠죠.


따라서 level1의 기억을 되살려 lelve3에 setUID가 걸린것을 찾아보도록 합시다.
$ find / -perm -4000 -user level3 2> /dev/null 명령어를 입력해주면 됩니다.


/usr/bin/editor가 출력되었네요.

/usr/bin/editor을 실행해 보면 vi와 같은 창이 뜹니다.
당황하지 않고 콜론모드에서 sh를 입력해 쉘을 띄워준후 whoami로 사용자를 확인합니다.


빙고! whoami 결과 level3으로 뜨네요
level3의 권한을 획득하였습니다. 그럼 이제 my-pass로 level3의 비밀번호를 획득하면 됩니다.

level3의 암호를 얻었습니다.

암호는 can you fly?입니다.

해커스쿨의 안내에 따라 FTZ level1으로 접속하여 파일 목록을 출력한다.



친절하게 hint라는 파일이 보이므로 hint를 읽어 주도록 하자

level2 권한에 setUID가 걸린 파일을 찾으라고 한다.


여기서 setUID가 뭔지 한번 알아보고 넘어가자

유닉스 파일 시스템에서는 각각의 파일마다 권한이 설정되어 있다.
위에 public_html의 줄을 보면(어두워서 뭐가 public_html인지 모르려나.. 2번째) drwxr-xr-x라고 쓰여 있는것이 보일것이다.

이러한 식으로 되어있는것이 유닉스 파일시스템의 권한이다.

r = 읽기권한
w = 쓰기권한
x = 실행 권한

앞에서부터 첫번째 뒤로 3개 단위로 소유자, 소유자가 속한 그룹, 다른 사용자의 권한을 나타낸다. 첫번째 자리는 d가 있으면 디렉토리, -로 되어있으면 일반 파일이다.

비트로 표현하면 8비트로 r = 4, w = 2, x = 1로 각 숫자를 더해 표현하면 public_html의 권한은 755가 된다.

setUID는 조금 특이한 권한으로 rwsr-xr-x 이런식으로 표현하며, 비트로는 4000으로 나타낸다. 즉, 위 권한은 비트로 표현하면 4755가 된다. 

이밖에 비슷한 기능으로 setGID, Sticky-bit가 있고 2000, 1000으로 표현한다.

setUID는 소유자권한의 x에 s로, setGID는 그룹권한의 x에 s로, Sticky-bit는 다른사용자권한의 x에 t로 표현하게 된다.


setUID가 걸린 파일을 찾기 위해선

find명령어를 사용하면 되는데, -perm 옵션과 -user옵션을 이용하면 된다.
지금 찾고자 하는건 권한이 4000대이고, 사용자가 level2이므로
$ find / -user 사용자이름 -perm -4000이라고 입력하면 된다.


실행을 하고 나면 /bin/ExcuteMe가 보인다.

Permission denied라는 표준 에러가 보이는것이 귀찮다면
$ find / -perm -4000 -user level2뒤에 2> /dev/null을 붙여주면 된다.
2는 표준 에러를 뜻하며
2> /dev/null 은 표준 에러를 null로 리다이렉션 하라는 뜻이다.
즉, 표준에러를 출력하지 않겠다는 뜻이다.


명령어를 다시 입력하면,

훨씬 짧게 나왔다.


이제 /bin/ExcuteMe의 파일 권한을 확인해 보면,

권한이 -rwsr-x---, 소유자가 level2임을 알수 있고 즉 lelvel2에 setUID가 적용 되어있음을 알 수 있다.


사실 이 방법 말고도 tmp폴더안의 test.txt의 내용을 확인해보면 /bin/ExcuteMe가 적혀있다.


/bin/ExcuteMe파일을 찾았으니
$ /bin/ExcuteMe로 파일을 실행하면 다음 화면이 뜬다.



암호를 아는 명령어가 my-pass이지만 그것은 안된다고 하니 쉘을 실행해서 level2의 권한을 획득하자.
쉘의 종류는 sh, bash, ksh, csh 등이 있다.


쉘을 띄운다음 암호를 확인하는 my-pass 명령어를 쓰면 암호를 얻을 수 있다.


암호는 : hacker or cracker이다. 






+ Recent posts