Executive Summary

We recently discovered a large-scale campaign that has been compromising legitimate websites with injected, obfuscated JavaScript code. Threat actors commonly use this type of campaign to invisibly redirect victims from legitimate websites to malicious pages that serve malware, exploits and spam.

The campaign uses a JavaScript obfuscation technique known as JSF*ck (profanity masked). Due to the profanity in the term, we refer to the method in the remainder of this article by using the nickname JSFireTruck.

Our key findings are:

  • Multiple websites have been identified with injected malicious JavaScript that uses JSFireTruck obfuscation, which is composed primarily of the symbols []+${}
  • The code’s obfuscation hides its true purpose, hindering analysis
  • The injected code checks the website referrer, and if the referrer is a search engine, the code redirects victims to malicious URLs
  • Retroactive hunting on VirusTotal and our internal telemetry revealed thousands of related samples, indicating this is a widespread infection campaign affecting many websites
  • Injected JavaScript will redirect users to websites that can lead to malware downloads or other harmful activities, like malvertising and traffic monetization

The campaign’s scale and stealth pose a significant threat. The widespread nature of these infections suggests a coordinated effort to compromise legitimate websites as attack vectors for further malicious activities.

Palo Alto Networks customers are better protected from the threats discussed in this article through the following products and services:

If you think you might have been compromised or have an urgent matter, contact the Unit 42 Incident Response team.

Background

Attackers compromise legitimate websites, so these sites will silently redirect viewer traffic for various malicious purposes, like malware downloads, traffic monetization or malvertising. Our telemetry recently revealed a large group of websites that were injected with malicious obfuscated JavaScript, as shown below in Figure 1.

Figure 1. Example of malicious injected JavaScript found in the HTML pages.

On an initial look, the JavaScript code consists of a few characters like []+${} and some numbers. The code’s purpose isn’t readily apparent, prompting further investigation. We soon discovered that this code partially implements the JSFireTruck programming technique.

Our telemetry detected 269,552 webpages infected with JavaScript code using JSFireTruck in the three months from March 26, 2025, through April 25, 2025. This data is shown below in Figure 2.

A bar chart displaying daily hit counts from March 27, 2025, to April 25, 2025, with a significant peak in April. The y-axis is labeled 'Count' and the x-axis represents the dates.
Figure 2. Telemetry data shows over 200,000 infected pages.

As indicated in Figure 2, we saw a notable increase in detections for this campaign starting on April 12, 2025. Ultimately, this campaign is widespread and has infected many websites.

Analyzing the JavaScript Obfuscation

The injected JavaScript code with JSFireTruck obfuscation uses a limited set of characters and numbers, as shown in Figure 3.

A matrix of hexadecimal green characters on a black background.
Figure 3. Injected code as found in the HTML page consists of only [, ], (, ), !, + and numbers.

This is unexpected compared to examples of malicious injected JavaScript code we normally find, as there is no single variable or function name that seems to be executed at first glance. But publicly available information indicates that the symbols from this code are ASCII characters used for JSFireTruck.

JSFireTruck is a branch of an earlier JavaScript obfuscation technique originally released in 2009 called JJEncode. This earlier technique was used in previous campaigns to obfuscate JavaScript, like Kahu Security’s 2013 analysis of a compromised automobile forum. JJEncode uses the following 18 ASCII characters: []()!+,\”$.:;_{}~=

By August 2012, a user named aemkei created a GitHub repository for JSFireTruck, where they reduced the number of ASCII characters to the following six symbols:

[

]

(

)

!

+

The example from Figure 3 above appears to combine JSFireTruck with other obfuscation techniques.

JavaScript Obfuscation Through Type Coercion

JavaScript has different value types like strings, numbers, booleans, arrays and objects. If we use two mismatched value types together, such as strings and numbers, JavaScript uses type coercion to make the code work. Type coercion results in converting a value from one type to another.

Type coercion has various uses, such as displaying a number in JavaScript code as a string. For example, the toString() method will display a numeric value as an ASCII string.

JSFireTruck relies on type coercion, which automatically converts its limited set of symbols into the various ASCII characters or numeric values used in unobfuscated JavaScript code.

For example, to generate a number value of zero, we can use the following characters:

