CSS-JS Steganography in Fake Flash Player Update Malware

This summer, MalwareBytes researcher Jérôme Segura wrote an article about how criminals use image files (.ico) to hide JavaScript credit card stealers on compromised e-commerce sites.

In a tweet, Affable Kraut also reported another similar obfuscation technique using .ico files to conceal JavaScript skimmers.

From the sample in his tweet, the “www.google-analytics.com URL is clearly visible within the malicious script. However, this script was only used as a dictionary of characters to build a URL for the real payload (priangan[.]com/wp-content/languages/blogid/favicon.ico and lebs[.]site/favicon.ico in other variations).

Steganography in CSS

Both of these two cases conceal malware within real, benign files — a technique referred to as steganography.

During a recent investigation this October, we came across another interesting variant leveraging the same technique. Instead of loading .ico files and extracting JavaScript from the EXIF data, however, the malware was found nestled within a .css file.

The script, which was almost identical to the one found in Affable Kraut’s tweet, had been injected at the bottom of the .js files wp-includes/js/wp-emoji-release.min.js, wp-includes/js/jquery/jquery.js, and at the top of index.php as seen below.

Infected index file with malicious URL
Infected index.php

This time, the //static.xx.fbcdn.net[.]com/plrhg URL was easily seen in plain text.

The string visually resembles a real URL used by Facebook: //static.xx.fbcdn.net. However, in reality the static.xx.fbcdn.net[.]com (with extra .com) does not even exist. It’s presence serves as a red herring: it’s real purpose is to provide a character dictionary to build the real malicious URL, which this script tries to load via XMLHttpRequest: “//polobear[.]shop/fonts.css

Since .css is just a text file, how can someone conceal malicious code in it? This part of the injected script explains it:

Algorithm CSS to JavaScript concealing malicious code
CSS to JavaScript algorithm

The algorithm takes the part after the last “}” in the requested .css, splits it into pieces separated by spaces, and then uses those pieces to construct binary representation of character codes, converting them to real characters using the fromCharCode function.

This method essentially constructs the JavaScript function character by character, which is then executed once the whole file is processed.

Demonstration of How It Works

To further illustrate this example, let’s review the fonts.css file containing the malicious payload:

Empty lines in a CSS file
Contents of polobear[.]shop/fonts.css

At first glance, there really doesn’t appear to be anything suspicious here. Just some benign CSS rules.

There are, however, many empty lines at the bottom of the file. Very many. 56,964 empty lines! And the size of this small fonts.css file is about 150 Kilobytes!

Empty lines are normally ignored by browsers and CSS parsers. While strange, this is still absolutely benign in normal circumstances. However we know that this malware uses the file not as CSS but as a source of a JavaScript code — and its binary representation is concealed by sequences of tab and non-tab characters.

Revealing the Code

If we select the empty lines after the last “}” character in a text editor, another story is revealed:

Selecting empty lines
Selecting invisible contents in text editor

Looks like Morse code with sequences of dots and dashes, doesn’t it?

When reviewed in hex, it appears like this:

Tabs, spaces, and line feeds in the fonts.css file
Hex view of fonts.css

Here you can explicitly see that the lines are not that empty. They consist of sequences of tabs (09), spaces (20) and line feeds (0A).

In these sequences, spaces work as delimiters between individual bytes (characters). Tabs and line feeds form binary representations of characters, where tab is 1 and line feed is 0.

For example, the first encrypted character after the last “}” is 09-09-09-0A-09-09, which can be converted to the binary “111011”. This is equal to decimal 59, which is the character code for “;” (semicolon).

Converting Empty Lines to JavaScript Code

Using this algorithm, we decoded all the 56,964 lines and got 20,233 bytes of this malicious JavaScript code:

WiseLoop JS Obfuscation
Result of conversion of empty lines to JavaScript code

Interesting — it’s the same WiseLoop JS Obfuscation that is found in EXIF metadata of .ico files used by web skimmers! In this case, however, it didn’t turn out to be a credit card skimmer.

Fake Flash Player updates

Here’s the decoded version of the script:

Decided script in flash player updates
Decoded script obtained from fonts.css

What the decoded script does is create an iframe from lopiax[.]us with a fake Flash Player update recommendation.

Fake flash layer updates phishing
Fake Flash Player update notification

While Flash player is reaching end of life on December 31, 2020 and all major browsers will stop supporting it in a couple months, Flash Player updates are still quite a popular lure for social engineering attacks that trick people into installing malware on their computers.

This particular popup seems to be related to what MalwareBytes calls the Domen social engineering kit.

The only way to get rid of this popup is to click on the Update button. This initiates a download of the adobeflpl_installer.zip file with an HTA file with VB script that uses PowerShell to download malicious .exe and .dll files (including the NetSupport RAT).

The download link changes quite often, pointing to malicious files on various compromised sites.

The zip files also change in size, but are still reliably detected by many antiviruses.

