리눅스 기반 시스템 탐색 및 데이터 분석
level 0
ssh를 이용해 원격으로 bandit.labs.overthewire.org를 접속하는 문제입니다. 접속하기 위해서는
ssh bandit0@bandit.labs.overthewire.org -p 2220
라는 명령어를 입력하면 됩니다.
level 0 -> 1
readme 파일을 열어 그 안에 있는 비밀번호를 읽는 문제입니다. 문제를 읽기 위해서는 파일 내용을 출력하는 cat이라는 명령어가 필요합니다.
cat readme
level 1 -> 2
이번 문제는 홈 디렉터리에 있는 ‘-‘ 라는 파일을 열어 비밀번호를 찾아야합니다. 그러나 특수문자인 ‘-‘는 그저 cat이라는 명령어를 그냥 써서 열리지 않습니다. 그렇기에 현재 경로를 명시해줘야 합니다.
cat ./-
level 2 -> 3
이번 파일의 제목은 –spaces in this filename–이라는 좀 특이한 이름을 가지고 있습니다. 그렇기에 그냥 cat으로 못 열기 때문에 리다이렉션을 이용해 열어줍니다. 리다이렉션을 쓰면 대상 파일의 내용을 복사하거나 생성, 합치거나 파일의 내용을 명령에 입력할 수 있습니다. 방향에 따라 다른데, < 방향은 후자입니다.
cat < --spaces in this filename--
level 3 -> 4
이번 문제는 숨어있는 파일을 찾아내어 그 안에 있는 비밀번호를 뜯는 문제입니다. ls를 이용하면 그 디렉터리 안에 있는 파일을 볼 수 있는데, 숨어있는 것도 보기 위해서는 -a라는 옵션을 이용해 숨겨져 있는 파일까지 모두 보여달라 해야합니다.
cd inhere
ls -a
cat ...Hiding-From-You
level 4 -> 5
inhere 디렉토리 어딘가에 있는 사람이 읽을 수 있고 크기는 1033바이트인 실행불가 파일을 열어야합니다. 그렇기에 파일 종류를 확인할 수 있는 file이라는 명령어로 찾아줄 것입니다. file 뒤에 사용된 ./-*으로 -로 시작하는 모든 파일을 확인해줄 것입니다. 결과에 나온 파일 중 읽을 수 있는 ASCII text인 -file07을 확인해주겠습니다.
cd inhere
file ./-*
cat ./-file07

level 5 -> 6
이번 문제에서는 디렉터리가 많이 있습니다. 하나하나 열어보기에는 시간이 많이 들기 때문에 문제에서 준 힌트: 사람이 읽을 수 있는 크기는 1033바이트 실행 불가 를 활용하여 이 조건에 맞는 파일을 찾기 위해 find라는 명령어를 사용해주겠습니다. find는 파일이나 디렉터리 검색하는 데 사용되는 명령어입니다. 그리고 -type f로 파일만 찾게 하고 -size 1033c로 찾는 파일의 크기를 찾아줍니다.
cd inhere
find . -type f -size 1033c ! -executable
cat ./maybehere07/.file2