+[]

If we debug the characters +[] in Chrome or Edge DevTools, we find these characters translate to a value of zero, as shown below in Figure 4.

A screenshot of the Google Chrome DevTools interface, focusing on the Sources panel. The image highlights the right-click menu option "Evaluate selected text in console" with a cursor pointing to it, and shows other development tools and icons. The converted value is in the Console pane.
Figure 4. Using DevTools to convert JavaScript code +[] to its numeric value of zero.

How is this possible? In JavaScript code, [] represents an empty array, and if we prefix it with +, JavaScript will use type coercion to convert the empty array value into a number. Since [] contains no value, using + converts it to a value of zero.

Using this approach, we can generate the number 1 with the following characters:

+!![]

Because the [] array is blank, prefixing it with ! converts it to the boolean value of False. Adding a second ! converts it to a boolean value of True. Prefixing the entire string with + converts it to a numeric value. When converting True to a number, its value is 1.

We can generate other numbers by adding the same +!![] text, which represents an additional value of 1. For example, we can generate the number 2 from:

+!![] + +!![]

We can generate the number 3 from:

+!![] + +!![] + +!![]

Similarly, we can increase the numeric value by adding more +!![] text to the string.

We can also generate characters using this approach. For example, to create the character a, we can use the following code:

(![]+[])[1]

In this example, ![] becomes the boolean value False as mentioned earlier. Adding the symbols for a blank array [] makes the string ![]+[], which represents False + no value. JavaScript uses type coercion to convert ![]+[] to the ASCII string False.

To select the second letter of the word False, we need the first offset (second character) of the string. We do this by enclosing the original symbols in parentheses and using 1 for the offset, so (![]+[])[1] is the code that generates the letter a.

Figure 5 shows Edge DevTools confirming that (![]+[])[1] generates the letter a.

A screenshot of the Google Chrome DevTools interface, focusing on the Sources panel. The image highlights the right-click menu option "Evaluate selected text in console" with a cursor pointing to it, and shows other development tools and icons. The converted value is in the Console pane.
Figure 5. Analysis of JavaScript code in DevTools showing how to generate the character a with this approach.

 

In a similar manner, we can generate the character b using the following string:

({}+[])[2]

In this example, {} represents an empty object. Adding the symbols for a blank array [] makes the string {}+[]. JavaScript’s type coercion changes {}+[] to the ASCII string [object Object]. To select the second letter of the word object in the string [object Object], we need the second offset (third character) of that string. We do this by enclosing the original symbols in parentheses and using 2 for the offset, so ({}+[])[2] is the code that generates the letter b.

Figure 6 shows Edge DevTools confirming that ({}+[])[2] generates the letter b.

A screenshot of the Google Chrome DevTools interface, focusing on the Sources panel. The image highlights the right-click menu option "Evaluate selected text in console" with a cursor pointing to it, and shows other development tools and icons. The converted value is in the Console pane.
Figure 6. Analysis of JavaScript code in DevTools showing how to generate the character b with this approach.

By using different combinations of symbols and terms, JavaScript’s type coercion can generate various ASCII strings. We can use the offset method to select each letter of the alphabet and different symbols from the resulting strings. Figure 7 shows examples analyzed in DevTools that result in the letters c, d, e and f.

Screenshot of DevTools with the Console tab selected, displaying code outputs in a console with various obfuscation examples in JavaScript.
Figure 7. Examples of this obfuscation approach in DevTools that generate the letters c, d, e and f.

 

From this approach, we can further condense the symbols to the six used by JSFireTruck: [, ], (, ), !, and +. For example, we can generate the letters a and b from the following characters:

a = (![]+[])[+!![]]

b = ({}+[])[+!![] + +!![]]

By using the JSFireTruck obfuscation technique, any JavaScript code can be obfuscated by using just six characters. Furthermore, attackers can combine JSFireTruck with other obfuscation techniques to make malicious JavaScript more difficult for defenders to analyze.

But using these obfuscation techniques has two drawbacks:

  • The obfuscated code usually involves a large amount of text
  • Due to the repeated use of the same characters, the obfuscated code is easy to detect, even if it is not easy to analyze

Example of Malicious Code

