信息安全公益宣传,信息安全知识启蒙。
加微信群回复公众号:微信群;QQ群:16004488
加微信群或QQ群可免费索取:学习教程
教程列表见微信公众号底部菜单
如何安全地进行SQL注入测试?
如果从Gitlab最近的离线事件(他们处理的非常好)能够吸取某个教训的话,那就是公司必须溺爱般地保护他们的生产数据库;而作为渗透工程师,这个责任也延伸到我们。生产数据库从本质上就不适合作为实验的场所,因为任何意外的结果都可能对数据造成不可逆的不良影响,但渗透测试(至少黑盒渗透)却必须通过实验的方式寻找漏洞。本篇文章讨论的就是如何在避免修改数据的情况下安全地在生产数据库寻找漏洞。
许多公司都允许对生产服务器和数据库的测试,而这也并非没有道理:生产环境是公司最可能被攻击的位置,所以必须经过严密测试。虽然本文中说的所有内容都同样适用于非生产环境,但在其他环境下意外修改数据的后果相比之下并不严重。作为渗透工程师,最大的噩梦恐怕就是自己的一个失误搞垮了客户的生产环境。运气好的话也许仅导致一些离线时间,通过备份可以恢复服务器;差的话可能用户没有完整的备份,失误直接导致关键数据丢失。我们必须找到一种不会意外修改生产数据的方法来测试SQL注入。
我用谷歌搜索了“安全的SQL注入”,却没有找到任何相关的结果。当然,肯定有其他人写过这个话题,NetSPI(原作者公司)的其他员工们也提到过他们解决这个问题的方法,但我希望通过这篇博文让这个话题获得更广泛的关注并易于访问。
准备测试环境
让我们来重现一下常见的数据库环境,来测试我们的注入。我们先安装三款企业常用的关系数据库管理系统(RDBMS),MySQL、MSSQL、和Oracle,并在它们中各创建一个储存用户的表(USERS),如下。
再添加一些用户。
新手渗透工程师的第一天
在设置完成后,每个数据库里都有一个名为USERS的表,它们的结构如下:
对于多数渗透测试来说,用户表通常第一个被触碰的表,因为它被用于用户登录。我们假设查询它的代码如下:
很明显,这段代码存在SQL注入漏洞,但它本身并不能对系统造成什么影响(仅是泄露数据),所以我们案例中的新手渗透工程师可以大胆地随意注入’ or 1=1 --。但如果是下面这段查询代码呢?这段代码用于更新用户的电子邮箱:
这回,如果渗透工程师还在大意地随便乱用’ or 1=1 --,则后果不堪设想。
糟啦!
公司数据库中的所有电子邮件都被删除了。假设这个公司没有完整的备份,无法恢复这些邮件,那接下来该怎么办?更新一下简历,准备去面试吧– 这个工程师可以和这份工作说再见了。
如何保住你的工作?
有几种办法可以避免上述的失误,而它们的关键其实都在于多花一秒时间去思考服务器需要执行什么类型的查询来实现被测试的功能。咱们换个角度来看刚才执行的这个查询。
虽然在黑盒测试中我们看不到服务器上执行的代码,但我们能看到浏览器向它发送的请求,如下:
从这个HTTP请求的格式和服务端点的名称应该不难推断出服务器需要执行的查询。很明显,这个服务端点的用途是更新用户的电邮,那必然会执行UPDATE查询。我们的目标就是找到既可证明SQL注入漏洞存在,又不会造成破坏的注入载荷,并用其进行测试。
我们先来试试串联两个字符串。我们先用一个单引号结束当前的字符串,然后用相应的串联运算符将另一个字符串与其串联。如果数据库成功将两个字符串串联在一起,我们就能得知它存在SQL注入漏洞了。
虽然每个数据库系统的语法不太一样,但它们的功效都等同于:
若是成功,那么数据库的内容将被更新为:
再来看看一些其他办法。MySQL和Oracle都允许对数字字符串进行算术运算。对于MSSQL,如果某个注入点不是字符串,而是整数值,则可以直接注入数字进行算术运算。
举例如下:
我们现在已经有办法根据不同数据库系统进行安全的SQL注入测试了。但如果我们不知道服务器运行的具体是哪个数据库系统,该怎么办?有没有任何一个载荷,可以通用于这三种RDBMS?
在做了一系列尝试后,我没能发现任何一个在这三种数据库系统中功能完全一样的运算符或函数。但是,我们并不需要这个载荷在对每种系统效果都一模一样,只要它能核实注入漏洞的存在就够了。
如之前所述,在MSSQL中“+”运算符被用于串联字符串和加法运算,而在 MySQL和Oracle中它只被用于加法运算。也就是说,在MSSQL中,表达式‘1’+‘1’ 会被评估为‘11’,而在MySQL和Oracle中它则会被评估为‘2’。所以,以下载荷便可通用于测试全三种数据库系统:
若数据库是 MSSQL ,则新的值会是‘11’。
成功了!我们现在可以利用这个载荷随意对最常见的三种RDBMS进行测试,并且不用担心会造成任何不可逆转的影响。未来的挑战是扩展它以适应更多的RDBMS和更复杂的注入点。这个挑战就留给读者了。
下面阅读原文,有啥 ?