Как замаскировать номера кредитных карт в лог-файлах с Log4J? - PullRequest
28 голосов
/ 17 марта 2010

Наше веб-приложение должно быть совместимым с PCI, т. Е. Оно не должно хранить номера кредитных карт. Приложение является интерфейсом к системе мэйнфреймов, которая обрабатывает номера CC внутри и, как мы только что выяснили, время от времени все еще выдает полный номер CC на одном из своих экранов ответов. По умолчанию все содержимое этих ответов регистрируется на уровне отладки, а также анализируемое из них содержимое может регистрироваться в разных местах. Поэтому я не могу выследить источник таких утечек данных. Я должен убедиться, что номера CC замаскированы в наших файлах журнала.

Регулярное выражение не является проблемой, я буду использовать регулярное выражение, которое мы уже используем, в нескольких других местах. Однако я просто не могу найти хороший источник о том, как изменить часть сообщения журнала с Log4J. Фильтры, по-видимому, гораздо более ограничены, они могут только решить, регистрировать ли конкретное событие или нет, но не могут изменить содержание сообщения. Я также нашел API оболочки безопасности ESAPI для Log4J, который на первый взгляд обещает делать то, что я хочу. Тем не менее, по-видимому, мне нужно будет заменить все регистраторы в коде на класс регистратора 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 был замаскирован этим регистратором, от случаев, когда это было сделано внутренним сервером или кем-либо еще
  • Я использую упрощенное регулярное выражение, потому что я не беспокоюсь о ложных срабатываниях

Код проверен модульно, поэтому я уверен, что он работает правильно. Конечно, если вы обнаружите какую-либо возможность улучшить его, пожалуйста, дайте мне знать: -)

Ответы [ 2 ]

15 голосов
/ 17 марта 2010

Вы можете написать свой макет и настроить его для всех приложений ...

В макете есть метод форматирования, который делает String из loggingEvent, содержащего сообщение журнала ...

5 голосов
/ 23 марта 2012

Лучшая реализация маскировки номера кредитной карты - http://adamcaudill.com/2011/10/20/masking-credit-cards-for-pci/.Вы хотите зарегистрировать эмитента и контрольную сумму, но не PAN (основной номер счета).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...