Adminer leaks passwords; Magecart hackers rejoice


Adminer up to 4.6.2 found vulnerable, all should upgrade to 4.7.0

Adminer is a popular PHP tool to administer MySQL and PostgreSQL databases. However, it can be lured to disclose arbitrary files. Attackers can abuse that to fetch passwords for popular apps such as Magento and Wordpress, and gain control of a site’s database.

Exploitation happens in three stages. First, the attacker needs a modified MySQL server, which is altered to send out data import requests to any client that connects.

Second, an attacker needs to find an open adminer.php on the victim system. That is not hard, as many people install it in the root of their site. Once found, the attacker can instruct Adminer to connect to his rigged MySQL server (external connections are actually a feature of Adminer):

Adminer will then connect to the foreign server, login with the credentials, and immediately receive a data import request from the server for a specific file. Here is an example session, where Adminer sends the contents of local.xml (where Magento stores it secret database password) to the attacker-controlled server.

Third stage: as the attacker now has the master password for the victim site, he can use the same Adminer to access the database of the victim. And continue to steal private data or inject a skimmer.

Abuse in the wild

Update Jan 18th: Twitter user Yasho made a similar discovery and wrote about it in August 2018.

AFAIK this attack method has not been published before, but in hindsight I have observed it being used by different Magecart factions at least since October 2018 (although I didn’t understand what was going on back then). The vulnerability was subsequently used to inject payment skimmers on several high-profile stores (government & multinationals).

Because different Magecart factions use it, I suspect that the modified MySQL server is for sale on the dark web.

Via my honeypots and customers I have observed a recent surge in the volume of open Adminer scans. I expect that anyone running an unfixed Adminer will be breached in the coming months.

The fix?

I have tested Adminer versions 4.3.1 up to 4.6.2 and found all to be vulnerable. Adminer 4.6.3 was released in June, 2018 and appears safe. It is unclear whether the security flaw was fixed deliberately or by accident, as Adminer does not mention a security release.

I would recommend anyone running Adminer to upgrade to the latest version (4.7.0). Also, I urge anyone to protect their database tools via an additional password and/or IP filter. Sometimes perpetrators can obtain your database password by other means, and an open Adminer makes life very easy for them.


Advanced sabotage among competing Magecart factions


Skimmers found to subtly sabotage each others fraud operations

Competition is grim in the online skimming business (aka “MageCart”). The aggressive MagentoCore skimmer was previously observed to kick contending parasites from its victim hosts. But this week, I discovered that the battle has entered a new stage: advanced sabotage of each others revenue streams and reputation.

Sample case in question: cosmetics shop Bliv.com. It contains multiple distinct skimmers that send credit cards to different exfiltration hosts. The more advanced one is onlineclouds.cloud, which is heavily obfuscated and uses cloaking techniques. But with some sweating and curses, I decoded it (full source).

The interesting part is copied below. It detects whether any cards are sent to the (competing but inferior) skimmer domains js-react.com and bootstrap-js.com. Then, it subtly changes the last digit of the intercepted card number, effectively sending bogus card numbers to its competitor:

jQuery.ajaxSetup({
  beforeSend: function(jqXHR, settings) {
    if (settings.url.indexOf("js-react.com") !== -1 || 
    settings.url.indexOf('bootstrap-js.com') !== -1) {
      // ...
      var myRandom = Math.floor(Math.random() * 10);
      var old_cc = settings.data.match(cc);
      var new_data = settings.data.replace(
          new RegExp("[0-9]{13,16}", 'g'), 
          old_cc[0].slice(0, -1) + myRandom);
      settings.data = new_data;
    }
  }
});

Why the subtle sabotage, instead of just killing the inferior skimmer? On the dark web markets, reputation is everything. If one sells non-working cards, angry customers will publicly complain and it will destroy the competing “brand”.

It is not likely that the MageCart battle will be finished soon, so stay tuned…

Thanks to Jérôme Segura of Malwarebytes for suggesting to decode the onlineclouds malware


Merchants struggle with MageCart reinfections


1 in 5 compromised merchants get reinfected, average skimming operation lasts 13 days

MageCart, the notorious actors behind massive online card skimming, has been busy. And so have I: my crawlers are continuously tracking the raging battle between card thieves and merchants. It seems that the latter are on the losing end: in October, I counted the 40,000th hijacked store since 2015. And in the last 3 months alone, I counted 5,400 unique online stores that got a skimmer added to their checkout pages.

