Log Injection es un ataque muy sencillo de realizar dirigido a aplicaciones web. Para el atacante es muy sencillo realizar el ataque. Sin embargo, para la aplicación web de destino o su administrador es muy difícil identificar el alcance del ataque realizado y su impacto.
Las aplicaciones web o cualquier aplicación para el caso almacenan una gran cantidad de registros en el backend. Pueden ser
- Registros de bloqueo : información sobre cuándo se bloqueó la aplicación, el motivo del bloqueo, los usuarios afectados, etc.
- Registros de errores/excepciones : detalles como la excepción lanzada desde el código, Stacktrace de la excepción lanzada.
- Registros de acceso: los registros de acceso contienen información sobre diferentes puntos finales a los que accede un usuario en el sistema con detalles de tiempo.
- Registros de GC : generalmente almacenados por Java para realizar un seguimiento de la recolección de basura.
- Monitoreo de registros : es útil cuando un usuario intenta realizar una actividad sospechosa en su sitio, puede detectarlo y enviarse un correo a usted mismo para recibir una notificación o registrarlo para futuros registros.
Aparte de estos, hay muchas categorías de registros de aplicaciones. Estos registros son muy útiles y absolutamente necesarios para depurar problemas de aplicaciones, auditar y controlar, monitorear el rendimiento de las aplicaciones, solucionar problemas, etc.
Estos registros generados pueden escribirse en un disco, generarse como un correo de alerta, enviarse a un servicio de almacenamiento de terceros o simplemente escribirse en un conjunto de archivos en función de la criticidad de los datos de registro generados y/o en función del volumen de datos que es generado.
Cuando no se maneja correctamente, incluso los registros pueden manipularse en la aplicación web. Digamos que tiene un punto final como el siguiente,
https://www.testsite.com/logDOSAttemptByUser?userName=user1
Esta API registrará los nombres de usuario de los usuarios que están intentando un ataque DOS en su sitio.
Y en el backend, tienes algo como,
List suspiciousAccountsLogged = new ArrayList(); suspiciousAccountsLogged = parseUserNamesFromLogs(); if(suspiciousAccountsLogged.size > 0) { for(String userName : suspiciousAccountsLogged) { doBlockUserForDOSAttempt(userName); } }
La idea es bloquear a los usuarios que intentan realizar un ataque DOS en su sitio. Puede encontrar esto en función de la cantidad de requests que sus servidores han recibido del usuario en particular en una unidad de tiempo. Al igual que arriba, puede haber una forma automatizada de procesar registros después de un tiempo y vaciar datos.
Dado que el punto final /logDOSAttemptByUser puede ser visible para el mundo externo, tiene la posibilidad de ser explotado. Un atacante podría modificar el parámetro de nombre de usuario de la solicitud como se muestra a continuación,
https://www.testsite.com/logDOSAttemptByUser?userName=user2
y el sistema podría bloquear a un usuario creíble (usuario2) que no haya intentado ningún intento de DOS en su sitio, pero dado que se inyectaron los registros, el sistema bloqueará al usuario.
Incluso si los registros se procesan manualmente, será muy engorroso diferenciar los registros válidos de los inyectados y puede ser imposible en algunos casos. Los detalles de registro que no sean confiables darán lugar a problemas graves.
También es posible confundir al administrador con mensajes de registro modificados como los siguientes.
https://www.testsite.com/logUsageLimitReached?msg=UsageReached
Esto podría modificarse como,
https://www.testsite.com/logUsageLimitReached?msg=UsageReached+"\n INFO : Looks like problem with our calculation"
y los registros se generarían como,
INFO : UsageReached INFO : Looks like problem with our calculation.
Soluciones
- En lugar de pasar mensajes directamente a través de parámetros, se pueden pasar códigos de registro. Sin embargo, todavía es explotable.
- No utilice llamadas API para registrar acciones, ya que las API estarán visibles en las llamadas de red del navegador.
- En caso de necesidad, pase ID de usuario o valores no identificables públicamente como parámetros en los puntos finales de registro.
- Utilice códigos de error adecuados y mensajes de error identificables.