level 6 -> 7
이 문제는 이전 단계와 비슷한데 어디에 저장된 파일인지 알 수 없어 서버 전체에서 찾아야합니다. 문제 조건은 사용자 bandit7 소유 bandit6 그룹 소유 크기는 33바이트 라고 합니다. find /로 전체에서 찾고 -user [소유자명]/ -group [소유 그룹] 2>/dev/null로 에러 메세지는 숨기겠습니다. 그러면 비밀번호가 담긴 파일이 어디에 위치했는지 알려주는데 이제 이 파일을 cat으로 열어 문제를 해결합니다.
find / -user bandit7 -group bandit6 -size 33c 2>/dev/null
cat /var/lib/dpkg/info/bandit7.password
level 7 -> 8
이 단계에서는 data.txt 파일의 “millionth”라는 단어 옆 에 저장되어 있다고 합니다. 여기서 grep을 사용해주어 파일에서 특정 단어가 포함된 줄만 출력하게 해줍니다.
grep "millionth" data.txt
level 8 -> 9
이 레벨의 비밀번호는 data.txt 파일에 저장되어 있으며 , 해당 파일에서 유일하게 한 번만 나타나는 텍스트 줄에 있습니다. uniq라는 명령어로 연속적으로 반복되는 행을 한 행으로 줄여주고, sort도 함께 써 정렬하며 한 행이 몇번 반복되는지 한눈에 알 수 있게 해주겠습니다. 하지만 우리가 찾는 건 한 번만 나타나는 텍스트기 때문에 uniq에 옵션 -u를 주어 중복없이 한 번만 나오는 줄을 출력합니다.
cat data.txt | sort | uniq -u
level 9 -> 10
비밀번호는 data.txt 파일의 몇 안 되는 사람이 읽을 수 있는 문자열 중 하나에 저장되어 있으며, 앞에는 여러 개의 ‘=’ 문자가 붙어 있다고 문제에서 말하고 있습니다. strings 명령어로 바이너리 파일에서 사람이 읽을 수 있는 문자열만 추출하여 비밀번호를 찾아줍니다.
strings data.txt | grep =
level 10 -> 11
비밀번호는 base64로 인코딩된 데이터가 포함된 data.txt 파일에 저장되어 있습니다. base64 인코딩된 데이터를 디코딩하기 위해 base64 -d라는 명령어로 data.txt를 읽습니다.
base64 -d data.txt
level 11 -> 12
여기에서는 비밀번호가 data.txt 파일에 저장되어 있으며, 모든 소문자(az)와 대문자(AZ)는 13자리씩 회전되어 있다고 합니다. 그러니 tr명령어로 조건에 맞게 고쳐 파일을 열어줍니다. tr ‘원본’ ‘변환’를 입력하면 문자를 다른 문자로 치환하여 우리가 원하는 비밀번호값을 알아낼 수 있습니다.
cat data.txt | tr 'A-Za-z' 'N-ZA-Mn-za-m'
level 12 -> 13
이번에도 비밀번호는 data.txt에 있으며 data.txt는 hexdump 파일이며 내부가 여러 번 압축되어 있습니다.
xxd -r으로 hexdump를 원래 바이너리로 변환해줍니다.
그러나 gzip으로 압축되어 있어 확인이 어렵습니다.
gzip -d을 이용해 압축을 풀어 확인해줍니다.
근데 이번에는 또 bzip2으로 압축되어 있었습니다.
bzip2 -d으로 압축을 풀어줍니다.
또 이번에는 tar로 아카이빙되어 있습니다.
tar -xf로 아카이브를 해제해줍니다.
이걸 반복하다보면 ASCII text인 파일을 찾을 수 있는데 이걸 읽으면 비밀번호를 찾을 수 있습니다.

