前言
在Windows10环境下,使用php-curl进行跨域请求伪造,避开验证 HTTP Referer 字段,提交登录信息,
需求分析
有一个WIFI登陆页,想写程序自动填写登陆信息表单并提交给认证页
起初想通过Javascript,对登录页模拟按钮点击或调用其自带函数来实现,但发现认证页会检测登录信息来源是否与认证页同域,报错内容为CORS 头缺少 'Access-Control-Allow-Origin'
,即访问请求来源不是和认证页同域的.
那么我想伪造HTTP头的Referer字段
(表明访问请求来自哪个网页地址)为同域的登录页地址,让认证页以为是同域访问而Javascript(包括jquery的ajax)不能修改发送的HTTP头,解决不了这个跨域问题.
另外这个登录页只能由手机端访问,也需要伪造客户端类型User-Agent
网上调研后得知PHP等后端语言可以实现对HTTP头的修改,从而有可能实现对来源Referer
和客户端类型User-Agent
的HTTP头自定义.
环境配置
从最初搭建环境说起.php这个后端语言需要服务器环境才能运行.
PHP配置文件
PHP版本:官网的php-7.0.30-nts-Win32-VC14-x64.zip
把php目录下的php.ini-development改成php.ini,查找以下配置语句,去分号启用
;我的注释:curl的扩展开启
extension_dir = "./ext"
extension=php_curl.dll
;我的注释:nginx和cgi的联动开启
cgi.fix_pathinfo=1
使用curl可能还得把libeay32.dll
和ssleay32.dll
丢进C:/Windows/System32/
,
PHP本地服务器
PHP运行所需的服务器环境有两种选择:
方法一是正规的Nginx服务器;
方法二是PHPstrom这个IDE编译运行时自带的模拟调试器.
方法一 Nginx
版本:nginx-1.14.0
修改nginx.conf
在nginx/conf目录下对nginx.conf进行修改,去#启用以下命令
nginx运行一个php文件,需要一个php-cgi.exe联动,占用一个地址端口。
若想运行多个php文件,cgi在Windows不会分多线程,只能开多几个端口,启动多个cgi,一个萝卜一个坑。
#日志
error_log logs/error.log;
http{
#日志
access_log logs/access.log;
#
#4个萝卜坑,能最多运行4个php文件
upstream fastcgi_backend{
server 127.0.0.1:9000;
server 127.0.0.1:9001;
server 127.0.0.1:9002;
server 127.0.0.1:9003;
}
#工作目录html,存放.php,.html等等网页文件,它们要运行得去fastcgi_backend找萝卜坑
location ~ \.php$ {
root html;
fastcgi_pass fastcgi_backend;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
#拒绝ht后缀的文件
location ~ /\.ht {
deny all;
}
}
启用nginx和php-cgi
分别从php和nginx的目录,开启1个nginx.exe和4个不同端口的php-cgi.exe,从而开启本地服务器
allstart.bat
SET php_home=F:/php/
SET nginx_home=F:/nginx-1.14.0/
start "cgi1" /MIN "%php_home%php-cgi.exe" -b 127.0.0.1:9000 -c "%php_home%php.ini"
start "cgi2" /MIN "%php_home%php-cgi.exe" -b 127.0.0.1:9001 -c "%php_home%php.ini"
start "cgi3" /MIN "%php_home%php-cgi.exe" -b 127.0.0.1:9002 -c "%php_home%php.ini"
start "cgi4" /MIN "%php_home%php-cgi.exe" -b 127.0.0.1:9003 -c "%php_home%php.ini"
start "nginx" "%nginx_home%nginx.exe"
pause
运行php文件
例如创建一个test.php
文件,通过访问http://localhost/test.php
即可运行它
关闭nginx和php-cgi
stop.bat
@ECHO off
ECHO Stopping nginx...
TASKKILL /F /IM nginx.exe
ECHO Stopping PHP FastCGI...
TASKKILL /F /IM php-cgi.exe
pause
方法二 PHPstrom
版本:2018.1.2
是Webstrom的升级版,多了php的支持.这类IDE自带模拟服务器的功能.
关联php.exe
FIle->Setting->Language&Frameworks->PHP
CLI Interpreter
关联PHP目录的php.exe
PHP language level
选择7.0
运行php文件
新建工程,新建php文件,像运行html一样点开浏览器图标即可运行
程序编写
php的curl模块能够制作HTTP包,以POST或者GET的方式向目标地址发送数组数据,还能伪造客户端来源,伪造客户端类型,接收目标地址的返回的json对象.
将客户端来源referer改成认证页同域的地址,从而欺骗目标,避开目标只有同域才能访问的限制,实现跨域访问.
post-roomwifi.php
<?php
function roompost(){
//根据登录网的表单元件名填写
$post_data = array (
//账号密码
"lpsUserName"=>'2222222',
"lpsPwd"=>'33333333',
//登录页已有参数得打上
'wlanuserip'=>'172.16.0.222',
'basip'=>'61.148.2.182'
);
//伪造来源的同域地址
$referer='http://114.247.41.52:808/protalAction!index.action?wlanuserip=172.16.0.222&basip=61.148.2.182';
//目标地址
$authurl='http://114.247.41.52:808/protalAction!portalAuth.action?';
//HTTP头其他选项
$header_ip=array(
/*
这个内容类型Content-Type(目标网站响应的对象类型),是什么格式?
不是application/json,
也不是content-type:application/x-www-form-urlencoded,
而是跟底下的"POST" 操作CURLOPT_POSTFIELDS有关.由php官网curl的文档可查到,
如果value是一个数组,Content-Type头将会被默认设置成multipart/form-data,一种提交文件用的数据编码格式
*/
'Content-type:multipart/form-data',//不写也行
);
//创建curl实例
$ch = curl_init();
//目标认证地址
curl_setopt ($ch, CURLOPT_URL,$authurl);
//伪装来源为登录页面,实现跨域访问伪造CSRF
curl_setopt ($ch,CURLOPT_REFERER,$referer);
//定义HTTP头的其他选项
curl_setopt($ch, CURLOPT_HTTPHEADER, $header_ip);
//1表示post,0表示用get
curl_setopt($ch, CURLOPT_POST, 1);
//传表单数据
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
//假装是火狐手机浏览器,因为这个登录页只有手机能认证
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Linux; Android 7.0; PLUS Build/NRD90M)");
//1表示把目标返回消息,作为之后的curl_exec()的返回结果;0表示直接输出返回消息不保存
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
//发送
$out_put=curl_exec ($ch);
//关闭curl实例
curl_close ($ch);
//看返回结果,返回是个json对象
echo $out_put;
return $out_put;
}
roompost();
调试
目标地址返回text/html
的文本出错了哈!
,是不恰当修改HTTP头的某些内容所致,比如Content-type
目标地址返回application/json
的json对象
{"msg":"connection created","obj":null,"success":false}
并且可以上网,认证成功
参考资料
Window+nginx+php-cgi的php-cgi线程/子进程问题
Windows下的Nginx安装与配置(PHP)
php curl伪造referer与来源IP实例
Client URL 库-PHP官网
Php+jquery+ajax简单Ajax调用示例