J2TEAM Security: A must-have extension for Chrome users. Install now!

XSS có nguy hiểm hay không?

Xin chào, mình là Juno_okyo. Như các bạn đã biết thì Cross Site Scripting (hay còn gọi là XSS) là một lỗi bảo mật cho phép người tấn công (Attacker, Hacker, Pen-tester,…) chèn và thực thi những đoạn mã nguy hiểm vào trong trang web bị dính lỗi. Những đoạn mã được chèn vào có thể là HTML, JavaScript hay thậm chí là những đoạn Text – văn bản thuần, nhưng đa phần sẽ là JavaScript.


Xin chào, mình là Juno_okyo.

Như các bạn đã biết thì Cross Site Scripting (hay còn gọi là XSS) là một lỗi bảo mật cho phép người tấn công (Attacker, Hacker, Pen-tester,…) chèn và thực thi những đoạn mã nguy hiểm vào trong trang web bị dính lỗi. Những đoạn mã được chèn vào có thể là HTML, JavaScript hay thậm chí là những đoạn Text – văn bản thuần, nhưng đa phần sẽ là JavaScript.
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCXa0kQM1lU_5gzMPPkOrH00XhakCs_M91qaKV-vSihaOdqsBhEf6GdRgBii_YaCPBMsU3V98Px74OFD6I-DvoL6UgmYWFo3rrBY9kRrsw5j_XK-8ohDtSRM_AvK8k0ijRRsa6tZhaHj-h/s320/xss-threat3.jpg

Nhưng có một sự thật là nhiều người thường nghĩ XSS không hề nguy hiểm (so với các lỗi bảo mật khác như SQL Injection, CSRF,…), có lẽ vì họ nghĩ XSS đơn giản chỉ là tạo ra một hộp thoại thông báo hay chỉ là ghi vài dòng chữ vào trong trang web. Cũng vì lý do đó mà nhiều Web-master thường chủ quan khi không lọc dữ liệu vào – ra (input – output). Hãy nhớ rằng, XSS luôn là một trong những lỗi bảo mật phổ biến thường gặp nhất và luôn nằm trong Top những lỗi bảo mật nguy hiểm xếp ngang hàng với SQL InjectionXSS còn có thể là một trong những tiền đề dẫn tới một cuộc tấn công CSRF. Nếu bạn nghĩ XSS không hề nguy hiểm thì chứng tỏ bạn chưa biết về DOM (Document Object Model), XSS sẽ thực sự nguy hiểm khi nó trở thành DOM-Base XSS.


Trong các bài viết trước mình đã từng giới thiệu về XSSDOM nên mình sẽ không nói lại các khái niệm cơ bản như XSS là gì hay DOM là gì, các bạn tự tìm hiểu thêm nhé. Hôm nay chúng ta sẽ cùng xem một vài ví dụ về hình thức tấn công DOM-Base XSS. Như các bạn đã biết (đặc biệt các Web-master, Developer) thì mọi trang web đều dựa trên DOM, sơ đồ của DOM như sau:



Nếu xét theo khái niệm cơ bản thì XSS là chèn các đoạn mã vào trong trang, ở đây ta xét theo trường hợp là các đoạn mã JavaScript. Sự nguy hiểm của DOM-Base XSS chính là với JavaScript, bạn có thể truy cập và thao tác với mọi đối tượng trong DOM. Sau đây là một vài ví dụ với những đoạn JavaScript cơ bản, trước tiên ta cần giả lập một trang bị dính lỗ hổng bảo mật XSS như sau:


Xem trên trình duyệt:



Trước tiên ta thử đăng một đoạn văn bản nào đó:
 
Ta thấy dòng Status sẽ thay đổi, OK vậy là có in lại truy vấn, giờ ta thử thay bằng đoạn JavaScript cơ bản để Test XSS:

<script>alert("XSS")</script>



Một hộp thoại thông báo hiện lên, như vậy là nạn nhân đã dính XSS. Chúng ta bắt đầu đi vào vấn đề chính của ngày hôm nay: DOM-Base XSS. Trước khi tiếp tục, mình sẽ thêm vào trang một đoạn code chứa các links như sau:


OK, đoạn code trên sẽ mô phỏng các liên kết trên trang dính lỗi bảo mật như Menu, Footer hoặc các liên kết tới bài viết. Chúng ta đi vào ví dụ 1 về DOM-Base XSS:

Ví dụ 1: Thay đổi toàn bộ liên kết trong một trang web dính lỗi




Kết quả sau khi Inject:


