在渗透测试中使用fuzz技术

hacker5年前黑客文章1490

前言:本文翻译自sans.org,有删节。在学习sulley的过程中发现中文参考资料很少,所以抛砖引玉翻译一下,希望对学习协议fuzz测试的同学有帮助。本文适合作为学习sulley协议测试过程中参考资料,如果需要学习sulley的使用可以参考其文档。

背景

不久前,我们接到了一个渗透测试的项目。分配任务的时候,团队里有的同学负责无线渗透,有的负责web应用渗透,我分到的任务是对外网开放的 *** 端口进行测试。我的主要测试范围包括:从外部可以访问的系统接口,不包括客户测的漏洞利用,不包括web应用,不包括外部的资源管理类的攻击(比如域名管理类的攻击),不包括账号密码猜解。

前期的扫描中并没有发现很多有意思的漏洞,这也在意料之中。不过Nmap的扫描也发现了一些有意义的目标。如下图所示。目标部署了一个CheckPoint服务器作为远程VPN接入。一共开放了两个端口。

264端口引起了我的兴趣,经过一番查证得知这是CheckPoint VPN 客户端用来通信的一个通道,使用的是一种私有协议,叫做SecuRemote。这个协议是没有加密的。网上能找到一些这个协议存在信息泄露的漏洞,不过我们客户这边都是新版本,不存在那些已知的问题。现在我有的资源就是一些协议资料和大把剩余的任务时间,我决定做一下协议fuzzing。

协议分析

做协议fuzz的首要条件就是要熟悉自己测试的协议。SecuRemote作为私有协议,没有详细的文档,而且我也没发现有人作为逆向分析。所以我得通过抓包自己分析协议。在Google上搜索了一下,找到几个别人抓的 *** 包文件。都是他们抓包让别人帮分析问题的。通过分析这些 *** 包,我分析出了SecuRemote协议的一些细节。

3次握手之后,CheckPoint客户端会发送两个4字节的小包。对于特定的CheckPoint服务器和客户端来说这两个字节看起来是固定的。在客户端发送第二个包之后,服务端返回了一个4字节的包。跟客户端发的之一个包很像。

第四个包发送字符串"securemote"到服务器。最后是一个NULL的结束字节。开始的4个字节看起来是大端存储的后面字符串的长度。因为0x0b刚好是"securemote0"的长度。第四个包发完之后,服务器返回了一个同样的带字符串长度的包,包含了一些服务器的相关信息。根据之前版本的CheckPoint exp,可以获取更多的协议数据。虽然没法简单的识别出每一个比特位代表的意义。但是根据上面的分析,也可以找到一些有意思的模糊测试目标。

四字节的长度标志。任何时候,在协议中发现了标志长度的字节,一定要对它进行模糊测试。几个固定的\x00的字节。减少了我们进行枚举组合的次数。在字符串结尾使用NULL结束符。因为协议提供了长度标志,所以结束符不是必须的。所以测试一下结束符不存在的情况也是不错的选择。

下一步就是准备测试样例,进行模糊测试了。

工具选择

我比较喜欢的智能模糊器是Sulley,一个用python完成的模糊测试框架。不过开发者Pedram已经不再维护Sulley。使用Peach也是一个不错的选择,peach使用XML进行协议描述,相对来说我更喜欢python的语法。在sulley中,我们使用基本的数据类型:字符串区,数字区,分隔符和静态值来描述协议。每一种类型的数据都可以自动突变来进行模糊测试。Sulley也提供了一些高级的功能来描述复杂协议,比如计算数据段长度和进行摘要校检。更多详细的sulley使用 *** 可以参考Sulley的项目文档。下面的脚本是对客户端发送的4个字节进行测试。其中使用了s_byte()这个定义一个字节的函数。将下面的脚本保存到sulley的目录就可以开始测试了。

#!/usr/bin/env python # Fuzzing the initial 4-byte packet from client to CheckPoint VPN server. import time import sys from sulley import * # Time to wait between mutations SLEEP_TIME=0.5 # Time to wait before claiming a host is unresponsive TIMEOUT=3 # number of crashes to observe before skipping the remainder of a group CRASH_THRESHOLD=3 # Initialize the Sulley mutation descriptor s_initialize("SecuRemote-Initial-Packet") s_byte("\x51",full_range=True) s_static("\x00\x00\x00") print "Total mutations: " + str(s_num_mutations()) + "\n" print "Minimum time for execution: " + str(round(((s_num_mutations() * (SLEEP_TIME))/3600),2)) + " hours." print "Press CTRL/C to cancel in ", for i in range(5): print str(5 - i) + " ", sys.stdout.flush() time.sleep(1) # For debugging purposes, uncomment these lines to see Sulley's mutations # in hex dump format #print "Hex dump mutation output:" #while s_mutate(): # print s_hex_dump(s_render()) sess = sessions.session(session_filename="SecuRemote-Initial-Packet.sess", sleep_time=SLEEP_TIME, timeout=TIMEOUT, crash_threshold=CRASH_THRESHOLD) # Tie this session to the SecuRemote-Simple-String fuzzing cases sess.connect(s_get("SecuRemote-Initial-Packet")) # Change this IP address to the target system target = sessions.target("127.0.0.1", 264) # Add the target to the session (can be repeated for multiple targets) sess.add_target(target) # Kick off the fuzzer, monitoring with WebUI on localhost:26000 sess.fuzz()

