Наше веб-приложение должно быть выполнено PCI-совместимым, то есть оно не должно содержать номера кредитных карт. Приложение является интерфейсом для системы мэйнфреймов, которая обрабатывает номера CC внутри, и, как мы только что узнали, иногда все еще выплескивает полный номер CC на одном из экранов ответа. По умолчанию все содержимое этих ответов регистрируется на уровне отладки, а также анализируемый из них контент может регистрироваться во множестве разных мест. Поэтому я не могу выследить источник утечки данных. Я должен убедиться, что номера CC маскируются в наших файлах журналов.Как скрыть номера кредитных карт в лог-файлах с помощью Log4J?
Часть регулярных выражений не является проблемой, я буду повторно использовать регулярное выражение, которое мы уже использовали в нескольких других местах. Однако я просто не могу найти хороший источник того, как изменить часть сообщения журнала с помощью Log4J. Фильтры, по-видимому, намного более ограничены, но только могут решить, следует ли регистрировать конкретное событие или нет, но не могут изменять содержимое сообщения. Я также нашел ESAPI security wrapper API для Log4J, который с первого взгляда обещает сделать то, что я хочу. Однако, по-видимому, мне нужно будет заменить все регистраторы кода кодом ESAPI logger - болью в прикладе. Я предпочел бы более прозрачное решение.
Любая идея, как замаскировать номера кредитных карт из выхода Log4J?
Update: на основе оригинальной идеи @ 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);
}
}
Примечания:
- I маска с
+
, а не*
, потому что я хочу сказать в случаях, когда CID был замаскирован этим регистратором, из случаев, когда это было сделано сервером backend, или кем бы то ни было - Я использую упрощенное регулярное выражение, потому что меня не беспокоят ложные срабатывания
Код проверен модулем, поэтому я уверен, что он работает правильно. Конечно, если вы заметили какую-либо возможность улучшить его, пожалуйста, дайте мне знать :-)
Не знаете, почему вы не позволяете супер-синтаксическому разбору события сначала вставлять, а затем фильтровать его. Вы бы избавили себя от большого количества кодирования. –
Спасибо, ребята, вы спасли мою жизнь ... !! – user381878
@ avok00, потому что LoggingEvent неизменен. –