Như các bạn thấy trong hình, khi ta trỏ con trỏ vào một link bất kì thì thanh Status của trình duyệt sẽ hiển thị liên kết mục tiêu – và trong hình trên liên kết đã thay đổi thành địa chỉ của Juno_okyo’s Blog và khi ta Inspect Element bằng Firebug thì toàn bộ Link từ 1 tới 10 đều đã chuyển thành http://junookyo.blogspot.com/. OK vậy là chỉ với một vòng lặp For đơn giản, ta đã Inject và thay đổi toàn bộ liên kết trong trang web dính lỗi về một địa chỉ mà ta muốn.

Mở rộng ra, nếu xét trường hợp thực tế thì sẽ ra sao nếu Hacker/Attacker chèn đoạn mã độc thay đổi toàn bộ liên kết trong trang thành địa chỉ chứa mã độc, tệp tin chứa Virus/Malware,… ? Điều này sẽ thực sự rất rất nguy hiểm nếu trang web dính lỗi lại là một trang web có lưu lượng truy cập lớn thì sự ảnh hưởng của nó sẽ khó mà tránh khỏi.

Ví dụ 2: Thay đổi toàn bộ nội dung của một trang chỉ với một click từ người dùng

Ta sẽ thay đổi lại một chút đoạn vòng lặp trong ví dụ 1 như sau:


Sau khi Inject xong, trong trường hợp người dùng truy cập vào trang đã bị Inject và click vào một liên kết bất kì trong trang thì hãy xem chuyện gì sẽ xảy ra:


WOW, URL của trang thì vẫn bình thường không bị chuyển hướng đi đâu cả. Nhưng cả trang web chỉ còn lại vẻn vẹn một đoạn Text « I am Juno_okyo ». Các bạn đã thấy JavaScript tương tác với DOM mạnh như nào rồi chứ?

Ví dụ 3: thay đổi tệp tin xử lý của Form trong trang

Trong ví dụ 3, chúng ta sẽ Inject một đoạn JavaScript thay đổi giá trị thuộc tính mục tiêu xử lý của Form (thuộc tính action). Trong hình đầu tiên các bạn sẽ thấy action hiện tại đang là index.php:


Kết quả sau khi Inject, action của Form đã chuyển thành « juno_okyo.php »:


Mở rộng từ ví dụ 3: xét theo trường hợp nếu một trang đăng nhập bị dính lỗi bảo mật XSS sẽ nguy hiểm như nào? Hacker/Attacker có thể thay đổi action sang một tệp PHP khác xử lý các giá trị nhận được bao gồm tài khoản, mật khẩu thậm chí là các thông tin nhạy cảm khác tùy vào nơi dính lỗ hổng XSS là khu vực đăng nhập, đăng ký, thanh toán,… Hacker/Attacker hoàn toàn có thể lưu lại (log) sau đó giả mạo việc đăng nhập bằng cách gửi trả (POST) dữ liệu tới tệp tin xử lý thật của Form ban đầu.

Ví dụ 4: Đặt bẫy sự kiện trong trang dính lỗi

Như chúng ta đều biết thì JavaScript là một ngôn ngữ kịch bản, có khả năng bắt và xử lý các sự kiện từ người dùng (khi trang đang tải, khi có một phím được nhấn, khi con trỏ di chuyển hay click, khi một Form nào đó được Submit,…). Trong ví dụ này, Juno_okyo sẽ đặt bẫy khi người dùng nhấn vào nút Save Status – tức là khi Form trên trang được Submit:


Sau khi nhấn Save, đoạn mã đã được Inject vào trong trang sẽ thiết lập thêm thuộc tính OnSubmit vào Form để bẫy sự kiện mỗi khi người dùng nhấn vào Save Status. Kết quả:


Nhìn trong khung Inspect Element của Firebug, chúng ta thấy thuộc tính đã được Inject thành công. Và khi Juno_okyo nhấn vào Save Status thì một hộp thoại thông báo đã hiện lên, khi nhấn OK thì trang đứng im vì đoạn JavaScript đã return false sau khi thông báo.

Hiện một hộp thông báo chỉ là mô phỏng trong ví dụ trên, mở rộng ra từ ví dụ 4, xét trường hợp nếu Hacker/Attacker viết một hàm xử lý Form rồi đặt thuộc tính OnSubmit trỏ tới hàm đó. Khi người dùng nhấn Submit Form thì hàm đó bắt các giá trị và thích làm gì thì làm sẽ ra sao nhỉ? Theo trường hợp Form đó nằm trong một trang thanh toán, mà người dùng phải nhập giá trị hàng và địa chỉ nhận hàng, nếu hàm xử lý thay đổi giá trị là địa chỉ nhận hàng mới rồi mới submit tới tệp tin xử lý của Form thì mức độ thiệt hại tất nhiên là người dùng chịu rồi.

Kết luận

