# 第 6 章:使用 Python 评估 Web 应用程序 与基础设施评估相比,Web 应用程序评估或 Web 应用程序渗透测试是不同的动物。这也取决于评估的目标。与移动应用程序评估一样,Web 应用程序评估也经常以错误的方式进行。网络或基础设施渗透测试已经成熟,客户对结果的预期也越来越明智。对于 web 应用程序或移动应用程序评估,这并不总是正确的。有多种工具可用于分析应用程序的漏洞,包括 Metasploit、Nexpose、Nessus、Core Impact、WebInspect、AppScan、Acunetix 等。对于 web 应用程序漏洞评估,有些方法要比其他方法好得多,但它们都有一些共同点。其中之一是,它们不能替代渗透测试。 这些工具有自己的位置,但取决于参与的范围和试图识别的弱点,它们往往达不到要求。WebInspect、AppScan 和 Acunetix 等特定产品适用于识别潜在漏洞,特别是在**系统开发生命周期**(**SDLC**期间),但它们会报告误报并错过复杂的多阶段漏洞利用。每个工具都有它的位置,但即使在使用这些工具时,相关风险也可能被忽略。 现在这枚硬币有另一面;渗透测试不会发现 web 应用程序中的每一个漏洞,但无论如何它也不会这么做。Web 应用程序渗透测试的重点是识别系统开发问题、过程和关键风险。因此,可以快速修复已识别的漏洞,但具体的弱点指向更大的安全实践,应该在整个 SDLC 中加以解决。 大多数应用渗透测试的重点应至少包括以下部分(如果不是全部): * 分析当前**开放式 Web 应用安全项目**(**OWASP**)前 10 个漏洞。 * 识别在某些位置泄漏数据或留下残余数据痕迹的应用程序区域,包括未记录或未链接的页面或目录。这也称为数据永久性。 * 恶意参与者可能从一种帐户类型横向移动到另一种帐户类型或升级权限的方式。 * 应用程序可为攻击者提供注入或操作数据手段的区域。 * 应用程序可以创建**拒绝服务**(**拒绝服务**)情况的方式,但这通常是在没有利用或明确验证的情况下完成的,以防止对业务运营造成任何影响。 * 最后,攻击者如何渗透内部网络。 考虑所有这些组件,您会发现应用程序扫描工具的使用将无法识别所有这些组件。此外,渗透测试应具有特定的目标和目的,以确定相关概念证明的指标和问题。否则,如果评估人员试图根据复杂性识别应用程序中的所有漏洞,则可能需要很长时间。 客户应审查这些建议和应用程序代码。客户应补救评估员强调的所有指定位置,然后跟进并确定评估员在该时间段内可能未发现的其他弱点。一旦完成 SDLC,应更新 SDLC,以便在开发过程中纠正未来的弱点。最后,应用程序越复杂,开发人员参与的越多;因此,在测试时,请注意漏洞热映射。 就像渗透测试人员一样,开发人员可以拥有不同级别的技能,如果组织的 SDLC 不是很成熟,那么每个开发团队在应用程序领域的漏洞级别可能会有所不同。我们称之为漏洞热映射,在该映射中,应用程序中的某些位置的漏洞比其他位置的漏洞多。这通常意味着开发人员或开发人员不具备在与其他团队相同的级别交付产品的必要技能。存在更多漏洞的区域也可能表明存在更严重的漏洞。因此,如果您注意到某个应用程序的某个特定区域像圣诞树一样亮起,并且存在弱点,请提升您正在查看的攻击向量的类型。 根据参与的范围,开始关注可能会破坏安全边界的漏洞,例如**结构化查询语言注入**(**SQLi**)、**远程**或**本地文件包含**(**RFI**/**LFI**),非有效重定向和转发,不受限制的文件上载,最后是不安全的直接对象引用。这些漏洞中的每一个都与应用程序的请求和响应模型的操作有关。 应用程序通常使用请求和响应模型,通过 cookie 跟踪特定的用户会话数据。因此,在编写脚本时,您必须在一个方法中构建脚本,以处理发送数据、接收数据以及解析结果以了解预期或不预期的内容。然后,您可以创建后续请求以进一步前进。 # 识别实时应用程序与开放端口 当评估大型环境以包括**内容交付网络**(**CDN**)时,您会发现您将识别数百个开放的 web 端口。大多数这些 web 端口都没有在这些端口上部署活动的 web 应用程序,因此您需要访问每个页面或请求 web 页面标题。只需对站点的`http://`和`https://`版本执行`HEAD`请求即可。使用`urllib2`的 Python 脚本可以非常轻松地执行此操作。此脚本只需获取主机**互联网协议**(**IP**地址)的文件,然后构建创建相关**统一资源定位器**(**URL**的字符串。在请求每个站点时,如果它收到成功的请求,则数据将写入文件: ``` #!/usr/bin/env python import urllib2, argparse, sys defhost_test(filename): file = "headrequests.log" bufsize = 0 e = open(file, 'a', bufsize) print("[*] Reading file %s") % (file) with open(filename) as f: hostlist = f.readlines() for host in hostlist: print("[*] Testing %s") % (str(host)) target = "http://" + host target_secure = "https://" + host try: request = urllib2.Request(target) request.get_method = lambda : 'HEAD' response = urllib2.urlopen(request) except: print("[-] No web server at %s") % (str(target)) response = None if response != None: print("[*] Response from %s") % (str(target)) print(response.info()) details = response.info() e.write(str(details)) try: response_secure = urllib2.urlopen(request_secure) request_secure.get_method = lambda : 'HEAD' response_secure = urllib2.urlopen(request_secure) except: print("[-] No web server at %s") % (str(target_secure)) response_secure = None if response_secure != None: print("[*] Response from %s") % (str(target_secure)) print(response_secure.info()) details = response_secure.info() e.write(str(details)) e.close() ``` 以下屏幕截图显示了此脚本在运行时在屏幕上的输出: ![Identifying live applications versus open ports](graphics/B04315_06_01.jpg) ### 注 此脚本的完整版本可在[找到 https://raw.githubusercontent.com/funkandwagnalls/pythonpentest/master/headrequest.py](https://raw.githubusercontent.com/funkandwagnalls/pythonpentest/master/headrequest.py) 。如果需要,可以轻松修改此脚本以执行后续任务。已有`PeppingTom`和`EyeWitness`等工具可以比脚本更好地完成此活动,但了解如何构建此基本脚本将允许您在必要时包含其他分析。 # 用 Python 识别隐藏文件和目录 当我们访问已识别 IP 地址的站点时,我们看到它是**该死的易受攻击的 Web 应用程序**(**DVWA**)。我们还看到,它已将默认登录页的详细信息附加到我们的初始请求中。这意味着我们从`http://192.168.195.145/dvwa/login.php`站点开始,如以下屏幕截图所示: ![Identifying hidden files and directories with Python](graphics/B04315_06_02.jpg) 我们现在有了一个测试的起始位置,使用这些详细信息,我们可以查找隐藏的目录和文件。让我们修改上一个脚本以自动查找隐藏的文件或目录。 最好的方法是从我们所在站点的基本目录开始。您可以升级,但在多个网站所在的环境中,您最终可能会跳出范围。因此,在以这种方式进行攻击之前,请先了解您的环境。如您所见,该脚本在目录和文件名文件中运行,并将它们附加到目标站点。然后,我们会报告它们是否有效: ``` #!/usr/bin/env python import urllib2, argparse, sys defhost_test(filename, host): file = "headrequests.log" bufsize = 0 e = open(file, 'a', bufsize) print("[*] Reading file %s") % (file) with open(filename) as f: locations = f.readlines() for item in locations: target = host + "/" + item try: request = urllib2.Request(target) request.get_method = lambda : 'GET' response = urllib2.urlopen(request) except: print("[-] %s is invalid") % (str(target.rstrip('\n'))) response = None if response != None: print("[+] %s is valid") % (str(target.rstrip('\n'))) details = response.info() e.write(str(details)) e.close() ``` 知道了这一点,我们可以加载四个最常见的隐藏或未链接的网站所在位置。它们是`admin`、`dashboard`、`robots.txt`和`config`。使用这些数据,当我们运行脚本时,我们确定了两个可行的位置,如下面的屏幕截图所示。`Robots.txt`很好,但`config`通常意味着如果权限不正确或文件未被 web 服务器使用,我们可以找到用户名和密码。 ![Identifying hidden files and directories with Python](graphics/B04315_06_03.jpg) 正如您在这里看到的,我们得到了目录内容的列表: ![Identifying hidden files and directories with Python](graphics/B04315_06_04.jpg) 不幸的是,当您打开`config.inc.php`文件时,如此屏幕截图所示,没有显示任何内容: ![Identifying hidden files and directories with Python](graphics/B04315_06_05.jpg) 管理员和支持人员并不总是了解他们的某些行为的影响。当从`config`文件进行备份时,如果这些文件未被积极使用,或者权限设置不正确,您通常可以通过浏览器读取它们。Linux 系统上的备份文件由尾部的`~`表示。我们知道它是 Linux 系统,因为之前的`HEAD`请求表明它是 Ubuntu 主机。 ### 提示 请记住,头文件可以由管理员和安全工具进行操作,因此不应将其视为确定的信息源。 正如您在下面的屏幕截图中所看到的,请求打开了一个`config`文件,为我们提供访问数据库服务器所需的详细信息,我们可以从中提取关键数据: ![Identifying hidden files and directories with Python](graphics/B04315_06_06.jpg) 作为一名渗透测试人员,您必须高效地利用您的时间,如前所述,这是成功渗透测试的障碍之一。这意味着,当我们研究数据库的内容时,我们还可以设置一些自动化工具。一个简单的测试就是使用入侵者使用 Burp 套件。 ### 注 `dirtester.py`脚本的完整版本可在[找到 https://raw.githubusercontent.com/funkandwagnalls/pythonpentest/master/dirtester.py](https://raw.githubusercontent.com/funkandwagnalls/pythonpentest/master/dirtester.py) 。 # 使用 Burp 套件的凭据攻击 从[下载打嗝套件免费版 http://portswigger.net/burp/download.html](http://portswigger.net/burp/download.html) 然后运行它。确保您使用的浏览器不会干扰应用程序测试的评估。大多数当前浏览器将自动减轻大部分测试,并且这些保护措施中的大多数无法关闭,以完成不受阻碍的测试。Firefox 具有这些保护功能,但可以在开发和安全分析时关闭这些功能。此外,Firefox 的插件支持允许您更好地评估应用程序。许多刚刚开始的评估人员无法理解为什么他们刚刚执行的一些新的**跨站点脚本**(**XSS**攻击被阻止。通常,是 Chrome 或 Internet Explorer 中的一些内置浏览器保护说它关闭了,但实际上不是。 现在,在 Firefox 中,通过在手动代理配置中输入`127.0.0.1`和`port 8080`来打开本地代理支持,如下所示: ![Credential attacks with Burp Suite](graphics/B04315_06_07.jpg) 在评估 web 应用程序时,您可能希望将范围仅限于要测试的系统。确保设置此选项,然后过滤所有其他目标,以清理输出并防止自己错误地攻击其他主机。这可以通过在**站点地图**窗口中右键单击主机或单击**范围**选项卡并手动添加来完成,如此屏幕截图所示: ![Credential attacks with Burp Suite](graphics/B04315_06_08.jpg) 现在已经设置了 Burp,我们可以开始评估 DVWA 站点,它有一个简单的登录页面,需要用户名和密码。加载每个网页时,您必须禁用**截取**模式或单击**转发**进入下一页。我们将在几分钟内需要拦截能力,因此我们将保持启用状态。基本上,前面提到的 Burp 套件是一个透明代理,它在网站和浏览器之间发送所有指定流量。这允许您实时操作数据和流量,这意味着您可以让应用程序以不同于预期的方式执行。 要开始此分析,我们必须了解登录页面在发送到服务器时如何格式化其请求,以便对其进行操作。因此,我们在登录提示中为两者提供了错误的用户名和密码,并在代理中捕获请求。下图显示了 Burp 入侵者捕获的错误登录的原始捕获。 ![Credential attacks with Burp Suite](graphics/B04315_06_09.jpg) 然后,右键单击它,选择 Send to 入侵者,并在代理中关闭 Intercept。这允许我们反复操作发送到服务器的请求,以查看是否可以得到不同的响应。 按照这种模式,我们可以将攻击配置为通过用户名和密码列表运行,这可能会授予我们访问权限。点击**入侵者**主要选项卡和**位置**次要选项卡。选择最初提供的用户名和密码的两个位置,然后从下拉列表中选择**集束炸弹**,如下图所示: ### 注 入侵者攻击有多种类型,在您的评估中,集束炸弹将是最常用的类型。有关入侵者攻击的更多详细信息,请访问[https://support.portswigger.net/customer/portal/articles/1783129-configuring-a-burp-intruder-attack](https://support.portswigger.net/customer/portal/articles/1783129-configuring-a-burp-intruder-attack) 。 ![Credential attacks with Burp Suite](graphics/B04315_06_10.jpg) 然后创建两个列表;有效负载集 1 用于用户名,有效负载集 2 用于密码。 ![Credential attacks with Burp Suite](graphics/B04315_06_11.jpg) 接下来,选择**始终**作为后续重定向,因为登录通常会创建网站过渡。 ### 提示 例如,为整个评估设置一个硬范围,然后使用入侵者忽略该范围的好处是,您知道在整个评估过程中,您不会进入意外的领域。 ![Credential attacks with Burp Suite](graphics/B04315_06_13.jpg) 然后点击**入侵者**菜单项,选择**开始**,将显示一个新的弹出窗口。您可以通过与其他结果相比大小的变化来确定可行的帐户。 ![Credential attacks with Burp Suite](graphics/B04315_06_14.jpg) 现在,您可以直接访问 web 应用程序,从而可以在应用程序中移动。 # 用斜纹布穿行光源 Python 有一个库,允许您在源代码级别浏览 web 应用程序并与之交互。安装库后,您可以导入库或使用名为`twill-sh`的`twill`shell。 ![Using twill to walk through the source](graphics/B04315_06_15.jpg) 然后,您可以加载目标网站,并使用以下命令查看页面的源代码: ``` go http://192.168.195.159/dvwa/index.php show ``` 这只是显示了该站点的源代码,允许您进一步与该站点交互。 ![Using twill to walk through the source](graphics/B04315_06_16.jpg) 这允许您直接与站点的组件交互,并确定需要提交的内容。`twill-sh`库在交互模式下运行时有帮助支持,但它是一个有限的工具。twill 的好处是与源代码交互并识别站点中可能感兴趣的区域。这对于那些拥有大量动态内容或大量页面的网站来说是不好的。例如,我运行了`info`命令来尝试识别站点的任何特定内容,如下所示: ![Using twill to walk through the source](graphics/B04315_06_17.jpg) 在这个基本级别上,您可以理解应用程序中可以操作的内容类型、数据格式和其他细节,但是 Python 中有更好的库,可以用于实现如下所述的相同结果: # 了解何时使用 Python 进行 web 评估 Python 有几个库,它们对于执行 web 应用程序评估非常有用,但也有一些限制。Python 最适合用于 web 应用程序的小型自动化组件,这些组件无法通过透明代理(如 Burp)手动模拟。这意味着您在应用程序中找到的特定工作流可能会动态生成,并且无法通过透明代理轻松复制。如果存在时间问题,这一点尤其正确。因此,如果您需要使用多种请求和响应机制与后端服务器进行交互,那么 Python 可能适合您的需求。 ## 了解何时使用特定库 在使用 web 应用程序时,主要有五个库。从历史上看,我最常使用`urllib2`库,这是因为它具有强大的功能和简单的代码原型制作方法,但该库很旧。您会发现它缺少一些主要功能,与新时代 web 应用程序交互的更高级方法被认为是不可靠的,这与下面描述的较新的库相比。当您与网站交互时,`httplib2`Python 库提供了强大的功能,但它比`urllib2`、`mechanize`、`request`和`twill`更难使用。这就是说,如果您正在处理与代理相关的棘手的检测功能,这可能是您的最佳选择,因为发送的头数据可以被完全操纵,以完美地模拟标准浏览器流量。在将其用于实际应用程序之前,应在模拟环境中对其进行全面测试。通常,库提供错误的响应仅仅是因为客户端请求的编制方式。 如果您来自 Perl 世界,您可能会在进入库时立即被吸引到`mechanize`,但它不能很好地用于动态网站,在某些情况下,它根本无法用于动态网站。那么今天的答案是什么?`request`图书馆。它非常干净,提供了必要的功能,可以快速应对当今复杂的 web 服务的挑战。为了突出两者与原型代码之间的差异,我使用`httplib2`和`request`创建了应用程序凭据攻击脚本。这些脚本的目的是识别实时凭证集并捕获相关 cookie。完成此操作后,可以向任一脚本添加其他功能。此外,这两个脚本突出显示了库集之间的差异。 第一个例子是`httplib2`版本,如下所示: ![Understanding when to use specific libraries](graphics/B04315_06_18.jpg) 第二个是`request`库版本,可以在下面的截图中看到: ![Understanding when to use specific libraries](graphics/B04315_06_19.jpg) ### 注 基于请求的脚本可在[找到 https://raw.githubusercontent.com/funkandwagnalls/pythonpentest/master/request_brute.py](https://raw.githubusercontent.com/funkandwagnalls/pythonpentest/master/request_brute.py) ,`httplib2`脚本可在[找到 https://raw.githubusercontent.com/funkandwagnalls/pythonpentest/master/httplib2_brute.py](https://raw.githubusercontent.com/funkandwagnalls/pythonpentest/master/httplib2_brute.py) 。 正如您所看到的,它们的长度几乎相同,但是请求中语句的构造使得 web 流量的模拟更加简单。 ## 在网络评估中高效 使用这样的脚本或 Burp 的好处是可以分析可以操纵、注入和/或强制执行的参数。具体地说,您能够以超出人机交互的速度与 web 浏览器中不易显示的代码功能进行交互。这方面的示例包括为常见的 SQLi 或 XSS 攻击建立攻击列表。生成常见 SQLi 攻击或 XSS 攻击的列表。然后将它们加载到网站上的相关参数中,以识别漏洞。您必须修改上述脚本以命中目标参数,但这将大大加快识别潜在漏洞的过程。 ### 注 对于每个数据库实例的常见注入类型,一些最佳 SQLi 列表可以在[中找到 http://pentestmonkey.net/category/cheat-sheet/sql-injection](http://pentestmonkey.net/category/cheat-sheet/sql-injection) 。同样好的 XSS 列表在[上提供 https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet](https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet) 。其中一些细节也内置在打嗝套件中,如[所示 https://support.portswigger.net/customer/portal/articles/1783128-Intruder_Common%20Uses.html](https://support.portswigger.net/customer/portal/articles/1783128-Intruder_Common%20Uses.html) 。 今天,我们必须应对**Web 应用程序防火墙**(**WAFs**)和可以绕过的保护工具,但您需要知道这些保护是如何设置的,以及哪些字符编码可以绕过它们。请记住,如果存在白名单或黑名单,它们会键入特定的字符集和/或编码,这可能会阻止您的攻击尝试。通过自动化测试,我们可以识别捕获上的关键项,从而防止 web 应用程序被利用,并由此调整注入以绕过已设置的保护。 ### 提示 用于 web 应用程序评估的字符编码与生成有效负载完全不同。所以,你应该明白这些说法并不矛盾。大多数 WAF 在将数据与其白名单和/或黑名单进行比较之前,不会智能地检测和解码数据。因此,您可以通过将字符格式更改为应用程序可以理解但 WAF 无法理解的格式来绕过这些保护机制。 这对于像`sqlmap`这样的工具很重要,这对于验证 SQLi 来说非常好,但是它应该定制它的请求。只有在确认存在合理的注入漏洞后,才应使用该漏洞。然后,它应该用于构建概念验证、提取数据或妥协系统。加载`sqlmap`来点击每个参数只是为了寻找 SQLi 是一个非常耗时的过程。它可以提供潜在的误报并破坏系统。 ### 提示 请记住,如果您不自定义参数并将请求传递给`sqlmap`,则可能会将非盲注入攻击转化为盲注入攻击,这将显著影响完成任务所需的时间。这个工具可能是市场上最好的,但是如果没有一个聪明的用户,它有时会迷失方向。 # 总结 在本章中,我们讨论了 web 应用程序评估和正常网络评估之间的区别。重点介绍了识别活动网页和打开端口的方法,并演示了如何识别未链接或隐藏的内容,以及如何使用 Burp 执行凭据攻击。此外,本章还演示了如何使用 twill 浏览网站,提取数据,然后创建脚本,以便使用不同的库构建请求-响应序列。本章的总结强调了如何通过使用脚本和开源工具来检查站点是否存在特定漏洞来提高效率。 在下一章中,我们将看到如何使用这些技术和其他弱点来突破组织的边界。