很不幸的是经过上面的测试,并没有发现有意义的结果。为了更深入的对目标系统进行评估,需要我们的Sulley实现一些协议状态,对协议进行更深入的测试。

对有状态的协议进行测试

在SecuRemote的案例中,从客户端发给VPN服务器的头两个包对我们来说并不够吸引人。客户端交换的第四个包才更有趣,包含了一个字符串和长度值,以及NULL结束符。为了测试VPN服务器对这个位置的畸形包的返回,我们需要在sulley中先模拟前面的两步。然后再发送这一步的畸形包。Sulley中已经提供了相关的接口。在发送每一个畸形包之前,Sulley会检查一个叫做pre_send的回调函数。通过定义我们自己的回调函数,读写socket,完成初始化的头两个4字节包的发送,然后读取服务器的返回。之后再发送我们的测试畸形包。进行测试的脚本如下:

#!/usr/bin/env python from sulley import * SLEEP_TIME=0.5TIMEOUT=3CRASH_THRESHOLD=3# The function Sulley will run prior to sending each mutation.  We leverage # it to setup the target system with the initial packets and response in the # protocol exchange prior to our target packet. def preconn(sock):     sock.send("\x51\x00\x00\x00")    time.sleep(0.5)     sock.send("\x00\x00\x00\x21")     # Set a socket timeout on the recv so we aren&#039;t waiting indefinitely if     # the server crashed from a previous test case.     sock.settimeout(5)    response = sock.recv(4)     print "Setup response: ",    for i in response:         print "%02x" % ord(i),     print s_initialize("SecuRemote-Simple-String") # Create a size field, which is based on the content of the named block # Sulley uses ">" to indicate big-endian values, "<" is little-endian s_size("client-name-string", length=4, endian=">") # This is the block of data used for filling in the s_sizeif s_block_start("client-name-string"):     # "securemote" is the default string     s_string("securemote")     # constant null terminator     s_byte("\x00") s_block_end() sess = sessions.session(session_filename="Securemote-Simple-string.sess", sleep_time=SLEEP_TIME, timeout=TIMEOUT, crash_threshold=CRASH_THRESHOLD) # Call preconn() before each mutation is sent to setup the target sess.pre_send = preconn


sess.connect(s_get("SecuRemote-Simple-String")) target = sessions.target("127.0.0.1", 264) sess.add_target(target) sess.fuzz()

通过这种方式,可以继续对其他的请求包进行测试。

成果

我们一共进行了好几个晚上的fuzz测试,通过记录的数据发现,确实发现了一些小问题,一些畸形的数据包会导致VPN服务重启,达到Dos的效果。客户对我们的这个报告也很认可。

标签: 黑客技术

相关文章

SQLNinja是否适用全部电脑操作系统?

SQLNinja是否适用全部电脑操作系统?

什么叫SQL Ninja? Sql Ninja使客户可以运用应用Microsoft SQL网络服务器做为其数据库查询后端Web程序运行。它致力于在远程控制服务器上获得运作的shell。一旦发觉了SQ...

xss跨站脚本攻击汇集

xss跨站脚本攻击汇集 (1)普通的XSS JavaScript注入 <SCRIPT SRC=http://3w.org/XSS/xss.js></SCRIPT>...

网络黑客专业知识

网络黑客专业知识

很多人想学网络黑客专业知识,却不知道怎样新手入门,在网上的实例教程也太繁杂,新手看过也头痛,那還是我要写网络黑客系列产品基础教程吧,跟着做,你可以黑客入门的。   端口扫描器就是指推送一组...

各种过安全狗一句话木马asp,php,aspx一句话

几个变性的asp–过防火墙 过狗效果都不错 <%Y=request(“x”)%> <%execute(Y)%> < %eval (eval(chr(114)+chr(...

phpweb后台拿shell简单方法

phpweb后台拿shell简单方法

关于phpweb后台拿shell简单方法。   首先登录后台admin.php   登录后台管理系统后,然后把下面的文件保存为xxx.ht...

WinDbg可用以调节核心方式运行内存转储

WinDbg可用以调节核心方式运行内存转储

什么叫WinDbg? WinDbg,像OllyDbg,是由Microsoft派发的Microsoft Windows多功能程序调试。该黑客工具可用以调节客户方式程序运行,驱动软件和电脑操作系统自身,...