SQL注入--二次注入

一.基本概念

二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,当Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入。

二.注入原理

二次注入的原理:在第一次进行数据库插入数据的时候,仅仅只是使用了 addslashes​ 或者是借助 get_magic_quotes_gpc​对其中的特殊字符进行了转义,在写入数据库的时候还是保留了原来的数据,但是数据本身还是脏数据。

在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次进行需要进行查询的时候,直接从数据库中取出了脏数据,没有进行进一步的检验和处理,这样就会造成SQL的二次注入。比如在第一次插入数据的时候,数据中带有单引号,直接插入到了数据库中;然后在下一次使用中在拼凑的过程中,就形成了二次注入。

三.注入过程

  1. 先构造语句(此语句含有被转义字符的语句,如mysql_escape_string、mysql_real_escape_string 转义)
  2. 将我们构造的恶意语句存入数据库(被转义的语句)
  3. 第二次构造语句(结合前面已被存入数据库的语句构造。因为系统没有对已存入的数据做检查,成功注入)

四.靶场示例

靶场:sqli-labs less 24

1.查看初始的users​表
  • 发现表中 admin 用户的密码为 admin
2.注册用户
  • 主要代码 login_create.php​ 如下:

    复制代码
      if (isset($_POST['submit']))
      {
      # Validating the user input........
      //$username= $_POST['username'] ;
      	$username=mysql_escape_string($_POST['username']) ;
      	$pass=mysql_escape_string($_POST['password']);
      	$re_pass=mysql_escape_string($_POST['re_password']);
      	// 对注册账号时输入的数据进行转义
      	echo "<font size='3' color='#FFFF00'>";
      	$sql = "select count(*) from users where
      	username='$username'";
      	$res = mysql_query($sql) or die('You tried tobe smart, Try harder!!!! :( ');
      	$row = mysql_fetch_row($res);
      //print_r($row);
      if (!$row[0]== 0)
      {
      ?>
      <script>alert("The username Alreadyexists, Please choose a different username ")
      </script>;
      	<?php
      	header('refresh:1, url=new_user.php');
      	}
      	else
      	{
      		if ($pass==$re_pass)
      		{
      			# Building up the query........
      			$sql = "insert into users (
      			username, password) values(\"$username\",\"$pass\")";
      			mysql_query($sql) or die('Error Creating your user account, : '.mysql_error());

    可以在该php文件末尾添加一句代码,在网页中打印出创建的用户名。

    ​echo "Hint: you input is: ".$username ."<br>";​

  • 注册一个名为 admin'# ,密码为 123456 的用户

3.修改用户密码

我们先查看一下此时的 users 表,发现多了一个用户admin'# ,而不是刚刚网页打印出来的 admin\'# ,这是因为创建用户的代码只是在单引号前加了一个 \ ,使得在执行的时候

单引号被认为是字符串里的一个字符,而不是被当成 sql 语句中的单引号。

  • 使用 admin'# 用户登录​

  • 修改 admin'# 用户的密码


  • 再次查看 users 表,发现用户 admin'# 的密码并没有修改,而是用户 admin 的密码被修改了。

原因

  • 介绍:在网站设计时,虽然过滤了注册的信息,把特殊字符进行了转义,但是在从数据库调用从外部保存下来的数据时,并没有进行过滤,使得 admin'# 被代入到 sql 语句执行,执行了这段 payload,达到了修改用户 admin 的密码的目的。

  • 具体代码:

    复制代码
    #原语句
    UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass'
    
    #插入 payload 后的语句
    UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass'
    #此时 'admin' 后的语句被注释
    
    #真正的生效的语句
    UPDATE users SET PASSWORD='$pass' where username='admin'
    #从而达到了修改用户 admin 密码的目的
相关推荐
有谁看见我的剑了?3 分钟前
k8s-临时容器学习
学习·容器·kubernetes
七芒星202310 分钟前
ResNet(详细易懂解释):残差网络的革命性突破
人工智能·pytorch·深度学习·神经网络·学习·cnn
easy202019 分钟前
Kaggle项目实践——Titanic: Machine Learning from Disaster
笔记·学习·机器学习
The_Second_Coming1 小时前
容器应用学习笔记:containerd 篇
运维·笔记·学习·容器·containerd
无名客01 小时前
SQL语句执行时间太慢,有什么优化措施?以及衍生的相关问题
java·数据库·sql·sql语句优化
咋吃都不胖lyh1 小时前
SQL数据分析原代码--创建表与简单查询
java·数据库·sql
知识分享小能手1 小时前
React学习教程,从入门到精通,React AJAX 语法知识点与案例详解(18)
前端·javascript·vue.js·学习·react.js·ajax·vue3
爱思德学术1 小时前
中国计算机学会(CCF)推荐学术会议-B(数据库/数据挖掘/内容检索):DASFAA 2026
数据库·区块链·数据管理·数据库系统
axban1 小时前
QT M/V架构开发实战:QAbstractItemModel介绍
java·数据库·qt
GIS开发特训营2 小时前
【智慧城市】2025年中国地质大学(武汉)暑期实训优秀作品(4):智矿中国
学习·gis·智慧城市·gis开发·webgis