Mã thông báo xác thực được sử dụng để ngăn chặn các cuộc tấn công giả mạo yêu cầu chéo trang web (CSRF). Để hiểu mã thông báo xác thực, trước tiên bạn phải hiểu các cuộc tấn công CSRF.
CSRF
Giả sử bạn là tác giả của bank.com
. Bạn có một biểu mẫu trên trang web của mình được sử dụng để chuyển tiền sang một tài khoản khác với yêu cầu NHẬN:
Một hacker có thể gửi yêu cầu HTTP đến máy chủ GET /transfer?amount=$1000000&account-to=999999
, phải không?
Sai lầm. Các tin tặc tấn công sẽ không hoạt động. Các máy chủ về cơ bản sẽ nghĩ gì?
Huh? Anh chàng này đang cố gắng để bắt đầu một sự chuyển giao. Đó không phải là chủ sở hữu của tài khoản, đó là điều chắc chắn.
Làm thế nào để máy chủ biết điều này? Bởi vì không cósession_id
cookie xác thực người yêu cầu.
Khi bạn đăng nhập bằng tên người dùng và mật khẩu, máy chủ sẽ đặt session_id
cookie trên trình duyệt của bạn. Bằng cách đó, bạn không phải xác thực từng yêu cầu bằng tên người dùng và mật khẩu của mình. Khi trình duyệt của bạn gửi session_id
cookie, máy chủ sẽ biết:
Ồ, đó là John Doe. Anh ấy đã đăng nhập thành công 2,5 phút trước. Anh ấy tốt để đi.
Một hacker có thể nghĩ:
Hừm. Một yêu cầu HTTP bình thường sẽ không hoạt động, nhưng nếu tôi có thể chạm tay vào session_id
cookie đó , tôi sẽ rất tuyệt vời.
Trình duyệt người dùng có một loạt các cookie được đặt cho bank.com
tên miền. Mỗi khi người dùng đưa ra yêu cầu cho bank.com
tên miền, tất cả các cookie sẽ được gửi cùng. Bao gồm cảsession_id
cookie.
Vì vậy, nếu một hacker có thể có được bạn thực hiện yêu cầu GET chuyển tiền vào tài khoản của mình, anh ta sẽ thành công. Làm thế nào anh ta có thể lừa bạn làm như vậy? Với giả mạo yêu cầu trang web chéo.
Nó thực sự đơn giản. Các hacker chỉ có thể khiến bạn truy cập trang web của mình. Trên trang web của mình, anh ta có thể có thẻ hình ảnh sau:
<img src="http://bank.com/transfer?amount=$1000000&account-to=999999">
Khi trình duyệt người dùng bắt gặp thẻ hình ảnh đó, nó sẽ tạo một yêu cầu GET cho url đó. Và vì yêu cầu đến từ trình duyệt của anh ấy, nên nó sẽ gửi cùng với tất cả các cookie được liên kết bank.com
. Nếu người dùng gần đây đã đăng nhập vào bank.com
... session_id
cookie sẽ được đặt và máy chủ sẽ nghĩ rằng người dùng có nghĩa là chuyển 1.000.000 đô la vào tài khoản 999999!
Chà, đừng truy cập các trang web nguy hiểm và bạn sẽ ổn thôi.
Điều đó là không đủ. Điều gì nếu một ai đó đăng hình ảnh đó lên Facebook và nó xuất hiện trên tường của bạn? Điều gì xảy ra nếu nó được đưa vào một trang web bạn đang truy cập bằng một cuộc tấn công XSS?
Nó không quá tệ. Chỉ các yêu cầu GET là dễ bị tổn thương.
Không đúng. Một hình thức gửi yêu cầu POST có thể được tạo động. Dưới đây là ví dụ từ Hướng dẫn Rails về Bảo mật :
<a href="http://www.harmless.com/" onclick="
var f = document.createElement('form');
f.style.display = 'none';
this.parentNode.appendChild(f);
f.method = 'POST';
f.action = 'http://www.example.com/account/destroy';
f.submit();
return false;">To the harmless survey</a>
Mã xác thực
Khi bạn ApplicationController
có thứ này:
protect_from_forgery with: :exception
Điều này:
<%= form_tag do %>
Form contents
<% end %>
Được tổng hợp vào đây:
<form accept-charset="UTF-8" action="/" method="post">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
Form contents
</form>
Cụ thể, những điều sau đây được tạo ra:
<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
Để bảo vệ chống lại các cuộc tấn công CSRF, nếu Rails không thấy mã thông báo xác thực được gửi cùng với yêu cầu, nó sẽ không xem xét yêu cầu đó an toàn.
Làm thế nào một kẻ tấn công được cho là biết mã thông báo này là gì? Một giá trị khác nhau được tạo ngẫu nhiên mỗi khi biểu mẫu được tạo:
Một cuộc tấn công Cross Site Scripting (XSS) - đó là cách. Nhưng đó là một lỗ hổng khác nhau cho một ngày khác nhau.