서론
리버스 쉘은 일반적인 연결 방향과 반대로 작동하는 원격 쉘 기법이다. 대상 시스템이 공격자의 시스템으로 연결을 시도해 원격 명령 실행을 가능하게 한다. 방화벽과 NAT 환경에서 특히 유용한데, 대부분의 방화벽이 들어오는 연결은 차단하지만 나가는 연결은 허용하기 때문이다.
작동 원리
리버스 쉘이 작동하는 기본 흐름은 다음과 같다:
- 공격자는 자신의 시스템에서 특정 포트의 연결을 수신하는 리스너를 설정한다
- 대상 시스템에서 실행된 코드가 공격자 시스템으로 연결을 시도한다
- 대상 시스템의 입출력이 공격자에게 전달된다
- 공격자는 대상 시스템에 명령을 실행하고 결과를 확인할 수 있다
일반적인 원격 접속은 ‘공격자가 대상 시스템에 접속하는’ 형태지만, 리버스 쉘은 ‘대상 시스템이 공격자에게 연결해오도록 만드는’ 방식이다. 이런 역방향 연결이 방화벽을 우회하는 열쇠가 된다.
바인드 쉘과의 차이점
특성 | 바인드 쉘 | 리버스 쉘 |
---|---|---|
연결 방향 | 공격자 → 대상 | 대상 → 공격자 |
방화벽 우회 | 어려움 | 쉬움 |
NAT 환경 | 접근 제한적 | 연결 가능 |
탐지 난이도 | 쉬움 | 어려움 |
포트 개방 | 대상 시스템 | 공격자 시스템 |
바인드 쉘은 대상 시스템에서 포트를 열고 대기하는 방식인데, 기업 네트워크 환경에서는 대부분 인바운드 연결이 차단되어 있어 실효성이 떨어진다. 반면 리버스 쉘은 대상 시스템이 먼저 연결을 시도하기 때문에 많은 방화벽 설정을 우회할 수 있다.
리버스 쉘 구현 방법
다양한 프로그래밍 언어와 도구로 리버스 쉘을 구현할 수 있다. 각 방법마다 장단점이 있으니 상황에 맞게 선택하면 된다. 여기서는 가장 일반적으로 사용되는 방법들을 소개한다.
Bash를 이용한 방법
|
|
이 한 줄의 코드가 리버스 쉘의 가장 기본적인 형태다. Bash의 특수 파일 경로인 /dev/tcp/
를 활용해 표준 입출력과 오류 스트림을 소켓으로 리디렉션하는 방식이다. -i
플래그는 대화형 쉘을 생성한다.
대부분의 Linux와 Unix 시스템에 기본 설치된 Bash를 활용하기 때문에 추가 도구가 필요 없다는 장점이 있다. 단, 모든 Linux 배포판이 /dev/tcp/
기능을 지원하는 것은 아니므로 주의가 필요하다.
공격자 측에서는 다음과 같이 리스너를 실행한다:
|
|
netcat 도구를 이용해 포트 4444에서 들어오는 연결을 기다리는 것이다. 연결이 성공하면 대상 시스템의 쉘에 접근할 수 있게 된다.
Python을 이용한 방법
|
|
Python은 강력한 소켓 프로그래밍 기능을 제공해 안정적인 리버스 쉘을 구현할 수 있다. 이 코드는 소켓을 생성하고 연결한 후, 표준 스트림을 소켓으로 복제하여 쉘 명령의 입출력이 소켓을 통해 전달되게 한다.
Python이 설치된 모든 시스템에서 동작하며, 에러 처리를 통해 연결 실패 시 조용히 종료되도록 하여 탐지를 어렵게 만든다. 윈도우 환경에서는 /bin/sh
대신 cmd.exe
또는 powershell.exe
로 변경하여 사용할 수 있다.
탐지 회피 기법
기본적인 리버스 쉘은 네트워크 모니터링 도구에 쉽게 탐지될 수 있다. 보안 장비가 발전함에 따라 탐지를 회피하기 위한 기법들도 함께 발전했는데, 더 은밀한 통신을 위한 방법들을 알아보자.
암호화된 통신
기본적인 리버스 쉘 연결은 대부분 암호화되지 않은 평문으로 전송되므로 네트워크 트래픽 분석에 취약하다. 암호화를 적용하면 내용 검사 기반의 탐지를 회피할 수 있다.
|
|
이 방법은 OpenSSL을 사용하여 암호화된 통신 채널을 생성한다. HTTPS 트래픽과 유사하게 보이므로 트래픽 분석을 어렵게 만든다.
HTTP 웹 트래픽 이용
대부분의 기업에서는 웹 트래픽(포트 80, 443)이 허용되므로, HTTP 프로토콜을 활용한 리버스 쉘은 탐지가 어렵다. 웹 요청으로 위장해 명령을 주고받는 방식으로, 일반적인 웹 브라우징과 구분하기 어렵다.
웹 기반 리버스 쉘은 다음과 같은 형태로 동작한다:
- 대상 시스템에서 주기적으로 공격자 서버에 HTTP 요청을 보낸다
- 서버는 요청에 대한 응답으로 실행할 명령을 전송한다
- 대상 시스템은 명령을 실행하고 결과를 다음 HTTP 요청에 포함시켜 전송한다
DNS 터널링
HTTP 트래픽마저 모니터링되는 극도로 제한된 환경에서는 DNS 쿼리를 활용한 리버스 쉘이 대안이 될 수 있다. 대부분의 네트워크에서 DNS 쿼리는 인터넷 접속에 필수적이므로 차단하지 않기 때문이다.
DNS 터널링은 명령과 응답을 DNS 패킷에 인코딩하여 전송하는 방식이다. 이 기법의 작동 원리는 다음과 같다:
- 공격자는 권한 있는 DNS 서버를 제어
- 명령을 DNS 하위 도메인 형태로 인코딩 (예:
cmd.ls-al.attack.com
) - 대상 시스템은 이 도메인을 조회하며 명령을 수신
- 명령 실행 결과를 DNS 응답으로 인코딩하여 전송
DNS 터널링은 느리지만 다른 모든 통신이 차단된 상황에서도 동작할 가능성이 높다.
간헐적 연결 및 지연 실행
지속적인 연결은 탐지될 가능성이 높으므로, 간헐적인 연결 방식을 활용하면 탐지를 어렵게 만들 수 있다:
|
|
이러한 방식은 네트워크 모니터링 시스템의 지속적인 연결 탐지를 우회하는 데 효과적이다. 또한 업무 시간 외 또는 관리자가 자리를 비운 시간대에만 연결하도록 설정하면 탐지 가능성을 더욱 낮출 수 있다.
방어 전략
리버스 쉘 공격에 대한 효과적인 방어는 크게 네트워크 레벨과 호스트 레벨로 나눌 수 있다.
네트워크 레벨 방어
아웃바운드 트래픽 제한은 리버스 쉘 방어의 핵심이다. 대부분의 조직은 인바운드 연결만 제한하고 아웃바운드는 자유롭게 허용하는데, 이것이 리버스 쉘의 약점이 된다.
효과적인 네트워크 방어:
- 필요한 연결만 허용: 서버가 접속해야 하는 특정 IP와 포트만 화이트리스트로 관리
- 비정상 연결 감시: 4444, 5555 같은 일반적인 리버스 쉘 포트로의 연결 차단
- 프록시 서버 활용: 모든 웹 트래픽을 프록시를 통해 검사하고 필터링
- DNS 모니터링: 내부 DNS 서버를 통해 외부 요청을 감시하고 이상 패턴 탐지
비정상 트래픽 패턴:
- 규칙적인 간격의 짧은 통신
- 비업무 시간대 발생하는 연결
- 일반적이지 않은 포트로의 아웃바운드 연결
- 서버에서 예상치 못한 목적지로의 통신
호스트 레벨 방어
호스트 레벨 방어는 공격이 성공했더라도 피해를 최소화하고 조기에 탐지하기 위한 마지막 방어선이다.
핵심 보안 조치:
- 불필요한 서비스 제거: 필요하지 않은 서비스와 소프트웨어는 모두 제거
- 스크립트 실행 제한:
- PHP:
disable_functions=system,exec,shell_exec,passthru
설정 - 임시 디렉토리:
/tmp
와/var/tmp
에noexec
옵션 적용
- PHP:
- 프로세스 모니터링: 웹 서버가 쉘 프로세스를 생성하는지 감시
- 중앙 로깅 시스템: 모든 서버의 로그를 중앙 서버로 수집하여 분석
행위 기반 탐지:
- 쉘 프로세스가 네트워크 연결을 시도하는 경우
- 사용자 로그인 없이 생성된 쉘 세션
- 여러 실패한 명령어 실행 (공격자의 시스템 탐색 흔적)
- 민감한 설정 파일에 대한 접근 시도
이러한 다층적 방어를 통해 리버스 쉘 공격을 효과적으로 탐지하고 차단할 수 있다.
결론
리버스 쉘은 현대 사이버 공격에서 매우 유용한 도구로, 방화벽과 NAT 환경에서도 효과적으로 작동한다. 다양한 구현 방법과 탐지 회피 기법을 이해하고, 이에 대한 방어 전략을 마련하는 것이 중요하다.