文章目录
简介
本文旨在介绍sql注入的靶场sql-labs每一关的具体思路。为了更好的去理解题目,有些关卡会放上关键部分的一部分源代码
另外在做的时候不明白的知识点可以参考如下博客
Sql注入基本知识
Less-1 '闭合
源码部分:
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row= mysql_fetch_array($result);if($row)
{
echo 'Your Login name:'. $row['username'];
echo 'Your Password:'.$row['password'];
}
通过报错可知,闭合符号是单引号
加一个\观察闭合符号更方便
order by 判断字段值3
获取数据库
获取表名
获取列名
?id=-1’ union select 1,2,group_concat(column_name) from information_schema.columns where table_schema =‘security’ and table_name = ‘users’ --+
获取数据库信息
Less-2 数字型无闭合字符
源码部分:
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
进入页面,加上\判断闭合字符
发现是数字型的不需要闭合字符,我们直接进行order by 来判断出字段数为3
然后继续判断出数据库的名字
剩下步骤同1
Less-3 ')闭合
源代码:
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
如图判断出闭合字符为’)
ordey by判断出字段数为3
剩下步骤同1
Less-4 ")闭合
源代码:
在id的前后方加上了双引号
$id ='"'. $id .'"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
如图判断出闭合字符为")
剩余步骤同1
Less-5报错注入 '闭合
源代码:
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row= mysql_fetch_array($result);if($row)
{
echo 'You are in...........';
}
如图判断出闭合字符为’
但是会发现没有显示位
因此我们利用报错注入(不了解详见简介链接)
查库名为security
查表名
?id=1’ and extractvalue(1,concat(‘~’,(select group_concat(table_name) from information_schema.tables where table_schema=‘security’))) --+
查表的列
查表信息
Less-6报错注入"闭合
源代码:
$id ='"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
如图发现闭合符号是"
发现同样是报错注入
获取库名
获取表名
剩余同5
Less-7写马注入
源代码:
$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
如图提示我们利用outfile,想到利用outfile函数写入一句话木马
没了解的可以去简介的链接简单了解一下写木马注入
试闭合符号为’))
错误的闭合符号会报错,因此可以通过这来确定最终的闭合符号
试字段数为3
写入一句话木马
如图成功写入一句话木马
用蚁剑连接
拿下webshell
Less-8布尔盲注 '闭合
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row= mysql_fetch_array($result);if($row)
{
echo 'You are in...........';
}
else
{
}
如图发现不管输入啥结果只有两种,说明是布尔盲注
不了解的可以去简介链接简单了解一下布尔盲注
通过判断可知是的情况输出you are in ,因此我们可以通过这判断出闭合符号是’
通过length函数去猜测数据库的长度为8
猜数据库的字符:
如图通过substr函数来控制截取的数据库名字的第x个字符,再通过ascii函数的值来判断字符是具体哪一个
substr(string,1,2)的含义是从stirng字符串的第一个位置开始截取两个字符
不断地通过ascii函数来缩小范围,最终确定第一个字符的ascii值是115,因此第一个字符是s
让我们用burpsuite来爆破出其它字符,
设置爆破模式为集束炸弹
分别设置爆破点1、2为
开始爆破
如图分别得出ascii值为101,99,117,114,105,116,121分别是字符ecurity,即数据库名字为security
得出数据库的名字后,用同样的方式去得出表名
先得出表的个数为4
通过limit 0,1来限制只获取第一个表名,通过subsrt来截取第一个表名的整个字符串,通过length来判断这个表名的长度
substr(sring,1)第三个参数省略的话是截取到字符串的末尾
如图判断出第一个表的长度是6
如图判断出第一个表的第一个字符的ascii值是101即e
剩余步骤同上述获取数据库的完整名称
先获取完第一个表的完整字符为emails,以此类推判断出第二个表和第三个表的信息
有了表的信息,再根据length()、ascii()、substr()这三个函数来获取表中的内容
Less-9时间盲注’闭合
如图试闭合符号,发现不管怎么试结果都是you are in,因此不能用布尔盲注,我们接下来考虑使用时间盲注
因为如果闭合符号错误,后面的语句就执行不到,因此sleep函数就不会执行,通过下面两张图结合起来可以知道闭合符号为单引号
我们利用同样的方法去获得数据库名字的长度
同样可以获得数据的第一个字符的ascii值为115即为字符s
通过这种方式能够获得数据库的完整名字为security
然后我们去获得表的个数为4个
如图判断出第一个表的长度是6
剩余步骤同Less8的布尔盲注,通过ascii函数来判断出表的名字然后以此类推获得数据库里面的信息
Less-10时间盲注"闭合
思路同9,通过sleep函数判断出闭合字符是"剩余按照时间盲注的正常流程走即可
Less-11 POST ’ 注入
if(isset($_POST['uname'])&&isset($_POST['passwd'])){$uname=$_POST['uname'];$passwd=$_POST['passwd'];
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
可知这里和以往不同的是不再是get传参,而改成了post传参,我们的注入点从url变成了登录框,因为参数是通过登录框去传过去的
尝试传参发现结果提示密码框有问题,我们直接在密码框也同样试一下
如图注入成功,剩余步骤略
Less-12 POST注入")闭合
$uname='"'.$uname.'"';$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
和第11题同思路,闭合符号为")
如图bp抓包去试
Less-13 POST报错注入 ’ )闭合
@$sql="SELECT username, password FROM users WHERE username=('$uname') and password=('$passwd') LIMIT 0,1";
用bp试出闭合字符是’),但是这里并没有显示位
由前面可知,当没有显示位的时候,我们尝试去报错注入获得信息
报错注入成功,剩余步骤参考前面的get报错注入
Less-14 POST报错注入"闭合
$uname='"'.$uname.'"';$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=$uname and password=$passwd LIMIT 0,1";
尝试注入,试出闭合符号为双引号
但是没有显示位,尝试报错注入
成功,剩余步骤略
Less-15 POST布尔盲注 '闭合
试闭合符号,为单引号
仍无显示位,尝试报错注入
发现虽然报错了,但是报错信息也没有显示,但由于显示结果只有成功和失败两个选项,因此可以尝试布尔盲注
盲注成功,判断出数据库的库名长度是8剩余步骤同前面布尔盲注
在盲注的时候,前面的用户名部分得用一个数据库中有的用户名才能盲注成功,比如这里用123不行,但admin和dumb均可
Less-16 POST 盲注")闭合
bp抓包试闭合符号,为")
没有显示位,尝试报错注入
报错注入失败,尝试布尔盲注
布尔注入成功剩余略
Less-17 POST 报错注入之密码框注入
@$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";$result=mysql_query($sql);$row=mysql_fetch_array($result);if($row){$row1=$row['username'];$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
进入页面,上面显示密码重置,这里不再是登录框而是密码修改的操作
我们抓包尝试在user name注入
如图注入失败,user name框过滤的比较多,我们再试着尝试在密码框去注入
注入成功,但没有显示位,因此利用报错注入
报错注入成功,剩余参考前面的报错注入
Less -18 POST 报错注入之Useragent注入
$uagent相关函数详解
$uagent=$_SERVER['HTTP_USER_AGENT']; 获取用户端的相关信息
$IP=$_SERVER['REMOTE_ADDR']; 获取用户端的IP地址
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
进入页面,发现页面显示我们的IP信息,推测它获得了用户的一些相关信息,通过源码可知,这里我们知道在报文头获取的useragent后续通过insert来交互,因此可以通过useragent来进行注入
如图注入成功,剩余略
这里的注入代码要和insert严格对应,因此后面多了两个1,另外这里不能直接用--+,需要用--空格(虽然两者本质相同,但用加号会报错) ,而且空格后面要加任意字符才能注入成功,可能是为了防止空格被吞掉
Less-19 POST 报错注入之reference注入
$uagent=$_SERVER['HTTP_REFERER'];$IP=$_SERVER['REMOTE_ADDR'];$insert="INSERT INTO `security`.`referers` (`referer`, `ip_address`) VALUES ('$uagent', '$IP')";
与18题同理,这题的注入点在报文头的reference里面
如图直接注入
注入成功
Less-20 POST 报错注入之cookie注入
$cookee=$row1['username'];setcookie('uname',$cookee,time()+3600);$sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";
进入页面随便注入,提示让我们利用cookie字段去注入
重新进入,因为第一次登录没有cookie,再进去就有了
尝试注入
注入成功
涉及到编码的注入,会出现一些特殊字符编码后报错的问题,这个问题需要注意,换其他注释思考即可
Less-21 POST 报错注入之cookie加密注入
$cookee=base64_decode($cookee);$sql="SELECT * FROM users WHERE username=('$cookee') LIMIT 0,1";
如图尝试注入
由源代码可知,这里源码中对cookie进行了一个base64解码,因此我们传进去的cookie需要先经过base64加密才能通过
从黑盒角度怎么发现的base64呢? 黑盒角度登录进去之后,你抓包会发现我们原本uname=admin,但是你会抓包后,你会看到自动把admin加密了,我们可以通过这样去想到这里自动对cookie的字段进行了base64编码
同理报错注入
成功注入,剩余略
Less-22 同21但“闭合
$cookee=base64_decode($cookee);$cookee1='"'.$cookee.'"';$sql="SELECT * FROM users WHERE username=$cookee1 LIMIT 0,1";
和21的区别在于闭合符号的变化
如图同理报错注入,成功注入
Less-23 报错注入之过滤注释符注入
$reg="/#/";$reg1="/--/";$replace="";$id=preg_replace($reg,$replace,$id);$id=preg_replace($reg1,$replace,$id);$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
preg_replace()函数详解
这里的特点是,不能用正常的注释符号,因为注释符号被过滤了,不用注释符号的情况下去无视后面的语句只需要构造对称去消耗掉后面的多于符号即可
Less-24 二次注入
二次注入原理详解
$username=$_SESSION["username"];$curr_pass=mysql_real_escape_string($_POST['current_password']);//这个函数能预防sql注入$pass=mysql_real_escape_string($_POST['password']);$re_pass=mysql_real_escape_string($_POST['re_password']);$sql="UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
mysql_real_escape_string()函数详解
通过修改密码的源代码我们可以发现只有username参数没有用到mysql_real_escape_string函数,更容易注入。由于这题能够添加新用户,我们可以尝试二次注入
首先注册新用户
然后去修改admin’#用户的密码,原理如下
表面上看我们是修改了admin‘#用户的密码,但实际上我们修改的是用户admin的密码
用刚才我们设置的密码和admin用户即可去登陆成功
Less-25 双写绕过 过滤and和or
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";$id=preg_replace('/or/i',"",$id);$id=preg_replace('/AND/i',"",$id);
我们由本题报错信息结合源码可知本题将and和or过滤了
直接双写绕过
如图成功绕过,通过报错信息来暴库
暴表
这里需要注意的点是后面字符出现的or和and也需要经过双写来绕过
Less-26 绕过空格及多字符的过滤
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";$id=preg_replace('/or/i',"",$id);//strip out OR (non case sensitive)$id=preg_replace('/and/i',"",$id);//Strip out AND (non case sensitive)$id=preg_replace('/[\/\*]/',"",$id);//strip out /*$id=preg_replace('/[--]/',"",$id);//Strip out --$id=preg_replace('/[#]/',"",$id);(or'1'='1) //Strip out #
$id= preg_replace('/[\s]/',"", $id); //Strip out spaces
$id= preg_replace('/[\/\\\\]/',"",$id);//Strip out slash
对于and和or的过滤,我们可以通过双写去绕过
对于注释符号的过滤,我们可以通过 or ‘1’='1 绕过
而对于空格的过滤,我们可以通过下列字符去绕过
%20 %09 %0a %0b %0c %0d %a0
思路同前面的绕过思路相同,直接看结果
这里空格字符多试几个因为有几个空格字符无法成功绕过过滤,剩余略
Less-27 select变写绕过多字符过滤
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";$id=preg_replace('/[\/\*]/',"",$id);//strip out /*$id=preg_replace('/[--]/',"",$id);//Strip out --.$id=preg_replace('/[#]/',"",$id);//Strip out #.$id=preg_replace('/[ +]/',"",$id);//Strip out spaces.$id=preg_replace('/select/m',"",$id);//Strip out spaces.$id=preg_replace('/[ +]/',"",$id);//Strip out spaces.$id=preg_replace('/union/s',"",$id);//Strip out union$id=preg_replace('/select/s',"",$id);//Strip out select$id=preg_replace('/UNION/s',"",$id);//Strip out UNION$id=preg_replace('/SELECT/s',"",$id);//Strip out SELECT$id=preg_replace('/Union/s',"",$id);//Strip out Union$id=preg_replace('/Select/s',"",$id);//Strip out select
和前面思路相同
但是在select的时候需要注意,要绕过过滤
如图注入成功,剩余略
Less-28 盲注绕过多字符过滤
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";$id=preg_replace('/[\/\*]/',"",$id);//strip out /*$id=preg_replace('/[--]/',"",$id);//Strip out --.$id=preg_replace('/[#]/',"",$id);//Strip out #.$id=preg_replace('/[ +]/',"",$id);//Strip out spaces.$id=preg_replace('/[ +]/',"",$id);//Strip out spaces.$id=preg_replace('/union\s+select/i',"",$id);(/i不区分大小写)//Strip out UNION & SELECT.
过滤了union和select,而且报错注入无回显,盲注
成功,剩余步骤同盲注略
剩余有机会再补充更新
版权归原作者 IDgoodis 所有, 如有侵权,请联系我们删除。