본문 바로가기

Pwnable/OvertheWire

[ProjectH4C] OverTheWire Bandit 26 ~ 32 write-up

Bandit26

 

Good job getting a shell! Now hurry and grab the password for bandit27!

쉘을 얻는 것에 대해 칭찬하면서 서둘러 bandit27의 패스워드를 잡으라고 한다.

 

ls -al 를 이용해 어떤 파일이 있는지 확인해보았다.

 

 

 

bandit27의 setUID가 설정된 bandit27-do 파일이 보인다. 해당 파일을 실행해보았다.

 

 

 

bandit20-do 와 같은 에러메세지가 출력된다. 사용법이 똑같은가 싶어 다음을 실행해보았다.

 

$ ./bandit27-do cat /etc/bandit_pass/bandit27

 

 

 

bandit27의 패스워드가 출력되었다.

 

 

Bandit27

There is a git repository at ssh://bandit27-git@localhost/home/bandit27-git/repo. 
The password for the user bandit27-git is the same as for the user bandit27.

해당 주소에 git 저장소가 존재한다. bandit27-git 패스워드는 bandit27의 패스워드와 똑같다고 한다.

 


Git

Git이란 소스코드를 저장하는 저장소를 뜻한다. 저장소에 저장된 소스 파일에 수정이 이루어졌을 때, 누가 언제 어떤 파일을 수정했는지 기록되고 추적할 수 있도록 관리해주는 것을 소스코드 저장소라고 하는데 이를 보통 리포지토리(Repository)라고 부른다.

Git은 이러한 소스코드 저장소를 구현한 프로그램 중 하나이다.

Git 저장소에 등록된 소스 파일을 받아오기 위해선 아래의 명령어를 사용하면 된다.

Git clone [소스 파일 주소]

깃 저장소에 저장된 소스파일을 현재의 디렉토리에 복사한다. 이를 이용해 위에 주어진 주소의 소스 파일을 내려받는다. 홈 디렉토리에선 파일 생성 권한이 없기 때문에 /tmp/bandit27 디렉토리를 만들어서 해당 파일에서 진행한다.

 

 

 

내려받기가 완료되면 repo라는 디렉토리가 생성된다. 해당 디렉토리로 이동한다.

 

 

 

README 파일이 존재한다. 읽어보도록 한다.

 

 

 

bandit28의 패스워드가 출력된다.

 

 

Bandit28

There is a git repository at ssh://bandit28-git@localhost/home/bandit28-git/repo. 
The password for the user bandit28-git is the same as for the user bandit28.

이전 레벨과 동일하다. /tmp/bandit28 디렉토리를 생성해 이동한 후 git clone을 이용해 내려받도록 한다.

 

 

 

repo 디렉토리로 이동한 후에 파일 목록을 출력해준다.

 

 

 

README.md 파일을 읽어보았다.

 

 

 

이후에 어떻게 해야할지 몰라서 알아보니, git log를 이용해 파일의 변경 사항을 확인할 수 있다고 한다.

 

 

$ git log ./README.md

 

 

 

각각의 변경 이력에 대해 commit이라는 것이 부여되고, git show [commit]을 이용해 무엇을 바꿨는지 확인할 수 있다.

맨 처음 만들어진 파일의 내용을 출력해보도록 한다.

$ git show de2ebe2d5fd1598cd547f4d56247e053be3fdc38

 

 

 

파일이 처음 등록되었을 때도 패스워드는 등록하지 않은 것 같다. 두 번째 log도 확인해 보도록 한다.

$ git show c086d11a00c0648d095d04c089786efef5e01264

 

 

password: <TBD> 부분이 삭제되고, 실제 bandit29의 패스워드가 저장되어 있다. 패스워드를 알아냈으니 bandit29에 로그인하면 된다.

 

 

Bandit 29

There is a git repository at ssh://bandit29-git@localhost/home/bandit29-git/repo. 
The password for the user bandit29-git is the same as for the user bandit29.

 

이번에도 git 저장소에 단서가 등록되어있다고 한다.

/tmp/bandit29 디렉토리 생성 후 해당 디렉토리에서 작업한다.

 

 

 

 

 

 

 

파일이 수정된 로그가 존재하는지 확인해준다.

 

 

 

 

password 부분은 수정 된 이력이 없다. 다른 작업 공간이 존재하는지 branch를 확인해보기로 한다.

 


Branch

