Balada Injector

Dive into how Balada exploits vulnerabilities within WordPress plugins. This research blog analyzes how Balada injects malicious code and the functionality of the scripts used in the campaign.

Balada Injector

Balada, also known as Balada Injector, is a malware campaign that targets and injects malicious PHP code into WordPress websites. Researchers have observed recent campaigns exploiting two vulnerabilities within WordPress plugins to inject the initial set of malicious code.

The first vulnerability exploited was CVE-2023-3169 (Pulsedive), which allowed for Unauthenticated Stored XSS attacks against versions of the tagDiv Composer plugin. CVE-2023-3169 allowed attackers to inject scripts into the HTML code of the website. Another vulnerability abused in the Balada injector campaign was CVE-2023-6000 (Pulsedive). CVE-2023-6000 was in the Popup Builder plugin that also allowed for XSS attacks. The scripts and code described in this blog focus on intrusions that used CVE-2023-6000 to start the infection. Below is an overview on:

  • How Balada infects websites
  • Scripts used within the campaign
  • Some of the functionality within the scripts. 
Figure 1: Balada threat overview

How Balada Spreads

The latest iteration of Balada campaigns exploited CVE-2023-6000 to inject the first stage of malicious code into websites. This CVE impacted versions of the Popup Builder WordPress plugin before 4.2.3. Successful exploitation of this vulnerability meant that attackers could inject code into the website and have it there permanently. This type of attack is called a Stored XSS attack. 

ℹ️
“Stored attacks are those where the injected script is permanently stored on the target servers, such as in a database, in a message forum, visitor log, comment field, etc. The victim then retrieves the malicious script from the server when it requests the stored information. Stored XSS is also sometimes referred to as Persistent or Type-II XSS.” (OWASP Cross Site Scripting Attacks Community Page)

Researchers at Securi identified several versions of the injected code. More recent versions of the code use meaningless comments to make reading the code more difficult, while earlier versions did not include comments.

💡
A PublicWWW query shared by Securi can help identify potentially compromised sites.

Injected Script

The first piece of injected code is used to retrieve additional code from an adversary-controlled domain. This externally stored code is added to the website by creating a new script element. 

A screenshot of a website infected with Balada is shown below. Note: the popup with injected code is not shown.

Figure 2: A website compromised by Balada

The code injected into the website was pulled using DevTools in Google Chrome and is displayed below.

Figure 3: Injected code looks for a particular popup ID and contains meaningless comments

The code uses comments to break up commands and make it more difficult for analysts to understand what the code is doing simply by reading it. Even though the code is somewhat obfuscated, analysts can gain insight into what may happen based on the plaintext code. Key code elements that provide insights are the eval and atob statements. The eval function shows that some code may be executed while the atob function is used to decode base64 encoded data. By combining these using the statements using the assignment below, we see that base64 encoded data will be passed to the eval function.

var lziecpcc=eval;

var rlnubtgnd=atob;

