SQL注入
什么是 SQL 注入
- 服务器没有严格的校验客户端发送的数据,导致将用户精心构造的数据作为 SQL 语句的一部分执行,从而使数据库信息泄露或被修改。
SQL 注入的发现流程
- 确认目标网页是动态的,网页能够接收用户的参数,并作出不同的反应。
- 精心的构造一个绝对会导致SQL语句执行出错的参数[‘“()],查看是否有影响。
- 根据报错信息或以其它方式猜测目标 SQL 指令的结构,【确认闭合的状态】。
如何闭合语句
- 如果有报错,根据报错猜测目标 SQL 指令的完整构成,猜测注入类型(数字\字符)
- 对于 syntax to use near ‘“()’ LIMIT 0,1 ‘ 报错信息,截取出 near 后面的一部分
- 闭合之后,为了让代码正常执行,需要将后面的内容注释掉,使用 — 或者 %
- 在确认目标网页已经存在注入漏洞,且能够正常闭合后,能够获取以及如何获取哪些重要的信息
- 直接使用 SQL 提供的内置函数获取到数据库的基本信息,例如:
- database(): 当前应用程序所使用的数据库的名称。
- version(): 获取当前所使用的数据库的版本,可用于确认数据库类型,找 0DAY。
- 根据不同类型的数据库,可能会提供不同的用于获取基本信息的函数。
数据库都存在配置信息表,其中保存了数据库、表和字段的所有信息
- 使用联合查询注入的过程(有回显)
- 使用联合查询(union select)或排序(order by)的方式获取目标的字段数量。
- union select 要求联合查询的两条 SQL 语句查询的字段数量是相同
- order by 要求指定的需要排序的字段必须是有效的数字或名称
- 如果网页始终返回仅 1 条数据,则将默认的查询设置为无效查询
- 联合查询会将两条语句的结果组合成一个结果集
- 如果原指令查询结果为空,则显示的是自己的查询结果
- 根据页面反馈的内容,确定哪些字段是可利用字段。
- 查询的字段并不一定会显示出来,只有看得到的才会被替换。
- 将第 3 步确定的有效字段修改为想要查询的函数,或子语句进行利用
- 使用联合查询(union select)或排序(order by)的方式获取目标的字段数量。
使用产生报错的语句进行注入(有报错)
- 已知闭合方式后,使用联合查询语句配合函数或指定语句完成利用
- updatexml(字符串,xpath,字符串) \ extractvalue(字符串, xpath):
- 函数的作用是查找符合 xpath 语法的子串进行替换。xpath 有规定的格式,如果格式出现了问题,会将出现问题的语句显示在报错信息中。
- 为了获取想要的信息,需要使用一个必然出错的字符(‘~’ 0x7C) 拼接想要查询的语句,使报错语句中出现查询的结果,例如 updatexml(0, CONCAT(0x7c, (SELECT version())), 0)
使用双注入的方式:
SELECT COUNT(*) FROM information_schema.columns GROUP BY FLOOR(RAND(0)*2);
- FLOOR(RAND(0)*2): 生成指定顺序的 0~1 组成的序列:0110110011101
- GROUP BY 和 COUNT() 的组合会使用 mysql 中的*虚拟表来实现。
第一次判断 FLOOR(RAND(0)*2[0] 是否已经存在对应的虚拟表(没有)
使用 FLOOR(RAND(0)*2[1] 表达式的结果创建一个虚拟表,并计数
第二次判断 FLOOR(RAND(0)*2[1] 是否已经存在对应的虚拟表(有)
将对应的虚拟表计数 +1
第三次判断 FLOOR(RAND(0)*2[0] 是否已经存在对应的虚拟表(没有)
使用 FLOOR(RAND(0)*2[1] 表达式的结果创建一个虚拟表,并计数
但是表1已经存在了,所以报错
表1: **
0110110011101
报错注入的缺陷:报错的长度不能超过 32 位,所以一次只能获取 32 位数据
and updatexml(0, concat(0x7e, (SELECT GROUP_CONCAT(TABLE_NAME) FROM information_schema.TABLES)),0)--+
and updatexml(0, concat(0x7e, substr((SELECT GROUP_CONCAT(TABLE_NAME) FROM information_schema.TABLES), 1, 31)),0)--+
使用写入文件的方式注入(开启了权限)
GROUP_CONCAT():将查询到的所有指定字段拼接成一个字符串
- CONCAT(): 将制定的普通字符串进行拼接,多用于报错注入
- FLOOR(): 向下取整函数,主要用于舍去小数点部分
- RAND(): 随机数函数,不传参默认初始化随机数种子,为了每一次成功,必须写 0。
- COUNT(): 聚合函数,在分组查询的时候会使用到。
- SUBSTR() \ SUBSTRING: 将指定的字符串进行拆分,报错注入使用较多
SQL 注入漏洞查找工具
- 爬取目标网站的所有页面(站内链接、站外的链接)
- 使用 re 模块:re.findall(html, ‘href=”.*?”‘),
- 使用 bs 模块:bs.select(‘a’)
- 爬取路径的过程中,需要注意
- 去重,将所有的重复链接去除掉,可以使用 set
- 注意绝对路径(直接访问)和相对路径(拼接),才能够正常访问
- 取出每一个链接,进行 FUZZING(枚举)
- 是否存在布尔注入漏洞,?id=1 and 1 ?id=1 and 0
- 判断是否有返回内容: 联合查询注入
- 判断是否有报错信息: 报错注入
- 进行盲注: 布尔盲注和时间盲注