EXTENDING BURP PROXY–扩展Burp代理
如果您曾经尝试过攻击web应用程序,您可能使用过Burp Suite执行信息爬取、代理浏览器流量,并执行其他攻击。Burp Suite还允许您创建自己的工具,称为 extensions (扩展)。使用Python、Ruby或纯Java,您可以在Burp GUI中添加面板,并将到Burp Suite中构建自动化技术。
我们将利用这个特性编写一些方便的工具来执行攻击和扩展侦察。第一个扩展将使用从 Burp Proxy 拦截的HTTP请求作为mutation fuzzer(变种模糊测试)的种子在Burp Intruder(入侵者)运行。第二个扩展将与微软必应API通信,以显示我们所有的虚拟主机用相同的IP地址作为目标网站,以及任何子域检测的目标域。最后,我们还将构建一个扩展,从一个目标网站创建一个单词列表,您可以在暴力破解密码攻击中使用到它。
本章假设你以前使用过Burp,知道如何用代理工具捕获请求,以及如何向Burp Intruder发送捕获请求。如果您需要关于如何完成这些任务的教程,请访问 PortSwigger Web Security (http://www.portswigger.net/)来入门。
我们必须承认,当我们第一次开始研究Burp Extender API时,我们花了一些时间来理解它是如何工作的。我们发现这有点令人感到困惑,因为我们是纯Python的用户,而且Java开发经验有限。但我们在Burp网站上发现了许多扩展,它们告诉我们其他人是如何开发扩展的。我们使用先前的技术来帮助我们理解如何开始实现我们自己的代码。本章将涵盖扩展功能的一些基础知识,但我们也将向您展示如何使用API文档作为指南。
安装配置
Burp Suite是在Kali Linux上默认安装的。如果您使用的是其他机器,请从http://www.portswigger.net/下载Burp并配置。
遗憾的是,我们不得不承认,您将需要安装新版的Java。Kali Linux也默认安装了。如果您在不同的平台上,请使用系统的安装方法(如apt、yum或rpm)来获取。接下来,安装 Jython ,一个用Java编写的Python 2的实现。到目前为止,我们所有的代码都使用了Python 3的语法,但在本章中,我们将恢复到Python 2,因为这是Jython所要求的。您可以在官方网站上找到这个 JAR 文件,https://www.jython.org/download.html。选择Jython 2.7独立安装程序。将JAR文件保存到一个容易记住的位置,比如您的Desktop(桌面)。
接下来,双击Kali机器上的Burp图标,或者从命令行运行Burp:
1 | > java -XX:MaxPermSize=1G -jar burpsuite_pro_v1.6.jar |
这将启动Burp,您应该会看到它的图形用户界面(GUI)有很多优质的选项卡,如图6-1所示。
现在让我们将Burp指向Jython解释器。单击 Extender 选项,然后单击 Options 选。在Python Environment部分中,选择Jython JAR文件的位置,如图6-2所示。你可以先不去管其他的选项。我们准备开始编码我们的第一个扩展。让我们动起来!
Burp 模糊测试
在黑客工作的某个时刻,您可能会发现自己攻击的web应用程序或服务不允许您使用传统的web应用程序评估工具。例如,应用程序可能使用了太多的参数,或者它可能以某种方式被混淆,使得执行手动测试过于耗时。我们运行的标准工具不能处理陌生的协议,甚至在很多情况下无法处理JSON,这可能让我们感到难过。这时,您会发现将请求体传递给自定义的fuzzer时,建立一个可靠的HTTP流量基线(包括身份验证cookie)是很有用的。这个fuzzer可以用你选择的任何方式操纵有效载荷。我们将创建世界上最简单的web应用fuzzer作为我们运行的第一个Burp扩展,然后你可以在它里面扩展一些更智能的东西。
Burp有很多工具,你可以在执行web应用程序测试时使用。通常,您将使用代理捕获所有请求,当您看到感兴趣的请求时,将它发送给另一个Burp工具。一种常见的技术是将它们发送到 Repeater (中继器)工具,该工具可以让你重放网络流量,并手动修改任何有趣的地方。在查询参数来执行更多的自动攻击,你可以发送一个请求到 Intruder (入侵者)工具,它试图自动找出应该修改哪些区域的网络流量,然后你可以使用各种攻击,试图引起错误消息或梳理出漏洞。Burp扩展可以以多种方式与Burp工具套件进行交互。在我们的例子中,我们将把额外的功能直接绑定到 Intruder 工具上。
我们的第一想法应该是查看 Burp API 文档,以确定需要扩展哪些 Burp 类,以便编写自定义扩展。您可以通过单击 Extender 选项卡,然后单击 APIs 选项卡来访问此文档。API看起来有点吓人,因为它是特有的Java-y文档。但是请注意,Burp开发人员对每个类都进行了恰当的命名,从而很容易地确定我们想从哪里开始。特别是,因为我们试图在入侵攻击期间模糊测试web请求,我们可能希望关注 IIntruderPayloadGeneratorFactory 和 IIntruderPayloadGenerator 类。让我们看一下 IIntruderPayloadGeneratorFactory 类的文档:
1 | /** |
说明文档的第一部分[1]告诉我们如何正确地在 Burp 中注册我们的扩展。我们将扩展主要的 Burp 类以及 IInteruderPayloadGeneratorFactory 类。接下来,我们看到 Burp 期望在我们的主类中有两个类函数。Burp 将调用 getGeneratorName 类函数[2]来检索扩展的名称,并且希望返回一个字符串。createNewInstance 类函数[3]希望我们返回值为 IInteruderPayloadGenerator 的一个实例,这是我们必须创建的第二个类。
现在让我们完成实际的Python代码来满足这些需求。然后,我们将了解如何添加 IIntruderPayloadGenerator 类。打开一个新的Python文件并命名为 bhp_fuzzer.py ,输入以下代码:
1 | [1] from burp import IBurpExtender |
这个简单的框架概述了我们需要什么来满足第一组需求。我们必须首先导入 IBurpExtender 类[1],这是我们编写的每个扩展的要求。我们通过导入创建 Intruder payload 生成器所必需的类来遵循此要求。接下来,我们定义 BurpExtender 类[2],它扩展了 IBurpExtender 和 IIntruderPayloadGeneratorFactory 类。然后我们使用 registerIntruderPayloadGeneratorFactory 类函数[3]注册我们的类,这样 Intruder 工具就知道我们可以生成payload。接下来,我们实现 getGeneratorName 类函数[4]来简单地返回我们的 payload 生成器的名称。最后,我们实现了 createNewInstance 类函数[5],该函数接收攻击参数并返回一个 IIntruderPayloadGenerator 类的实例,我们称之为 BHPFuzzer 。
让我们看一下 IIntruderPayloadGenerator 类的文档,这样我们就知道要实现什么了:
1 | /** |
很好,现在我们知道我们需要实现基类,它需要有三个类函数。第一个是hasMorePayloads [1],它决定是否继续向Burp Intruder发送变异的请求。我们会用柜台来处理这件事。一旦计数器达到最大值,我们将返回 False 以停止生成模糊测试用例。getNextPayload 函数[2]将从您捕获的HTTP请求中接收原始有效载荷数据。或者,如果您在HTTP请求中选择了多个有效负载区域,您将只收到您计划进行模糊测试的字节部分(稍后将对此进行详细介绍)。这个函数允许我们产生原始的模糊测试用例,然后返回给Burp发送。最后一个类函数,reset [3],如果我们生成一组已知的模糊测试请求,模糊测试器就可以针对 Intruder 标签中指定的每个有效载荷位置迭代这些值。我们的模糊测试功能没有那么繁琐;它将总是随机模糊测试每个HTTP请求。
现在让我们看看当我们在Python中实现它时会是什么样子。将以下代码添加到 bhp_fuzzer.py 的底部:
1 | [1] class BHPFuzzer(IIntruderPayloadGenerator): |
我们首先定义一个 BHPFuzzer 类[1],它扩展了 IIntruderPayloadGenerator 类。我们定义所需的类变量,然后添加 max_payloads [2]和 num_iterations 变量,用于让 Burp 知道我们何时完成模糊测试。当然,如果您愿意,您可以让扩展一直运行下去,但是出于测试目的,我们将设置时间限制。接下来,我们实现 hasMorePayloads 类函数[3],它只是检查我们是否已经达到模糊测试迭代的最大次数。您可以通过始终返回 True 来使它可以持续运行扩展。getNextPayload 类函数[4]接收原始的HTTP有效载荷,我们将在这里进行模糊化测试。 current_payload 变量以字节数组的形式返回,因此我们将其转换为字符串[5],然后将其传递给 mutate_payload 模糊测试函数[6]。然后,我们增加 num_iterations 变量[7]并返回变异后的有效载荷。我们的最后一个函数是 reset 函数,它什么也不做就返回。
现在让我们写一个世界上最简单的模糊测试函数,你可以根据自己的想法来修改。例如,这个函数知道当前有效数据载荷的值,所以如果您有一个棘手的协议需要一些特殊的东西,比如CRC校验和或长度字段,您可以在返回之前在这个函数中执行这些计算。将以下代码添加到 bhp_fuzzer.py 的 BHPFuzzer 类中:
1 | def mutate_payload(self,original_payload): |
首先,我们获取有效载荷 payload ,并将其分成两个随机长度的块, front 和 back [1]。然后,我们从三个变异器中随机挑选:一个简单的SQL注入测试,它在 front 块[2]的末尾添加一个单引号;一个跨站点脚本(XSS)测试,它在 front 块[3]的末尾添加一个脚本标签;以及最后一个变异器,它从原始有效负载 payload 中选择一个随机块,随机重复多次,并将结果添加到 front 块[4]的末尾。然后,我们将 back 块添加到修改后的 front 块,以组成变异后的有效载荷[5]。我们现在有了我们可用的 Burp Intruder 扩展。让我们看看如何加载它。
Kicking the Tires
首先,我们必须加载扩展并确保它不会包含错误。单击 Burp 中的 Extender 选项卡,然后单击 Add 按钮。应该会出现一个屏幕,让你把 Burp 指向 fuzzer 。请确保您设置了与图6-3所示相同的选项。
单击 Next ,这时Burp应该已经开始加载扩展了。如果有错误,请单击 Errors 选项卡,调试错误,然后单击 Close 。您的扩展器屏幕现在应该如图6-4所示。
如您所见,我们的扩展已经被加载,Burp已经识别了注册的 Intruder payload 生成器。我们现在准备在真正的攻击中利用扩展。确保您的网络浏览器设置为使用 Burp Proxy 作为端口8080上的本地主机代理。现在让我们开始攻击与第5章相同的 Acunetix web应用程序。只需访问至http://testphp.vulnweb.com/。
例如,作者使用他们网站上的小搜索栏提交了对字符串“test”的搜索。图6-5显示了如何在 Proxy 菜单的HTTP历史标签中看到这个请求。右键单击请求,将其发送给 Intruder 。
现在切换到 Intruder 选项,并单击 Positions 选项。将出现一个屏幕,突出显示每个查询参数。这是 Burp 识别我们应该模糊测试的点的方法。如果您愿意,您可以尝试移动 payload 分隔符或者选择整个有效负载来进行模糊测试,但是现在,让Burp决定模糊测试什么部分。为了清楚起见,请参见图6-6,它显示了有效负载突出显示是如何起效的。
现在单击 Payloads 选项。在此屏幕中,单击 Payload type 下拉列表,然后选择 Extension-generated 。在 payload 选项部分,单击 Select generator 按钮,并从下拉列表中选择 BHP Payload
Generator 。您的 Payload 屏幕窗口现在应该如图6-7所示。
现在我们准备发送请求。在 Burp 菜单栏的顶部,单击 Intruder ,然后选择 Start Attack 。 Burp 应该会开始发送用于模糊测试的请求,很快你就能查看到结果。当作者运行fuzzer时,我们收到了如图6-8所示的输出。
从对请求7的响应中的粗体警告可以看出,我们发现了一个SQL注入漏洞。
即使我们构建这个fuzzer只是为了演示,你也会惊讶于它对于让web应用程序输出错误、公开应用程序路径或生成许多其他扫描器可能会错过的行为的有效性。最重要的是,我们设法让我们的定制扩展来协同 Burp 的 Intruder 攻击。现在让我们创建一个扩展,它将帮助我们对web服务器执行扩展侦察。
Burp中利用Bing
一个web服务器服务多个web应用程序并不少见,其中一些您可能并不知道。如果您正在攻击服务器,您应该尽最大努力发现其他主机名,因为它们可能会让您更容易获得 shell 。在你的目标同一台机器上发现不安全的web应用程序,甚至开发资源,并不罕见。微软的 Bing (必应)搜索引擎具有搜索功能,允许您使用 “IP” 搜索修饰符查询必应在单个IP地址上找到的所有网站。如果您使用 “domain” 搜索修饰符,Bing还会告诉您给定域的所有子域。
现在,我们可以使用 scraper 将这些查询提交给必应,然后获得结果中的HTML,但这不是好的习惯方式(也违反了大多数搜索引擎的使用条款)。为了避免麻烦,我们将改为使用 Bing API (必应应用编程接口)以编程方式提交这些查询,并自己解析结果。(访问https://www.microsoft.com/en-us/bing/apis/bing-web-search-api/使用您自己的免费必应应用编程接口密钥进行设置。)除了一个上下文菜单,我们不会用这个扩展实现任何花哨的 Burp 图形用户界面;我们只需在每次运行查询时将结果输出到 Burp 中,任何检测到的 Burp 目标范围的URL都会被自动添加。
(笔者注:Web Scraper,一个轻量的数据爬虫利器。)
因为我们已经向您介绍了如何阅读 Burp API 文档并将其翻译成 Python ,所以现在让我们直接进入代码。打开 bhp_bing.py 并输入以下内容:
1 | from burp import IBurpExtender |
这是我们的Bing扩展的第一部分。请确保将您的必应应用编程接口密钥粘贴到位置[1]。你每月可以免费搜索1000次。我们首先定义一个 BurpExtender 类[2],它实现了标准的 IBurpExtender 接口,以及 IContextMenuFactory ,它允许我们在用户右键单击Burp中的请求时提供一个上下文菜单。该菜单将显示 “Send to Bing” 选项。我们注册一个菜单处理器[3],它将判定用户点击了哪个站点,使我们能够构建我们的必应查询。然后我们设置一个 createMenuItem 函数,它将接收一个 IContextMenuInvocation 对象,并使用它来确定用户选择了哪个HTTP请求。最后一步是渲染菜单项,并用 bing_menu 函数[4]处理点击事件。
现在,让我们执行Bing查询,输出结果,并将所有发现的虚拟主机添加到 Burp 的目标范围:
1 | def bing_menu(self,event): |
当用户单击我们定义的上下文菜单项时, bing_menu 函数会被触发。我们检索突出显示的HTTP请求[1]。然后,我们检索每个请求的主机部分,并将其发送到 bing_search 函数进行进一步处理。bing_search 函数首先确定主机部分是IP地址还是主机名[2]。然后,我们向 Bing 查询与主机具有相同IP地址的所有虚拟主机[3]。如果我们的扩展也收到了一个域,那么我们会对 Bing 反馈的所有子域进行二次搜索[4]。
现在让我们安装所需的管道,以便将请求发送给 Bing ,并使用 Burp 的 HTTP API 解析结果。在 BurpExtender 类中添加以下代码:
1 | def bing_query(self,bing_query_string): |
Burp 的 HTTP API 要求我们在发送之前将整个HTTP请求构建为一个字符串。我们还需要添加我们的 Bing API key (必应应用编程接口密钥)来进行 API 调用[1]。然后,我们向微软服务器发送HTTP请求[2]。当响应返回时,我们分离出报文头[3],然后将其传递给我们的 JSON 解析器[4]。对于每组结果,我们输出一些关于我们发现的站点的信息。如果发现的站点不在 Burp 的目标范围内[6],我们会自动把它添加进去。
在这样做的过程中,我们将 Jython API 和纯Python混合在一个 Burp 扩展中。这应该有助于我们在攻击特定目标时进行额外的侦察工作。我们来试一试吧。
Kicking the Tires
为使 Bing 搜索扩展正常工作,请使用与我们在模糊测试扩展中相同的步骤。加载后,浏览URL:http://testphp.vulnweb.com/。然后右键单击您刚刚发出的 GET 请求。如果扩展加载正确,您应该会看到显示菜单选项 Send to Bing ,如图6-9所示。
当你点击这个菜单选项时,你应该可以开始看到 Bing 的返回结果,如图6-10所示。您得到的结果取决于您在加载扩展时选择的输出。
如果您在Burp中单击 Target 选项并选择 Scope ,您应该会看到新的项目自动添加到目标范围中,如图6-11所示。目标范围会将攻击、爬取和扫描等活动限制于已定义的主机。
Turning Website Content into Password Gold–将网站内容变成密码黄金
很多时候,安全性归结为一点:用户密码。这是令人悲伤但十分真实的。更糟糕的是,当涉及到web应用程序,尤其是定制应用程序中,发现在一定次数的身份验证尝试失败后,他们没有将用户锁定在自己的帐户之外是非常常见的。在其他情况下,他们不会强制使用强密码。在这种情况下,像上一章那样的在线密码猜测的会话可能只是进入网站的入场券。
在线密码猜测的诀窍是获得正确的单词列表。如果你的时间很紧张,你总不能测试1000万个这样量级的密码,所以你需要能够创建一个针对有问题的网站的单词列表。当然,Kali Linux 中有一些脚本可以抓取网站,并根据网站内容生成单词列表。但是如果你已经用 Burp 扫描了网站,为什么仅仅为了生成一个单词列表就要发送更多的流量呢?另外,这些脚本通常需要记住大量的命令行参数。If you’re anything like us, you’ve already memorized enough command line arguments to impress your friends, so let’s make Burp do the heavy lifting.(笔者注:直译为:如果你和我们一样,你已经记住了足够多的命令行参数来打动你的朋友,所以让我们用 Burp 来完成这个重任。但是感觉有点不对,感觉这里朋友是不是指代可能实践中有同时合作的伙伴。结合上下文译为:如果你不能像我们一样记住这些命令行参数并说服伙伴一同使用,那我们还是让 Burp 来完成这项重任吧。)
打开 bhp_wordlist.py ,敲出下面的代码:
1 | from burp import IBurpExtender |
上面的代码您现在应该很熟悉了。我们开始先导入所需的模块。一个辅助的类 TagStripper 稍后将帮助我们从要处理的HTTP响应中剥离出HTML标签。它的 handle_data 函数将页面文本[1]存储在一个成员变量中。我们还定义了 handle_comment 函数,因为我们希望将存储在开发人员注释中的单词也添加到密码列表中。以同一种方式, handle_comment 只是换了 handle_data 函数名称[2] (以防我们想要改变以后处理页面文本的方式)。
strip 函数将HTML代码发送给基类 HTMLParser ,并返回页面文本结果[3],这将在以后派上用场。其余部分几乎与我们刚刚完成的 bhp_bing.py 脚本的开头完全相同。同样,目标是在 Burp UI (用户界面)中创建一个上下文菜单项。这里唯一的新东西是我们将单词列表存储在一个 set (集合)中,这确保了我们不会在运行过程中引入重复的单词。我们用每个人最喜欢的密码, password [4]来初始化这个集合,只是为了确保它最终出现在我们的最终列表中。
现在,让我们添加一些逻辑功能,以从 Burp 获取选定的HTTP流量,并将其转换为基本单词列表:
1 | def wordlist_menu(self,event): |
我们的第一项工作是定义 wordlist_menu 函数,让它负责处理菜单点击。它保存响应主机的名称[1]以备后用,然后检索 HTTP 响应并将其提供给 get_words 函数[2]。 get_words 检查响应报文头,以确保我们只处理基于文本的响应[3]。 TagStripper 类[4]从页面文本的其余部分剥离 HTML 代码。我们使用正则表达式来查找所有以字母字符开头并跟随如正则表达式 \w{2,} 所指定的两个或多个 “word” 的字符的单词[5]。我们以小写形式保存匹配该模式的单词到 wordlist [6]。
(笔者注:\w:匹配非特殊字符,即a-z、A-Z、0-9、_、汉字)
现在,让我们优化一下脚本,让它能够修改和显示捕获的单词列表:
1 | def mangle(self, word): |
非常好!mangle 函数接受一个基础单词,并根据一些常见的密码创建策略将其转换为多个密码猜测。在这个简单的例子中,我们创建了一个后缀列表来附加在基础单词的末尾,包括当前年份[1]。接下来,我们循环遍历每个后缀,并将其添加到基础单词中[2],以创建唯一的密码尝试。我们用大写的基础词做了另一个循环,以获得好的效果。在 display_wordlist 函数中,我们打印了一个 “John the Ripper” 样式的注释[3]来提醒我们使用了哪些站点来生成这个单词列表。然后我们修改每个基础词并打印修改结果。现在是时候上场试一下了。
Kicking the Tires
单击 Burp 中的 Extender 选项,单击 Add 按钮,然后使用与我们之前的扩展相同的步骤来使 Wordlist 扩展工作。
在 Dashboard (仪表盘)选项中,选择 New live task (新建实时任务),如图6-12所示。
当对话框出现时,选择 Add all links observed in traffic (添加流量中嗅探到的所有链接),如图6-13所示,然后单击 OK 。
配置完扫描后,浏览器访问 http://testphp.vulnweb.com/ 并运行脚本。一旦 Burp 访问了目标站点上的所有链接,在 Target 选项的右上角窗格中选择所有请求,右键单击它们以调出上下文菜单,然后选择 Create Wordlist ,如图6-14所示。
现在检查扩展的 Output 标签。实际上,我们将它的输出保存到一个文件中,但是为了演示的目的,我们在 Burp 中显示单词列表,如图6-15所示。
现在,您可以将此列表反馈给 Burp Intruder ,以执行实际的密码猜测攻击。
我们现在已经通过生成我们自己的攻击 payload ,以及构建与 Burp UI 交互的扩展,演示了Burp API的一个小子集。在渗透测试过程中,您经常会遇到特定的问题或自动化的需求,而 Burp Extender API 提供了一个极好的接口来为您的代码提供方向,或者至少让您不需要不断地将捕获的数据从 Burp 复制并粘贴到另一个工具中。