JSP para Vasculhar logs de acesso do tomcat

Administrar um servidor web não é uma tarefa simples, ainda mais quando seu servidor web esta exposto para a internet.
Como o tomcat é um servidor WEB, é necessário acessar o log de acesso web para saber quais acessos ao servidor estão sendo executados e qual a sua origem, para saber se algum agente esta tentando forca bruta para encontrar uma senha, acesso indevido, script kiddies que tentam injetar código malicioso para corromper o sistema ou tomar posse do servidor para propositos que desconhecemos.

Embora nas empresas costuma haver uma turma de TI que olhe os logs e faca o bloqueio, as vezes, um pequeno integrador com equipe reduzida não tem tempo para entrar numa conexao remota, entrar na pasta de logs e olhar os logs, procurar por anomalias e corrigir.

Visando isso, Criei um Script JSP que colocado na pasta webapps/ROOT, permite sem precisar logar no ScadaBR e ter acesso ao log do dia atual do servidor WEB tomcat, listando todos os acessos via web do servidor tomcat.

Como uso Linux, no ScadaBR 1.2 que fica instalado em /opt/ScadaBR/tomcat/webapps/ScadaBR.

logo, fui até a pasta: /opt/ScadaBR/tomcat/webapps/ROOT
criei o arquivo nomeado capivara_acessos.jsp e joguei esse script dentro.

<%@ page import="java.io.*, java.util.*, java.util.regex.*" %>
<%
    // Caminho para a pasta de logs do Tomcat
    String logsPath = application.getRealPath("/") + "../../logs/";
    File logsDir = new File(logsPath);

    // Verifica se o diretório de logs existe
    if (!logsDir.exists() || !logsDir.isDirectory()) {
        out.println("<h2>ERRO: Diretório de logs não encontrado!</h2>");
        return;
    }

    // Filtra os arquivos de log no formato localhost_access_log.<data>.txt
    File[] logFiles = logsDir.listFiles((dir, name) -> name.startsWith("localhost_access_log.") && name.endsWith(".txt"));
    if (logFiles == null || logFiles.length == 0) {
        out.println("<h2>Nenhum arquivo de log encontrado!</h2>");
        return;
    }

    // Ordena os arquivos por data (nome do arquivo)
    Arrays.sort(logFiles, (f1, f2) -> f2.getName().compareTo(f1.getName()));

    // Seleciona o arquivo de log mais recente
    File latestLogFile = logFiles[0];

    // Lê e processa o conteúdo do arquivo de log mais recente
    List<String[]> logEntries = new ArrayList<>();
    try (BufferedReader reader = new BufferedReader(new FileReader(latestLogFile))) {
        String line;
        Pattern logPattern = Pattern.compile("^(\\S+) - - \\[(.*?)\\] \"(.*?)\" (\\d{3}) .*");

        while ((line = reader.readLine()) != null) {
            Matcher matcher = logPattern.matcher(line);
            if (matcher.matches()) {
                String ip = matcher.group(1);               // IP de origem
                String date = matcher.group(2);             // Data e hora
                String logRequest = matcher.group(3);       // URL e método HTTP
                String status = matcher.group(4);           // Código HTTP

                logEntries.add(new String[]{ip, date, logRequest, status});
            }
        }
    } catch (IOException e) {
        out.println("<h2>ERRO: Não foi possível ler o arquivo de log!</h2>");
        return;
    }

    // Renderiza o conteúdo do log em uma tabela
%>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Log de Acesso</title>
    <style>
        table {
            width: 100%;
            border-collapse: collapse;
        }
        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }
        th {
            background-color: #f2f2f2;
        }
        tr:nth-child(even) {
            background-color: #f9f9f9;
        }
        tr:hover {
            background-color: #ddd;
        }
    </style>
</head>
<body>
    <h1>Log de Acesso: <%= latestLogFile.getName() %></h1>
    <table>
        <thead>
            <tr>
                <th>Data</th>
                <th>IP de Origem</th>
                <th>C&oacute;digo HTTP</th>
                <th>URL</th>
            </tr>
        </thead>
        <tbody>
            <% for (String[] entry : logEntries) { %>
                <tr>
                    <td><%= entry[1] %></td>
                    <td><%= entry[0] %></td>
                    <td><%= entry[3] %></td>
                    <td><tt><%= entry[2] %></tt></td>
                </tr>
            <% } %>
        </tbody>
    </table>
</body>
</html>

uma vez criado, basta acessar a url: http://ip_scada:8080/capivara_acessos.jsp

image

Por que um nome tão pitoresco?

evite usar nomes muito sugestivos como logs.jsp pois são genericos demais e alguns atacantes remotos podem usar esse nome de url para ver se conseguem colher o chamado fingerprint do sistema.

Quando voce estuda para o Pentest que é um teste de seguranca, um Atacante verifica se a porta 80 de um IP alvo esta ativo, caso contrario, tenta a porta 8080.
tenta baixar index.html, index.php, index.jsp para ver a pagina inicial do servidor,
tenta simular uma url aleatória para justamente obter o codigo 404 e obter a tela abaixo:

Para muitos, é apenas uma mensagem de erro sem valor, para um atacante é algo precioso, pois a ultima linha diz que esse servidor WEB esta rodando o tomcat 9.0.52
De posse desta informação,
O atacante vai procurar por boletins de seguranca desta versão sobre defeitos encontrados e corrigidor, Com isso, ele tenta explorar essas falhas para tentar derrubar o sistema, injetar arquivos e espalhar o caos.

Portanto, verifique regularmente acessando essa pagina e olhando no log alguma entrada estranha e acessos com o codigo http diferente de 200

Num outro artigo, vou mostrar como substituir as paginas de erro do tomcat

1 curtida