Mình làm nốt phần cuối của loạt bài về security cho web để bạn nào quan tâm thì nghiên cứu nốt. Đây là loạt bài mà theo đánh giá của riêng mình là khá hay và có nhiều thông tin bổ ích.
Nội dung được dịch từ bài viết Writing Secure PHP, Part 4 bởi babyinternet.
Ghi rõ nguồn http://vnwebmaster.com khi phát hành tại website khác
Phụ mục
Cross-Site Scripting (XSS)
Phần này đã được tôi nói đến ở phần 3 rồi. Nên bạn có thể đọc lại bài viết ấy và đọc thêm Tìm hiểu và chống các lỗi bảo mật trong ứng dụng web để biết thêm.
Cross-Site Request Forgery (CSRF)
Mặc dù có tên gần giống nhưng CSRF không giống như XSS đã nói ở trên. CSRF là hình thức sử dụng chứng thực thông tin(authenticate) của một người khác để thực hiện một hành động của mình trên website (dựa vào quyền của người khác).
Chúng ta giả định rằng Jack có một tài khoản tại ngân hàng nào đó và login vào tài khoản của mình anh ta có thể thực hiện được các giao tác của mình như chuyển tiền hoặc kiểm tra tài khoản, tải các trang thông tin cá nhân. Mỗi lần anh ta thực hiện giao tác với máy chủ ngân hàng, cookie được lưu lại và chứng thực là Jack là người sử dụng chức năng này.
Bill là một người khác và sử dụng một website khác, nhưng Jack có sử dụng website của Bill và Bill nhân cơ hội này thu thập các cookie của Jack. Một trong các trang web của Bill có gửi một yêu cầu đến hệ thống ngân hàng được Jack sử dụng thông qua một iframe. Giả định rằng iframe được tải lên thực hiện một lệnh chuyển tiền từ tài khoản của Jack sang tài khoản của Bill. Bởi vì lệnh chuyển tiền được gửi từ máy tính của Jack và ngân hàng nhận được cookie từ Jack (bởi vì Jack đã login vào hệ thống của ngân hàng và đang mở trang web của Bill). Do đó, ngân hàng ghi nhận lệnh chuyển tiền là do Jack thực hiện và chấp nhận giao dịch đó như một giao dịch hợp lệ và tiền được chuyển đến tài khoản của Bill.
Loại tấn công kiểu này cực kì nguy hiểm và hầu như rất khó phòng bị. Là một nhà phát triển web, công việc của bạn là tìm cách ngăn chặn loại tấn công này. Lúc này, bạn hãy nhớ Qui luật 1: Đừng bao giờ tin vào người dùng mà tôi đã nói đến ở phần 1.
Trong PHP, bạn có thể dễ dàng quản lý và chống lại lỗi CFRS thông qua thói quen lập trình. Không bao giờ cho phép người dùng làm bất cứ điều gì quan trọng với một yêu cầu _GET, hãy sử dụng _POST. Các hành động quan trọng cần được xác nhận lại của người dùng thông qua một trang web riêng có 2 nút “Đồng ý” và “Hủy lệnh” riêng biệt. Bạn có thể trình bày URL gốc gửi yêu cầu để người dùng biết rằng lệnh đó xuất phát từ đâu, thực hiện tính năng gì để họ đề phòng và xác nhận nếu họ muốn chuyển.
Bạn cũng có thể phá bỏ IFrame để đề phòng những giao dịch bất hợp phát xuất phát từ việc chèn Iframe vào website khác bằng đoạn lệnh sau:
Điều chỉnh thời gian timeout của Session cũng là một việc bạn nên làm (nên thiết lập theo phút, đừng thiết lập theo giờ – quá lâu). Khuyến khích người dùng logout sau khi hoạt hoàn tất các thao tác trên website của bạn cũng là một việc cần thiết. Ngoài ra, bạn cũng nên kiểm tra biến môi trường HTTP_REFERER(bạn có thể thực hiện ngầm). Nếu HTTP_REFERER gửi lệnh không xuất phát từ tên miền của bạn, bạn có thể nghĩ đến trường hợp bị tấn công CFRS.
Mã hóa kí tự
Nên có một bộ kí tự mã hóa riêng cho website của bạn và cơ sở dữ liệu. Nếu một yêu cầu gửi từ một website khác đến website bạn, nó không thể trùng với thông tin được mã hóa giống như trên website bạn và bạn có thể từ chối xử lý yêu cầu này.
Ví dụ, bạn có thể từ chối một yêu cầu xử lý (ví dụ upload file lên server chẳng hạn) nếu bộ mã hóa charactor không tương ứng với website (HTTP request headers, dữ liệu, PHP’s default encoding, PHP MySQL module, MySQL’s default set, thiết lập charset của mỗi table sử dụng…)
Những nhà phát triển website sử dụng tiếng Anh thường ít quan tâm đến bộ charset (vì tiếng Anh không có dấu). Cũng bởi nguyên nhân này nên nhiều người trong số họ thường không quan tâm đến bộ mã kí tự và dẫn đến sự mù mờ hoặc để xảy ra lỗi đáng tiếc. Tuy nhiên, các bộ mã kí tự là một phần cơ bản của các ứng dụng web. Tiếng Anh có thể hiển thị ở bất kì đâu nhưng những thứ tiếng khác (Tiếng Việt chẳng hạn :D ) chưa chắc có thể hiển thị tốt ở các bộ mã khác. Hai bộ mã thường được các nhà phát triển sử dụng là ISO-8859-1 và UTF-8, ngoài ra còn có UCS-2, UTF-16 hoặc windows-1252.
Tuy nhiên, ngay cả khi có 2 bộ mã khác nhau, PHP cũng có thể đồng hóa chúng để có thể đưa vào cơ sở dữ liệu bình thường và điều này làm cho việc kiểm tra bộ mã quan trọng hơn đối với bảo mật.
Chuyên gia bảo mật Chris Shiflett đã viết về vấn đề này khá kĩ. Trong đó, anh ta đã đưa kèm một ví dụ về việc tấn công SQL Injection ngay cả khi bạn đã xử lý dữ liệu đầu vào bằng addslashes() mà tôi đã nói đến trong phần lỗi SQL Injection ở phần trước.
Giải pháp là luôn luôn sử dụng hàm mysql_real_escape_string() thay cho addslashes(). Lý tưởng nhất, hãy sử dụng cùng một bộ thiết lập kí tự trên toàn bộ hệ thống website của bạn (tốt nhất là sử dụng UTF-8), nơi nào PHP cho phép bạn chỉ định mã hóa dữ liệu (htmlspecialchars() hoặc htmlentities()) – hãy sử dụng nó.