“인가된 교육용 CTF이며, 실습 후 Bind Shell과 웹쉘을 제거했다”
이번 문제는 파일 업로드 취약점을 이용해 웹쉘을 업로드한 후, 웹쉘을 통해 내부 자격증명을 획득하고 내부망의 SSH 서버에 접근하는 문제이다.
전체적인 공격 흐름은 다음과 같다.
파일 업로드 취약점 → 웹쉘 업로드 → www-data 권한 RCE → 환경변수 및 설정 파일 탐색 → 내부 자격증명 획득 → 내부 SSH 서버 접근 → 플래그 획득
아래 내용은 실습용으로 구성된 환경에서 진행했다.
먼저 아래 사진처럼 파일을 업로드할 수 있는 기능이 보인다.

일반적으로 파일 업로드 기능에서는 확장자, MIME 타입, 파일 내용 등을 검사해서 실행 가능한 파일이 업로드되지 않도록 막아야 한다.
하지만 이 서버는 별도의 필터링 없이 .php 파일을 업로드할 수 있었고, uploaded files에 올라온 PHP 파일에 직접 접근하면 서버가 해당 파일을 단순히 보여주는 것이 아니라 PHP 코드로 실행했다.
즉, 공격자가 임의의 PHP 파일을 업로드하고 웹에서 실행할 수 있는 Arbitrary File Upload 취약점이 존재했다.

웹쉘을 이용해 시스템 명령어를 실행해보니 정상적으로 결과가 반환되었다. 실행 권한을 확인해보면 웹 서버 프로세스 계정인 www-data 권한이었다.
무난하게 www-data 권한의 RCE까지 확보를 했다.
물론 아직 낮은 권한이기 때문에 바로 시스템 전체를 장악한 것은 아니지만, 서버 내부의 파일과 환경변수 등을 확인할 수 있는 발판은 마련한 셈이다.
컨테이너 안을 찾아봤지만 플래그는 없었다. 따라서 플래그가 현재 컨테이너가 아닌 다른 내부 서버에 있을 가능성이 높다고 판단했다.
이제 내부망으로 이동할 수 있는 정보가 있는지 확인하기 위해 환경변수와 애플리케이션 설정 파일을 찾아보기로 했다.

처음으로 env 파일을 살펴봤는데 애플리케이션의 폴더 구조와 함께 파일 서버에 대한 계정 정보도 확인할 수 있었다.
환경변수나 .env 파일에는 데이터베이스 접속 정보, API 키, 내부 서버 주소와 같은 민감한 정보가 저장되는 경우가 많다. 따라서 웹쉘이나 LFI 등을 통해 파일 읽기 권한을 얻었다면 우선적으로 확인해볼 만한 곳이다.
다음으로는 설정 파일을 확인했다.

여기에 강사님이 말한 숨어있는 SSH에 대한 정보가 있었다.
설정 파일 안에는 내부 파일 서버의 주소와 함께 SSH 포트 번호 22, user, password가 전부 평문으로 저장되어 있었다. 또한 remote_path 항목을 통해 파일 서버에서 실제 파일이 저장되는 경로까지 확인할 수 있었다.
즉, 현재 웹 서버는 단순한 최종 목표가 아니라 내부 파일 서버로 이동하기 위한 중간 거점 역할을 하고 있었다.
웹쉘만으로도 명령어를 실행할 수 있지만, 매번 웹 요청을 보내야 해서 불편하다. 조금 더 편하게 서버를 조작하기 위해 Bind Shell을 열기로 했다.
Bind Shell은 대상 서버가 특정 포트를 열고 대기하면 공격자가 해당 포트에 직접 접속하는 방식이다. 공격자 쪽에서 연결을 기다리는 Reverse Shell과는 연결 방향이 반대다.
이제 대상 서버에서 socat으로 9001 포트를 열고 접속을 대기한 후, 칼리 터미널에서 해당 포트로 접속할 것이다.
# 대상에서 socat으로 9001 Bind Shell 기동 (웹쉘을 통해 실행)
nohup socat TCP-LISTEN:9001,bind=0.0.0.0,reuseaddr,fork \
EXEC:/bin/bash,pty,stderr,setsid,sane &
# 칼리에서 대상의 9001 포트가 열려 있는지 확인
nc -z -v 192.168.10.105 9001
# 실제 Bind Shell 접속
nc 192.168.10.105 9001
여기서 nc -z -v는 포트가 열려 있는지만 확인하는 명령어이기 때문에, 실제 셸에 접속하려면 -z 옵션 없이 다시 연결해야 한다.

정상적으로 연결이 되었고, 기존 웹쉘에서 실행했던 명령어들을 터미널에서도 실행할 수 있었다.
이제 앞에서 설정 파일을 통해 획득한 파일 서버의 주소와 fileserver 계정 정보를 이용해 내부 SSH 서버에 접속했다.
ssh fileserver@<내부_파일서버_IP>
비밀번호를 입력하니 정상적으로 로그인이 되었다. 이것으로 외부에서 직접 접근하기 어려운 내부망 서버에, 탈취한 자격증명을 사용해 접근하는 데 성공했다.
그 후 설정 파일의 remote_path에서 봤던 경로로 이동해 파일을 확인해보니 flag.txt가 보였다.

이번 문제에서는 파일 업로드 취약점 하나가 단순한 웹쉘 실행으로 끝나지 않고, 서버 내부에 평문으로 저장된 자격증명까지 노출시키면서 내부망 침투로 이어졌다.
특히 업로드 파일의 실행 방지, 환경변수 및 설정 파일의 비밀정보 관리, 내부 서버 자격증명 분리 등이 제대로 적용되지 않으면 여러 개의 작은 문제가 연결되어 큰 침해 사고로 이어질 수 있다는 것을 볼 수 있었다.
끗