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服務器