如何使用 Log4J 掩盖日志文件中的信用卡号?

Posted

技术标签:

【中文标题】如何使用 Log4J 掩盖日志文件中的信用卡号?【英文标题】:How to mask credit card numbers in log files with Log4J? 【发布时间】:2011-01-28 12:53:30 【问题描述】:

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

正则表达式部分不是问题,我将重用我们已经在其他几个地方使用的正则表达式。但是,我只是找不到任何关于如何使用 Log4J 更改日志消息的一部分的好资料。过滤器似乎受到更多限制,只能决定是否记录特定事件,但不能改变消息的内容。我还为 Log4J 找到了ESAPI security wrapper 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);
    

注意事项:

我使用 + 而不是 * 进行屏蔽,因为我想区分 CID 被此记录器屏蔽的情况、后端服务器或其他任何人完成的情况 我使用简单的正则表达式,因为我不担心误报

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

【问题讨论】:

不知道为什么你不让超级先将事件解析为字符串然后过滤它。你会省去很多编码。 谢谢你们——你们救了我的命...!! @avok00,因为 LoggingEvent 是不可变的。 PCI DSS 3.0 允许最多显示 BIN 和最后四个。当您有大量流量时,最好使用那些最大允许参数进行屏蔽。这可以通过更改这两行来完成。 private static final String MASK = "$1++++++$3";private static final Pattern PATTERN = Pattern.compile("([0-9]6)([0-9]6,10)([0-9]4)"); 【参考方案1】:

您可以编写自己的 layout 并为所有附加程序配置它...

Layout 有一个 format 方法,它从一个包含日志消息的 loggingEvent 生成一个字符串...

【讨论】:

您可以使您的新布局与您正在使用的现有布局相结合:将任何与您的正则表达式不匹配的内容委托给它,然后删除或删除包含信用卡号的行 谢谢,这似乎是可行的。尽管在这种情况下我更喜欢子类化而不是聚合。让我们尝试一下......【参考方案2】:

http://adamcaudill.com/2011/10/20/masking-credit-cards-for-pci/ 是信用卡号屏蔽的更好实施方式。 您想记录发行者和校验和,而不是 PAN(主帐号)。

【讨论】:

好吧,最好是相对的 :-) 在这种情况下,我既不想记录颁发者也不想记录校验和。我对具体的卡号根本不感兴趣——我们不需要在日志或任何东西中搜索它们。这就是为什么我也不关心误报的原因。唯一的一点是,永远不会有完整的卡号进入日志。但我同意在其他情况下,亚当的解决方案可能会更好。

以上是关于如何使用 Log4J 掩盖日志文件中的信用卡号?的主要内容,如果未能解决你的问题,请参考以下文章

用Python编写一个程序,如何判断用户输入的八位信用卡号码是不是合法?

使用 OpenCV 和 Python 识别信用卡号

用于检测信用卡号的算法减少误报/负数

信用卡号验证 用c++如何解决?

使用 PySpark 屏蔽信用卡号

如何检查只有信用卡号有效而不是借记卡..?