
文章來源: HP-Fortify 翻譯整理:叡揚資訊 資訊安全事業處
上期文章中介紹了JavaScript Hijacking【劫持JavaScript程式(上)】,本次將繼續說明JavaScript的防禦方式:
第一代的網站應用程式是不易被JavaScript Hijacking攻擊的,因它們在傳輸資料時是用HTML文件的方式傳送,而不是單純只用JavaScript傳送。若應用程式無機密資料,對於JavaScript Hijacking也是相對的安全。
如果一個網站本就有跨網站指令碼攻擊的弱點(XSS),那它就無法抵擋JavaScript Hijacking的攻擊。因為XSS本身會允許執行來自同一網域的指令碼。就算一個網站沒有XSS問題,也不代表它不會遭受JavaScript Hijacking的攻擊。
因Web 2.0會處理一些機密性的資料,以下是兩種用來防禦JavaScript Hijacking的基本方法:
( 1 ) 拒絕惡意請求
( 2 )避免直接執行JavaScript的回應
最好的防範方法就是同時採用上述兩種作法。
站在伺服器的角度,JavaScript Hijacking攻擊是非常類似CSRF攻擊的,因此若能擋掉CSRF攻擊也就能擋掉JavaScript Hijacking攻擊。
為了要偵測惡意的請求,每一個請求都必須包含一個很難讓攻擊者去猜測的參數。當伺服器收到請求之後,它就去檢查那個特定的參數是否和session cookie中的一致。惡意的程式碼並不能去存取session cookie(因為同源政策),所以攻擊者並不容易去偽造一個會通過檢查的請求。除了session cookie的方法外,也可以使用一個不同的暗碼。只要你這個暗碼是很難被猜測出來的,而它只會出現在正常的應用程式中,而不能被來自不同網域的應用程式使用,它就能防止攻擊者來偽造合法的請求。
一些架構是只在客戶端作用的。換言之,它們完全是用JavaScript來執行,對於伺服器程式如何的運作是一無所知的。這指出它們並不知道session cookie的名稱。即使不知道session cookie的名稱,它仍然能在送請求到伺服器時,加入此類cookie的防禦方式。下列的JavaScript片斷,列出了"blind client"政策:
var httpRequest = new XMLHttpRequest();
...
var cookies="cookies="+escape(document.cookie);
http_request.open('POST', url, true);
httpRequest.send(cookies);
在伺服端也可以去檢查HTTP referer的表頭,來確認目前的請求是從正常的應用程式或是從惡意的程式而來。但就過往的經驗來說,HTTP referer的表頭是不可靠的,所以我們不建議用這種方式。
還有一種防禦的作法是伺服端程式只回應POST的請求,而不回應GET的請求。因為很多使用的攻擊都是使用GET請求而載入的。所以程式開發人員若為了安全性考量,那麼省略一些功能是必要的。
為了要讓一個惡意的網站去執行包含JavaScript的回應,合法的客戶端程式就可利用這點,在執行前先對其進行修改,因這些惡意程式必定包含了的標籤。當伺服端在同步一個物件時,它必須包含一個字首(prefix)來讓它能夠藉由來執行JavaScript。一個合法的客戶端程式能在執行JavaScript將這些額外的資料移除。實作的方式有非常多種,我們將列出兩種:
字首:
while(1);
除非客戶端的程式能正確的移除這個字首,否則在評鑑這個JavaScript程式後,程式將會進入無窮迴圈。
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
if (txt.substr(0,9) == "while(1);") {
txt = txt.substring(10);
}
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
第二,可在JavaScript的前後加入註解符號/* ... */,在它去呼叫eval()之前必須先去移除這些註解符號才能被正確執行。
如下列的JSON物件:
/*
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@fortifysoftware.com" }
]
*/
客戶端的程式可用下面的方式移除:
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
if (txt.substr(0,2) == "/*") {
txt = txt.substring(2, txt.length - 2);
}
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
那麼惡意網站就不能再使用來取得這些內含的資料