20% reinfection rate, counter measures fail

In the last quarter, 1 out of 5 breached stores were infected (and cleaned) multiple times, some even up to 18 times. This shows that counter measures taken by merchants and their contracted security firms often fail. There are multiple reasons for this. First, MageCart operatives are getting more sophisticated in hiding their presence and ensuring future access. Once an operative gains access to a merchant’s server, it is common to litter the site with backdoors and rogue admin accounts. Second, they use reinfection mechanisms such as database triggers and hidden periodic tasks to reinstate their payload. Third, they use obfuscation techniques to make their presence indistinguishable from legitimate code. Fourth, it is more and more common for MageCart actors to utilize unpublished security exploits (aka 0days). Researching these requires a significant investment. All in all, it takes some very keen eyes and a lot of effort to clean all traces of a breach.

Public examples of stores battling with reinfections are TechRabbit.com (2 times), Kitronik.co.uk (4 times) and Zapals.com (4 times).

Black hats are faster than white hats

Here’s a histogram of the number of days it takes merchants after a MageCart breach to clean up, and how many days between cleanup and a subsequent reinfection. Conclusion: skimmers persist on average for 12.7 days, while on average I saw reinfections occur within 10.5 days. We are one step behind here.

Cleaned during the week, hacked in the weekend

The red lines are newly identified infections, the green ones are cleanups. You can see that merchants and their security firms work mostly during the week, while the black hats, unsurprisingly, dont stick to office hours.

Conclusion

MageCart operations have become more professional while expanding methodologies and changing tactics. Merchants need to step up their efforts in protecting their reputation and the privacy of their customers.


Backdoor found in Webgility


Update Nov 23rd: Webgility has released a patch and a public statement, urging all customers to upgrade to version 345.

Update Nov 30th: Webgility has discovered another security issue and urges all customers to upgrade to version 346.


When an accounting software firm proclaims to do epic shit, you know they are up to no good. The VC-funded Webgility software contains a backdoor for the purpose of remote upgrades. As a side effect, this allows anyone to upload PHP code and do all kinds of naughty stuff. Curiously, the Webgility engineering team denies the existence of the backdoor, even when confronted with a functional proof of concept and a demonstration video.

Because of the severity, I recommend Webgility customers to restrict access to trusted IPs or temporarily remove the software until there is a fix.

The backdoor was discovered by Eric Seastrand as part of a PCI code audit. He reported the security flaw on Oct 16th to Webgility, together with an extensive explanation, sample code and a demo video. Then, he got this odd response:

Our engineers further reviewed your E-mail and we would like to inform you that, this file can’t execute automatically or through a Web Browser […] we request you kindly do not test or trial anything in Webgility module folder

Eric answered patiently and explained once again how the unauthorized update mechanism poses a serious security threat. Webgility thanked him for the suggestion and closed the ticket without further ado.

I also gave it a couple of tries to explain the situation, but they would have none of it.

Just to be sure: I have validated Eric’s proof of concept exploit code on my live store. Because of the intense efforts that criminals are undertaking to find vulnerabilities in 3rd party ecommerce software, it won’t be long before this flaw will be massively exploited to turn the thousands of Webgility customers into card skimming zombie stores.

Hopefully this post will get Webgility to release a fixed version. If not, better to stay far from its software.

Thanks to Eric and the fine people at Hypernode, you can now use Magereport to check whether your store runs a vulnerable Webgility.


Multiple 0days used by Magecart


Online credit card theft has been all over the news: criminals inject hidden card stealers on legitimate checkout pages. But how are they are able to inject anything in the first place? As it turns out, thieves are massively exploiting unpublished security flaws (aka 0days) in popular store extension software.

While the extensions differ, the attack method is the same: PHP Object Injection (POI). This attack vector abuses PHP’s unserialize() function to inject their own PHP code into the site. With that, they are able to modify the database or any Javascript files. As of today, many popular PHP applications still use unserialize(). Magento replaced most of the vulnerable functions by json_decode() in patch 8788, but many of its popular extensions did not.

It appears that attackers have amassed a large number of extensions and found numerous POI vulnerabilities. And they are now probing Magento stores in the wild for these extensions. I collected the following probes. If you are running any of them, you’d better disable them quickly and search your logs for unauthorized activity.

