Bảo mật website với Nonce trong WordPress

Minh Đức Digital - 9:40 sáng 28/06/2014
Bảo mật website với Nonce trong WordPress

Khi bạn Thiết kế website thì vấn đề quan trọng không thể thiếu đó là bảo mật. Có rất nhiều cách để tăng cường tính bảo mật trong WordPress. Đã có nhiều người đưa ra các bài viết về một số cách bảo mật trong WordPress. Hôm nay trong bài viết này mình sẽ hướng dẫn […]

Khi bạn Thiết kế website thì vấn đề quan trọng không thể thiếu đó là bảo mật. Có rất nhiều cách để tăng cường tính bảo mật trong WordPress. Đã có nhiều người đưa ra các bài viết về một số cách bảo mật trong WordPress. Hôm nay trong bài viết này mình sẽ hướng dẫn thêm cho các bạn cách bảo mật với Nonce, một cách hiệu quả để hạn chế việc tấn công theo kỹ thuật Cross Site Request Forgery (CSRF).

Bảo mật website với Nonce trong WordPress

Bảo mật website với Nonce trong WordPress

Trước tiên ta sẽ tìm hiểu về một vài vấn đề sau:

Nonce là gì?

Hiểu đơn giản nó là 1 chuỗi duy nhất được tạo ra bởi WordPress cho mỗi người dùng. Nó giúp bảo vệ website khỏi những request tự tạo với mục đích xấu.

Để dễ hiểu vấn đề này hơn mình giả sử có 1 link dùng để xóa bài viết như thế này:

<a href=”http://domain/?action=delete&id=1″>Xóa Bài</a>

Khi mình click vào link thì bài viết sẽ được xóa bình thường và không vấn đề gì. Nhưng vấn đề xảy ra nếu một người dùng khác có dụng ý xấu. Họ sử dụng 1số thủ thuật nào đó để thông qua quyền của mình và thực hiện việc chạy lại đường link trên với 1 địa chỉ (id)khác thì sao? Bài viết khác có thể bị xóa cho dù mình không click vào nút xóa. Các bạn đã thấy đó vấn đề này rất lớn rồi đó. Ngoài ra thì khi dùng form để submit dữ liệu cũng vẫn bị vấn đề trên.

Vậy làm thế nào để xác định được chính xác 1 request do người dùng thực hiện thông qua click link hay submit form ?

Việc cần làm là chúng ta phải tạo ra thêm 1 nonce cho request và trang xử lý phải xác nhận cái nonce này. Nếu nonce không hợp lệ thì không xử lý request. Làm như vậy thì chúng ta mới xác định được chính xác thao tác đấy là do chính người dùng tạo ra không với mục đích xấu.

Các sử dụng Nonce

Như đã nói ở trên nonce là 1 chuỗi vậy chuỗi này được tạo ra như thế nào? Mở file wp_config.php lên và tìm đến 2 hằng NONCE_KEY và AUTH_SALT. WordPress đã sử dụng dụng 2 hằng này và hash cùng với một số thông số khác sau như action, user id … sau đó cắt ra 1 đoạn để tạo ra nonce.

Cách đơn giản và linh động nhất là các bạn sử dụng hàm wp_create_nonce($action) để tạo nonce và dùng hàm wp_verify_nonce($nonce, $action) để xác nhận.

Giả sử với link xóa bài như bên trên, mình cần tạo ra 1 nonce, đưa nonce này vào query string, bên trang xử lý sẽ xác nhận nonce thông qua query string.

$nonce = wp_create_nonce(‘ delete_1’); //tạo nonce

echo ‘<a href=”http://domain/?action=delete&id=1&_nonce=’.$nonce.'”>Xóa</a>’;

Các bạn thấy đấy, mình đã tạo thêm 1 nonce với $action truyền vào là delete_1. Và mình đã đưa nó vào query string để verify bên trang xử lý. Tên _nonce các bạn có thể đổi lại tùy ý. MộtLưu ý với các bạn là: với $action các bạn đặt như thế nào thì trang xử lý các bạn phải verify lại như thế đó.

Bên trang xử lý các bạn chỉ cần xác nhận cái nonce này trước khi xử lý. Không hợp lệ thì ngưng xử lý:

if(!wp_verify_nonce($_GET[‘_nonce’], ‘delete_’.$_GET[‘id’])) exit();

