JavaScript 伪造 Referer 来路方法

Javascript 是一种由Netscape的LiveScript发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,好比Perl,遗留的速度问题,为客户提供更流畅的浏览效果。javascript

 

 

由于服务器端脚本能够轻易伪造referer,因此各大统计站点cnzz,百度统计,ga,51la等都是经过js来判断来路,不过如今有个方法js的referer也能够伪造了。php

WinHttp.WinHttpRequest.5.1 是 msxml 4.0 的底层对象,也就是说 XMLHTTP/ServerXMLHTTP 也是在它的基础上封装而来。用 WinHttpRequest 发的请求,Fiddler 监测不到。html

Google一下发现它竟然用能够成功伪造全部 http 请求的 header 信息!下面的代码经过伪造 referer 的值,伪装从百度首页提交一个表单到指定的 url 去:java

var url = "http://www.yourtarget.com";  
var param = "name=david&age=30";  
var obj = new ActiveXObject("WinHttp.WinHttpRequest.5.1");  
obj.Open("POST", url, false);  
obj.Option(4) = 13056;  
obj.Option(6) = false; //false能够不自动跳转,截取服务端返回的302状态。  
obj.setRequestHeader("Content-Type","application/x-www-form-urlencoded");  
obj.setRequestHeader("Referer", "http://www.baidu.com");  
obj.Send(param);  
WScript.Echo(obj.responseText);

既然能够用它来伪造全部 http 请求的 header,那 Cookies、Sessionid 天然也就能够获得并传递了。下面是实战代码,用命令行登陆博客园,共三次请求,第一次请求获取表单的 VIEWSTATE 和 EVENTVALIDATION,第二次带帐户登陆,第三次带Cookie访问其首页:json

//封装成远程访问的函数  
function RemoteCall(method, url, param, header){  
    var obj = new ActiveXObject("WinHttp.WinHttpRequest.5.1");  
    obj.Open(method||"GET", url, false);  
    obj.Option(4) = 13056;  
    obj.Option(6) = false;  
    if(method=="POST"){  
        obj.setRequestHeader("Content-Type","application/x-www-form-urlencoded");  
    }  
    if(header){  
        for(var key in header){  
            if(key=="Cookie"){//根据 MSDN 的建议,设置Cookie前,先设置一个无用的值  
                obj.setRequestHeader("Cookie", "string");  
            }  
            obj.setRequestHeader(key, header[key]);  
        }  
    }  
    obj.Send(param);  
    return obj;  
}  
//第一次远程访问博客园的登陆入口  
var url = "http://passport.cnblogs.com/login.aspx";  
var objFirst = RemoteCall("GET", url, null);  

//取得 viewstate 与 eventvalidation  
var viewstate = objFirst.responseText.match(/id="__VIEWSTATE" value="(.*?)" \/>/)[1];  
var eventvalidation = objFirst.responseText.match(/id="__EVENTVALIDATION" value="(.*?)" \/>/)[1];  

//输入本身的帐户与密码  
var username = "";  
var password = "";  
var param = ""
+ "__VIEWSTATE="+encodeURIComponent(viewstate)   
+ "&__EVENTVALIDATION="+encodeURIComponent(eventvalidation)   
+ "&tbUserName="+username  
+ "&tbPassword="+password  
+ "&btnLogin="+encodeURIComponent("登  录");  

var objSecond = RemoteCall("POST", url, param);  

//登陆成功后服务器执行 Response.Redirect 跳转,即向客户端发送了 302 状态代码  
WScript.Echo(objSecond.status); //302即登陆成功, 若是是200,则登陆失败,页面没有跳转  

//带上登陆成功后的cookie,再次访问其首页  
var json = {"Cookie": objSecond.getResponseHeader("Set-Cookie")};  
var objThird = RemoteCall("GET", "http://www.cnblogs.com", null, json);  
fso = this.fso || new ActiveXObject("Scripting.FileSystemObject");
var file = "c:/output.txt", newTxt = 0;
newTxt = fso.OpenTextFile(file, 2, true);
newTxt.WriteLine(objThird.responseText);
//WScript.Echo(objThird.responseText);

 

上面的代码其实已经有必定恶意,只为证实使用 WinHttpRequest 确实能够模拟浏览器发送请求,服务端也没法区别是从浏览器来的,仍是从命令行来的。浏览器

 

结论:从客户端提交来的任何数据都不可信,由于发送的 http 数据包不但表单值能够修改,连数据包的 header 均可以随意修改。同时也说明,使用 VIEWSTATE 对表单的安全性无任何用处。安全

文章来自:http://www.phperz.com/article/14/0702/2917.html服务器

相关文章
相关标签/搜索