转自:http://drops.wooyun.org/tips/4715

NTP 漏洞相关的文章在 Drops 已经有过了,并且不止一篇,之所以又翻译了这一片文章,是觉得文章的整体思路很不错,希望对看这篇文章的你有所帮助。

BTW:本文翻译比较随意,但是并没有破坏原文含义。

0x00 简介

NTP 放大攻击其实就是 DDoS 的一种。通过 NTP 服务器,可以把很小的请求变成很大的响应,这些响应可以直接指向到受害者的电脑。

NTP 放大使用的是 MONLIST 命令。MONLIST 命令会让 NTP 服务器返回使用 NTP 服务的最后 600 个 客户端 IP。通过一个有伪造源地址的 NTP 请求,NTP 服务器会将响应返回给那个伪造的 IP 地址。你可以想象,如果我们伪造受害者的 IP 对大量的 NTP 服务器发送 MONLIST 请求,这将形成 DOS 攻击。

显然我们不能容忍这样做,但我比较有兴趣的是去发现有多少 NTP 服务器能够发大这种数据。他不是什么新的攻击,所以你希望不会有太多的 NTP 服务器支持 MONLIST 命令。

0x01 如何去做

为了确定有多少 NTP 服务器响应 MONLIST 请求,我会通过两个独立的部分去做。

第一部分

在第一部分,通过 masscan 工具,对 UDP 的 123 端口进行扫描,扫描结果保存到 ntp.xml 文件中,命令如下:

./masscan -pU:123 -oX ntp.xml --rate 160000 101.0.0.0-120.0.0.0

由于我的服务器带宽比较小,如果选择全网扫描,肯定会较慢,所以我随机的选择了一个 IP 段:101.0.0.0-120.0.0.0。

扫描完成后,会把 UDP 123 端口开放的设备保存在 XML 文件中。不知道什么原因,我的扫描结果 xml 文件中包含了许多重复的记录,我写了一个 python 脚本用于处理这些重复的记录,去重后的结果会保存到 port123.txt 文件中。

代码如下:

from lxml import etree

port = None

address = None

parsedServers = []

#Opens the file used to store single enteries.

outputFile = open('port123.txt', 'a')

#Iterates through the masscan XML file.

for event, element in etree.iterparse('ntp.xml', tag="host"):

for child in element:

if child.tag == 'address':

#Assigns the current iterations address to the address variable.

address = child.attrib['addr']

if child.tag == 'ports':

for a in child:

#Assigns the current iterations port to the port variable.

port = a.attrib['portid']

#is both port and IP address are present.

if port > 1 and address > 1:

#If the IP hasnt yet been added to the output file.

if address not in parsedServers:

print address

#Write the IP address to the file.

outputFile.write(address + '\n')

#write the IP to the parsedServers list

parsedServers.append(address)

port = None

address = None

element.clear()

outputFile.close()

print 'End'

这个脚本运行后,port123.txt 文件中包含开放 UDP 123 端口并且去重后的所有 IP。

第二部分

在第二部分中我们主要来确定 port123.txt 中的 IP 的 123 端口是否运行 NTP 服务,如果是 NTP 服务,是否响应 MONLIST 请求。

我写了一个 python 脚本来实现上面的需求,主要用到 scapy 库。

首先我导入我脚本需要的所有库,并且定义一些变量:

from scapy.all import *

import thread

然后我构造了发给 NTP 服务器的 MONLIST 请求的原始数据。在这个过程中我发现请求的数据必须达到一定的值服务器才会返回数据,具体原因不清楚。只要请求超过 60 字节,服务器就会返回数据,因此我下面的代码中有 61 个\x00 字符。

rawData = "\x17\x00\x03\x2a" + "\x00" * 61

在 python 脚本中我打开了两个文件:port123.txt 是 masscan 发现的开放 UDP 123 端口的 IP 地址,monlistServers.txt 是用于保存支持 MONLIST 命令的 NTP 服务器。

