Thứ Năm, 11 tháng 5, 2017

Sử dụng class NOCSRF để ngăn chặn tấn công CSRF trong PHP


Giới thiệu


Khi xây dựng 1 ứng dụng hoặc 1 website sử dụng PHP, bạn cần quan tâm đến vấn đề bảo mật.

Một trong nhiều cách thức tấn công được sử dụng bởi những tin tặc (hackers) là Cross-Site Request Forgery (CSRF) chúng ta có thể hiểu là tấn công bằng cách mạo danh 1 website hay ứng dụng nào đó. Để hiểu rõ về CSRF thì bạn có thể đọc bài viết SERIES BẢO MẬT NHẬP MÔN – CSRF – NHỮNG CÚ LỪA NGOẠN MỤC của tác giả Phạm Huy Hoàng.

Bài viết này sẽ hướng dẫn bạn sử dụng class NOCSRF, 1 class đơn giản viết bằng PHP5 nhằm phòng chống CSRF.

Download


Trước hết bạn tải class NOCSRF ở địa chỉ https://github.com/BKcore/NoCSRF

Sử dụng


Bước 1: Giả sử mình có file test.php và giờ mình muốn dùng class NOCSRF trong file đó thì nội dung bên trong file sẽ như sau:

// Token được lưu trữ ở session nên bạn phải khởi tạo session
session_start();
// Khai báo file nocsrf.php từ mã nguồn tải về. Đường dẫn bạn có thể thay đổi tùy
// vào nơi bạn đặt file nocsrf.php
require_once('nocsrf.php');

Bước 2: Sử dụng method NoCSRF::generate() để sinh ra 1 token và gán qua biến $token

$token = NoCSRF::generate( 'csrf_token' );



 Giá trị chuỗi 'csrf_token' thực chất là key của session sẽ được tạo ra.

Bước 3: Cuối cùng bạn đặt giá trị $token vào thẻ input hidden trong form của bạn

<form name="csrf_form" action="#" method="post">
    <input type="hidden" name="csrf_token" value="<?php echo $token; ?>">
    ...Other form inputs...
    <input type="submit" value="Send form">
</form>

Bước 4: Bên code xử lý khi form được submit bạn đặt khối try catch như sau:

try
{
    NoCSRF::check( 'csrf_token'$_POST, true, 60*10, false );
    // lệnh của bạn
}
catch ( Exception $e )
{
    // Bị tấn công CSRF
}

Method NoCSRF::check() để kiểm tra tính hợp lệ của token. Cú pháp tổng quát của method này như sau:

NoCSRF :: check ($key, $origin [, $throwException [, $timespan [, $multiple]]]) 



  • Tham số $key (String): key của session lưu giữ token.
  • Tham số $origin (Mixed): đối tượng/mảng để truy xuất dữ liệu token (thường là $_POST)
  • Tham số $throwException (Boolean): ném ngoại lệ hoặc không ném ngoại lệ khi kiểm tra thất bại. Nếu gán true tức là sẽ ném ra ngoại lệ, false thì method sẽ trả về giá trị Boolean. Ở ví dụ này mình truyền giá trị true vào nên chúng ta mới xài khối try catch, nếu bạn truyền vào là false thì ko dùng try catch mà bạn gán giá trị trả về của method check qua 1 biến và kiểm tra xem biến đó giá trị true hay false mà xử lý.
  • Tham số $timespan (Integer): Giá trị token sẽ hết hạn sau 1 khoảng thời gian (giây). Mặc định là không bao giờ. 
  • Tham số $multiple (Boolean): Tái sử dụng token hoặc không (nên gán true nếu là 1 yêu cầu ajax nặng)
Ở ví dụ này mình chỉ định token được lưu giữ 60*10 s = 10 phút, dùng cách ném ngoại lệ khi lỗi kiểm tra token và không tái sử dụng token.  


Nếu nhảy vào khổi catch tức bạn đang bị tấn công CSRF từ 1 người dùng mạo danh website của bạn. Bạn có thể viết code xử lý tùy ý ví dụ như thông báo lỗi hoặc chuyển hướng người dùng đó về trang chủ.

Kiểm tra


Để kiểm tra xem mọi thứ đã hoạt động tốt chưa thì bạn có thể sử dụng POSTMAN để gửi 1 yêu cầu giả mạo đến trang web của bạn. 

Chúc bạn cài đặt thành công.


EmoticonEmoticon