I. Đặt vấn đề
1. Giới thiệu lỗ hổng File upload
Chắc hẳn các bạn đều đã quen thuộc với các tính năng thay đổi ảnh đại diện, ảnh bìa trong quá trình hoàn thành hồ sơ cá nhân. Quá trình tải lên một ảnh đại diện chính là đang thực hiện hành động upload file, cụ thể tệp tải lên ở đây là tệp tin dạng hình ảnh.
Giống với các chức năng khác, hành động upload file cũng ẩn chứa những mối nguy tới hệ thống. Dạng lỗ hổng này thường được gọi là File upload vulnerabilities.
2. Lỗ hổng File upload hoạt động ra sao
Giả sử, một hệ thống được xây dựng dựa trên ngôn ngữ PHP, cho phép người dùng upload các file định dạng php và có thể thực thi những file này. Khi đó, thay vì upload một file avatar, kẻ tấn công có thể tải lên một tệp có phần mở rộng .php
, sau đó truy cập đường dẫn thư mục chứa tệp đã tải lên khiến hệ thống thực thi các lệnh trong tệp này.
3. Tìm hiểu về Webshell
Webshell có thể hiểu là một dạng mã độc chứa các chức năng được xây dựng bởi kẻ tấn công, hỗ trợ họ trong quá trình khai thác và xâm nhập hệ thống dễ dàng hơn.
Webshell có thể xây dựng bằng nhiều ngôn ngữ lập trình khác nhau. Tùy vào công nghệ sử dụng và các đặc trưng của mục tiêu, kẻ tấn công có thể lựa chọn ngôn ngữ phù hợp để xây dựng Webshell cùng các chức năng mong muốn cho mình.
Thông thường, Webshell thường được sử dụng làm công cụ thu thập các thông tin, dữ liệu nhạy cảm; làm phần mềm trung gian cho việc tải lên hoặc lan truyền các dạng phần mềm, mã độc khác; Hỗ trợ cho các dạng tấn công khác cũng như chiếm quyền hệ thống; ...
4. Lỗ hổng File upload mang lại hậu quả gì?
Khi thay đổi ảnh đại diện, một người dùng thông thường sẽ tải lên một tệp hình ảnh. Các bạn thử tưởng tượng, nếu hệ thống cho phép người dùng tải lên một tệp bất kì, thì sẽ xảy ra hậu quả gì? Rõ ràng, chức năng của hệ thống sẽ chỉ làm việc được với các file đúng định dạng mong muốn, nếu một file có định dạng nằm ngoài khả năng xử lý được tải lên sẽ gây ra các lỗi không thể lường trước. Thậm chí, kẻ xấu có thể lợi dụng điều này để tải lên các tệp mã độc, phần mềm độc hại.
Kẻ tấn công thường lợi dụng lỗ hổng File upload để xây dựng cho mình các Webshell, từ đó chiếm quyền hệ thống hoặc thu thập các thông tin, dữ liệu nhạy cảm.
II. Phân tích và khai thác các lỗ hổng File upload
1. Những dòng code vội vàng
Chúng ta cùng xem xét đoạn mã với chức năng upload file được code bằng php sau:
<?php if (isset($_POST["submit"])) { $file_dir = "uploads/"; $file_name = $_FILES["file"]["name"]; $file_location = $file_dir . basename($file_name); if (file_exists($file_location)) { echo "This image already exists!"; exit(); } else { if (move_uploaded_file($_FILES["file"]["tmp_name"], $file_location)) { echo "<pre>{$file_name} succesfully uploaded at </pre><a href='" . $file_location . "'>here</a>"; } else { echo "<pre>Your image was not uploaded!</pre>"; } } } ?>
Trong đoạn mã trên, biến $file_dir
chỉ thư mục lưu trữ file do người dùng tải lên, $file_name
là tên file người dùng tải lên, $file_location
chỉ đường dẫn tới file sau khi lưu. Đoạn mã chỉ có duy nhất một bước kiểm tra rằng trong thư mục lưu trữ đã tồn tại file trùng tên với file tải lên hay không. Sau đó sẽ cho phép người dùng upload bất kì dạng tệp nào.
Bởi vậy, chúng ta có thể upload một file shell.php
với nội dung như sau:
<?php if (isset($_GET['cmd'])) { system($_GET['cmd']); }
?>
Upload shell.php
lên hệ thống:
Truy cập tới đường dẫn file shell.php
, đoạn code trong file sẽ được thực thi, bởi vậy có thể sử dụng dụng tham số cmd
thực hiện các lệnh command:
Phân tích lab Remote code execution via web shell upload
Miêu tả: Trang web chứa lỗ hổng Upload File trong chức năng upload ảnh, nó không thực hiện bất kì bước kiểm tra nào đối với file do người dùng tải lên. Để giải quyết bài lab, chúng ta cần upload một Webshell PHP, từ đó đọc nội dung tệp /home/carlos/secret
. Tài khoản hợp lệ được cung cấp: wiener:peter
.
Đăng nhập với tài khoản wiener:peter
, trang cá nhân chứa chức năng upload ảnh đại diện:
Upload một file ảnh bình thường:
Có thể click chuột phải xem đường dẫn tới ảnh đã upload:
Như vậy file ảnh sau khi upload được lưu tại thư mục /files/avatars/
.
Chúng ta sẽ upload một file shell.php
với nội dung như sau:
<?php echo file_get_contents('/home/carlos/secret');
?>
Hàm file_get_contents()
sẽ lấy nội dung file /home/carlos/secret
và được lệnh echo
in ra.
Sau khi upload, truy cập tới /files/avatars/shell.php
:
Submit và hoàn thành bài lab:
2. Bypass lỗ hổng File upload bằng header Content-Type
Giả sử một trang web chỉ cho phép upload các file ảnh với đoạn code chứa cơ chế ngăn chặn như sau:
$file_content_type = $_FILES["file"]["type"]; if (!in_array($file_content_type, array("image/png", "image/jpg", "image/jpeg"))) { die("Only allowed png, jpg, jpeg file!");
}
Trang web chỉ cho phép người dùng upload lên các file ảnh với định dạng .png
, .jpg
, .jpeg
. Do giá trị $_FILES["file"]["type"]
được xác định thông qua header Content-Type trong request:
Bởi vậy chúng ta có thể bypass cơ chế ngăn chặn này bằng cách thay đổi giá trị header Content-Type theo định dạng cho phép của trang web.
Phân tích lab Web shell upload via Content-Type restriction bypass
Miêu tả: Trang web chứa lỗ hổng file upload. Để giải quyết bài lab, chúng ta cần upload một web shell PHP nhằm đọc nội dung file /home/carlos/secret
. Tài khoản hợp lệ được cung cấp wiener:peter
.
Đăng nhập với tài khoản wiener:peter
, trang web chứa chức năng upload avatar.
Thử upload một file shell.php
với nội dung:
<?php echo file_get_contents('/home/carlos/secret');
?>
Trang web báo lỗi do chỉ cho phép upload các file dạng image/jpeg
hoặc image/png
. Dự đoán hệ thống xác định định dạng file upload dựa vào header Content-Type, nên chúng ta có thể thay đổi giá trị header này thành image/png
để bypass cơ chế ngăn chặn này:
Upload thành công, truy cập đường dẫn file ảnh để đọc nội dung tệp /home/carlos/secret
:
Submit chuỗi secret và bài lab được giải quyết: