Lỗi bảo mật này thường ít được chú ý đến, nhưng thiệt hại của nó cũng không kém so với XSS. Cơ chế của lỗi này là đánh lừa người dùng thực hiện việc họ không muốn như xóa dữ liệu, tài khoản, gửi nội dung sai mục đích... Lỗi này thường được kết hợp với XSS để đánh lừa dễ dàng hơn. Ví dụ ta có một form gửi bài viết mới: post-csrf.php
Sau đó, chèn đoạn mã sau đây vào trang nào đó:<?php
if(isset($_GET['title'])) {
file_put_contents('new_post.txt', $_GET['title']."\n", FILE_APPEND);
echo 'OK';
} else {
?>
<form action="">
Title: <input type="text" name="title"/>
<input type="submit" value="Post">
</form>
<?php } ?>
Khi chạy trang có chèn mã trên, nội dung sẽ được lưu trữ trong new_post.txt. Đối với ví dụ này thì không có gì nguy hiểm, nhưng nếu website có đường dẫn để xóa bài viết hay tài khoản nào đó:<img src="http://localhost/post-csrf.php?title=test" />
Nếu không bảo mật, bài viết thứ 123 sẽ bị xóa khi bất kỳ ai truy cập vào trang có đoạn mã trên. Nếu là một trang bán hàng nào đó, có URL: buy.php?item=1 thì rất có thể người dùng sẽ bị thiệt hại tài sản khi đặt hàng những thứ mà mình không có chủ ý mua. Hoặc nguy hiểm hơn, hacker có thể đánh lừa người quản trị truy cập trang có mã độc để xóa hay sửa đổi dữ liệu của website mà người quản trị không hay biết. Website sẽ chứa đầy spam nếu phần xử lý gửi bài viết của diễn đàn, trang tin chưa xử lý lỗi CSRF!!!<img src="http://localhost/post-csrf.php?type=post&id_delete=123" />
Cách chống CSRF
- Lỗi này một phần là do bạn đã sử dụng phương thức $_GET để thực hiện các hành động. Cách tốt nhất là hãy chuyển sang $_POST và hãy quên đi $_REQUEST. - Dùng token để xác thực hành động và nên tạo một trang xác nhận khi thực hiện hành động nào đó.
Đoạn mã trên tạo một token và lưu nó vào trong Session tại thời điểm người dùng duyệt trang này, như vậy sẽ không thể thực hiện hành động lúc nào cũng được.Mã:
- set_magic_quotes_runtime(FALSE);
- $token = md5(uniqid(rand(), TRUE));
- $_SESSION['token'] = $token;
- $_SESSION['token_timestamp'] = time();
- ?>
- <form action="" method="POST">
- <input type="hidden" name="token" value="<?=$token?>" />
- Item: <input type="text" name="item_id" /> <input type="submit" value="Post">
- </form>
- <?php
- if(isset($_POST['item_id']) && !empty($_POST['item_id'])) {
- if (isset($_POST['token']) && isset($_SESSION['token']) && $_POST['token'] == $_SESSION['token'])
- {
- $token_limit = time() - $_SESSION['token_timestamp'];
- if ($token_limit <= 300) {
- // Quá hạn thời gian
- } else {
- // Hành động hợp lệ
- }
- }
- }
Tạo trang xác nhận: Bạn hãy để ý trang Yahoo 360, khi xóa blog nào đó, bạn sẽ bấm vào liên kết GET, lúc đó mới chuyển qua trang xác nhận và hành động xóa được thực hiện bằng POST, cách này khá an toàn và thân thiện.


LinkBack URL
About LinkBacks
hiepgia
Trả lời với trích dẫn