A traffic direction system (TDS) nicknamed Parrot TDS has been publicly reported as active since October 2021. Websites with Parrot TDS have malicious scripts injected into existing JavaScript code hosted on the server. This TDS is easily identifiable by keywords found in the injected JavaScript that we will explore to show the evolution of this threat.
This injected script consists of two components: an initial landing script that profiles the victim, and a payload script that can direct the victim’s browser to a malicious location or piece of content. To help the reader better understand Parrot TDS, this article provides in-depth analysis of the landing scripts and payload scripts we have collected from this campaign.
In early September 2023, we investigated a notification concerning a compromised website based in Brazil. Our investigation revealed that this website served pages with injected JavaScript identified as Parrot TDS. Further research uncovered many variations of Parrot TDS script from various servers worldwide.
Our research reveals several versions of injected JavaScript associated with this campaign. Before reviewing all variations of this script, we should better understand the basic nature of Parrot TDS.
Parrot TDS Overview
While campaigns involving malicious or injected JavaScript code are fairly common, Parrot TDS is notable due to its wide scope and ability to threaten millions of potential victims. This TDS is easily identifiable by keywords from the injected JavaScript, such as:
Ndsj
Ndsw
Ndsx
The threat operators have consistently used these keywords for Parrot TDS. The presence of these keywords makes it easier for researchers to group samples from this campaign together, making it one of the most investigated campaigns in recent years.
Although its origin remains unclear and public reports indicate Parrot TDS started in 2021, our data indicates it first appeared as early as 2019, with full samples available by August of that year. This relatively high-profile campaign would in that case have been active for more than four years.
Our investigation into Parrot TDS has revealed different versions of injected JavaScript that illustrate its evolution. Throughout its evolution, the chain of events used by Parrot TDS has remained consistent.
Chain of Events for Parrot TDS Payload Distribution
Although we have observed different versions of Parrot TDS, the attack chain follows the same basic pattern as shown below in Figure 1.
In most cases, a web server compromised by Parrot TDS injects a landing JavaScript code snippet into existing JavaScript files. This code usually contains keywords such as ndsj or ndsw.
We call this the Parrot TDS “landing script” as shown above in Steps 3 and 4 from Figure 1. The landing script conducts environment checks as a way to avoid detection.
If conditions set by the landing script are successfully met, the victim’s web browser queries a payload server. This payload server then returns a JavaScript payload containing keywords such as ndsx.
We call this second script the “payload script” as shown in Steps 5 and 6 from Figure 1 above. The Parrot TDS payload script can direct the victim’s browser to a malicious webpage or other potentially harmful content.
Ultimately, the two components we have identified from Parrot TDS traffic are:
Landing scripts (usually containing keywords ndsj or ndsw)
Payload scripts (containing keywords such as ndsx)
To better understand these two components, we must first examine the landing script.
Parrot TDS Landing Script
We analyzed more than 10,000 Parrot TDS landing scripts from internal and external data sources. The range of this dataset is from August 2019 through October 2023.
These samples reveal four versions of Parrot TDS landing script that represent approximately 95.8% of the collected data as indicated in Figure 2 below. The remaining 4.2% could be the future of this campaign, since the characteristics of these samples do not match the four versions of landing script we have identified so far.
The four versions of Parrot TDS landing script from 95.8% of our samples use either the keyword ndsw or ndsj, while the other 4.2% use the keyword ndsj. Scripts with the keyword ndsj use more obfuscation techniques such as Canvas, decodeURI or WebAssembly.
Most Parrot TDS landing scripts from earlier in the campaign were injected as a single line of code, often appended at the end of JavaScript files served from the compromised website. We identify this as Version 1 (V1), and Figure 3 shows one such example. Note: We will acronymize each version as V paired with its sequential version number for the remainder of the article.
The example in Figure 3 indicates a single line of injected code, with the JavaScript normalized and beautified above it.
The different landing script versions have no significant differences in the core function of the injected script. Later versions include more obfuscation. The V1 sample from Figure 3 above shows the core function quite clearly. The sixth line of beautified JavaScript code shows an XMLHTTPRequest that interacts with the payload server and executes the response as a payload.
The major function and workflow of the landing script of V2 are almost the same as those of V1. The only difference is that V2 appends a token every time it interacts with the payload server. This token contains two random strings as noted below in Figure 4, and the token is usually 21-22 bytes long.
Compared to V1 and V2, the landing script for V3 looks very different. V3 includes a new function that primarily serves as storage for strings, noted as “serving strings” in Figure 5 below.
Parrot TDS landing script V3 hosts a long array of strings. Each string in the array could be a word or part of a word used by other functions to dynamically construct a keyword or string at runtime.
Also shown in Figure 5, another function modifies the string array from the previously-noted function. This makes static deobfuscation for analysis more difficult. Other than that, the core function of V3 is not much different from previous versions.
The remaining portions of our V3 landing script example are shown below in Figures 6 and 7.
Compared to V3, V4 landing scripts contain additional obfuscation and use somewhat different array indexes. V4 also implements additional changes affecting how its JavaScript handles numbers and strings. Despite these changes, V4 has the same overall functionality as V3 landing scripts.
Figures 8 through 11 below show an example of a V4 landing script.
Parrot TDS landing script samples using an ndsj keyword are much rarer than ndsw in our collected data. We treat the majority of ndsj landing script samples as minor versions among V3 and V4.
In reviewing our collected landing script samples, we found other versions that do not fully fit V1 through V4 or the ndsj landing scripts. These samples include:
A special version that loads its payload with a Canvas object
Advanced versions that involve more obfuscation and WebAssembly code such as decodeURIComponent and String.fromCharCode
Samples that also contain injected JavaScript code from different campaigns (if a web server remains vulnerable for an extended period of time, its JavaScript files could be injected with many different snippets of malicious code)
Several minor versions that apply interchangeable obfuscation, such as using a number value or string value, or using [] or a period to access the property of an object – the numeric or string values can also be represented as decimal or hexadecimal numbers
While earlier samples of the injected landing script consist of a single line of JavaScript code, we observed an increasing number of Parrot TDS samples with multiple lines of injected JavaScript code since August 2022. This is likely an evasion technique, since a single long line of malicious code is easier to spot in a script file than multiple lines of shorter malicious code.
Parrot TDS landing scripts profile the victim’s web browser, and if all conditions are successfully met, they direct the victim’s browser to retrieve a payload script.
Parrot TDS Payload Script
Parrot TDS payload scripts use an ndsx keyword, making them relatively easy to identify.
Compared to the landing scripts, we found fewer unique samples of Parrot TDS payload scripts. We have classified these into nine versions, compared to the four major versions of Parrot TDS landing scripts.
These payload scripts are mostly malicious, but V1 only sets a cookie value for the victim and is basically benign. The other eight major versions of the Parrot TDS payload script are malicious.
V2 is the most common payload script, representing more than 70% of our sample set. Figure 12 shows a column chart revealing the Parrot TDS payload script distribution.
V1 is the simplest version of the Parrot TDS payload script, and it merely sets a cookie that expires after one year as shown below in Figure 13. This payload script is effectively benign.
A Parrot TDS landing script will only query the payload server if the victim’s browser has no cookie set by a previous payload script. This V1 payload script basically removes the current browser from any follow-up actions for one year.
The V2 payload script is straightforward. Without any obfuscation, it creates a new script tag to load JavaScript from a malicious URL as shown in Figure 14.
This payload script is the most common version we see for Parrot TDS. Around 70% of our collected payload samples are V2.
Parrot TDS payload script V3 contains obfuscation and only targets victims running Microsoft Windows. Figure 15 shows an example of a V3 payload script.
In the bottom third of the script, ls represents a decode function that decodes several strings in the script. Our investigation revealed that V3 payload scripts will check for the following conditions:
A referrer
Acceptable URL format
A platform identifier of “windows”
That Parrot TDS had not previously set a cookie
After passing all checks, the V3 payload script functions the same as V2, loading an additional script from a malicious URL.
V4 and V5 payload scripts are similar. V4 is effectively a V1 payload script plus additional code as shown in Figure 16.
V5 is effectively a V2 payload script plus additional code (see Figure 17). In both cases, the additional code appears before the original V1 or V2 functions.
With V4 and V5, Parrot TDS payload scripts involve more obfuscation, which is similar to the obfuscation seen in V3 landing scripts. The core function of this extra payload script code is to hook all clickable links in the landing page. Whenever a visitor to the webpage clicks a link, the script will create a new image object and load from a specific URL.
V6 through V9 of the payload script include more obfuscation. These are very rare in our dataset.
Targets of Parrot TDS
Parrot TDS is part of an ongoing campaign targeting victims across the globe. We see landing script or payload script samples daily from a variety of websites compromised through this campaign. While our study began with a tip about a compromised Brazilian website, the variety of compromised websites we found serving Parrot TDS indicates victims are not limited to a single industry, nationality or geographic area.
The attackers likely use automatic tools to exploit known vulnerabilities. The majority of the compromised servers use WordPress, Joomla or other content management systems (CMS) to host a website. Even websites without CMS could be compromised through this campaign, since server-side vulnerabilities are not limited to CMS.
Conclusion
Parrot TDS is a notable part of our threat landscape. This campaign has lasted more than four years, and it keeps evolving with new techniques and obfuscations. Most websites compromised through this campaign use some sort of CMS like WordPress or Joomla.
Website administrators can detect if Parrot TDS has compromised their sites by searching files hosted on the associated web server. For example, they can search server content for the keywords associated with Parrot TDS, like ndsj, ndsw and ndsx. Administrators can also conduct an audit to discover any extra .php files on a web server.
Protections and Mitigations
Palo Alto Networks customers are better protected from the threats discussed above through the following products:
The Next-Generation Firewall with the Advanced Threat Prevention security subscription can help block the Webshell file traffic with best practices via the following Threat Prevention signatures: 94702
Advanced WildFire: The Advanced WildFire machine-learning models and analysis techniques have been reviewed and updated in light of the IoCs shared in this research.
If you think you might have been compromised or have an urgent matter, contact the Unit 42 Incident Response team or call:
North America Toll-Free: 866.486.4842 (866.4.UNIT42)
EMEA: +31.20.299.3130
APAC: +65.6983.8730
Japan: +81.50.1790.0200
Palo Alto Networks has shared our findings with our fellow Cyber Threat Alliance (CTA) members. CTA members use this intelligence to rapidly deploy protections to their customers and to systematically disrupt malicious cyber actors. Learn more about the Cyber Threat Alliance.
Indicators of Compromise
Landing Script Examples
The following are SHA256 hashes for 100 examples of JavaScript files with injected landing script code for Parrot TDS. These files have been submitted to VirusTotal.
The following are SHA256 hashes for 100 examples of JavaScript files with injected payload script code for Parrot TDS. These files have been submitted to VirusTotal.