二次注入
- 简介
- 工具环境
- 具体实施
简介
二次注入是一种较为隐蔽的 SQL 注入攻击方式。它并非直接在输入时进行攻击,而是先将恶意数据存储到数据库中,这些数据看似正常。随后,应用程序在后续的操作中,再次使用或处理这些之前存储的恶意数据时,未进行充分的过滤和验证,导致恶意数据被解释为可执行的 SQL 语句,从而引发安全漏洞。例如,用户注册时输入看似合法的用户名,之后在修改密码等操作中,系统未正确处理该用户名,使得攻击者能够篡改数据库中的数据。二次注入攻击具有很强的迷惑性,对数据库安全构成严重威胁,需要开发人员高度重视并采取有效的防护措施。
为了更方便理解和直观明白什么是二次注入这里借助2018年网鼎杯的CommentCTF比赛题目
工具环境
BUUCTF在线靶场
burp suite抓包工具
具体实施
首先进入靶场你会看到一个类似于论坛贴吧的页面,当你点击发帖的时候会让你进行登录操作,如下所示
在这里我们看到了提示这里账号和密码都大致给出了,但是密码后三位没有给出,在这里我们可以利用burpsuite暴力破解一下,尝试登录,
我们挂上代理然后在页面内发送请求,利用burpsuite成功抓到数据,然后我们在password=zhangwei &000& 这里进行标记发送的Intruder界面,设置为number数字为:000-999然后进行暴力破解
破解后如图所示在数字为666的时候字段长度有明显区别,很有可能这就是密码的后三位,尝试登录后成功登录
到了这个页面可以看到页面一共就几个操作就是发帖和发帖后的详情页面,自己也尝试了使用简单的单引号双引号等等测试发现没有任何反馈,那么就试一试能不能够获取到网页源码,在斜杠后输入.git
可以看到出现了一个页面并不是404,那么就可以尝试利用githacker工具尝试获取到网页源码,这里也是成功获取到了网页源码
//write_do.php
<?php
include "mysql.php";
session_start();
if($_SESSION['login'] != 'yes'){
header("Location: ./login.php");
die();
}
if(isset($_GET['do'])){
switch ($_GET['do'])
{
case 'write':
$category = addslashes($_POST['category']);
$title = addslashes($_POST['title']);
$content = addslashes($_POST['content']);
$sql = "insert into board
set category = '$category',
title = '$title',
content = '$content'";
$result = mysql_query($sql);
header("Location: ./index.php");
break;
case 'comment':
$bo_id = addslashes($_POST['bo_id']);
$sql = "select category from board where id='$bo_id'";
$result = mysql_query($sql);
$num = mysql_num_rows($result);
if($num>0){
$category = mysql_fetch_array($result)['category'];
$content = addslashes($_POST['content']);
$sql = "insert into comment
set category = '$category',
content = '$content',
bo_id = '$bo_id'";
$result = mysql_query($sql);
}
header("Location: ./comment.php?id=$bo_id");
break;
default:
header("Location: ./index.php");
}
}
else{
header("Location: ./index.php");
}
?>
通过代码我们可以看到一个简单的登录和读写操作,首先判定我们是否登录成功,我们已经破解成功并登录了,然后就是获取用户的do操作,这里的do操作我们需要进行判定具体在哪个位置进行的操作
打开f12可以看到就是我们的提交按钮的两种状态,一个是发帖时候的提交就是write另外一个就是提交后帖子的详情页面内容的提交
通过代码我们可以看到在write选项下的参数都是经过addslashes()函数进行过滤了的这个函数就是可以对单引号双引号反斜线进行转义这就是刚开始简单注入无效的原因
但是addslashes函数虽然会对输入的payload进行转义加上斜杠,但是在写入数据库的时候并不会进行转义而是直接写入不会带上斜杠,这里我们可以简单的实验一下
这里我将某个登录界面的用户登录获取设置为addslashes函数进行包裹
然后在去登录界面进行登录
我们可以看到登录的账号和数据库的写入是一模一样的并没有带入斜杠
那么回到刚才的步骤,既然不会影响写入数据库那我我就能够考虑到二次注入的可能性,刚好在comment选项中
会再次调用category参数并写入数据库,最后回显到页面,回显去网页查看可以知道是content参数,那么我们可以在第一个写贴的页面构造这样一个payload
insert into board set category= '',content=database(),/*',.....bo_id='*/#'"
这样就成功实现闭合后构造出自己的payload,在留言框可以看到已经成功的看到数据库的名字。
这就是一个实现二次注入的简单例子,就是通过写入数据库数据在调用的一个过程,这种注入比赛有很多题目,只有多练习才能有更大的收获。