We now understand how just six characters can represent any JavaScript code. Malware authors use this technique to make code analysis more difficult.

During our analysis, we found thousands of websites with this type of obfuscated JavaScript injected into their webpages.

Figure 8 below shows an example of the injected script following the String.fromCharCode function.

Image displaying a portion of JavaScript code with a div element and variable declarations, involving string manipulations and array operations.
Figure 8. Example of injected code starting from the String.fromCharCode function.

Of note, the obfuscated script contains an additional String.fromCharCode function, which presents another obfuscation layer.

Decoding the Obfuscated Script

We can decode the obfuscated JavaScript shown in Figure 8 through various publicly available deobfuscators for JSFireTruck. We automated our decoding process using one such tool.

When the script from Figure 8 is decoded, the output appears to be further obfuscated as shown in Figure 9.

Image displaying a line of code with a mix of numbers, Boolean values, and text strings, mostly related to various properties such as IDs, indexes, counts, and sizes.
Figure 9. Decoded JSFireTruck script shows that it’s further obfuscated.

The decoded script remains obfuscated, using an array variable $. It then accesses the values at different indexes within this array.

These array variables are present inside the script shown in Figure 10.

Screenshot of injected code with a portion highlighted in yellow.
Figure 10. Injected code showing use of String.fromCharCode function used as an array.

If we decode these character arrays and use them to replace the characters in the previous JavaScript where array $[index] is used, we get the result shown in Figure 11 below.

A screenshot of computer code in an editor, highlighting a script involving conditional checks for referrers from well-known search engines such as Google, Bing, DuckDuckGo, Yahoo, and AOL. The code includes HTML manipulation to insert an iframe. Parts of the code and URLs are intentionally blurred for privacy.
Figure 11. Decoded JavaScript code shows the iframe code that will be injected into the HTML page.

The decoded script checks for a document.referrer, meaning the traffic must have been directed from a different source, instead of directly typing a URL or domain into the web browser bar. In this case, the script is checking for a referral from one of many popular search engines. Then, depending on which search engine was used, the script will use the random ElementID present inside the page and add an iframe containing the malicious domain using the innerHTML property highlighted in blue in Figure 11 above. This ensures that traffic originating from these search engines is redirected to the injected link.

The script also extracts data following the # character in the viewer’s URL. It then uses the atob function to decode Base64 text from this data and inject another iframe using the innerHTML property (Figure 12).

A screenshot of code in an IDE, highlighting a JavaScript snippet checking the URL for specific parameters related to search engines like Yahoo, AOL, and DuckDuckGo. A portion of the code injecting an iframe is highlighted in a box. Parts of the code and URLs are intentionally blurred for privacy.
Figure 12. If the referral is not from any search engine, then it will use the code from the URL.

In Figures 11 and 12, code for the iframe includes a CSS property z-index with a value of 30000, and it has the iframe’s width and height values as 100%, with left and top as zero. With these values, the iframe will cover the entire browser window and hide the original content. This means someone can only interact with the content from the iframe and not the webpage’s actual content. This is a common technique used in clickjacking, phishing attacks and malicious redirects.

Figure 13 shows a page from a legitimate website after redirection, leading to a ZIP archive download.

Screenshot of a spoofed MediaFire download page displaying an option to download a vector drawing app for Mac. The page highlights a button labeled "Download" and provides information about the file, including its type as a ZIP archive.
Figure 13. After redirection, the iframe shows content spoofing a hosting service and leading to a suspicious ZIP archive.

In Figure 13, note how the right side of the browser window contains two scroll bars. The outer scrollbar is for the legitimate webpage, while the inner scrollbar is for the iframe.

Conclusion

This analysis demonstrated how malicious JavaScript obfuscated with JSFireTruck redirects victims to unintended websites and unwanted content.

Website injection is a common attack method. Each day, thousands of legitimate websites are compromised in this manner. These compromised but legitimate websites can lead to malicious content, like pages serving unwanted content, exploits or malware.

Website administrators must keep their web servers up to date with the latest security updates, and administrators should also analyze their web servers for any signs of infection or compromise.

