linefilt

RDP over SSH Tunnel 본문

Rules/malicious

RDP over SSH Tunnel

mong.goose 2019. 4. 10. 11:19

원격 데스크톱은 대상 컴퓨터가 원격 데스크톱을 허용해두었다면, 윈도의 mstsc 이용해서 간단하게 접속할 수 있고 RDP 환경에서는 대부분의 기능을 거의 동일하게 사용할 수 있기에 많은 표적이 될 수 있다.

 

그림 1. mstsc 접속 요청 패킷

 

그림 2. 우분투 RDP 프로그램 접속 요청 패킷


그림 1은 윈도우에서 mstsc를 이용한 원격 데스크톱 접속 시 패킷, 그림 2는  우분투에서 RDV, KRDC, Remmina를 통해서 접속 시의 패킷 페이로드를 나타낸다.


두 개의 패킷에서 공통적으로 찾아볼 수 있는 패턴은 |03 00 00|과 |e0 00 00 00 00| 이며, 이 패턴들은 Emerging-Threats Open 룰에서도 거의 동일하다시피 찾아볼 수 있는 패턴이다. 이처럼 RDP가 경유하는 구간에서는 IDS, IPS의 간단한 정책만으로도 RDP 요청을 탐지할 수 있다.

문제는 RDP over SSH Tunnel과 같이 RDP 스트림의 시작부터 암호화가 적용되었을 경우이다. 이렇게 RDP가 암호화되었을 때는 RDP의 특정 패턴을 확인할 수 없어 관리 측면에서 제어하기 어렵다는 문제가 발생한다. RDP over SSH Tunnel에서 세션에 따른 상황을 알아보고 위협을 제어하기 위한 방안을 모색한다.

그림 3. RDP over SSH (Forward)

RDP over SSH는 세션 개시 방향에 따라 룰을 두가지로 나눌 수 있다.

 

1. Forward

Forward 방향은 내부 사용자가 외부의 서버에 3389와 같은 특정 포트를 사용할 수 없는 경우, SSH 포트를 사용하여 RDP를 터널링하는 방법이다. 최종적으로 RDP가 연결되는 서버는 SSH서버와 동일하거나 다를 수 있다.

 

그림 4. 암호화 구간에서의 mstsc 요청
그림 5. 복호화 구간에서의 mstsc 요청

클라이언트가 서버로 전송하는 Ingored Unknown Record 등은 RDP 클라이언트 별로 가변 길이를 가지는 경우가 있어 탐지 요소로 선정하기 어려운면이 있다. 만약 내부 사용자 제어를 위한 탐지가 필요하다면 스트림에서 공통적이거나 경우의 수가 적은 것을 선택해야 한다.

 

그림 6. RDP over SSH (Reverse)

2. Reverse

Reverse는 외부의 공격자가 특정 네트워크의 내부 컴퓨터를 제어하기 위해 사용할 수 있다. 공격자는 내부로의 접근 제어가 적용된 방화벽을 우회하기 위해 Drive-By-Download와 같은 공격을 통해 내부 컴퓨터가 자신의 C2서버에 SSH를 통해 직접적으로 연결하도록 한다.

 

그림 7. 내부 컴퓨터에서의 plink 실행
그림 8. plink를 통한 ssh 세션 수립(ESTAB)

내부 컴퓨터가 C2서버로 연결 되면, 공격자는 SSH터널을 통해 RDP클라이언트를 사용하여 내부 컴퓨터를 제어할 수 있다.

 

그림 9. 암호화 구간에서의 RDP over SSH (Reverse)
그림 10. RDP over SSH 연결 시 로컬 포트 수립 (ESTAB)

Reverse와 Forward 모두 비슷한 트래픽 양상을 보이지만 SSH터널의 세션 방향이 다르다는 점과 일부 응답 패킷에서 차이가 존재한다.

 

TS: to_server

TC: to_client

 

그림 9는 Reverse RDP over SSH로 연결되었을 때 Traffic Flow의 양상을 보여준다. 그중 TS96 - TS304 - TS400 - TS192는 RDP 서버가 클라이언트로 보내는 응답 메시지 중 탐지하기에 적절한 메시지들 중 일부이다. 암호화 스트림에서 주로 기준이 되는 것은 얼마나 적은 경우의 수를 가지고 있는지를 고려할 수 있다. RDP와 같이 서버의 종류보다 클라이언트의 종류가 많은 경우에는 클라이언트를 기준하기에는 더 많은 Case가 발생한다. 반대로 카카오톡과 같은 특정 응용프로그램들은 클라이언트의 종류가 적거나 한정적인 경우에는 클라이언트를 기준 잡는 것이 적절할 수 있다.

 

Reverse Rules

