Magento and the Log4j vulnerability
by Sansec Forensics Team
Published in Threat Research − December 13, 2021
Updated Dec 20th. This article describes how Magento is affected by the critical log4j vulnerability, and what you can (and should) do to prevent a hack.
A critical vulnerability in the popular Log4j Java library has been massively exploited since December 1st. It exposes full control to a remote attacker, is easy to exploit, and almost every company that uses Java is affected. Attackers have launched mass scanners in the first 48 hours, while most organizations are struggling to find affected components in their IT landscape.
- Another, but less severe, issue was discovered on Dec 14th.
- A third, but also less critical issue was discovered on Dec 16th.
The good news: popular ecommerce platforms such as Magento are not written in Java and in itself are not vulnerable. However, your store may use Java-based components, so you should ensure to upgrade those as soon as possible, in particular:
- ElasticSearch - versions 6.8.9+, 7.8+ running on Java JDK9+ are NOT at risk. Older ES or SDK versions may allow remote code execution (ES5) or leaking of server variables. To be on the safe side, ElasticSearch has provided new releases which disable the contested behavior. If you can, upgrade to 6.8.21 or 7.16.1. Further analysis on this.
- Logstash - upgrade 6.8.21 or 7.16.1. Vulnerable in combination with JDK8 or below.
- Solr - upgrade to 8.11.1.
- Sumo Logic has a Java agent that may be vulnerable (not confirmed yet)
Sansec has ran a global scan of all Magento stores and found a handful of stores that appeared susceptible to the basic attack method. However, this is not a safety guarantee for other stores, because:
- Your WAF (such as Cloudflare, Fastly, Incapsula) may have blocked our probes, and attackers may be able to circumvent this first line of defense. Or,
- Your site may have already been compromised and the attackers have "fixed" the vulnerability to keep out other attackers.
To maximize visibility of any log4j fallout, we recommend to eComscan on your store. It will detect any vulnerable log4j versions in Java archives, and it should detect whether any malicious assets have been deployed already. Get a fully functioning trial with coupon SECURE2021 and run a scan within 5 minutes.
Believe you are under attack right now? Contact us!
Development agencies: do reach out if you want to do a mass rollout of security measures for all your customers.
Preferred solution
Find and upgrade vulnerable log4j components to version 2.17 as quickly as possible. If that is somehow not possible, please see the other sections below for quick fixes.
To identify any Java based applications on your servers and see if they use the Log4j library, you can use the latest eComscan release. Run it like this:
ecomscan --key=LICENSE_KEY -m0 --maxsize=0 /path/to/java/application
If you find any vulnerable versions, chances are that attackers have already injected malware on your system. You should consider your system as compromised. Launch an incident response investigation, and use a server side malware scanner to find malicious files and processes.
Sansec has identified numerous attacks methods already. The primary vector is to install zombie agents on vulnerable systems. These agents (RATs) can be used at a later stage to install cryptominers, skimmers or ransomware. We will likely see a flood of hacked organizations in the coming weeks. Update Dec 14th: first cases of ransomware have been reported
Configure system flag to disable the vulnerability
If you cannot upgrade right away, early guides recommended to set the JVM flag log4j2.formatMsgNoLookups=true
, but this does not protect against all attacks. You should implement it just in case, but do not rely on this.
Magento log4j protection with Varnish
Fastly has published a Varnish log4j ruleset that will block all requests that have ${
in incoming HTTP headers or POST data. This is very effective but also a very crude measure, as it may block regular (API) calls. We recommend to use these rules, if:
- your WAF/CDN has not implemented log4j security rules
- you use Varnish
- you cannot upgrade or fix vulnerable log4j components elsewhere
# Apache Log4j2 <=2.14.1 JNDI RCE - CVE-2021-44228
# This is a more strict sibling of https://fiddle.fastlydemo.net/fiddle/049ae446 , it will generate false positives.
if (
std.strstr(urldecode(req.body), "${")
|| std.strstr(urldecode(req.http.accept), "${")
|| std.strstr(urldecode(req.http.accept-additions), "${")
|| std.strstr(urldecode(req.http.accept-ch), "${")
|| std.strstr(urldecode(req.http.accept-charset), "${")
|| std.strstr(urldecode(req.http.accept-ch-lifetime), "${")
|| std.strstr(urldecode(req.http.accept-datetime), "${")
|| std.strstr(urldecode(req.http.accept-encoding), "${")
|| std.strstr(urldecode(req.http.accept-features), "${")
|| std.strstr(urldecode(req.http.accept-language), "${")
|| std.strstr(urldecode(req.http.accept-patch), "${")
|| std.strstr(urldecode(req.http.accept-post), "${")
|| std.strstr(urldecode(req.http.accept-ranges), "${")
|| std.strstr(urldecode(req.http.cache-control), "${")
|| std.strstr(urldecode(req.http.connection), "${")
|| std.strstr(urldecode(req.http.content-length), "${")
|| std.strstr(urldecode(req.http.content-range), "${")
|| std.strstr(urldecode(req.http.content-type), "${")
|| std.strstr(urldecode(req.http.cookie), "${")
|| std.strstr(urldecode(req.http.cookie2), "${")
|| std.strstr(urldecode(req.http.dnt), "${")
|| std.strstr(urldecode(req.http.if-modified-since), "${")
|| std.strstr(urldecode(req.http.if-none-match), "${")
|| std.strstr(urldecode(req.http.if-range), "${")
|| std.strstr(urldecode(req.http.range), "${")
|| std.strstr(urldecode(req.http.referer), "${")
|| std.strstr(urldecode(req.http.referer-root), "${")
|| std.strstr(urldecode(req.http.sec-fetch-dest), "${")
|| std.strstr(urldecode(req.http.sec-fetch-mode), "${")
|| std.strstr(urldecode(req.http.sec-fetch-site), "${")
|| std.strstr(urldecode(req.http.sec-websocket-accept), "${")
|| std.strstr(urldecode(req.http.set-cookie), "${")
|| std.strstr(urldecode(req.http.set-cookie2), "${")
|| std.strstr(urldecode(req.http.user-agent), "${")
|| std.strstr(urldecode(req.http.via), "${")
|| std.strstr(urldecode(req.http.x-content-type-options), "${")
|| std.strstr(urldecode(req.http.x-device-accept), "${")
|| std.strstr(urldecode(req.http.x-device-accept-charset), "${")
|| std.strstr(urldecode(req.http.x-device-accept-encoding), "${")
|| std.strstr(urldecode(req.http.x-device-accept-language), "${")
|| std.strstr(urldecode(req.http.x-device-user-agent), "${")
|| std.strstr(urldecode(req.http.x-forwarded-for), "${")
|| std.strstr(urldecode(req.http.x-forwarded-host), "${")
|| std.strstr(urldecode(req.http.x-forwarded-proto), "${")
|| std.strstr(urldecode(req.url), "${")
) {
error 403;
}
Magento log4j protection with Nginx
If you don't have Varnish but use the Nginx webserver, you can filter attack requests as well. However, you need to have the LUA scripting engine installed. Infiniroot shared a good example:
-- LUA block to detect, block and log Log4Shell attacks (C) Infiniroot 2021 (@infiniroot)
-- with lua fixes and other enhancements from Andreas Nanko (@andreasnanko)
rewrite_by_lua_block {
function decipher(v)
local s = tostring(v)
s=ngx.unescape_uri(s)
if string.find(s, "${base64:") then
t=(string.gsub(s, "${${base64:([%d%a%=]+)}}", "%1"))
s=string.gsub(s, "${base64:([%d%a%=]+)}", tostring(ngx.decode_base64(t)))
end
s=string.gsub(s, "${lower:(%a+)}", "%1")
s=string.gsub(s, "${upper:(%a+)}", "%1")
s=string.gsub(s, "${env:[%a_-]+:%-([%a:])}", "%1")
s=string.gsub(s, "${::%-(%a+)}", "%1")
if string.lower(s) == string.lower(tostring(v)) then
return string.lower(s)
else
return decipher(s)
end
end
local req_headers = "Headers: ";
local h, err = ngx.req.get_headers()
for k, v in pairs(h) do
req_headers = req_headers .. k .. ": " .. tostring(v) .. "\n";
if v then
if string.match(decipher(v), "{jndi:") then
ngx.log(ngx.ERR, 'Found potential log4j attack in header ' .. k .. ':' .. tostring(v))
ngx.exit(ngx.HTTP_FORBIDDEN)
end
else
if err then
ngx.log(ngx.ERR, "error: ", err)
return
end
end
end
local uri = tostring(ngx.var.request_uri)
if string.match(decipher(uri), "{jndi:") then
ngx.log(ngx.ERR, 'Found potential log4j attack in request: ' .. uri )
ngx.exit(ngx.HTTP_FORBIDDEN)
end
Read more
In this article
Easy CSP for your store?
Try Sansec Watch! Free, simple and fully integrated. Get PCI compliant alerting with minimal effort.
Sansec WatchScan your store now
for malware & vulnerabilities
eComscan is the most thorough security scanner for Magento, Adobe Commerce, Shopware, WooCommerce and many more.
Learn more