lziecpcc(rlnubtgnd(

Moreover, this part of the code is only executed if the popupId value is equal to 4248. The popup value will differ on every compromised website as it requires the id of the popup that will be used during the code. Active popups will have their IDs included in the HTML code. This can be used to obtain the id. 

The following CyberChef recipe cleans up the code shown in Figure 3.

Find_/_Replace({'option':'Regex','string':'\\/\\*\\w+\\*\\/'},'',true,false,true,false)

Subsection('{var.*',true,true,false)

Find_/_Replace({'option':'Regex','string':'\\"'},'',true,false,true,false)

Find_/_Replace({'option':'Regex','string':'\\+'},'',true,false,true,false)

Merge(true)

Generic_Code_Beautify()

Syntax_highlighter('auto detect')

💡
CyberChef is an excellent open-source tool that allows analysts to quickly perform analysis on artifacts based on predefined operations. These operations can be combined into "recipes" that decode or transform more complicated data. Common uses of CyberChef include base64 operations, xor, and the encryption/decryption of data.
Figure 4: The code in Figure 3 cleaned up using the CyberChef Recipe shown above

The CyberChef recipe can be further expanded to decode the base64 data and get the executed code. The additions are to extract the variables that hold the eval and atob functions, identify the base64 string, and decode it. The last step of the recipe is to replace the variables with the actual value they hold. For example, in Figure 4, lziepcc will be replaced by eval in the final string.

Find_/_Replace({'option':'Regex','string':'\\/\\*\\w+\\*\\/'},'',true,false,true,false)

Subsection('{var.*',true,true,false)

Find_/_Replace({'option':'Regex','string':'\\"'},'',true,false,true,false)

Find_/_Replace({'option':'Regex','string':'\\+'},'',true,false,true,false)

Merge(true)

Generic_Code_Beautify()

Register('var (\\w+) = eval;',true,false,false)

Register('var (\\w+) = atob;',true,false,false)

Subsection('$R1\\((.*)\\)',true,true,false)

From_Base64('A-Za-z0-9+/=',true,false)

Merge(true)

Find_/_Replace({'option':'Regex','string':'$R0\\($R1'},'eval',true,false,true,false)

Syntax_highlighter('auto detect')

Figure 5: Base64 decode code of the injected script (Figure 3) showing the script requests additional code from an external resource

The decoded code shows that the evaluated section of the script creates a new script element and gets the text for that element from an external URL - hxxps[://]soft[.]specialcraftbox[.]com/JZFYbC. WHOIS data indicates that the domain specialcraftbox[.]com was registered on 2023-12-13 with Nicenic, a domain registrar and web hosting service operating out of Hong Kong, China.

Figure 6: WHOIS data for specialcraftbox[.]com within Pulsedive
💡
To search for other IoCs using the same registrar in Pulsedive, query whois.++registrar="NICENIC INTERNATIONAL GROUP CO., LIMITED"
Figure 7: Pulsedive results for domains with the same registrar

The URL, hxxps[://]soft[.]specialcraftbox[.]com/JZFYbC, contains the obfuscated code shown in the Figure 8 below:

Figure 8: Obfuscated code available on hxxps[://]soft[.]specialcraftbox[.]com/JZFYbC

Based on research from Sucuri, the injected script works to establish persistence by dropping a backdoor. The new script checks for keywords related to cookies present with users with admin privileges. If the cookies are not present, additional scripts may be loaded to redirect users to push notification scams. 

However, if cookies for admin users are detected, the script appends additional parameters to the URL and executes several network requests that are used to install a malicious WordPress plugin.

Figure 9: The additional scripts check for certain cookies indicating an admin is accessing the site to install an additional backdoor. If the cookies do not indicate the user is an admin, then the user is redirected to a notification scam
Figure 10: Code used to install the wp-felody.php plugin. Source: Sucuri

Once the plugin has been installed, the URL is sent back to adversary-controlled infrastructure in the form of a GET request where the compromised URL is included in the URL as a parameter.

Backdoor Functionality

The wp-felody.php backdoor can check if the backdoor is installed and able to upload files to the server. 

Figure 11: Content of wp-felody.php plugin. Source: Sucuri

The first check an adversary can make is to confirm that the backdoor is still active. This is done by sending a POST request to the wp-felody.php endpoint with the parameter w33. If the value of the parameter is w33, then the backdoor echoes the hash of the value received.

The other parameters that can be sent are the q33 and q34 values used to upload files to a temporary directory. The md5 hash of the POST Request parameter q33 is hashed again before being compared to a hardcoded value; if the received value matches the hardcoded value, then a file is written to a temporary directory. The content of the file is the base64 decoded data sent in the q34 parameter. Once executed, the file is deleted from the server. In certain intrusions, the wp-felody.php backdoor is used to download additional malicious files. 

Conclusion

Security researchers estimate that in its most recent campaign, Balada infected over 6,000 websites. This campaign allowed additional malware to be uploaded to compromised sites or redirected users to other types of phishing attempts. Additional backdoors installed on infected hosts offer threat actors expanded functionality on the compromised sites. 

WordPress is one of the most popular CMS providers in the world, used by millions to create hundreds of millions of websites. Its popularity is due to the flexibility offered by its plugins that augment out-of-the-box functionality with additional features and ease of use. While WordPress is great for website development, it also poses a risk to users since vulnerabilities within plugins may not be patched as quickly as in other servers. Expect exploitation of WordPress components to continue as the popularity of the technology means a rich target environment for attackers.

Recommendations

  • Vulnerability Management
    • Periodically check for updates within all WordPress components and update them accordingly.
  • Monitor for Suspicious User Accounts
    • Some malware variants that target WordPress sites will attempt to establish persistence by creating admin users. Monitor users with access to admin consoles to ensure that only required users are granted access.

Indicators of Compromise

The table below contains a list of Baladanetwork IoCs identified and added to the Pulsedive platform. This data can be queried in Pulsedive using the Explore query threat="Balada" and is available for export in multiple formats (CSV, STIX 2.1, JSON).

Balada Injector IOCs

specialcraftbox[.]com

from[.]forwardstarlight[.]com

page[.]bridgelinering[.]com

lineferaline[.]com

colorschemeas[.]com

statisticsong[.]com

north[.]statisticplatform[.]com

decentralappps[.]com

promsmotion[.]com

stablelightway[.]com

And more, retrieve all indicators here

MITRE ATT&CK TTPs

Tactic

Technique

Command and Control

Data Obfuscation (T1001)

Defense Evasion

File Deletion (T1070.004)

Execution

Exploitation for Client Execution (T1203)

Initial Access

Drive-by Compromise (T1189)

Exploit Public-Facing Application (T1190)

Phishing (T1566)

Persistence

Create Account (T1136)

Server Software Component (T1505)

Web Shell (T1505.003)

Privilege Escalation

Web Shell (T1505.003)

Resource Development

Develop Capabilities (T1587)

Malware (T1587.001)

Stage Capabilities (T1608)

Upload Malware (T1608.001)

References

https://blog.sucuri.net/2023/04/balada-injector-synopsis-of-a-massive-ongoing-wordpress-malware-campaign.html#client-hosts-C2-servers

https://blog.sucuri.net/2019/04/from-tk-redirects-to-pushka-browser-notification-scam.html

https://blog.sucuri.net/2024/01/thousands-of-sites-with-popup-builder-compromised-by-balada-injector.html

https://publicwww.com/websites/%22sgpbWillOpen%5C%22%2C+function%28e%29+%7Bif+%28e.detail.popupId%22+atob/3

https://wpscan.com/blog/stored-xss-fixed-in-popup-builder-4-2-3/

https://wpscan.com/vulnerability/e6d8216d-ace4-48ba-afca-74da0dc5abb5/

https://www.hivepro.com/threat-advisory/balada-injector-a-large-scale-malware-campaign-targeting-wordpress/

https://www.geoedge.com/balda-injectors-2-0-evading-detection-gaining-persistence/

https://socprime.com/blog/balada-injector-malware-campaign-detection-hackers-exploit-a-tagdiv-composer-vulnerability-infecting-thousands-of-wordpress-sites/