logfile = open('port123.txt', 'r')

outputFile = open('monlistServers.txt', 'a')

然后我定义了一个叫 sniffer 的函数,这个函数的作用主要就是监听在 48769 端口上的 UDP 数据,这个端口是发送 MONLIST 请求的源端口,只要任何 NTP 服务器响应 MONLIST 请求,都将响应到这个端口上。目标网络地址是你的 IP 地址,NTP 服务器的响应将返回到这个 IP 上,在本文中,我讲设置这个 IP 为:99.99.99.99。

def sniffer():

sniffedPacket = sniff(filter="udp port 48769 and dst net 99.99.99.99", store=0, prn=analyser)

任何符合 UDP 端口 48769 的数据包都会被捕获到,并且会放到 analyser 函数中,稍后我讲介绍 analyser 函数。

sniffer 定义好了,并且会在线程中执行,同时会放到后台运行。

thread.start_new_thread(sniffer, ())

接下来,我遍历 masscan 发现的所有 IP 地址。对于每个 IP 地址我都会发送一个源端口为 48769,目的端口是 123 的 UDP 数据包,数据包就是我们前面构造的 rawData。实际上这个就是对所有的 IP 发送 MONLIST 请求。

for address in logfile:

send(IP(dst=address)/UDP(sport=48769, dport=123)/Raw(load=rawData))

只 要有 NTP 服务器响应 MONLIST 请求,这个响应数据将会被运行在线程中 sniffer 抓取,sniffer 会把所有接收到的数据放到 analyser 函数中处理,而 analyser 函数会检查捕获到的数据包,并且确定包的大小超过 200 字节。在实际的测试中我发现,如果 NTP 服务器不响应 MONLIST 请求,响应包的大小通常在 60-90 字节,或者不存在响应包。如果 NTP 服务器响应 MONLIST 请求,响应包就会比较大,一般包含多个响应包,通常每个包为 480 字节。所以只要检查到所接收的响应包是大于 200 字节就表示该 NTP 服务器支持 MONLIST 请求。最后我们会把响应包大约 200 字节的 IP 地址写入到 outputFile。

if len(packet) > 200:

if packet.haslayer(IP):

outputFile.write(packet.getlayer(IP).src + '\n')

通常如 果 NTP 服务器支持 MONLIST 请求,那么它将会返回多个数据包用于包含使用 NTP 服务的 IP 地址。因为 sniffer 会捕捉所有符合条件的数据包,所以 outputFile 文件中将会有许多重复的数据。我通过 sort 和 uniq 命令来对 outputFile 文件进行去重。

sort monlistServers.txt | uniq

这个结果文件中包含所有支持 MONLIST 命令的 NTP 服务器。

