使用 WinHttpRequest 僞造 Referer (附實戰代碼)

首先說明,僞造訪問來路不是什麼光明正大的事情,目的就是爲了欺騙服務器。本來覺得給 XMLHTTP 對象增長一個 Referer 的header 就能夠,結果卻沒有任何做用,改用 ServerXMLHTTP 也如此。json

無心間發現公司內部項目使用的 paypal 扣款程序裏面有 WinHttp.WinHttpRequest.5.1 對象,它負責把客戶的信用卡信息提交到 paypal 的服務器,看來是一個核心的遠程訪問方法,google一下發現它竟然用能夠成功僞造全部 http 請求的 header 信息!下面的代碼經過僞造 referer 的值,僞裝從百度首頁提交一個表單到指定的 url 去:瀏覽器

var url = "http://www.aspxhome.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);

保存爲 xxx.js 文件,在命令行中運行 cscript.exe xxx.js。安全

 

從msdn得知,WinHttp.WinHttpRequest.5.1 是 msxml 4.0 的底層對象,也就是說 XMLHTTP/ServerXMLHTTP 也是在它的基礎上封裝而來。用 WinHttpRequest 發的請求,連 Fiddler 也監測不到,看來確實是比較底層的東西。服務器

---------------------------邪惡的分割線------------------------cookie

既然能夠用它來僞造全部 http 請求的 header,那 Cookies、Sessionid 天然也就能夠獲得並傳遞了。下面是實戰代碼,用命令行登陸博客園,共三次請求,第一次請求獲取表單的 VIEWSTATE 和 EVENTVALIDATION,第二次帶帳戶登陸,第三次帶Cookie訪問其首頁:app

//封裝成遠程訪問的函數 
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("Set-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); 
WScript.Echo(objThird.responseText);

 

上面的代碼其實已經有必定惡意,我只爲證實使用 WinHttpRequest 確實能夠模擬瀏覽器發送請求,服務端也沒法區別是從瀏覽器來的,仍是從命令行來的。這證實到一點,從客戶端提交來的任何數據都不可信,由於發送的 http 數據包不但表單值能夠修改,連數據包的header均可以隨意修改。同時也說明,使用 VIEWSTATE 對錶單的安全性無任何用處。函數

引用一張著名的漫畫,在互聯網上,沒有人知道你是一條狗。在服務端,沒有人知道你是從命令行發送出來的。 google

相關文章
相關標籤/搜索