阅读须知
本文的知识内容,仅供网络安全从业人员学习参考,用于已获得合法授权的网站测试,请勿用于其它用途。请勿使用本文中的工具、技术及资料,对任何未经授权的网站、系统进行测试,否则,所造成的直接或间接后果,均由您自行承担。
靶场说明
测试背景:本靶场模拟了一个 web 购物界面,当用户查询商品时候,会调用 SQL 查询语句SELECT * FROM products WHERE category = 'Gifts' AND released = 1
,其中Gifts 为可控的输入语句,请你构造 SQL 查询语句,从而查询出未发布的商品表单。
使用工具:HTTP抓包测试工具。
工具下载:TangGo测试平台
测试靶场名称:SQL injection vulnerability in WHERE clause allowing retrieval of hidden data
(靶场原文描述)
测试思路
访问目标网站:首先,访问目标网站并进入购物页面。
抓取数据包:抓取查询商品时的请求数据包。
构造语句查看是否存在漏洞:使用 HTTP 重放模块的数据处理功能,依次构造带有闭合符号(单引号和双引号)的请求参数,查看页面返回内容。
确认漏洞存在:当页面返回为“Internal Server Error”时,确定闭合符为单引号。
构造查询语句:构造查询语句Accessories' or 1=1 --+'
尝试绕过限制查询商品。
绕过成功:成功绕过查询限制,获取到未发布商品的数据。
测试案例
首先启动 HTTP抓包测试工具,打开右上角内置浏览器,之后在浏览器中访问靶场的网站,加载后为一个在线商城的页面:
(在线商城)
点击“Accessories”页面,观察页面此时仅存三个数据:
(Accessories 筛选)
回到 HTTP抓包测试工具中,打开拦截开关,回到内置浏览器中,刷新页面,发现 HTTP抓包测试工具中已经抓取到数据包:
(抓取数据包)
分析数据包可以发现,该数据为 GET 型的请求,请求的路径为“/filter ” ,请求参数为“ category ”
,参数携带的请求值为“ Accessories ”,接下来需要通过修改携带的请求值,以便测试出对应的闭合符号。
因为需要测试多个请求值,所以把数据发送到重放模块。在操作选项卡中把抓取到的数据发送到数据重放模块中。
在重放模块中,点击右侧选项卡打开数据处理模块:
在左侧数据包中勾选需要处理的数据“Accessories”,在右侧数据流程一中填入需要替换的数据Accessories "
(替换数据)
在流程二中选择需要的编码类型,因为此处为 GET 型请求,应当对数据进行URL 编码,否则可能会导致数据被过滤掉。
选择类型为编码,选择 URL 编码:
(选择编码)
设置完成编码后,鼠标移至【应用到请求数据】按钮右侧悬停,在弹出的选项框中点击【应用并发送数据包】。
(应用并发送)
数据发送完成后,返回的响应数据为 200, 为了方便查看返回数据,我们点击“页面响应”,其中返回了刚刚输入的值Accessories "
。
(返回数据)
继续使用数据处理功能,替换值为Accessories '
,再次点击【应用并发送数据包】。
(修改数据)
数据发送完成后,返回的响应数据为 500,其内容为“Internal Server Error”。
(错误响应)
由此可知该查询语句的闭合符为单引号,接下来只需要修改构造的语句即可绕过查询限制,修改传入值为Accessories' or 1=1 --+
。
在数据处理模块中修改对应的值,之后点击【应用并发送数据包】。
(修改数据并发送)
解释:对于本靶场,在使用 MySQL 数据库的时候,查询使用的语句为:
SELECT * FROM products WHERE category = 'Accessories' AND released = 1 #默认查询语句
# 这条命令的含义是查找products表中类别(category)为'Accessories'且已经发布(假设released字段中1代表已发布)的所有产品记录。
修改后的语句如下:
构造查询语句
SELECT * FROM products WHERE category = 'Accessories' or 1=1 --+ AND released = 1;
# 输入语句为:Accessories' or 1=1 --+
# SELECT * FROM products:这部分与标准的SQL查询相同,意在从products表中选择所有列。
# WHERE category = 'Accessories':这是查询条件的一部分,表示只选择那些category列为'Accessories'的记录。
# or 1=1:这里引入了一个始终为真的条件(因为1确实等于1),这意味着无论category列的值是什么,这个条件都会使得整个WHERE子句为真。这是SQL注入常用的技巧,用来绕过原本的条件限制,使查询结果包括所有记录。
# -- + AND released = 1;:这部分是一个注释指示符和注释内容的开始。在SQL中,--后面的内容被视为单行注释,直到行尾。因此,--之后的 AND released = 1; 实际上不起到任何查询逻辑上的作用,它和之后的任何内容都被视为注释而被数据库忽略。
总结起来,这个SQL语句本意是想筛选出类别为'Accessories'且已发布(released字段中1代表已发布)的商品,但因为被注入了or 1=1 --这样的恶意代码,实际上它将返回products表中的所有记录,忽略了released = 1的条件限制,这是SQL注入攻击中常见的手法之一。
数据发送完成后,再返回的响应数据中,我们可以看到“Congratulations, you solved the lab!”,说明已经成功解决该靶场。
(响应内容)
回到 HTTP抓包测试工具,然后点击放行,回到内置浏览器:
(正确过关)
至此成功构造了 SQL 注入语句,绕过了released = 1
限制,查询到许多未发布的商品。
测试总结
测试漏洞:
SQL 注入漏洞中的字符型注入是指攻击者利用应用程序中的输入字段,向后端数据库注入恶意的 SQL 代码片段,从而执行恶意操作或获取未授权的数据。
工作原理:
- 应用程序将用户输入直接拼接到 SQL 查询语句中,而没有进行充分的验证或过滤。
- 攻击者利用这些输入字段,构造包含恶意 SQL 代码的输入,以达到修改查询逻辑、获取敏感数据或执行其他恶意操作的目的。
解决方案:
- 使用参数化查询或预编译语句:使用参数化查询可以将用户输入作为参数传递给 SQL 查询,而不是将其直接拼接到 SQL 语句中。这样可以确保用户输入不会被解释为 SQL 代码。
- 输入验证和过滤:在接受用户输入之前,对其进行严格的验证和过滤,只允许预期的输入格式。例如,对于数字输入,确保只包含数字字符;对于文本输入,可以使用白名单过滤器,只允许特定的字符或模式。
- 最小化权限:确保应用程序连接到数据库的账户具有最小的权限,以限制攻击者在发生注入时能够执行的操作。例如,避免使用具有管理员权限的数据库账户进行应用程序连接,而是为应用程序分配只读或仅执行必要操作的账户。
- 使用ORM框架:使用对象关系映射(ORM)框架可以帮助将数据库操作与用户输入隔离开来,并提供内置的参数化查询功能,从而减少 SQL 注入的风险。
- 错误消息处理:避免向用户披露详细的错误消息,特别是涉及数据库的错误消息。攻击者可以利用这些信息来获取有关数据库结构和查询逻辑的重要信息。
- 定期更新和漏洞修复:及时更新应用程序和相关组件,以确保已修复已知的 SQL 注入漏洞和其他安全漏洞。
注意:工具使用内容请以最新版本为主。