OK, qua 4 ví dụ trên Juno_okyo đã chỉ ra mức độ nguy hiểm của lỗi bảo mật XSS với trường hợp tấn công sử dụng kỹ năng DOM-Base XSS. Xin nhắc lại là JavaScript hoàn toàn có thể truy cập và tương tác với mọi phần tử của DOMXSS chính là bước đà giúp Hacker/Attacker chèn các đoạn mã JavaScript vào trong trang nạn nhân. Vì thế chúng ta – trên phương diện là các Web-master/Developer khi phát triển một Website không thể chủ quan, coi thường những lỗ hổng cơ bản như XSS, luôn cẩn trọng trong việc xử lý các nơi dữ liệu đầu vào từ người dùng như Form đăng nhập, đăng ký, tìm kiếm thông tin,… Lọc tất cả dữ liệu trước khi lưu vào cơ sở dữ liệu hoặc khi in ra trên trang.

Ngăn ngừa, lọc và vá các lỗ hổng XSS

Việc chặn các lỗ hổng XSS xảy ra không khó, bạn chỉ cần cẩn thận với các dữ liệu được nhập vào từ người dùng trước khi in ra. Trong ví dụ ngày hôm nay, Juno_okyo sẽ viết lại tệp tin mô phỏng như sau:


Các bạn hoàn toàn có thể chỉ cần dùng một trong hai hàm trên, nhưng mình thì thường lồng cả hai hàm với nhau (htmlentities lồng ngoài strip_tags). Lý do:
·        Strip_tags sẽ giúp lọc toàn bộ những chuỗi là thẻ HTML từ người dùng (đủ an toàn).
·        Htmlentities sẽ lọc lần 2, tác dụng của hàm này là chuyển tất cả những ký tự nguy hiểm thành các ký tự HTML an toàn.
Kết quả sau khi vá lỗ hổng XSS:


Sau khi đoạn JavaScript được Inject:
·        Strip_tags: lọc đoạn script – loại bỏ 2 thẻ <script></script> nên chỉ còn chuỗi: alert(‘I am Juno_okyo’).
·        Htmlentities: lọc tiếp chuỗi lần 2 chuyển 2 dấu nháy kép thành &quot ; (chúng ta sẽ vẫn thấy nháy kép trên trang, nhưng khi view-source sẽ thấy tác dụng của Htmlentities).

Vậy là xong, chúng ta đã có xử lý và cản lọc dữ liệu đầu vào từ người dùng. Bài viết tới đây là hết, hãy chia sẻ nếu thấy hay và ủng hộ cho Juno_okyo. Mọi ý kiến đóng góp hay góp ý thêm cho bài viết xin gửi về địa chỉ Email: junookyo@gmail.com hoặc juno_okyo@yahoo.com.vn . Cảm ơn đã theo dõi!

Chúc các bạn thành công!
Mọi trường hợp chia sẻ bài viết hoặc đăng tải lại lên các Website/Forum khác vui lòng ghi rõ nguồn: Juno_okyo’s Blog (http://junookyo.blogspot.com).
Leader at J2TEAM. Website: https://j2team.dev/

7 nhận xét

  1. Anh ơi, em muốn đăng bài này lên website của em và ghi nguồn là Junookyo Blog Spot có được không ạ?
    1. Tự nhiên đi anh :D
  2. Bài Viết rất Pro...........Rất đáng để học hỏi
  3. Đôi khi rất xem thường XSS, nhưng mà qua bài này công nhận hiểu được nhiều hơn .........Thank junookyo nhieu
  4. Cậu XSS như thế thì chỉ có máy tính cậu thực thi đoạn xss do cậu đặt ra thôi.

    Còn nếu muốn người dùng dính mã độc do mình thiết lập như virus,trojan v.v... thì phải là XSS được lưu lại. Nghĩa là XSS được thực thi trên máy victim.

    Còn XSS dạng này chỉ dùng được cho ta thôi.

    Mình noob, có gì xin chỉ giáo thêm :)
    1. Trong bài viết này mình đã ghi là mô phỏng một trang bị dính lỗi bảo mật XSS.

      Nên mình chỉ code sơ qua. DOM XSS hoàn toàn có thể áp dụng với các trường hợp Stored XSS (tức là kiểu XSS như bạn nói).

      Link dưới đây là một bài viết khác mình test trên Stored XSS nhé :)
      http://junookyo.blogspot.com/2014/05/showcase-j2team-xss-injector.html
  5. Cho mình hỏi là hàm strip_tags hay htmlentities có bypass được không ?
Cảm ơn bạn đã đọc bài viết!

- Bạn có gợi ý hoặc bình luận xin chia sẻ bên dưới.

- Hãy viết tiếng Việt có dấu nếu có thể!