Palo Alto Networks customers are better protected from the threats discussed above through the following products:

  • The Advanced WildFire machine-learning models and analysis techniques have been reviewed and updated in light of the IoCs shared in this research.
  • Advanced URL Filtering and Advanced DNS Security identify URLs and domains that host similar obfuscated JavaScript as malicious.
  • Cortex Cloud provides Web Applications and API Security (WAAS) protection through the runtime detection of OWASP Top 10 API risks, configuration drift such as misconfigurations and vulnerabilities and security breaches. Including, SQL injection (SQLi), Cross-site scripting (XSS), CVE exploit attempts, authentication bypass, sensitive data leakage, bot and scanner activity, and traffic anomalies. Cor​​tex Cloud protects WAAS infrastructure from the threats discussed within this article.

If you think you may have been compromised or have an urgent matter, get in touch with the Unit 42 Incident Response team or call:

  • North America: Toll Free: +1 (866) 486-4842 (866.4.UNIT42)
  • UK: +44.20.3743.3660
  • Europe and Middle East: +31.20.299.3130
  • Asia: +65.6983.8730
  • Japan: +81.50.1790.0200
  • Australia: +61.2.4062.7950
  • India: 00080005045107

Palo Alto Networks has shared these 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

SHA256 for 25 examples of webpages with injected script using JSFireTruck obfuscation:

  • 03ba72c2b7b0e2a9c459b95646b4301840ae66b87de47d1117a44e2d2d3e3584
  • 044cb5f61172adb60a8bca0a7addadb6bb69107a4916057338c6578aa846b057
  • 0f7903f7822c6a958d94db1b5fe83a5032eaf40ef3439c9d7bf8beec66971615
  • 1476e45493ac53a8ee99fae8c3ac6b80ba724de0bba4c995f9d4c506c2f38165
  • 17e9650f044dda1c48854e460a3cd9fe092ddc11c2e8631fed9ec293b1df2a6a
  • 1fdc283f40e64818fc5dace2a7416d1d7bd1e494e28f759ac600958f55d25dfb
  • 2053fc3b075a4661ffead5a5aebcf32a4e6fcff3c67519da7e7b0ca887e27c67
  • 21b1ff38713db80d78393b28e345de9dac97e3a69242de849555a0b6c9beee45
  • 2c452a201153e0c6c9aa2f53496d9fb43accb1a6939fe1dad8b9941fdedd0002
  • 3378883ded7d58334d375584e3b1e8a78f6db1e4f024bb2b8fd7b2b44a5233d2
  • 34c427d2e8b83877cae2a6b7c9afddf2c58efef203e44f01aaca115d99cb9e37
  • 4a90e10d497d35306bbe2db4f7d35beb0aac3468f46cef497a8438f89e63b8b7
  • 4e96d39e316fe179dff7e23c7817f0333aac6f19733a93ec4a6d6ec0c5c3ce65
  • 6105f6bb9b3f11babc219aab72d5c0cfb61feb1c0d9da06835c66ce3b180f97a
  • 6f545f17b2111f84aea5319e8425d1219c4202c2bf634013af2dec9f358a7625
  • 76578de2041f34b550a963f286827e75112ee608314611df9bc1fdb195b8838d
  • 7d840b55806e1b6e733d416cffa472978f8ff574b3d87131a40d99447189ed52
  • 9aa62bcc51798458e79f36b5812cd0ba2b62f4388d4f36f04708880601fb37ec
  • 9e42e7df0921b694be99c50db3bbd25ed6cf8a21ba3a4f2c0c56623e8e0db570
  • ae99713386f4497131473d901f006548fde88e9f78cadfad720e5a1c7850586a
  • dc58b2cec0319310ec07546a8c9cf643f31d7eecdcf4937817d06a051b80c212
  • dedeb23e38f775ed45196c506c1cc4e8b64ca88204209d63a075c98a47c20cb8
  • e48fab88fe3a144e2bd21d73e343391fd5cf642ed52827c7f663e33776437f60
  • e924c0b5261d298fec104880cc1274abd9d8ceff123974ee44e57bbf7bdc9985
  • ed1d05c988981fd0ddbf4ef634849436c99ad09c3f891189652aa97a2f66f9c3

 

Share. Facebook Twitter Pinterest LinkedIn Tumblr Email

Comments are closed.