level 13 -> 14
비밀번호는 /etc/bandit_pass/bandit14 파일에 저장되어 있으며, bandit14 사용자만 읽을 수 있답니다. 당황스럽네요. 저는 bandit13인데 말이죠. 하지만 저희는 이미 원격으로 bandit13에 접속할 수 있다는 것을 알기 때문에 key만 알면 bandit14에도 접속할 수 있을 겁니다. key는 private key와 public key의 한 쌍으로 이루어져있는 비대칭 키가 있는데 ls로 확인해보니 Private key가 보관되어 있습니다. 이걸 이용해 ssh -i sshkey.private bandit14@localhost -p 2220를 입력해 원격으로 접속해줍니다. bandit14로 로그인 하면 /etc/bandit14_pass/bandit14파일에 저장된 비밀번호를 확인할 수 있습니다.
ssh -i sshkey.private bandit14@localhost -p 2220
cat /etc/bandit14_pass/bandit14
level 14 -> 15
이 레벨에서의 비밀번호는 현재 레벨의 비밀번호를 localhost의 30000번 포트로 전송하면 얻을 수 있습니다. 주어진 텍스트를 화면에 출력할 때 사용하는 echo라는 명령어에 현재 비밀번호를 담고 nc명령어로 localhost에 30000번 포트로 전송합니다. nc는 netcat의 줄인말로 지정 호스트나 포트로 데이터 전송합니다.
echo "MU4VWeTyJk8ROof1qqmcBPaLh7lDCPvS" | nc localhost 30000
level 15 -> 16
비밀번호는 현재 레벨의 비밀번호를 SSL/TLS 암호화를 사용하여 localhost의 30001 포트로 전송함으로써 얻을 수 있습니다. openssl s_client -connect [시스템 주소:포트]를 입력하면 SSL/TLS 암호화를 사용하여 지정한 주소:포트에 비밀번호를 전달할 수 있습니다.
openssl s_client -connect localhost:30001
level 16 -> 17
31000 ~ 32000 포트 중 SSL을 사용하는 포트를 찾아 비밀번호를 전송하는 문제입니다.
nmap -sV localhost -p 31000-32000
echo "kSkvUpMQ7lBYyCM4GBPvCvT1BfWRy0Dx" | openssl s_client -connect localhost:31790 -ign_eof
으로 nmap -sV로 포트 스캔을 하는 동시에 서비스 버전 확인합니다. -p옵션을 붙여 31000 ~ 32000까지 스캔하라고 정합시다. 그러면 몇번 포트로 현재 비밀번호와 함께 보내어 문제를 해결합니다.
level 17 -> 18
홈 디렉터리에는 passwords.old와 passwords.new라는 두 개의 파일이 있습니다. 다음 레벨의 암호는 passwords.new 파일에 있으며, passwords.old와 passwords.new 파일 사이에서 변경된 유일한 줄이라고 합니다. 변경된 줄이라면 passwords.old와 passwords.new 사이에 다른 줄을 찾으면 된다는 생각이 들었습니다. 그래서 diff라는 명령어를 사용했는데 이는 두 파일의 차이점 비교하고 출력하는 명령어입니다.
diff passwords.old passwords.new
level 18 -> 19
비밀번호는 홈 디렉터리의 readme 파일에 저장되어 있습니다. 안타깝게도 누군가 .bashrc 파일 을 수정하여 SSH로 로그인할 때 로그아웃되도록 설정했습니다. 그러니 로그인을 하고 readme 파일을 열기보다 로그인과 동시에 파일을 여는 방법을 고안해야합니다. 원격으로 접속할 때 /bin/sh 명령어를 추가적으로 입력하여 bash쉘이 아닌 sh로 가장 기본 쉘을 통해 접속하면 됩니다. 그러고 나서 cat으로 readme 파일을 열어주어 비밀번호를 찾아줍니다.
ssh bandit18@bandit.labs.overthewire.org -p 2220 /bin/sh

