How masking of sensitive data is achieved using slf4j framework?
Solution 1
Try this one. 1. First of all, we should create a class for handling our logs (each row)
public class PatternMaskingLayout extends PatternLayout {
private Pattern multilinePattern;
private List<String> maskPatterns = new ArrayList<>();
public void addMaskPattern(String maskPattern) { // invoked for every single entry in the xml
maskPatterns.add(maskPattern);
multilinePattern = Pattern.compile(
String.join("|", maskPatterns), // build pattern using logical OR
Pattern.MULTILINE
);
}
@Override
public String doLayout(ILoggingEvent event) {
return maskMessage(super.doLayout(event)); // calling superclass method is required
}
private String maskMessage(String message) {
if (multilinePattern == null) {
return message;
}
StringBuilder sb = new StringBuilder(message);
Matcher matcher = multilinePattern.matcher(sb);
while (matcher.find()) {
if (matcher.group().contains("creditCard")) {
maskCreditCard(sb, matcher);
} else if (matcher.group().contains("email")) {
// your logic for this case
}
}
return sb.toString();
}
private void maskCreditCard(StringBuilder sb, Matcher matcher) {
//here is our main logic for masking sensitive data
String targetExpression = matcher.group();
String[] split = targetExpression.split("=");
String pan = split[1];
String maskedPan = Utils.getMaskedPan(pan);
int start = matcher.start() + split[0].length() + 1;
int end = matcher.end();
sb.replace(start, end, maskedPan);
}
}
-
The second step is we should create appender for logback into logback.xml
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <layout class="com.bpcbt.micro.utils.PatternMaskingLayout"> <maskPattern>creditCard=\d+</maskPattern> <!-- SourcePan pattern --> <pattern>%d{dd/MM/yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n%ex</pattern>--> </layout> </encoder>
-
Now we can use logger into our code
log.info("card context set for creditCard={}", creditCard);
-
As a result, we will see
one row from logs
card context set for creditCard=11111******111
without these options, our logs would be like this row
card context set for creditCard=1111111111111
Solution 2
Maybe this library will helpfull: owasp-security-logging
It related to OWASP Security Logging Project and provide related features:
LOGGER.info("userid={}", userid);
LOGGER.info(SecurityMarkers.CONFIDENTIAL, "password={}", password);
The intent is to produce the following output in the log:
2014-12-16 13:54:48,860 [main] INFO - userid=joebob
2014-12-16 13:54:48,860 [main] [CONFIDENTIAL] INFO - password=***********
More you can find in Wiki
Solution 3
Assuming you're using Java/Groovy. In your log4j2.xml, add something like:
<PatternLayout pattern="%mm"/>
then take that pattern and create a converter for it:
@Plugin(name = 'maskLog', category = 'Converter')
@ConverterKeys(['mm'])
class MaskLogConverter extends LogEventPatternConverter {
private static final String NAME = 'mm'
private MaskLogConverter(String[] options) {
super(NAME, NAME)
}
static LogMaskingConverter newInstance(final String[] options) {
return new LogMaskingConverter(options)
}
@Override
void format(LogEvent event, StringBuilder outputMessage) {
String message = event.message//.formattedMessage
// Do your masking logic here
outputMessage.append(message)
}
}
Inside that class you can mask, transform, parse, etc. accordingly.
Raghvendra
Updated on June 05, 2022Comments
-
Raghvendra almost 2 years
I wanted to mask the sensitive data like username/password using an slf4j framework. Immediate help is appreciated. Thanks in advance.
-
Kirill G. about 6 yearsYou advise is bad because doing this manually is error prone. It is better to have a common generic solution for this to make sure nothing is missed.
-
Bob Dalgleish about 6 yearsIn my experience, you have to manually inspect every potential exposure of confidential data as part of your auditing process. Again, this is not the responsibility of the logging framework.
-
Ganesh Satpute about 4 yearsNo, log4j does support overwriting password by asterics.
-
Punisher660 almost 4 yearsSo I know this is a pretty old thread, but does anyone know where Utils.getMaskedPan(pan); comes from? What library has to be imported for that?
-
Alexandr Kovalenko almost 4 yearsUtils.getMaskedPan(pan) - this is my own method ) with the custom realization of mask sensitive data.
-
dasun_001 about 3 yearsHi, Cant we take private static final String NAME = 'mm' from application.properties file?
-
S.Javed almost 3 yearsChecking every log call for sensitive data leak in a big application is impractical and you can never guarantee human errors.