如何使用Log4J屏蔽日志文件中的信用卡号?

Pét*_*rök 28 java log4j credit-card mask

我们的网络应用程序需要符合PCI标准,即不得存储任何信用卡号码.该应用程序是大型机系统的前端,它在内部处理CC号码 - 正如我们刚刚发现的那样 - 偶尔会在其响应屏幕上吐出一个完整的CC号码.默认情况下,这些响应的全部内容都以调试级别记录,并且从这些响应中解析的内容也可以记录在许多不同的位置.所以我无法追捕这些数据泄漏的来源.我必须确保在我们的日志文件中屏蔽了CC编号.

正则表达式部分不是问题,我将重用我们已在其他几个地方使用的正则表达式.但是我找不到有关如何使用Log4J更改日志消息的一部分的任何好的来源.过滤器似乎更受限制,只能决定是否记录特定事件,但不能改变消息的内容.我还发现了Log4J 的ESAPI安全包装API,它初看起来有望实现我的目标.但是,显然我需要用ESAPI记录器类替换代码中的所有记录器 - 这是一个痛苦的屁股.我更喜欢更透明的解决方案.

知道如何屏蔽Log4J输出的信用卡号码吗?

更新:根据@ pgras的最初想法,这是一个有效的解决方案:

public class CardNumberFilteringLayout extends PatternLayout {
    private static final String MASK = "$1++++++++++++";
    private static final Pattern PATTERN = Pattern.compile("([0-9]{4})([0-9]{9,15})");

    @Override
    public String format(LoggingEvent event) {
        if (event.getMessage() instanceof String) {
            String message = event.getRenderedMessage();
            Matcher matcher = PATTERN.matcher(message);

            if (matcher.find()) {
                String maskedMessage = matcher.replaceAll(MASK);
                @SuppressWarnings({ "ThrowableResultOfMethodCallIgnored" })
                Throwable throwable = event.getThrowableInformation() != null ? 
                        event.getThrowableInformation().getThrowable() : null;
                LoggingEvent maskedEvent = new LoggingEvent(event.fqnOfCategoryClass,
                        Logger.getLogger(event.getLoggerName()), event.timeStamp, 
                        event.getLevel(), maskedMessage, throwable);

                return super.format(maskedEvent);
            }
        }
        return super.format(event);
    }
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 我屏蔽+而不是*,因为我想分辨CID被这个记录器屏蔽的情况,从后端服务器完成的情况,或者其他人
  • 我使用简单的正则表达式,因为我不担心误报

代码经过单元测试,所以我相信它能正常工作.当然,如果您发现任何改进它的可能性,请告诉我:-)

pgr*_*ras 15

您可以编写自己的布局并为所有appender配置它...

Layout有一个格式方法,它从包含日志消息的loggingEvent生成一个String ...


Con*_*net 5

http://adamcaudill.com/2011/10/20/masking-credit-cards-for-pci/可以更好地实现信用卡号码屏蔽。您要记录发行者和校验和,而不是PAN(主帐号)。

  • 好吧,最好是相对的:-)在这种情况下,我既不想将校验和也记录在发行者的日志中。我对具体的卡号一点都不感兴趣-我们不需要在日志或任何内容中搜索它们。这就是为什么我也不在乎误报。唯一的一点是,任何完整的卡号都永远不会进入日志。但是我同意在其他情况下,亚当的解决方案可能会更好。 (2认同)