Antivirus detections
VirusTotal detections

Revelations of the polobear[.]shop Site

This malware is not a leftover from some old attack. It’s pretty recent because the domain polobear[.]shop was registered just a few weeks ago on October 9th, 2020.

The site is not properly protected, and we can see directories and files hosted there.

directories and files on a compromised website
File listing on polobear[.]shop

In the /tmp/active directory, you can see IP addresses of computers attacked by this malware in real time. Around 5-10 new IPs are typically listed every few seconds.

IPs attacked in real time
IPs of attacked computers

Important files


The generate.php file is responsible for the generation of JavaScript code which attackers inject into compromised websites.

Scripts generated to work with the URL

The script’s interface shows that the generated code has been defined to work for the polobear[.]shop domain.

Attackers can choose a version with or without the “Anti-Debug” feature. As an Anti-Debug mechanism, the script puts the main functionality into the requestAnimationFrame function callback.

The CSS-JS name tells us that the script was specifically designed to work with CSS files as the source of JS payload.

On every load of the generate.php script, variable names randomly change — leaving the remaining parts of the code intact.


Gate.php is a common name for data exfiltration scripts used by web skimmers. In this case, however, this is the file that generates the fonts.css response with a payload concealed by tabs, spaces and line feeds.

Most likely this is accomplished by an .htaccess rule for .css files, since fonts.css is not present in the file list. Moreover, when a request to fonts.css files is considered unwanted by the malware, a  “The requested URL was not found on this server” page with a 200 response code is displayed — instead of the 404 that you get for any other types of really nonexistent pages on the site.

GeoIP.dat (1).zip

According to the timestamp found on the /index page, the first file uploaded to the site was GeoIP.dat (1).zip. This occurred on October 9th, 2020 — the same date the polobear[.]shop domain was registered.

The zip archive contains three files: geoip.inc, GeoIP.dat (both created on Sept 3, 2020) and index.php (Oct 1, 2020). The first two files belong to a GeoIP library which helps identify the geographic origin of the requests.

The index.php file is more interesting, though. It’s a boilerplate script for fake Flash Player update attacks. The script checks to ensure that a visitor is not a bot and comes from an eligible country (in this file it’s: USA, Italy, Germany, UK and Canada).

If the user agent and geographic location match the success criteria, then a web page is displayed with the Flash Player update warning.

success criteria defined to load flash player update warnings
Code that generates fake Flash Player Update warnings

Actual download links are not present in the file. These must be specified by the attacker whenever they prepare a new download location. Most likely, something similar currently works on the lopiax.us site.

162.0.235[.]12 Server

At this moment, polobear[.]shop is hosted on the server IP 162.0.235[.]12 which belongs to Namecheap Inc.

A quick search shows that this IP address is associated with multiple phishing sites:

IP addresses associated with phishing sites
Last seen domains hosted on 162.0.235[.]12

We found a number of active phishing sites targeting many popular platforms:

  • PayPal: tierretyr[.]live and Pp-login-alert[.]com.
  • Docusign: dorcsign[.]cloud, Doscug[.]live.
  • Banking sites: www.ehb-onlinebank[.]ml, halifax-alerts[.]com, ing-app-nl[.]me.

A hacker admin panel also exists on hxxps://techvita[.]biz/PL341/panel/admin.php (located on the same server).

Techvita[.]biz has also been found receiving requests from Windows malware (with detections by Azorult, Lokibot and GuLoader signatures), as  seen in this JoeSandbox report.


Multiple types of web malware (including web skimmers and social engineering malware droppers) have recently started using this same 3-step approach to obfuscation in their attacks.

To begin, attackers inject an obfuscated script into a compromised environment. Next, the malicious script loads a seemingly benign file from a remote third-party website — for example, an ICO or CSS file. An obfuscated malicious payload concealed within the inconspicuous file is then extracted at whim.

One distinctive trait of this approach is that the obfuscation algorithms used for each step are very specific and stay the same — regardless of the type of the attack. This suggests that attackers are using the same toolkit containing steganography features to hide the malicious behavior of their injections.

Front-end scripts like the one described for generate.php clearly demonstrate that they were created to be used by an unlimited number of users. The script allows any bad actors to easily incorporate their payload into an attack by installing it on their own domain, without making any changes to the code — we can assume this feature allows for easy monetization and distribution of the malicious toolkit.

As attackers continue to look for ways to automate their malware campaigns and avoid detection, it’s likely that we may see even more attacks using similar steganography-obfuscation approaches.

For site owners it doesn’t change much though. They should keep their site software up-to-date, employ website security best practices, and leverage integrity monitoring to detect unwanted changes.

*** This is a Security Bloggers Network syndicated blog from Sucuri Blog authored by Denis Sinegubko. Read the original post at: https://blog.sucuri.net/2020/11/css-js-steganography-in-fake-flash-player-update-malware.html