最近的一次渗透测试里,在我们捕获的一些数据包中发现了一些未经加密的 Microsoft SQL Server(MSSQL) 流量。起初,我们认为这样就可以直接嗅探到认证凭证,然而,MSSQL 加密了认证的流量,这就意味着我们需要先解密才能获取到认证凭证。如果安装的是一个自签名证书,就很容易进行破解。
不幸的是,破解 MSSQL 加密不在授权范围之内,我们不得不先放下好奇心完成对客户的渗透测试。不过,因为心里总想着一件事以至于无法继续正常进行工作,我们可以在没有用户凭证的情况下攻击 SQL Server 吗?带着疑问我们开始进行实验。
最终,我们发现使用中间人攻击可以通过利用一些数据包达到无需用户凭证直接控制 Microsoft SQL Server。
中间人攻击
回到实验室,我们开始进行了更多的研究。实验环境为,在 Windows Server 2012 R2 上运行 MSSQL Server 2014,工作站为在 Windows 10 系统上运行 MSSQL Management Studio 2014,攻击机为新版的 Kali 2.0 Linux。所有的系统都处在同一个子网内,以模拟进行内网攻击。这些设置与我的客户几乎一致。
这种攻击被称为中间人(MITM)攻击。典型的攻击方式就是进行一些重定向,例如,ARP缓存投毒攻击,迫使两个系统之间的通信被重定向到攻击者的机器上,这就允许攻击者不仅可以看到被攻击者之间的通信,也可以对通信流量进行篡改。而这正是我们下面想要干的事情。
理解数据
我们要做的第一件事情就是查看 MSSQL 查询操作产生的流量。为了使实验更加有趣,我们使用 “SA” 进行登录。SA 账户是 SQL Server 的系统管理员账户,可以进行任何操作。如果我们试验成功,那我们可以使用 SA 账户的权限进行很多有趣的事情。
登录后,我们在服务器上开启 Wireshark 2.0 进行抓包。我们配置 Wireshark 显示过滤 “tds.query”,这样就可以过滤除 TDS 查询数据包以外的数据包(顺便一提,我们注意到在低版本的 Wireshark 上面没有 “tds.query” 这个过滤对象)。
随着开始进行抓包,我们切换回了工作站然后在特别准备的数据库中执行查询语句,这个数据库名为 testdb 包含一个名为 Products 的表,Products 表中有两列分别名为 ProductID 和 ProductName。表内没有任何实际数据只用作测试,所以不用担心。查询操作的目的是显示表中的所有数据。
查询执行成功后返回了一个空表给我,你可以在下面的截图中看到。回到 Wireshark,我们停止了抓包并开始着手分析数据包,我们发现了一个 TDS 查询数据包,点开数据包后我们发现它包含所有的信息,这表明 MSSQL Server 2014 Express 默认没有对数据进行加密处理,也就是说数据可以很容易被获取到。
仔细查看下方解码后的数据,我们可以很容易的识别出查询操作,里面甚至包含回车和换行符。有趣的事是,每个字符之间都有一个 Unicode 的空字节(0×00),查看十六进制视图时这点尤为明显,这意味着 Wireshark 周期性的显示这些字节,它们实际上不是真为空的,所以我们不能直接查找一个简单的字符串,如”select”。我们之后对数据进行搜索需要把这些 Unicode 空字节也加入考虑之中。
有趣的 Ettercap Filters
我们已经了解了数据的样子,下面就该对这些数据进行操作了,这里我们决定使用 Ettercap。Ettercap 是一个专门用来进行 MITM 攻击的工具,其内置了一个名为 Ettercap filters 的功能,这个功能允许我们搜索特点的数据包随后处理数据。我们可以在 Ettercap 里写一个过滤,这样 Ettercap 在每次匹配到的时候会自动帮我们替换数据。这个功能稍有限制,但足以用于我们的 POC 了。
过滤代码里我们打算使用的主要函数为搜索和替换函数,搜索函数将在数据包内搜索指定的数据,替换函数其实就是先搜索指定数据然后替换成其他数据,这也是整个项目的关键点。
由于 TDS 查询数据中包含一些空字节和不可打印的字节,这意味着我们不能只简单搜索字符串并使用另一个字符串替换它。我们需要一种方法搜索非空的不可打印字符,但是我们又无法通过键盘输入,因此需要其他的方法。幸运的是,Ettercap 过滤支持十六进制编码,例如,搜索字母 ‘s’可以使用”\x73″,搜索空字节可以使用”\x00″。Kali 里有一个名为 hexdump 的程序可以将字符串转换成十六进制,我们使用这个程序将字符串”select”转换成十六进制。
在有了我们需要的数据后,写下了下面这个名为 “mssql.filter” 的第一个过滤代码:
第一行代码确过滤只运行在端口号为 1433 的 TCP 流量上,如果匹配成功,过滤器会输出调试信息到控制台,让我们知道它发现了 SQL 流量。下一个 “if” 语句则是用于搜索十六进制数据的,这个十六进制翻译过来是 “select”。如果过滤器定位到这个字符串,会将调试信息输出到控制台。
最后,会替换执行命令为另一个字符串 “ssssss”。这只是一个测试,看这个脚本是否可以正常工作,但需要注意的是,当你替换 TCP 中数据的时候必须替换相同数量的字节数,如果数据包大小发送变化,则 TCP 连接会被断开。
过滤代码写完后记得要进行编译,使用 etterfilter 命令可以很容易完成编译。
没有报错,所以我们的过滤器已经准备好进行测试了。我们首先启动 Ettercap 图形化界面并对 MSSQL 服务器和客户机发起 ARP 欺骗攻击,在开启 Wireshark 进行验证看流量是否在两个目标间发送。然后,在 Ettercap 菜单 “Filters -> Load a filter”里选择我们的过滤器,这时我们就在控制台中获得了一个 “Content filters loaded” 消息。几乎在开启的一瞬间我们就收到了 “SQL Traffic Discovered” 的消息,一切看起来跟我们预想的一样。
下一步就是切换回工作站并尝试执行查询操作。如果一切正常,则 “select” 字符串会被替换成 “ssssss” 并造成查询失败。在执行查询操作后,这次没有在收到空表的结果,相反收到了一个报错。
“Incorrect syntax near ‘ssssss’.”很好,过滤器如预期一样的正常工作了,替换 “select” 字符串为 “ssssss”。而 MSSQL 服务器不知道如果处理就返回了一个报错。这是我们通向成功的第一步,下一步就是替换整个查询字符串,以更好的进行攻击。
新建账户
我们决定在服务器上增加一个账户,对攻击者来说这是很常见的操作,特别是在目标的登录账户为 “SA” 时,为了新建一个账户我们需要在 MSSQL 服务器上执行如下查询:
CREATE LOGIN anitian WITH PASSWORD=