java - configurar - log4j properties configure
¿Cómo enmascarar números de tarjetas de crédito en archivos de registro con Log4J? (2)
Nuestra aplicación web debe ser compatible con PCI, es decir, no debe almacenar ningún número de tarjeta de crédito. La aplicación es una interfaz para un sistema de mainframe que maneja los números CC internamente y, como acabamos de descubrir, en ocasiones todavía escupe un número CC completo en una de sus pantallas de respuesta. De forma predeterminada, todo el contenido de estas respuestas se registra a nivel de depuración, y también el contenido analizado a partir de estas se puede registrar en muchos lugares diferentes. Así que no puedo cazar la fuente de tales fugas de datos. Debo asegurarme de que los números CC estén enmascarados en nuestros archivos de registro.
La parte de expresiones regulares no es un problema, reutilizaré la expresión regular que ya usamos en otros lugares. Sin embargo, simplemente no puedo encontrar una buena fuente sobre cómo modificar una parte de un mensaje de registro con Log4J. Los filtros parecen ser mucho más limitados, solo pueden decidir si registrar un evento en particular o no, pero no pueden alterar el contenido del mensaje. También encontré la API de envoltorio de seguridad ESAPI para Log4J que a primera vista promete hacer lo que quiero. Sin embargo, al parecer, tendría que reemplazar todos los registradores en el código con la clase de registrador ESAPI, un dolor en el trasero. Preferiría una solución más transparente.
¿Alguna idea de cómo ocultar los números de tarjeta de crédito de Log4J?
Actualización: Basado en la idea original de @ pgras, aquí hay una solución de trabajo:
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);
}
}
Notas:
- Enmascaré con
+
lugar de*
, porque quiero diferenciar los casos en que el CID fue enmascarado por este registrador, en los casos en que fue realizado por el servidor back-end, o por cualquier otra persona. - Uso un regex simplista porque no me preocupan los falsos positivos
El código se ha probado en unidades, por lo que estoy bastante convencido de que funciona correctamente. Por supuesto, si encuentra alguna posibilidad de mejorarlo, hágamelo saber :-)
Podría escribir su propio layout y configurarlo para todos los agregadores ...
El diseño tiene un método de formato que crea una cadena a partir de un loggingEvent que contiene el mensaje de registro ...
Una mejor implementación del enmascaramiento del número de tarjeta de crédito se encuentra en http://adamcaudill.com/2011/10/20/masking-credit-cards-for-pci/ . Desea registrar el emisor y la suma de comprobación, pero no el PAN (Número de cuenta principal).