Cross-site History Manipulation (XSHM)

Kaito KID

VIP Members
02/07/2013
23
41 bài viết
Cross-site History Manipulation (XSHM)
[h=4]1. Tổng quan[/h][h=5]1.1 Same Origin Policy (SOP)[/h]SOP là cơ chế của các ngôn ngữ client-script (như Javascript) chỉ cho phép các trang trên một site truy cập đến nội dung của những trang khác trên cùng site đó. Những nội dung này có thể là mã HTML, cookie, history,…Cơ chế này cho phép một trang web có thể gửi các request đến các trang khác không cùng site đó nhưng không thể nhận được kết quả trả về. Ví dụ trang http://bkav.com.vn/a.aspx có thể chèn iframe: nhưng không thể biết nội dung bên trong của iframe này: document.getElementById(“google”).innerHTML là không thể.
Một số kỹ thuật khai thác client-side, điển hình là XSS giúp hacker vượt qua cơ chế này và lấy được cookie của người dùng.
[h=5]1.2 Browser History Object[/h]Cross-site History Manipulation dựa trên một đối tượng trong Javascript là history object. History object chứa thông tin về các trang web đã duyệt qua trong một browser tab. Mỗi browser tab là một đối tượng history riêng biệt.
Cơ chế SOP không cho ta biết được danh sách các URL trong history object, tuy vậy nó không chặn:

    • Thuộc tính history.length: số các URL trong history object
    • Phương thức history.go(URL): chuyển hướng đến URL nếu nó tồn tại trong history object
Các kỹ thuật khai thác XSHM sẽ được giới thiệu dưới đây dựa trên hai điểm này.
[h=4]2. Khai thác XSHM[/h][h=5]2.1 Khai thác XSHM sử dụng history.length[/h][h=6]2.1.1 Điều kiện[/h]Do cơ chế thực thi Javascript ở mỗi trình duyệt là khác nhau nên không phải tất cả các trình duyệt đều có thể bị khai thác XSHM. Để khai thác được XSHM dựa trên history.length, trình duyệt phải thỏa mãn 3 điều kiện cơ bản sau:
i. Cơ chế redirect: Nếu trang A chứa một redirect đến trang B thì chỉ trang B được lưu trong history object.
ii. Giả sử trình duyệt đang ở trang A (tức là A đang ở đầu danh sách trong history object), ta request đến A một lần nữa thì A không được lưu thêm vào history object.
iii. Nếu trang A chứa một iframe đến trang B thì B cũng được lưu trong history object.
Qua thử nghiệm trên một số các trình duyệt phổ biến thì chỉ có IE thỏa mãn cả ba điều kiện này. Do đó khai thác XSHM dựa trên history.length chỉ thực hiện trên IE.
Internet Explorer8.0
Firefox3.5.9
Chrome5.0.375.55
Opera10.53
Safari4.0.5
i
ii
iii

[h=6]2.1.2 Kỹ thuật khai thác[/h]Nếu một trang web có điều kiện rẽ nhánh như sau:
Page A: If (CONDITION)
Redirect(Page B)
thì ta có thể kiểm tra được giá trị của CONDITION dựa vào history.length. Thuật toán như sau:

    • Tạo một iframe với giá trị src=Page B
    • Thay đổi giá trị src của iframe thành Page A
    • Nếu giá trị history.length trước và sau khi thay đổi src của iframe là như nhau à CONDITION = true
Giải thích: Khi ta tạo iframe với src=Page B, do cơ chế (i) nên Page B được lưu trên đỉnh của history.object. Khi thay đổi src của iframe = Page A:

    • Nếu CONDITION = false, điều kiện rẽ nhánh không được thực hiện, do vậy Page A sẽ được lưu vào history object, history.length tăng thêm 1
    • Nếu CONDITION = true, điều kiện rẽ nhánh được thực hiện và trình duyệt sẽ chuyển đến Page B, bình thường do B trong iframe nên nó cũng được lưu vào history object nhưng lúc này, Page B đã ở trên đỉnh của history object nên nó không lưu thêm nữa. Biến history.length không đổi.
Một ví dụ điển hình nhất của kỹ thuật này là kiểm tra đăng nhập. Giả sử một trang web protected.php yêu cầu xác thực người dùng như sau:
If (!isAuthenticated()) then
Redirect(“login.php”);
Kịch bản kiểm tra xem người dùng đã đăng nhập hay chưa như sau:

    • Tạo một iframe với src = “login.php”
    • Thay đổi src của iframe thành protected.php
    • Nếu history.length không đổi, người dùng chưa đăng nhập
Đoạn mã sau kiểm tra xem người dùng đã đăng nhập facebook chưa

Cross-Site Login Detection










var check = -1;
function checkHistory() {
if (check == -1) {
check = history.length;
document.getElementById(‘myframe’).src=’http://www.facebook.com/home.php’;
}
else {
if (check == history.length) {
alert(“Not authenticated!”);
}
else {
alert(“Authenticated”);
}
}
}


[h=5]2.2 Khai thác XSHM sử dụng history.go()[/h]Kỹ thuật này được sử dụng để kiểm tra xem người dùng đã duyệt qua những trang web nào. Hàm history.go(URL) chuyển hướng đến URL nếu nó đã tồn tại trong history object. Đoạn mã sau kiểm tra người dùng đã vào http://www.google.com.vn/ chưa dựa vào sự kiện onunload():

onunload test

function fnunload(){
alert(“unload”);
}
function check(){
history.go(‘http://www.google.com.vn/’)
}
setTimeout(“check()”, 1000);






[h=4]3. Giải pháp[/h][h=5]3.1 Khắc phục cơ chế SOP ở các trình duyệt[/h]
  • Biến history.length chỉ là số các URL đã duyệt qua trên cùng một site
  • Phương thức history.go(URL) chỉ chuyển hướng đến URL cùng site
[h=5]3.2 Khắc phục trong khâu lập trình: sử dụng token mạnh[/h]Tất cả các trang nên được chèn thêm một biến token và giá trị này được kiểm tra ở từng trang:
if (!isAuthenticated())
Header(“Location: login.php?token=” + randomToken());

Kiểm tra token, nếu không hợp lệ thì redirect đến một trang khác
if(!isValid($_REQUEST[“token”]))
Header(“Location: home.php”);
 
Mời các bạn tham gia Group WhiteHat để thảo luận và cập nhật tin tức an ninh mạng hàng ngày.
Lưu ý từ WhiteHat: Kiến thức an ninh mạng để phòng chống, không làm điều xấu. Luật pháp liên quan
Bên trên