//code xử lý ở đây ….

Bên trang xử lý chúng ta verify nonce thông qua hàm wp_verify_nonce. Với $nonce là $_GET[‘_nonce’], và $action là ‘delete_’.$_GET[‘id’]. Vì ở trên nonce được tạo từ ‘delete_1′ nên trang xử lý cần verify đúng $action đó theo dạng delete_{id}.

Thực chất hàm này sẽ tạo ra 1 nonce khác theo $action và so sánh nó với nonce get được.

Ngoài cách sử dụng trên wordpress còn cung cấp các hàm để tạo và kiểm tra nonce khác để áp dụng vào từng trường hợp cụ thể.

Để tạo nonce cho url, ngoài cách trên ra chúng ta có thể sử dụng thêm hàm wp_nonce_url( $actionurl, $action, $name ) hàm này sẽ trả về cho chúng ta 1 đường dẫn đầy đủ chứa nonce.

Một vài tham số cần chú ý:

$actionurl chính là đường dẫn để add nonce vào.

$action tương tự trên.

$name là tên của nonce, mặc định là _wpnonce

Cũng với ví dụ trên mình sử dùng hàm wp_nonce_url() để tạo:

$nonce_url = wp_nonce_url(‘http://domain/?action=delete&id=1’, ‘delete_1’);

echo ‘<a href=”‘. $nonce_url.’ “>Xóa</a>’;

Khi xem thì các bạn thấy đường dẫn nó cũng tương tự cách trên, _wpnonce chính là tham số $name mặc định, các bạn muốn đổi thành tên khác thì tùy chỉnh tại tham số này.

http://domain/?action=delete&id=1&_wpnonce=e73a52569c

Tiếp tục để tạo nonce cho 1 form các bạn có thể dùng thêm hàm wp_nonce_field( $action, $name, $referer, $echo ). Các tham số như $action và $name thì tương tự trên. Tham số $referer sẽ nhận giá trị true hoặc false, quyết định hiển thị thêm 1 field ẩn chứa đường dẫn hiện tại. $echo cũng nhận giá trị true hoặc false, quyết định hàm wp_nonce_field() sẽ hiển thị hay trả về kết quả.

Khi sử dụng hàm này với $referer là true các bạn sẽ thấy trong form có thêm 2 trường dạng như thế này:

<input type=”hidden” id=”_nonce” name=”_nonce” value=”43bc8cf75e” />

<input type=”hidden” name=”_wp_http_referer” value=”/phanmem/ ” />

Về cách verify nonce thì WordPress cung cấp thêm cho chúng ta 2 hàm nữa khác là check_admin_referer() và check_ajax_referer().

Hàm check_admin_referer() sẽ dùng để verify nonce trong trang quản lý. Hàm này nhận 2 tham số là $action và $query_arg với $action thì tương tự, $query_arg chính là $name của nonce. Hàm này sẽ trả về true nếu nonce hợp lệ và ngược lại là false.

Giả sử có 1 form dạng như thế này:

<form method=”post”>

    //…….

   <?php wp_nonce_field( ‘myaction’,’mynonce’ ); ?>

</form>

Thì khi verify các bạn làm như sau:

if(!check_admin_referer(‘myaction’, ‘mynonce’)) die();

Hàm check_ajax_referer() sẽ verify nonce thông qua Ajax. Hàm này nhận 3 tham số, 2 tham số đầu là $action và $query_arg tương tự hàm trên, với tham số thứ 3 là $die, nếu nonce không hợp lệ, và tham số này set true thì sẽ ngưng xử lý, nếu false thì bỏ qua. Mặc định là true.

Thời gian sống mặc định của 1 nonce là 24 giờ. Các bạn vẫn có thể chỉnh sửa lại thông qua hook nonce_life.

add_filter( ‘nonce_life’, function () { return 4 * HOUR_IN_SECONDS; } );

Hằng HOUR_IN_SECONDS sẽ trả về số giây trên giờ (3600).

Mình vừa hướng dẫn xong cho các bạn cách bảo mật WordPress với Nonce để hạn chế việc tấn công theo kỹ thuật CSRF trong khi phát triển theme và plugin. Mong rằng các bạn có thể bảo vệ website của mình một cách tốt hơn với Nonce