Update: As Sander mentioned in his answer below we dropped the CloudLoggerFactory
starting with version 3.0.0 of the SAP Cloud SDK.
Our reasoning behind this is that we cannot change the used Logger
implementation of every library our consumers might use in their application. This means we are not able to add the token mentioned below to all log messages of the consumer, which reduces its effectiveness tremendously.
Therefore we decided to drop the CloudLoggerFactory
and advise the consumer to configure his logging implementation in a such way, that this token is automatically added. On this level it is possible to have this token at the end of every log message, allowing for automated tests on forged logs.
What the sanitized logger is supposed to do is making log forging identifiable. To allow this it does the following:
This logger has your provided class (SampleClass.class
in your case) as the logger name. This name will be placed in the printed output depending on the configuration of your logger implementation. This is the default behavior of SLF4J.
Add (END OF LOG ENTRY)
(or your provided token) at the end of every log message created with this logger. If this token is encountered in your log message it is replaced with (MESSAGE MIGHT BE FORGED!)
, as that would be an indicator that some input tried to tamper with your log messages.
Both of these properties allow you to identify whether a log message is actually valid or was created via Log Forging.
To see that have a look at the following example, at first with the "unsanitized" logger:
final Logger logger = CloudLoggerFactory.getLogger(SampleClass.class);
logger.error("Some valid first message");
logger.info("Something still valid\n[main] ERROR very.important.class Major Database Error!");
logger.error("Some valid last message");
On my machine the output of this looks like
[main] ERROR com.sap.sandbox.SampleClass - Some valid first message
[main] INFO com.sap.sandbox.SampleClass - Something still valid
[main] ERROR very.important.class Major Database Error!
[main] ERROR com.sap.sandbox.SampleClass - Some valid last message
So there is no chance to identify that something is wrong with those messages.
Therefore, if you use CloudLoggerFactory.getSanitizedLogger
instead of CloudLoggerFactory.getLogger
you get the following log output:
[main] ERROR com.sap.sandbox.SampleClass - Some valid first message (END OF LOG ENTRY)
[main] INFO com.sap.sandbox.SampleClass - Something still valid
[main] ERROR very.important.class Major Database Error! (END OF LOG ENTRY)
[main] ERROR com.sap.sandbox.SampleClass - Some valid last message (END OF LOG ENTRY)
Here you can see that one of the messages from the SampleClass
, which should actually end with the token, ends without one. Therefore you can deduce that there is some error in the log and you need to investigate this issue further.
So much for the Log Forging aspect, which is the actual attack the sanitized logger makes identifiable.
Regarding the CLRF injection issue: This issue heavily depends on the further usage of the created log output:
- If you store the log messages in a database there needs to be some way to prevent SQL injection.
- If you watch the log files with a web-based log analyzer there needs to be some way to prevent XSS.
- ...
If we would escape all of those potential use case it would make actually just reading the log files with an editor, which is imo the most common use case, much more complicated.
So you would need to decide whether for your case this is an actual issue or just a false positive.
Another point is that also all your other dependencies would need to escape their log messages for your use case. This means an easier and overarching solution would be to configure that on the actual logger implementation, e.g. for Logback: https://logback.qos.ch/manual/layouts.html#replace.