完整的 python 脚本如下:

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('output.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 99.99.99.99", 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'

0x02 最后

正如我前面所提到的,我的带宽实在是太小了,所以我只能够选择一个 IP 段:101.0.0.0-120.0.0.0。如果我的数学不是体育老师教的话,那么我应该不会算错,这个 IP 段内包含 318,767,104 个 IP 地址(19256256)。

masscan 发现 253,994 个设备开放了 UDP 的 123 端口,占了扫描 IP 的 0.08%。

在 253,994 个设备中,支持 MONLIST 命令的设备有 7005 个,占比为 2.76%。

如果按照这个比例进行换算的话,那个整个互联网上将有 91,000 台开启 MONLIST 功能的 NTP 服务器。

over!

linux ntp攻击python脚本,(转)如何发现 NTP 放大攻击漏洞相关推荐

  1. linux 定时运行脚本_教你如何在Linux下让Python脚本自启动和定时启动

    本文简单介绍如何在Linux下设置Python脚本自启动和定时启动. 一.Python开机自动运行 假如Python自启动脚本为auto.py.那么用root权限编辑以下文件: sudo vim /e ...

  2. linux定时执行python脚本_linux定时执行python脚本的方法以及失败不执行的处理方法...

    首页,linux定时任务用到的是crontab,我们来看一下crontab如何使用 crontab-1[user]-列出用户目前的crontab. crontab-e[user]-编辑用户目前的cro ...

  3. linux后台运行python脚本

    &符号 这两天要在一直运行一个Python脚本,当然就想到了在命令后面加&符号 $ python /data/python/server.py >python.log & ...

  4. linux运行脚本文件python,Python脚本:Linux自动化执行Python脚本

    1.环境及其工具: ubuntu 16.04 python2.7(自带) pip2.7(安装) virtualenv(安装) crontab (自带) 2.pip2.7安装 (1)尝试使用 sudo ...

  5. linux运行python脚本语句,如何在Linux下运行Python脚本

    1.使用python的IDEL运行python 如果你的Linux安装了python,Ctrl+Alt+T打开Terminal后输入指令:python,会出现>>>,这个时候就可以在 ...

  6. linux开机自启动python脚本_Linux下Python脚本自启动和定时启动的详细步骤

    一.Python开机自动运行 假如Python自启动脚本为 auto.py .那么用root权限编辑以下文件: sudo vim /etc/rc.local 如果没有 rc.local 请看 这篇文章 ...

  7. Linux下设置python脚本文件为服务

    (最简单的方式nohup python xxx.py) ------------------------------------------------------------------------ ...

  8. Linux定时运行Python脚本

    Linux–CentOS定时运行Python脚本 最近公司的项目开始进入运营阶段,数据库的记录也开始多了起来.看了postgresql的自动清理好像不太符合需求,暂定对接口请求记录表保留3个月内的记录 ...

  9. python linux上屏幕截图_在Linux上通过Python脚本拍摄屏幕截图

    我想通过python脚本截取屏幕截图,并毫不干扰地保存它. 我只对Linux解决方案感兴趣,应该支持任何基于X的环境. 任何原因您不能使用scrot? 很想检查以下建议方法的性能. 新链接:manpa ...

最新文章

  1. c++内存对齐的规则
  2. 发展农业对话国际农民丰收节贸易会 菲律宾学中国还是印度?
  3. How to trouble shoot if there is no entityset available when creating a tile
  4. 【算法竞赛学习】数字中国创新大赛智慧海洋建设-Task1地理数据分析常用工具
  5. python全栈工程师能接到私活么_Python全栈工程师(包、模块 的导入)
  6. bash: shasum: command not found
  7. .Net中委托的协变和逆变详解
  8. GitHub标星近10万:只需5秒音源就能实时“克隆”你的声音!
  9. Java : 实体类不能序列化异常
  10. css_02 | CSS——CSS 选择器详解
  11. 1.海康威视-在浏览器中摄像头激活
  12. 米粒搜---团购信息搜索软件 Android平台
  13. DevOps定义基础入门及历史
  14. win10无法修改mac地址_Oops,手机MAC地址也可以随机了
  15. java发送http请求 utf8_Java 发送http请求(get、post)的示例
  16. WireShark基本使用(7)第 7 章 高级
  17. nu.xom:Attribute
  18. vue.js+muse-ui制作在线简历编辑
  19. “为了交项目干杯”对“那周余嘉熊掌将得队”、“男上加男,强人所男”的Beta产品测试报告...
  20. 诗词创作[2] 赠春

热门文章

  1. 《一万年以后》一段充满癫狂想象力的奇幻之旅
  2. 对现在糟糕的自己剖析
  3. 20200415阿里笔试 Python3
  4. 【2023软考】信息系统监理师与系统集成项目管理工程师哪个更好考?
  5. 二维码制作(QRCode)
  6. 【linux应用开发】
  7. windows 配置host
  8. Python判断时间
  9. 刨根问底,5问分析法
  10. Unity中手动压缩图片 修改图片分辨率