Cross-Site Request Forgery (CSRF) - Series Web Application Security

1. Nội dung

  • Giới Thiệu
  • Cross-Site Request Forgery (CSRF)
  • Cách Phòng Chống
  • Các Bài Viết Liên

2. Giới thiệu

Cross-Site Request Forgery (CSRF) là cách tấn công mà kẻ tấn công sử dụng một trang web độc hại, email, blog, tin nhắn để dụ người dùng ấn vào những thành phần ở trong trang web đó như các link, ảnh … rồi sau đó thực hiện một hành động trên một trang web tin cậy mà người dùng hiện đang được chứng thực.

3. Cross-Site Request Forgery (CSRF)

  • Một kịch bản cho cách thức tấn công lỗi CSRF như sau:
  1. User truy cập vào 1 trang web bình thường, website dạng như facebook, gmail, bank…
  2. Hệ thống của website cung cấp cho User một session.
  3. User vẫn login hệ thống mà chưa logout ra khỏi hệ thống
  4. User duyệt một trang web khác của Malicious Attacker
  5. User click vào link ở trên trang web của kẻ tấn công. Link này sẽ tự động thực hiện một hành vi nào đó ko tốt trên hệ thống của website bình thường ban đầu user truy cập

Xem xét các thức hoạt động

  • Web Application có một chức năng sau

  • Một ứng dụng web đơn giản đó là thay đổi password người dùng. Việc gửi lên server theo phương thức HTTP GET thông thường. Nội dung gửi lên là password mới và confirm lại password vừa nhập.

  • Sau khi nhập và gửi lên server thì password người dùng sẽ bị thay đổi trên hệ thống.

  • Ứng dụng trên hoàn toàn OK không có vấn đề gì hết nếu người dùng tuân thủ đúng mong muốn của developer.

  • Một số kẻ ác ý kiểm tra thử xem ứng dụng này có mắc lỗi CSRF hay không bằng cách thử copy link trên URL:
    https://webtest1.com/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change#
    và thay đổi password thành password1: https://webtest1.com/vulnerabilities/csrf/?password_new=password1&password_conf=password1&Change=Change#
    vào trình duyệt hiện tại (mà ko cần bấm nút Change).

  • OHHH tuyệt vời! với kết quả trên thì có thể dùng URL để thay đổi mật khẩu 1 cách nhanh chóng mà chẳng cần phải bấm nút Change! Nhưng sự tuyệt vời này lại là một lỗ hổng bảo mật nguy hiểm.

  • Giả sử một kịch bản sau:

  • Người dùng user truy cập vào trang webtest1.com

  • Trong thời gian truy cập vào webtest1.com. Người dùng chưa logout khỏi web, và đi thăm thú các trang web khác như facebook.com, vietnamlab.vn, vnexpress.net …. và vào 1 trang web: webtest2.com

  • webtest2.com là một trang mà hacker (hoặc kẻ ác ý khác – muốn chôm mật khẩu tại trang webtest1.com). Nội dung của webtest2.com có một URL được ẩn đi dạng: 
    https://webtest1.com/vulnerabilities/csrf/?password_new=hacked&password_conf=hacked&Change=Change#
    Victim (User) lúc này vào trang webtest2.com và vô tình đã thay đổi mật khẩu của bản thân tại webtest1.com

  • Victim( User) sau khi thoát ra khỏi web: Logout, thì không thể vào lại hệ thống với mật khẩu cũ.

  • Thiết lập kịch bản trên:

  • Nội dung file hosts dẫn đến các server:
    192.168.33.100 webtest1.com
    192.168.33.110 webtest2.com

  • Nội dung trang web của hacker

<script> 
function hacked() {
  var password = "hacked"; 
  $('body').append('<img src="https://webtest1.com/vulnerabilities/csrf/?password_new=' + password + '&password_conf=' + password + '&Change=Change#" height="1" width="1">');
  alert("RIP you! your password is changed!"); 
} 
</script>

<br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<div width="100%">
  <div width="50%" align="center"> 
    <button align="center" onClick='hacked()'>Click day hay lam! yen tam di ko co virus dau</button> 
  <div>
<div>  

  • Khi người dùng lỡ tay click vào Button thì sẽ hiện ra thông báo: [RIP you! your password is changed!] kết quả như hình dưới

  • Như vậy khi Victim (User) vô tình vào trang webtest2.com đã làm thay đổi password của bản thân tại trang webtest1.com. Hacker nếu biết thông tin username sẽ thử vào với password đã cài đặt:hacked và có thể vào một cách bình thường, ví dụ vào trên trình duyệt khác với username: admin, password: hacked thì sẽ vào webtest1.com một cách bình thường. –> mọi người tự thử nhé.

  • Với ví dụ trên thì Hacker vẫn còn tốt chán vì có yêu cầu click và thông báo cho user là đã bị mất mật khẩu. Nhưng thực tế hacker sẽ dùng một số thủ thuật để Victim không thể biết là mình vừa mất mật khẩu. Thông qua thẻ <img src=’URL_LINK’> hoặc <iframe src=’URL_LINK’>

4. Cách Phòng chống

  • Với những chức năng thay đổi thông tin của hệ user, các thông tin quan trọng, khi muốn thay đổi phải có yêu cầu xác thực ví dụ như ứng dụng trên đó là password hiện tại là gì. Khi đó cho dù gửi yêu cầu thay đổi password như ví dụ trên được gửi cũng cần phải có password hiện tại. Chức năng này cũng có rất nhiều trong facebook khi mà bạn thay đổi bất kỳ thông tin gì của cá nhân sẽ có yêu cầu password hiện tại. Ngoài ra có thể check cả http_refferer xem có trùng với domain hiện tại đang xử lý hay không.
  • Dùng csrf_token: token này sẽ thay đổi liên tục trong phiên làm việc, và khi thay đổi thông tin gửi kèm thông tin token này. Như vậy nếu token được sinh ra và token được gửi lên ko trùng nhau thì loại bỏ request. Việc làm này sẽ chống được 100% có khi lên tới 1000% lỗ hổng csrf. csrf_token thường là bảng băm hash của đầu vào random. Quá trình kiểm tra như sau
    • server sinh ra csrf_token : generateSessionToken() và lưu vào SESSION: $_SESSION[‘session_token’]
  • User load giao diện màn hình sửa thông tin, lúc này sẽ tạo cho user một trường hidden: user_token có giá trị lấy từ SESSION ra: user_token = $_SESSION[‘session_token’].
  • User sửa thông tin cần thay đổi và gửi lên server, khi gửi lên server sẽ gửi kèm thông tin user_token
  • Server kiểm tra user_token === $_SESSION[‘session_token’] ??? nếu không giống nhau –> request giả mạo, nếu giống nhau thì xử lý thay đổi
  • Trường hợp OK thì thay đổi được cập nhật,  lúc này Server thực hiện lại bước đầu tiên để sinh ra csrf_token mới cho User: generateSessionToken() và lưu vào SESSION: $_SESSION[‘session_token’]

5. Các Bài Viết Liên Quan Tới Series

- 1. Giới thiệu tổng quan series Web Application Security