A라는 사람이 Git에 저장된 파일을 수정하는 동안, B라는 사람도 Git에 저장된 파일을 수정하는 경우가 생긴다. 이 때, 이들이 서로의 작업에 영향을 미치지 않도록 하기 위해 각각의 작업 영역을 만들어주는 기능이 바로 브랜치(Branch)이다. 브랜치로 각자의 작업영역을 분리한 뒤에 각자 작업을 실행하고, 작업이 완료되었을 때 다시 하나로 합쳐서(Merge) 하나의 브랜치로 만들어 줄 수 있다. 이 때, 만약 A가 작업을 마치고 메인 브랜치와 병합해서 자신의 결과물을 저장시켰는데, B라는 사람이 그 후에 작업을 완료하고 메인 브랜치와 병합해서 결과를 덮어씌우면 A의 작업 내용이 날라가게 된다. 이러한 경우를 방지하기 위해서 결과물이 업로드 될 때마다 commit을 부여하는 것이다. 현재 git에 존재하는 모든 작업공간을 확인하고, 해당 작업 공간에 접근하는 방법은 다음과 같다.

 

$ git branch -a : 브랜치에 존재하는 모든 작업 공간을 출력한다.
$ git checkout [작업공간] : 해당 작업 공간에 접근한다.

 


 

우선, 다른 작업 공간이 존재하는지 확인해준다.

 

 

 

master 브랜치 아래에 remotes/origin/dev, remotes/origin/master, remotes/origin/sploits-dev가 존재하고 그 중 master를 사용하고 있다. remotes/origin/dev 공간을 살펴보도록 한다.

 

 

origin/dev가 HEAD가 되었다. 이제 git log를 이용해 수정 로그를 확인해준다.

 

 

 

아까와는 다른 커밋이 발견된다. 맨 위의 커밋을 확인해준다.

 

 

 

 

password 부분이 추가된 것을 볼 수 있다. 해당 패스워드를 이용해 bandit30에 로그인하면 된다.

 

 

Bandit30

There is a git repository at ssh://bandit30-git@localhost/home/bandit30-git/repo. 
The password for the user bandit30-git is the same as for the user bandit30.

이번에도 역시 git에 저장되어 있다고 한다.

 

 

 

이번에도 역시나 README.md 파일이 보인다. 내용을 출력한다.

 

 

 

비어있는 파일이라고 한다. 원래의 내용을 알아보기 위해 git log를 이용한다.

 

 

 

만들 때부터 저 내용을 저장한 듯 하다. 혹시 모르니 다른 브랜치가 존재하는지도 확인해준다.

 

 

 

 

다른 브랜치는 존재하지 않는다. 

 

 


.git 디렉토리

git clone을 이용해 다운 받은 디렉토리 내에는 .git이라는 디렉토리가 존재한다. 이를 git 저장소라 하고, .git 디렉토리 아래에는 해당 git을 관리하기 위한 파일 및 디렉토리가 존재한다.

.git의 기본 구성은 다음과 같다.

 

  • /hooks/ : 훅 스크립트 파일이 저장되는 곳. 특정 Git 관련 명령어가 실행될 때 자동으로 실행되는 명령어의 묶음이 들어있다.
  • /refs/ : 커밋 객체의 포인터가 저장되는 곳.
  • /info/ : 관리 제외 대상의 목록을 저장한 exclude 파일과 레퍼런스의 목록을 저장한 refs 파일이 저장되는 곳.
  • /objects/ : 모든 파일이 객체 형식으로 저장되는 곳.
  • /HEAD : HEAD 레퍼런스가 가리키는 커밋의 아이디가 저장되어 있는 파일이다. 만약 git checkout으로 브랜치를 체크아웃 하면, HEAD파일에는 해당 브랜치의 레퍼런스가 저장된다. 

그 외에도 packed-refs 라는 파일이 존재한다. 

Git은 때가 되면 자동으로 auto gc 명령을 실행한다. auto gc는 패키지 파일이 너무 많아지면 아무런 커밋도 가리키지 않는 개체와 오랫동안 사용되지 않는 개체들을 삭제하는 명령어이다.

이 때, refs 디렉토리에 있는 파일은 삭제하기 전에 압축해서 보관하도록 한다. Git은 레퍼런스가 가리키고 있는 값을 찾을 때 refs 디렉토리에서 우선적으로 검색하고 refs에 없다면 packed-refs 파일에서 찾게 된다.


/bandit30/repo 디렉토리에서 ls -al 명령을 실행하면 .git 디렉토리가 보인다. 해당 디렉토리로 이동한다.

 

 

 

packed-refs 라는 파일이 보인다. 해당 파일을 출력하여 어떠한 레퍼런스들이 묶여있는지 보도록 한다.

 

 

 

 

branch -a 로 브랜치들을 출력했을 때 볼 수 없었던 refs/tags/secret 레퍼런스가 존재한다. git show 명령어를 이용해 해당 커밋을 들여다보도록 한다.

 

 

 

bandit31의 패스워드가 출력되었다!

 

 

 

Bandit31

There is a git repository at ssh://bandit31-git@localhost/home/bandit31-git/repo. 
The password for the user bandit31-git is the same as for the user bandit31.

 

해당 레벨도 git clone을 이용해 다음 레벨의 패스워드를 알아내야 한다.

/tmp/bandit31/ 디렉토리에서 git clone을 통해 내려받는다.

 

 

 

 