POST /index.php/madecache/varnish/esi/
POST /index.php/freegift/cart/gurlgift/
POST /index.php/qquoteadv/download/downloadCustomOption/
POST /index.php/ajaxproducts/index/index/
POST /index.php/minifilterproducts/index/ajax/
POST /index.php/advancedreports/chart/tunnel/
POST /index.php/bssreorderproduct/list/add/
POST /index.php/rewards/notifications/unsubscribe/
POST /index.php/emaildirect/abandoned/restore/
POST /index.php/vendors/withdraw/review/
POST /index.php/vendors/credit_withdraw/review/
POST /index.php/gwishlist/Gwishlist/updategwishlist/
POST /index.php/rewards/customer/notifications/unsubscribe/
POST /index.php/aheadmetrics/auth/index/
POST /index.php/customgrid/index/index/
POST /index.php/customgrid/Blcg/Column/Renderer/index/index/
POST /index.php/tabshome/index/ajax/
POST /index.php/customgrid/Blcg_Column_Renderer_index/index/
POST /index.php/rewards/customer_notifications/unsubscribe/
POST /index.php/vendors/credit/withdraw/review/
POST /index.php/multidealpro/index/edit/
POST /index.php/layaway/view/add/
POST /index.php/simplebundle/Cart/add/
POST /index.php/CustomGrid/index/index/
POST /index.php/netgocust/Gwishlist/updategwishlist/
POST /index.php/prescription/Prescription/amendQuoteItemQty/
POST /index.php/ajax/Showroom/submit/

The payload for all of these POSTs is a specially crafted Zend_Log object that contains rogue code. Max Chadwick wrote a nice summary of this vulnerability class.

Fixing this mess

Now, I contacted several authors (kudo’s to Webcooking for being the first to fix their code within hours!), but I cannot derive the original author from all of these URLs. So my request to you: do you recognize any extension in these URLs? Please contact the author and keep me posted (email/twitter DM), I will update the status below. Together we can get all of these extensions fixed quickly.

URIModuleStatusOrg
rewards/*TBT_Rewardsfixed in 1.8.7.3link
simplebundleWebcooking_SimpleBundlereported and fixed in 1.6.9link
ajaxproducts/indexEM_AjaxProductsfixed in 1.0.0link
qquoteadv/downloadCart2Quotefixed in 5.4.5link
advancedreports/chartAW_AdvancedReportsreported, fix announcedlink
aheadmetrics/authAW_AheadMetricsreported, abandonedlink
ajax/Showroom?? 
bssreorderproduct/listBSS_ReorderProductfixed in 1.2.4link
customgrid/*BL_CustomGrid?abandonedlink
emaildirect/abandonedCampaignerfixed in 1.1.6link
freegift/cartMW_Gift?? 
*/GwishlistmageGwhishlistreported, not fixedlink
layaway/viewCed_Layaway??link
madecache/varnishMade_Cachereported and fixedlink
minifilterproducts/indexEM_ProductsFilterWidgetreportedlink
multidealpro/indexEM_Multidealreportedlink
prescription/Prescription?? 
tabshome/indexVes_Tabshome? 
vendors/creditVes_VendorsCredit?link
vendors/credit_withdraw?? 
vendors/withdraw?? 

Modus operandi

Some more info on this group’s modus operandi. Once any of the probes above is successful, a malicious actor will come back and insert a customized Javascript payment overlay for the specific site. This works for sites that have external payments, or no credit card payments at all, because a fake credit card payment section is inserted. Once a user enters his CC details and clicks submit, the fake credit card form disappears and the unsuspecting (?) user will likely try again. The fake form will not show a second time, because a cookie is set to prevent that.

fake cc form fake cc form

Under the hood it currently uses a two step payment exfiltration method. First, a jQuery call is made to one of these (the first one has been taken down already):

records.nstatistics.com/records.php
stat.statisticvisit.com/rec.php

Up to now, they have returned various CC drop servers in the ngrok.io domain, such as:

b0b127c6.ngrok.io
f0c806aa.ngrok.io
e7900f9c.ngrok.io

As Ngrok takes these down quickly (as I predicted earlier), they use this mechanism to easily switch drop servers.

How to block all probes

As suggested by Sean H, you could hard block specific requests to these modules in Nginx. Their functionality will probably break though:

 location ~* ^/index.php/(madecache|freegift|qquoteadv|ajaxproducts|minifilterproducts|advancedreports|bssreorderproduct|rewards|gwishlist|aheadmetrics|customgrid|tabshome|vendors|multidealpro|layaway|simplebundle|netgocust|prescription|ajax/Showroom)/.* { deny all; }

Header image credits: Maxpixel


Pagination