alert tcp-pkt any any -> any 22 (msg:"RDP over SSH (Reverse) set"; flow:established,to_server; dsize:96; prefilter; flowbits:isnotset,rostr; flowbits:set,rostr1; noalert; sid:16; rev:2; metadata:linefilt.tistory.com, created_at 2019_05_09 updated_at 2020_03_09;)
alert tcp-pkt any any -> any 22 (msg:"RDP over SSH (Reverse) chaning1"; flow:established,to_server; flowbits:isset,rostr1; dsize:304; prefilter; flowbits:unset,rostr1; flowbits:set,rostr2; noalert; sid:13; rev:2; metadata:linefilt.tistory.com, created_at 2019_05_09 updated_at 2020_03_09;)
alert tcp-pkt any any -> any 22 (msg:"RDP over SSH (Reverse) chaning1"; flow:established,to_server; flowbits:isset,rostr1; dsize:352; prefilter; flowbits:unset,rostr1; flowbits:set,rostr2; noalert; sid:12; rev:2; metadata:linefilt.tistory.com, created_at 2019_05_09 updated_at 2020_03_09;)
alert tcp-pkt any any -> any 22 (msg:"RDP over SSH (Reverse) chaning1 flush"; flow:established,to_server; flowbits:isset,rostr1; dsize:>352; prefilter; flowbits:unset,rostr1; noalert; sid:11; rev:2; metadata:linefilt.tistory.com, created_at 2019_05_09 updated_at 2020_03_09;)
alert tcp-pkt any any -> any 22 (msg:"RDP over SSH (Reverse) chaning1 flush"; flow:established,to_server; flowbits:isset,rostr1; dsize:0<>304; prefilter; flowbits:unset,rostr1; noalert; sid:10; rev:2; metadata:linefilt.tistory.com, created_at 2019_05_09 updated_at 2020_03_09;)
alert tcp-pkt any any -> any 22 (msg:"RDP over SSH (Reverse) chaning1 flush"; flow:established,to_server; flowbits:isset,rostr1; dsize:304<>352; prefilter; flowbits:unset,rostr1; noalert; sid:9; rev:2; metadata:linefilt.tistory.com, created_at 2019_05_09 updated_at 2020_03_09;)
alert tcp-pkt any any -> any 22 (msg:"RDP over SSH (Reverse) chaning2"; flow:established,to_server; flowbits:isset,rostr2; dsize:400; prefilter; flowbits:unset,rostr2; flowbits:set,rostr3; noalert; sid:8; rev:2; metadata:linefilt.tistory.com, created_at 2019_05_09 updated_at 2020_03_09;)
alert tcp-pkt any any -> any 22 (msg:"RDP over SSH (Reverse) chaning2 flush"; flow:established,to_server; flowbits:isset,rostr2; dsize:>400; prefilter; flowbits:unset,rostr2; noalert; sid:7; rev:2; metadata:linefilt.tistory.com, created_at 2019_05_09 updated_at 2020_03_09;)
alert tcp-pkt any any -> any 22 (msg:"RDP over SSH (Reverse) chaning2 flush"; flow:established,to_server; flowbits:isset,rostr2; dsize:0<>400; prefilter; flowbits:unset,rostr2; noalert; sid:6; rev:2; metadata:linefilt.tistory.com, created_at 2019_05_09 updated_at 2020_03_09;)
alert tcp-pkt any any -> any 22 (msg:"RDP over SSH (Reverse) chaning3"; flow:established,to_server; flowbits:isset,rostr3; dsize:192; prefilter; stream_size:client,<,11500; flowbits:unset,rostr3; flowbits:set,rostr4; noalert; sid:5; rev:2; metadata:linefilt.tistory.com, created_at 2019_05_09 updated_at 2020_03_09;)
alert tcp-pkt any any -> any 22 (msg:"RDP over SSH (Reverse) chaning3 flush"; flow:established,to_server; flowbits:isset,rostr3; dsize:>192; prefilter; flowbits:unset,rostr3; noalert; sid:4; rev:2; metadata:linefilt.tistory.com, created_at 2019_05_09 updated_at 2020_03_09;)
alert tcp-pkt any any -> any 22 (msg:"RDP over SSH (Reverse) chaning3 flush"; flow:established,to_server; flowbits:isset,rostr3; dsize:0<>192; prefilter; flowbits:unset,rostr3; noalert; sid:3; rev:2; metadata:linefilt.tistory.com, created_at 2019_05_09 updated_at 2020_03_09;)
alert tcp-pkt any any -> any 22 (msg:"RDP over SSH IP (Reverse)"; flow:established,to_server; flowbits:isset,rostr4; dsize:0; prefilter; flowint:rostr,+,1; noalert; sid:2; rev:2; metadata:linefilt.tistory.com, created_at 2019_05_09 updated_at 2020_03_09;)
reject tcp-pkt any any -> any 22 (msg:"RDP over SSH IP DROP (Reverse)"; flow:established; dsize:0; prefilter; flowint:rostr,<,4; sid:1; rev:2; metadata:created_at 2019_05_09 updated_at 2020_03_09;)

OS 환경

 - Windows Version 1809, Version 1803 (Windows 10), Windows Server Version 1607 (Server 2016)

 

RDP Client

 - KRDC(ubuntu 18.04, centos 7.6), Remote Desktop Viewer(ubuntu 18.04, centos 7.6), Remmina(unbutu 18.04)

 

윈도 10계열 기준이라도 적용되지 않는 버전이 있을 수 있습니다. 윈도 8.1 등 그 외 버전까지 지원하기에는 룰의 범위가 너무 커지기 때문에 기본적인 10 기준으로 진행된 설정이다.

 

Q. 그림 9에서 4개의 패킷이 선택된 이유

A. 그림 9 와이어 샤크 캡처에서 No. 27 패킷은 Client Hello 패킷이고 No. 28은 Sever Hello 메시지로 4개의 패킷은 TLS Handshake 또는 직후에 나오는 메시지들로 주로 특정 정보 교환에 포함된다고 볼 수 있다. 일반적인 데이터 패킷이 아니며, 여러 환경에서 주로 동일하거나 근접 범위에서 나오는 페이로드 size로 인해서 선택된 것이다.

 

Q. flush 룰이 사용된 이유
A. 탐지된 스트림이 연속성 가지고 있는지를 검증하기 위함이다. 각각의 패킷들이 개별적으로 등장할 경우 오탐의 빈도가 많아질 수밖에 없다. 그림 7과 같이 발생한 패킷들이 연속적으로 발생하였을 경우 악성 행위라고 볼 수 있기 때문에 이를 검증하고자 하는 것이다.


 

Comments