NTP 放大攻击,原理与实践

昨天在微博上看到乌云知识库分享了一篇关于 NTP 放大攻击的文章,点进去看了一下,发现内容很有意思,漏洞本身利用的原理很简单,实现的难度也并不高,但是产生的效果却十分明显,于是决定按照文章中的方式简单复现一下攻击。

本文大部分内容来自 《NTP Amplification Discovery》 原文链接

首先在进行介绍之前,需要你具有基本的背景知识,比如什么是 DDos 攻击。

NTP 放大攻击所利用的协议是 NTP 协议,全称是 Network Time Protocol,网络时间协议。是用于在互联网中对不同主机进行时间同步的协议。其中运行某些版本NTP 的服务器默认开启了对 MONLIST 命令的支持,这条命令的作用是向请求者返回最近通过 NTP 协议与本服务器进行通信的 IP 地址列表,最多支持返回600条记录。也就是说,如果一台 NTP 服务器有超过600个 IP 地址使用过它提供的 NTP 服务,那么通过一次 MONLIST 请求,你会收到返回的包含600条记录的数据包。这应该远远大于你发送查询命令的数据包大小。

那么,都有谁可以发起 MONLIST 查询请求呢?与 DNS 协议类似,NTP 协议也是基于 UDP 实现的,并且无法识别伪造了来源的请求数据包,使得任何人都可以伪装成需要攻击的目标主机对 NTP 服务器发起查询请求,支持 MONLIST 命令的 NTP 服务器在收到攻击者的数据包后,会将结果通过 UDP 的方式发送到攻击者指定的 IP 地址,造成流量攻击。而 NTP 放大攻击的可怕之处在于,它能够将攻击流量上百倍的放大,在最理想的情况下,可以将攻击的流量放大206倍(来源:https://blog.cloudflare.com/understanding-and-mitigating-ntp-based-ddos-attacks/)。在我后面的测试中,放大的效果也很轻松的达到了100倍以上。

介绍完相关背景,下面开始记录一次简单的模拟攻击流程。

首先第一步是发现网络上开启了 NTP 协议的主机,NTP 协议使用的端口是123端口。所以可以通过扫描123端口来获得一份开启 NTP 的主机列表。使用 Masscan 工具可以快递的完成大量的端口扫描任务。

./masscan -pU:123 -oX ntp_alive.xml --rate 160000 100.0.0.0-220.0.0.0 --exclude 255.255.255.255

其中,–exclude 255.255.255.255 是在扫描量较大的时候要求强制使用的,否则无法发起扫描,会得到如下的错误提示。

FAIL: range too big, need confirmation
 [hint] to prevent acccidents, at least one --exclude must be specified
 [hint] use "--exclude 255.255.255.255" as a simple confirmatio

在进行测试的时候,不需要使用100.0.0.0-220.0.0.0这样巨大的范围,因为这样的话,你的网络流量将会变成下面这样。

masscan_traffic

在 25Mbps 的带宽下,这个扫描请求跑了近三个半小时才完成。绿色部分代表出口流量,蓝色部分代表返回流量。即便是当发出和收到的数据包大小相等的时候,在线的 NTP 主机占比也不到10%,实际上考虑到 NTP 的放大效应,粗略地估计最终捕获到的主机数量所占扫描总量的比例应该在0.1%以内。

我一共对120*2^24=2013265920台主机的123端口进行了扫描,其中包括了一些非公网的 IP 地址,大约是16777216+1048576+65536=17891328。所以一共是1995374592+1(127.0.0.1)个IP。最终得到的扫描结果去重后是263493,大概占到了0.013%。

下一步是删选出可以接受 MONLIST 命令的主机,使用开头链接里博客给出的代码

from scapy.all import *
import thread
#Raw packet data used to request Monlist from NTP server
rawData = "\x17\x00\x03\x2a" + "\x00" * 61
#File containing all IP addresses with NTP port open.
logfile = open('uniq_ntp.txt', 'r')
#Output file used to store all monlist enabled servers
outputFile = open('monlistServers.txt', 'a')
def sniffer():
    #Sniffs incomming network traffic on UDP port 48769, all packets meeting thease requirements run through the analyser function.
    sniffedPacket = sniff(filter="udp port 48769 and dst net your_server_ip", store=0, prn=analyser)

def analyser(packet):
    #If the server responds to the GET_MONLIST command.
    if len(packet) > 200:
        if packet.haslayer(IP):
            print packet.getlayer(IP).src
            #Outputs the IP address to a log file.
            outputFile.write(packet.getlayer(IP).src + '\n')

thread.start_new_thread(sniffer, ())

for address in logfile:
    #Creates a UDP packet with NTP port 123 as the destination and the MON_GETLIST payload.
    send(IP(dst=address)/UDP(sport=48769, dport=123)/Raw(load=rawData))
print 'End'

需要将代码部分中 your_server_ip 替换成进行测试的主机 IP,这样才能接受到返回的 MONLIST 数据包并对主机是否可用进行判断。最终这263493主机中,筛选出了5121台主机。比 Cloudfare 遭受攻击时使用的4529台服务器还要多。

其实在这里是可以进行优化的,因为每台 NTP 主机所在的网络环境和繁忙程度不同,可能一部分 NTP 主机只有为数不多的主机与其进行通信,这样他返回的数据包的大小并没有比请求的数据包高出太多,会拉低整体的放大效果。因此可以稍微修改 analyser 函数,将放大倍数较小的主机抛弃,或者依据返回的大小安排不同的权重,从而达到在有限带宽下获得最大放大倍数的效果。

接下来我们已经有了一份可以利用的 IP 列表并进行测试了。这里我拿自己的 VPS 进行了简单的测试,测试的方法和数据可能不是十分准确,但是应该足以说明这种攻击方式的实现难度和效果了。

iptraf

通过图中的数字可以看到 48769测试端口收到的流量是102050K,发出的流量是1253082,简单的计算后81.44倍的放大效果。实际上放大倍数比这个值要大,因为数据包发出后服务器收到再返回会有一定的延迟,所以实际最后收到的流量应该大于当前实时看到的数字。在我上午进行的测试中,最后的放大倍数在110左右。在没经过任何优化的情况下取得这样的效果,还是很可怕的。具体的攻击测试脚本就不放出来了。以免造成了不希望看到的结果,如果需要测试的话可以在前面的扫描脚本上进行简单的修改就能够得到一个威力强大的攻击工具。如果部署在一定数量的服务器上同时运行,会产生很可观的攻击流量。

相关参考:

https://blog.cloudflare.com/understanding-and-mitigating-ntp-based-ddos-attacks/

https://blog.cloudflare.com/technical-details-behind-a-400gbps-ntp-amplification-ddos-attack/

 

Ubuntu下Shadowsocks服务器搭建与各平台客户端的使用。

0x00 Wiki for Shadowsocks

关于服务端的搭建与客户端的选择,你都可以在 Github 上的 Shadowsocks Wiki 找到相关的内容。这里基本有你想要的一切。

0x01 Setup Shadowsocks on Server

apt-get install python-gevent python-pip

接下来用 pip 安装 Shadowsocks

pip install shadowsocks

安装完成后有两种方式启动 Shadowsocks 的服务,一种是在命令行中指定参数运行,另一种是将配置信息写在文件中,运行时读取配置文件。

以后一种为例,在/etc/下建立文件 shadowsocks.json,并写入以下内容

{
    "server":"0.0.0.0",
    "port_password":{
        "1111":"password1",
        "2222":"password2"
    },
    "timeout":300,
    "method":"aes-256-cfb"
}

这里 port_password 下面可以包含多个端口和密码的组合,方便开启多个端口进行分享。配置好端口和密码之后然后在命令行运行ssserver -c /etc/shadowsocks/config.json -d start即可,关于参数的具体含义可以使用 ssserver – h 查看。-d的作用是在后台运行。如果想要调试或者查看信息可以直接运行

ssserver -c /etc/shadowsocks/config.json

之后可以在终端中看到链接情况。

0x02 Enjoy

Windows

在 Wiki 的 Ports and Clients 中,可以看到在不同的平台下的客户端支持情况。以Windows 为例,下载并运行运行 Shadowsocks.exe 后,在我的电脑上报错提示端口冲突,可能是默认的1080端口被占用导致的,只需在服务器的设置中指派一个空闲代理端口(如1099)即可。

在软件的右键菜单中,有给局域网共享代理的选项,开启此选项后可以给同局域网的其他主机共享连接,从而无须重复运行多个客户端。比如当你使用 VMWare 运行虚拟机时,不需要考虑虚拟机操作系统,可以直接使用主机提供的代理,仅需在配置时正确填写即可。

配置好后,可以安装 Chrome 的扩展 SwitchySharp,进行简单配置如下:

情景模式中选择手动配置,socks v5 代理地址填127.0.0.1 或 运行客户端的主机 ip (如192.168.5.1),端口填写刚才设置的代理端口,如未修改默认为1080。

切换规则中勾选在线规则列表和 AutoProxy 兼容列表,规则列表 URL 可以使用这个地址

http://autoproxy-gfwlist.googlecode.com/svn/trunk/gfwlist.txt

同时在最右侧的情景模式选择刚刚填写好的配置。

按照如上设置,梯子应该可以使用了。在 Chrome 工具栏里点 SwitchySharp 图标并选择自动切换模式,访问 Google 测试一下,应该可以无障碍浏览了。

OS X

Mac下面的客户端可以有多个选择,最直接的可以使用 ShadowsocksX 项目提供的客户端,迫于官方的压力,原作者 @clowwindy 已宣布停止维护,最后版本的客户端可以在 Github 上面下载到。只需要简单的配置服务器、端口、加密方式和密码就可以直接使用了。

OS X 的客户端提供了 PAC 代理和全局代理两种方式,常见的墙外网站已经包含在了 PAC 当中,如果需要自定添加地址到代理列表里,可以编辑用户自定规则。格式的话参考 gfwllist 文件即可,具体的语法规则参考 https://adblockplus.org/filters 上面的说明。我简单举几个例子供大家参考,以便快速添加自定规则。

plugins.jetbrains.com
106.185.1.1
https://www.gerritcodereview.com
*.stackoverflow.com

当然,匹配规则支持正则表达式,不过由于性能原因,应该尽可能少地在 PAC 中使用正则表达式。语法规则应该是使用 Perl 的格式,即 /pattern/ 类型的正则表达式,下面是一个例子,用来匹配 https://edge*.digicert.com (*代表任意数字)的结果

/https:\/\/edge[0-9]+\.digicert\.com/

目前依旧在积极开发的还有 shadowsocks-libev 这个项目,配置文件的方法和服务端类似,给一个例子做参考吧。

{
    "local_address":"0.0.0.0",
    "server":"1.2.3.4",
    "server_port":443,
    "local_port":10010,
    "password":"yourpassword",
    "timeout":300,
    "method":"aes-256-cfb"
}

iOS

iOS 平台可以直接在 App Store 中搜索 ShadowSocks 下载,不过 Shadowsocks 在手机上的应用价值不如 VPN 提供全局代理方便,所以感兴趣的自己下一个玩就好了。

iOS 9 开始,Apple 提供了新的公共 API,预计 iOS 上会涌现出不少类似的应用,不妨关注一下。