원격 저장소에 파일을 push 해야 한다고한다. 파일의 이름은 key.txt이고 내용은 'May I come in?'이며, master 브랜치에서 수행해야 한다.


원격 저장소에 파일 추가

원격 저장소에 파일을 추가하기 위해선 add, commit, push 의 단계를 거쳐 추가해야 한다. 원래는 저장소 생성이 맨 앞에 있어서 총 네 단계지만, 기존에 존재하는 원격 저장소를 기준으로 작성하도록 한다.

 

git add

git add [파일명] 형태로 사용되며, 해당 파일을 staging area 라는 곳에 추가해준다.

git commit

git commit -m "Message" 형태로 사용되며, staging area에 추가된 파일을 local repository(로컬 저장소)에 저장한다.

git push

git push [저장소명] [브랜치명] 형태로 사용되며, 로컬 저장소를 원격 저장소에 업로드 함으로써 최종적으로 원격 저장소에 변경된 사항이 저장된다.

 


key.txt 파일은 master 브랜치에 존재해야 하기 때문에 현재 브랜치가 어디인지부터 확인해주도록 한다.

 

 

 

master 브랜치에 위치하는 것을 확인했으니, key.txt 파일을 만들고 내용에 May I come in? 을 넣어준다.

 

 

 

 

key.txt 파일을 add, commit, push 과정을 거쳐 원격 저장소에 추가하도록 한다.

 

 

 

정말 추가하고 싶다면 -f 옵션을 사용하라고 한다. -f 옵션을 이용해 다시 추가하였다.

git add 이후에 git status 명령을 통해 현재 상태를 확인할 수 있다.

 

 

 

 

key.txt 라는 파일이 새로 추가됐다고 초록 글씨로 쓰여있다. 이 곳이 바로 staging area이다. staging area에 등록된 파일을 git commit 명령어를 통해 로컬 저장소에 등록해준다.

 

 

 

 

key.txt 파일이 저장소에 저장되었다. 마지막으로 git push를 이용해 원격 저장소에 저장해준다.

 

 

 

 

 

 

다음 레벨의 패스워드가 출력되었다! 해당 레벨에서 알아야 할 것은 git 원격 저장소에 파일을 등록할 땐 add, commit, push 세 단계를 거쳐서 진행된다는 것이다.

 

 

 

Bandit32

After all this git stuff its time for another escape. 
Good luck!

 

 

 

해당 레벨에 로그인하면 UPPERCASE SHELL이 뜬다. /bin/sh 쉘로 실행되고, 모든 입력이 대문자로 변환되어 입력된다.

실제로 이러한 쉘이 존재하는게 아닌, 입력 받은 것을 대문자로 변환한 후 sh 쉘에 입력하는 프로그램이 실행중인 듯 하다.

이를 해결하기 위해선 대소문자의 개념이 없는 특수문자, 숫자 등을 이용해야 한다.

리눅스에서는 쉘 명을 비롯한 쉘에 대한 정보를 $0 ~ $9로 표현할 수 있다.

 

$$ : 쉘의 프로세스 번호
$0 : 쉘스크립트 이름
$1 ~ $9 : 명령줄 인수
$* : 모든 명령줄 인수리스트
$# : 인수의 개수

쉘이 저장된 위치는 /bin 디렉토리로 명령어들을 모아놓은 디렉토리이다. 무슨말인가 하면, 기본적으로 리눅스는 프로그램을 실행할 때 "경로 + 파일명"을 입력해서 실행시키지만, /bin 디렉토리에 있는 프로그램은 해당 파일명만 입력하면 실행이 된다는 이야기이다. ls, pwd, cat 등등이 모두 /bin 디렉토리에 저장되어 있다. 

마찬가지로 sh 쉘을 실행시키기 위해선 /bin/sh 가 아닌 sh만 입력해도 실행이 가능한데, $0를 입력하면 sh가 출력되고, UPPERCASE SHELL 프로그램에 "sh"가 실행인자로 넘어가서 실제 sh 쉘을 불러낼 수 있다는 것이다.

 

 

 

 

UPPERCASE SHELL의 입력 칸인 ">>"가 출력되지 않고 sh쉘의 "$"가 출력되었다. 이 상태에서 평소에 사용하던 bash 쉘을 불러보도록 한다.

 

 

 

bandit32로 로그인했지만 bandit33이 되어있는 이유는 바로 uppercase 프로그램 때문이다.

 

 

 

bandit33 유저로 SetUID가 설정되어 있기 때문에, 아직 uppershell 프로그램이 종료된 것이 아니므로 bandit33 유저로 인식되어 있는 것이다. 이 상태에서 /etc/bandit_pass/bandit33 의 내용을 출력해서 bandit33의 패스워드를 알아내면 된다.

 

 

'Pwnable > OvertheWire' 카테고리의 다른 글

[ProjectH4C] OverTheWire Bandit 0 ~ 25 write-up  (0) 2020.08.23