WSL 환경에서 리눅스 기본 명령어를 활용하여 탐색, 식별, 해석한다.
미션 목표 : WSL(Windows Subsystem for Linux) 환경에서 리눅스 기본 명령어를 활용하여 파일 시스템을 탐색하고, 숨김 파일 및 특수 파일을 식별하며, 인코딩된 데이터를 해석하는 능력을 습득한다. 또한CLI(Command Line Interface) 환경에 익숙해지고, 보안 및 시스템 분석의 기초 역량을 기른다.
관련 링크 : OverTheWire
레벨 0
pw : bandit0
레벨 0 > 1
로그인 후 ls 를 통해 파일을 확인하고 readme 파일을 cat을 통해 불러온다.
- ls : 현재 디렉토리 파일 목록 확인
- cat : 파일 내용 출력
pw : ZjLjTmM6FvvyRnrb2rfNWOZOTa6ip5If
레벨 1 > 2
로그인 후 ls 로 파일 목록 확인, - 는 파일명이 아니라 표준 입력으로 해석되기때문에 cat ./- 를 통해 비밀번호를 얻는다.
pw : 263JGJPfgU6LtdEvgfWU1XP5yac29mFx
레벨 2 > 3
로그인 후 ls 로 파일 목록을 확인하고 쉘이 공백을 기준으로 파일명을 여러개로 분리하기 때문에
cat “./–spaces in this filename–“ 를 통해 비밀번호를 얻는다.
pw : MNk8KNH3Usiio41PRUEoDFPqfxLPlSmx
레벨 3 > 4
로그인 후 ls 로 파일 목록을 확인하고 cd inhere 을 통해 디렉토리로 이동한다. ls 로 파일 목록을 확인했지만 아무것도 뜨지않아서
ls -a 를 통해 숨겨져있는 파일 목록까지 불러온다. 이후 cat …Hiding-From-You 을 통해 비밀번호를 얻는다.
- ls -a : 숨김 파일 포함 전체 출력
pw : 2WmrDFRmJIq3IPxneAaMGhap0pFhF3NJ
레벨 4 > 5
로그인 후 ls 로 파일 목록을 확인하고 cd inhere 을 통해 디렉토리로 이동한다. 다시 ls 를 통해 파일 목록 확인.
file ./* 를 통해 파일 타입을 확인하고 그 중에서 ACSII text 로 되어있는 ./-file07 을 cat 을 통해 불러온다.
pw : 4oQYVPkxZOOEOO5pTW81FB8j8lxXGUQw
레벨 5 > 6
로그인 후 ls 로 파일 목록을 확인하고 cd inhere 을 통해 디렉토리로 이동한다. 다시 ls 를 통해 파일 목록 확인.
find 명령어를 통해 조건에 맞는 파일을 검색한다. 이후 cat 을 통해 비밀번호를 얻는다.
- find : 파일 검색
pw : HWasnPhtq9AVKe0dmk45nxy20cvUa6EG
레벨 6 > 7
find 명령어를 통해 조건에 맞는 파일을 검색한다. 이후 cat 을 통해 비밀번호를 얻는다.
pw : morbNTDkSW6jIlUc0ymOdMaLnOlFVAaj
레벨 7 > 8
로그인 후 ls 로 파일 목록을 확인하고 grep 명령어를 통해 data.txt 에서 “millionth” 문자열이 포함된 줄 찾는다.
- grep : 문자열 검색
pw : dfwvzFQi4mU0wfNbFOe9RoWskMLg7eEc
레벨 8 > 9
로그인 후 ls 로 파일 목록을 확인하고 sort 명령어를 통해 문자열을 정렬한다.
유일하게 한번만 나타나는 텍스트라고 하였으니 uniq -u 를 통해 중복되지 않는 줄만 출력하도록 한다.
- sort : 문자열 정렬
- uniq -u : 중복되지 않은 줄만 출력
-
Pipe ( ) : 왼쪽 출력 > 오른쪽 입력 전달
pw : 4CKMh1JI91bUIZZPXDqGanal4xvAg0JM
레벨 9 > 10
로그인 후 ls 로 파일 목록을 확인하고 사람이 읽을 수 있는 문자열 중 하나에 저장되어있다고 하며
‘=’ 문자가 붙어있다고 하여 strings data.txt | grep “=” 을 통해서 문자열을 추출한다.
- strings : 바이너리 내부 문자열 추출
pw : FGUW5ilLVJrxX9kMYMmlN4MgbpfMiqey
레벨 10 > 11
로그인 후 ls 로 파일 목록을 확인하고 base64로 인코딩된 데이터로 포함된 data.txt 파일에 저장되어 있기때문에
base64 -d data.txt 를 통해 비밀번호를 얻는다.
pw : dtR173fZKb0RRsDFSGsg2RWnpNVj3qRr
레벨 11 > 12
로그인 후 ls 로 파일 목록을 확인하고 cat data.txt | tr ‘A-Za-z’ ‘N-ZA-Mn-za-m’ 을 통해서
회전되어 있는 알파벳을 다시 회전시키는 치환방식으로 비밀번호를 얻는다.
- tr : 문자 치환 명령어
pw : 7x16WNeHIi5YkIhWsfFIqoognUTyj9Q4
레벨 12 > 13
우선 디렉토리를 생성하고 생성한 디렉토리로 이동한다.
cp ~/data.txt . 를 통해 원본파일을 복사하고 xxd -r data.txt > data.bin 를 통해 hex dump를 복원시킨다.
반복적으로 gunzip / bunzip2 / tar -xf 를 진행하고 중간마다 file 파일명을 통해 타입을 확인한다.
최종적으로 data8 을 통해 비밀번호를 얻는다.
pw : FO5dwFsc0cbaIiH0h8J2eUks2vdTDwAn
레벨 13 > 14
로그인 후 ls 로 파일 목록을 확인하고 HINT 파일을 확인했다.
The current version of OverTheWire prevents logging in from one level to another via localhost.
Log out. 라인을 통해서 기존처럼 서버 내부에서 ssh -i sshkey.private bandit14@localhost -p 2220 처럼 접속하는 방식이
막혀있어서 로컬에서 직접 접속해야함을 알수있다.
scp -P 2220 bandit13@bandit.labs.overthewire.org:sshkey.private . 를 통해서
현재 bandit 서버에 있는 private key를 로컬 WSL 환경으로 가져온다.
권한이 너무 넓으면 보안상 거부하기 때문에 chmod 600 sshkey.private 를 통해 권한을 설정해준다.
ssh -i sshkey.private bandit14@bandit.labs.overthewire.org -p 2220 를 통해 로그인을 하면 로그인이 성공적으로 된다.
cat /etc/bandit_pass/bandit14 를 통해 현재 단계의 비밀번호를 얻는다.
pw : MU4VWeTyJk8ROof1qqmcBPaLh7lDCPvS
레벨 14 > 15
현재 레벨의 비밀번호를 localhost의 30000번 포트 로 전송하면 얻을수있다고 적혀있기에
echo “MU4VWeTyJk8ROof1qqmcBPaLh7lDCPvS” | nc localhost 30000 를 통해서 비밀번호를 얻는다.
- netcat (nc) : TCP 연결 테스트 도구
- Pipe 입력 : echo 결과를 nc로 전달
pw : 8xCjnmgoKbGLhHFAZlGE5Tmu4M2tKJQo
레벨 15 > 16
echo “ 8xCjnmgoKbGLhHFAZlGE5Tmu4M2tKJQo “ | openssl s_client -connect localhost:30001 -quiet
를 통해서 비밀번호를 얻는다.
- openssl s_client : SSL/TLS 연결 테스트 도구
- -quiet : 불필요한 출력 최소화
pw : kSkvUpMQ7lBYyCM4GBPvCvT1BfWRy0Dx
레벨 16 > 17
nmap -sV -p 31000-32000 localhost 를 통해 포트를 스캔한다.
echo “ kSkvUpMQ7lBYyCM4GBPvCvT1BfWRy0Dx “ | openssl s_client -connect localhost:31790 -quiet
를 통해서 SSH private key 를 얻는다.
pw : jmMyCOppv3KKkRgiHI4s5h3I7LwyCgms8uSG06KClQ4
레벨 17 > 18
로그인 후 ls 를 통해 파일을 확인하고 diff 명령어를 통해 두개의 파일 차이를 확인한다.
- diff : 두 파일 차이 비교
pw : x2gLTTjFwMOhQ8oWNbMN362QKxfRqGlO
레벨 18 > 19
그냥 로그인을 시도하면 Byebye! 가 뜨며 로그아웃이 된다.
ssh bandit18@bandit.labs.overthewire.org -p 2220 “cat readme” 를 통해 SSH 접속 시 명령어를 직접 실행한다.
pw : cGWpMaKXVwDUNgPAVJbWYuGHVn9zl3j8
레벨 19 > 20
로그인 후 ls 를 통해서 파일을 확인하고 ls -l 을 통해 파일 권한을 확인한다.
./bandit20-do 를 통해 확인하고 ./bandit20-do cat /etc/bandit_pass/bandit20 을 통해 비밀번호를 얻는다.
pw : 0qXahG8ZjOVMN9Ghs7iOWsCfZyXOUbYO
레벨 20 > 21
netcat listener
nc는 간단한 네트워크 연결을 만들거나 테스트할 때 사용하는 도구다.
이번 문제에서는 특정 포트에서 대기하는 서버 역할로 사용했다.
- nc -lvp 8888
옵션 의미:
- -l : listen 모드
- -v : verbose, 연결 정보 출력
- -p : 포트 지정
파이프
-
echo “password” nc -lvp 8888
echo의 출력값을 nc의 입력으로 전달한다.
즉 클라이언트가 연결되면 nc가 해당 문자열을 보내게 된다.
백그라운드 실행
- &
명령어 뒤에 &를 붙이면 해당 명령이 백그라운드에서 실행된다.
이번 문제에서는 nc가 포트에서 계속 대기해야 하므로, 백그라운드로 실행한 뒤 같은 터미널에서 suconnect를 실행했다.
suconnect 동작 구조
이번 문제의 흐름은 다음과 같다.
[echo 비밀번호] → [nc listener: 8888번 포트 대기]
↑
[suconnect 8888]
즉 suconnect가 8888번 포트에 연결하면, nc가 현재 비밀번호를 보내고, suconnect가 이를 검증한 뒤 다음 비밀번호를 출력한다.
트러블슈팅
처음에는 nc -lvp 8888을 실행한 상태에서 같은 터미널에 ./suconnect 8888을 입력하려고 하면,
그것은 명령어 실행이 아니라 nc를 통해 전송되는 문자열이 된다.
따라서 반드시 두 개의 터미널을 사용하거나, 이번 풀이처럼 nc를 백그라운드로 실행해야 한다.
-
(echo “0qXahG8ZjOVMN9Ghs7iOWsCfZyXOUbYO” nc -lvp 8888 &) && ./suconnect 8888
pw : EeoULMCra2q0dSkYj561DX7s1CpBuOBt
레벨 21 > 22
cron 설정 디렉토리 확인
먼저 cron 설정 파일 목록을 확인했다.
- ls /etc/cron.d/
출력:
behemoth4_cleanup
cronjob_bandit22
cronjob_bandit24
…
이번 문제와 관련 있는 cronjob_bandit22 파일이 보인다.
cron 설정 파일 확인
- cat /etc/cron.d/cronjob_bandit22
출력:
@reboot bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
-
-
-
-
- bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
-
-
-
해석:
- 서버 부팅 시 실행
- 매 1분마다 실행
- 실행 계정: bandit22
- 실행 파일: /usr/bin/cronjob_bandit22.sh
즉 1분마다 bandit22 권한으로 특정 스크립트가 실행된다.
실제 스크립트 확인
- cat /usr/bin/cronjob_bandit22.sh
출력:
#!/bin/bash
chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
분석
스크립트 동작:
- /etc/bandit_pass/bandit22 읽음
- 내용을 /tmp/… 파일에 저장
- 읽기 가능 권한 부여
즉 비밀번호를 /tmp에 복사해둔다.
비밀번호 확인
- cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
출력:
****
이 값이 bandit22 비밀번호다.
cron
리눅스 예약 작업 스케줄러.
형식:
-
-
-
-
- command
-
-
-
의미:
분 시 일 월 요일
예:
매 분 실행.
/tmp 디렉토리
임시 파일 저장 위치.
여러 사용자가 접근 가능한 경우가 많다.
pw : tRae0UfB9v0UzbCdn9cY0gQnds9GF58Q
레벨 22 > 23
cron 설정 확인
- cat /etc/cron.d/cronjob_bandit23
출력:
@reboot bandit23 /usr/bin/cronjob_bandit23.sh
-
-
-
-
- bandit23 /usr/bin/cronjob_bandit23.sh
-
-
-
실제 스크립트 분석
- cat /usr/bin/cronjob_bandit23.sh
출력:
#!/bin/bash
myname=$(whoami)
mytarget=$(echo I am user $myname | md5sum | cut -d ‘ ‘ -f 1)
cat /etc/bandit_pass/$myname > /tmp/$mytarget
동작 분석
스크립트 흐름:
myname=$(whoami)
현재 사용자 이름 저장.
cron은:
- bandit23
권한으로 실행되므로:
- myname = bandit23
다음:
-
echo I am user bandit23 md5sum
실행:
-
echo I am user bandit23 md5sum
결과:
- 8ca319486bfbbc3663ea0fbe81326349
즉 파일 경로:
- /tmp/8ca319486bfbbc3663ea0fbe81326349
비밀번호 읽기
- cat /tmp/8ca319486bfbbc3663ea0fbe81326349
출력:
****
bandit23 비밀번호 획득.
whoami
현재 사용자 확인.
md5sum
문자열 해시 생성.
예:
-
echo hello md5sum
command substitution
- $(command)
명령 결과를 변수에 저장.
whoami
↓
bandit23
↓
echo “I am user bandit23”
↓
md5
↓
파일명 생성
↓
/tmp/해시값
pw : 0Zf11ioIjMVN551jX3CmStKLYqjk54Ga
레벨 23 > 24
cron 설정 확인
먼저 cron 설정 파일 확인:
- cat /etc/cron.d/cronjob_bandit24
출력:
@reboot bandit24 /usr/bin/cronjob_bandit24.sh
-
-
-
-
- bandit24 /usr/bin/cronjob_bandit24.sh
-
-
-
즉 매 1분마다 bandit24 권한으로 특정 스크립트가 실행된다.
실행 스크립트 분석
- cat /usr/bin/cronjob_bandit24.sh
출력:
1
2
3
4
5
6
7
#!/bin/bash
for i in /var/spool/bandit24/foo/*
do
timeout -s 9 60 $i
rm -f $i
done
동작 분석
스크립트 흐름:
- /var/spool/bandit24/foo/ 내부 파일 확인
- 각 파일 실행
- 60초 제한
- 실행 후 삭제
즉 작성한 스크립트를 이 디렉토리에 넣으면 bandit24 권한으로 실행된다.
작업 디렉토리 생성
임시 디렉토리 생성:
- mktemp -d
예:
- /tmp/tmp.IvmEd0yuZc
이동:
- cd /tmp/tmp.IvmEd0yuZc
스크립트 작성
처음에는 nano로 만들려 했지만:
- Unable to create directory /home/bandit23/.local/share/nano/
경고가 발생했다.
그래서 heredoc 방식 사용:
1
2
3
4
5
cat > getpass.sh << 'EOF'
#!/bin/bash
cat /etc/bandit_pass/bandit24 > /tmp/my_bandit24_pass_yh
chmod 644 /tmp/my_bandit24_pass_yh
EOF
내용 설명:
- cat /etc/bandit_pass/bandit24
bandit24 비밀번호 읽기
-
/tmp/my_bandit24_pass_yh
임시 파일 저장
- chmod 644
읽기 권한 부여
실행 권한 부여
- chmod +x getpass.sh
cron 실행 디렉토리에 복사
- cp getpass.sh /var/spool/bandit24/foo/
cron 실행 대기
- sleep 70
cron은 1분마다 실행되므로 여유 있게 기다렸다.
결과 확인
- cat /tmp/my_bandit24_pass_yh
출력:
- gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8
bandit24 비밀번호 획득.
Privilege Escalation
낮은 권한 사용자가 높은 권한으로 코드 실행.
이번 구조:
bandit23
↓
cron
↓
bandit24 권한 실행
heredoc
멀티라인 파일 생성:
cat « EOF
내용
EOF
chmod +x
실행 권한 부여.
pw : gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8
레벨 24 > 25
문제 분석
입력 형식:
- 현재비밀번호 PIN
예:
- gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8 1234
PIN 경우의 수:
- 10000개
수동 불가능.
자동화 필요.
홈 디렉토리 실패
처음 홈 디렉토리에서:
- cat > brute.sh
시도했지만:
- Permission denied
발생.
Bandit 홈은 쓰기 제한이 걸려 있었다.
/tmp 사용
작업 디렉토리 생성:
1
2
mktemp -d
cd /tmp/tmp.xxxxx
brute force 스크립트 작성
1
2
3
4
5
6
7
cat > brute.sh << 'EOF'
#!/bin/bash
for i in $(seq -w 0 9999)
do
echo "gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8 $i"
done | nc localhost 30002
EOF
분석
- seq -w 0 9999
생성:
0000
0001
0002
…
9999
-w는 자리수 고정.
루프:
- for i in …
각 PIN 반복.
전송:
- echo “비밀번호 PIN”
형식 생성.
파이프:
| nc localhost 30002
서버 전송.
실행 권한
- chmod +x brute.sh
실행
- ./brute.sh
출력:
Wrong!
Wrong!
Wrong!
…
Correct!
iCi86ttT4KSNe1armKiwbQNmB3YJP3q4
bandit25 비밀번호 획득.
Brute Force
가능한 모든 경우를 시도.
seq -w
고정 자리 숫자 생성.
Automation
수작업 대신 스크립트 자동화.
1
2
3
4
5
6
7
8
9
0000~9999 생성
↓
현재비밀번호와 조합
↓
nc로 서버 전송
↓
정답 PIN 발견
↓
비밀번호 획득
pw : iCi86ttT4KSNe1armKiwbQNmB3YJP3q4