level 19 -> 20
홈 디렉터리에 있는 setuid 바이너리를 사용해야하며 인자 없이 실행하면 사용 방법을 알 수 있다고 합니다. 즉, 이 문제는 홈 디렉터리의 setuid 바이너리로 bandit20 권한의 파일을 읽는 문제입니다. cat으로 문제에서 알려준 경로를 입력하여 파일을 열어보려 했지만 권한이 없습니다. 권한을 확인하기 위해 ls -l로 읽어봅시다. 설정된 권한은 -rwsr-x— 1 bandit20 bandit19 14888 Apr 3 15:17 bandit20-do이었습니다. 알파벳마다 각각의 의미가 있는데, r: 읽기 권한 w: 쓰기 권한 s: setUID 설정 x: 실행 권한 -: 권한 없음 을 의미합니다. ./bandit20-do id 명령어로 user, group 정보를 출력하니 euid가 bandit20이었습니다. euid는 파일을 실행했을 때 실제 사용하는 uid를 의미합니다. 그러니 다른 user권한으로 아까와 같이 파일을 열면 비밀번호를 찾을 수 있습니다.
./bandit20-do id
./bandit20-do cat /etc/bandit_pass/bandit20
level 20 -> 21
홈 디렉터리에 있는 setuid 바이너리는 다음과 같은 작업을 수행합니다. 먼저 명령줄 인수로 지정한 포트의 localhost에 연결합니다. 그런 다음 연결을 통해 텍스트 한 줄을 읽어 이전 레벨의 암호(bandit20)와 비교합니다. 암호가 올바르면 다음 레벨의 암호(bandit21)를 전송합니다. 이 레벨의 문제 조건입니다. 이번에도 setuid설정이 된 파일이 있습니다. ./suconnect로 확인해본 결과 이 프로그램은 TCP를 사용하여 로컬 호스트의 지정된 포트에 연결하고 다른 쪽에서 올바른 암호를 받으면 다음 암호는 다시 전송된다고 합니다. 그러니까 터미널을 두개를 열어 서로 통신하게 해서 풀어야하는 문제입니다. nc로 열어주고 다른 터미널에서 접속하는 문제입니다. nc 옆에 붙은 옵션들은 각각 l: listen 모드로 서버처럼 동작하면서 연결을 기다림 n: DNS 해석 비활성화해 IP 주소를 도메인 이름으로 변환하지 않음 v: 상세 출력, 연결 정보를 자세히 보여줌 p: 사용할 로컬 포트를 지정
nc -lnvp 1234
[현재 비밀번호]
./suconnect 1234

level 21 -> 22
이 레벨은 cron 작업 분석하는 문제입니다. ./etc/cron.d/ 디렉토리에서 설정 파일을 확인하고 어떤 명령이 실행되고 있는지 살펴보라고 문제에서 말합니다. cron은 정해진 시간마다 자동으로 명령어를 실행하는 스케줄러입니다. cron의 실행 파일들은 /etc/cron.d에 있습니다. 우리가 찾는 것은 cronjob_bandit22이니 이걸 cat으로 열어 확인해줍니다. 확인해보니 1분마다 /usr/bin/cronjob_bandit22.sh가 실행되고 있는 사실을 알 수 있었습니다. tmp디렉토리에 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv라는 파일을 만들고 bandit22의 비밀번호를 cat을 통해 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv파일에 저장하고 읽으면 해결됩니다.
cat /etc/cron.d/cronjob_bandit22
cat /usr/bin/cronjob_bandit22.sh
cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
level 22 -> 23
cron에 연결된 파일을 읽어보면 이번에는 /usr/bin/cronjob_bandit23.sh파일로 연결되어있다고 합니다. 저걸 열어보면
#!/bin/bash
myname=$(whoami)
mytarget=$(echo I am user $myname | md5sum | cut -d ' ' -f 1)
echo "Copying passwordfile /etc/bandit_pass/$myname to /tmp/$mytarget"
cat /etc/bandit_pass/$myname > /tmp/$mytarget
이라는 스크립트가 있습니다.
스크립트 내용을 토대로 whoami 명령어로 user id를 얻고 형식에 맞춰 입력하면 비밀번호를 찾을 수 있습니다.

level 24 -> 25
이 문제는 포트 30002에 bandit24 비밀번호와 핀코드[0000 ~ 9999]를 전송하면 다음 레벨의 비밀번호를 받을 수 있습니다. 핀코드를 찾기 위해서 임의의 파일에 btureforce를 위한 비밀번호 조합 생성 스크립트를 만들어주고 seq -w 0000 999900로 0000부터 9999까지 숫자 생성하여 반복합니다. 그러면 뭐가 나오다 비밀번호 하나가 마지막에 나옵니다.
mktemp -d
cd /tmp/tmp.T7wqCUer7K
cat > bruteforce.sh << 'EOF'
#!/bin/bash
for i in $(seq -w 0000 9999); do
echo "gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8 $i"
done | nc localhost 30002
EOF
bash bruteforce.sh
bandit 풀이 이미지들
