目录
原理依据:Nginx与PHP对Host处理方式不同
环境搭建:
1、提前安装完成nginx+php+mysql,然后上传文件pwnhub到nginx/html下
2、修改nginx.conf配置文件:
server { listen 80; server_name www.php.com; root html/pwnhub/web; index index.html index.php index.htm; #location / { # root html/mhz/web; # index index.html index.htm 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; } }
3、在nginx/sbin目录下运行
./nginx -s reload
4、运行MySQL数据库并创建数据库和表:
[root@localhost ~]# mysql -u root -p Enter password: mysql> show databases; mysql> create database security; mysql> use security; mysql>SET NAMES utf8; mysql>SET FOREIGN_KEY_CHECKS = 0; mysql>DROP TABLE IF EXISTS `flags`; mysql>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; mysql>DROP TABLE IF EXISTS `users`; mysql>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; mysql>SET FOREIGN_KEY_CHECKS = 1;
5、在本地“C:\Windows\System32\drivers\etc/hosts”中添加映射关系。
6、在本地浏览器中访问“www.php.com”,便可以看到如下图片,默认登录页面地址为“http://www.php.com/main/login”,
切换为“http://www.php.com/main/register”就可以注册新用户,如下图所示
第一种处理方式
Nginx在处理Host的时候,会将Host用冒号分割成hostname和port,port部分被丢弃。所以,我们可以设置Host的值为www.php.com:xxx'"@example.com
,这样就能访问到目标Server块:
如上图,成功触发SQL报错。
总结:Nginx通过冒号分隔只截取到冒号之前的内容,而PHP会将全部内容都拿到。
第二种处理方式
当我们传入两个Host头的时候,Nginx将以第一个为准,而PHP-FPM将以第二个为准。
Host:www.php.com Host:xxx'"@example.com
Nginx将认为Host为www.php.com
并交给Server处理;但是PHP中使用$_SERVER['HTTP_HOST']
取到的值却是xxx'"@example.com
。这种方法也可以实现绕过。
注意:只有Nginx+PHP会出现这个问题,Apache与此不同,将会是另一种情况。
第三种处理方式
原理:在发送https数据包的时候,SNI中指定的域名是example2.com,而无需和HTTP报文中的Host头保持一致,Nginx会选择SNI中的域名作为Server Name。
我们可以直接使用Burpsuite来测试这个trick,比如我在后端编写PHP代码echo $_SERVER['HTTP_HOST']。正常访问是会显示此时的Host头。
在HTTP协议时,如果我们修改Host头,Nginx将因为识别不到Server Name被导向默认的页面。
但此时我们在Burpsuite里修改协议为https,并指定好https的Host,也就是SNI,如图4。我们再修改HTTP数据包的Host头,就能正常访问目标后端了。