Technical Articles
Scan your Cloud Integration tenant for Log4j libraries with CPILint
A few days ago, a serious vulnerability in the Apache Log4j library was made public. Log4j is a very widely used open source logging library. If this vulnerability is successfully exploited, an attacker can execute their own code on the system hosting the library. In other words: itโs bad. The vulnerability is present in all Log4j releases from 2.0 beta 9 and onwards. Fortunately, there is a fix: Upgrading to Log4j version 2.15.0 or later, where the exploitable behaviour is disabled by default. You can read more about the vulnerability, designated CVE-2021-44228, here.
If you are a Cloud Integration customer, you have probably received an email from SAP by now, urging you to check your iflows for use of the Log4j library and to upgrade to a safe version as soon as possible. What to do is described in Note 3130846 (the note also states that Cloud Integration itself is not vulnerable to the exploit). If you have a very large number of iflows, this is a cumbersome task and one that is prone to human error. If you are running CPILint, however, you can accomplish it easily.
CPILint is my automated governance tool for Cloud Integration. It lets you check your iflows against a number of rules covering best practices, connectivity, security and more. You can read a longer introduction to CPILint here. And no, CPILint does not use Log4j ๐
The tool ships with a rule called JavaArchives that lets you allow or disallow certain Java libraries. If we use this rule to disallow Log4j, CPILInt will scan the tenant and output a list of iflows that contain Log4j JAR files and are therefore not compliant. This list can then be used to make sure that only version 2.15.0 is in use.
The JavaArchives rule allows or disallows libraries based on JAR file names and it supports wildcards. Based on the Apache Log4j vulnerability page, it seems to me (but please verify this on your own!) that the relevant JAR files are called log4j-core-*.jar
. We can disallow those with the following rule:
<?xml version="1.0" encoding="UTF-8"?>
<cpilint>
<rules>
<disallowed-java-archives>
<disallow>log4j-core-*.jar</disallow>
</disallowed-java-archives>
</rules>
</cpilint>
To perform the scan, save the rules file to a file called, say, disallow-log4j.xml
. Then run CPILint as follows:
cpilint -rules disallow-log4j.xml -tmn-host <your TMN hostname> -username <your username>
(The Tenant Management Node hostname is the hostname you see in the browser, when you use the Web UI.)
I added the safe version of Log4j to a sample iflow and this is the output I received from CPILint:
Before using this technique, please note the following caveats:
- Using the described technique in response to CVE-2021-44228 is at your own risk.
- CPILint only checks iflow artifacts, so JAR files uploaded to Script Collection and Message Mapping artifacts are not checked. You need to go through these artifacts manually.
- Log4j JAR files that have been renamed will not be detected.
- CPILint only checks iflow resources, so custom adapters using Log4j will not be detected.
- Log4j class files that have been distributed inside other JAR files will not be detected.
- You should do your own verification of the JAR file naming scheme utilised by the rule.
- CPILint is distributed under the MIT license, which means that the tool comes with no warranty whatsoever.
Thank you, Morten
There is a nice thread about lod4j and SAP products here: https://answers.sap.com/questions/13547385/sap-and-log4j.html
Great, Morten, now I finally found an urgent reason to try out your linting tool which I wanted to do since a long time ๐
Thank you,
Philippe
Cool - let me know how it works out!
Worked! And no security issue with log4j ๐
Well done tool! Just one tiny thing: I would check if the rules file exists before asking for the password to avoid having to enter it multiple times if the file contains a typo or doesn't exist. ๐
Glad to hear it. And good point about checking the rules file first; I'll add it to the list ๐
This has been fixed now (GitHub commit). There's not a new version out yet, but when there is, this fix will be in there.
Hi Morten Wittrock ,
Thanks for this great tool.
I tried this however, I do have an error. Could you please give me a feedback what should be a reason?
Fetching package ID error
Is it a missing authorization, or something else?
Thanks in advance,
Cagri
Hi Cagri
I'll help you debug that. I've followed you here on the SAP Community. If you follow me back, we can use the message system and take it from there.
Regards,
Morten
Thank you Morten Wittrock , after your feedback I corrected my command and this worked. I forgot to add the all hostย definition including hana.ondemand.com.ย
For those who wants to see the example the command can find my command below.
Hi Morten,
I am getting the same error message. I think, it is authorization issue!
for Example, if I call this link:
https://xxxxxxxxxxxx.it-xxxxxx.xxxxxx.eu20.hana.ondemand.com/api/v1/IntegrationPackages
getting response:
which permission do we have. Do you any idea?
Hi there
I'll help you figure out what the problem is. I've contacted you via the SAP Community message system.
Regards,
Morten
Thank You Morten for your support,
My S-User had an authorization issue with one of the packages and because of SAP GLobal ID, I have to reset of S-User Password. Now, it works fine ๐
Regards,
Bรผlent
Hi Morten Wittrock !!!
Thanks for a fabulous tool
I get the same error message. Can you help me?
Hi Jose
Sure, I'll help you debug that. I've followed you here on the SAP Community. If you follow me back, we can exchange messages and we'll take it from there.
Regards,
Morten
Hey Morten Wittrock
Thanks for the great tool. In one of our CPI's it works well, but in the other one I get this error:
Any idea what the issue is?
Thanks,
Viktor
Hi Viktor
That one's new ๐ I'd like to take a closer look. I've followed you here on the SAP Community. If you follow me back, we can use the message system and I'll help you debug it.
Regards,
Morten
Thanks Morten for your support.
I've got a slash at the end of the hostname. That was the problem. Now it works!
Thanks,
Viktor