O livro "Bash e segurança cibernética: ataque, defesa e análise a partir da linha de comando do Linux"

imagemOlá, habrozhiteli! A linha de comando pode ser uma ferramenta ideal para segurança cibernética. A flexibilidade incrível e a disponibilidade absoluta transformam a interface da linha de comando padrão (CLI) em uma solução fundamental se você tiver a experiência apropriada.

Os autores Paul Tronkon e Karl Albing falam sobre ferramentas e truques da linha de comando que ajudam a coletar dados com proteção proativa, analisar logs e monitorar o status da rede. Os pentesters aprenderão como realizar ataques usando funcionalidade colossal incorporada a quase qualquer versão do Linux.


Para quem é este livro?


O livro "Bash and cybersecurity" é destinado a quem deseja aprender a trabalhar com a linha de comando no contexto de segurança de computadores. Nosso objetivo não é substituir as ferramentas existentes por scripts de linha de comando, mas ensiná-lo a usar efetivamente a linha de comando para melhorar a funcionalidade existente.

Ao longo do livro, fornecemos exemplos de métodos de segurança, como coleta de dados, análise e teste de penetração. O objetivo desses exemplos é demonstrar os recursos da linha de comando e apresentar alguns dos métodos fundamentais usados ​​nas ferramentas de nível superior.

Este livro não é uma introdução à programação, embora alguns conceitos gerais sejam abordados na Parte I.

Monitoramento de log em tempo real


A capacidade de analisar uma revista após a ocorrência de um evento é uma habilidade importante. Mas é igualmente importante poder extrair informações do arquivo de log em tempo real para detectar ações maliciosas ou suspeitas no momento em que ocorrem. Neste capítulo, consideraremos métodos para a leitura de lançamentos no diário, à medida que são criados e formatados para exibir análises e gerar alertas com base em indicadores de ameaças conhecidos para a operação de um sistema ou rede (indicadores de comprometimento).

Monitoramento de log de texto


A maneira mais fácil de monitorar o log em tempo real é usar o comando tail com o parâmetro –f - ele lê o arquivo continuamente e os exibe em stdout à medida que novas linhas são adicionadas. Como nos capítulos anteriores, por exemplo, usaremos o log de acesso do servidor web Apache, mas os métodos descritos são relevantes para qualquer log de texto. Para rastrear o log de acesso do Apache usando o comando tail, digite o seguinte:

tail -f /var/logs/apache2/access.log

A saída do comando tail pode ser passada para o comando grep, para que apenas os registros correspondentes a determinados critérios sejam exibidos. O exemplo a seguir rastreia o log de acesso do Apache e exibe entradas correspondentes a um endereço IP específico:

tail -f /var/logs/apache2/access.log | grep '10.0.0.152'

Você também pode usar expressões regulares. Neste exemplo, apenas os registros retornando o código de status HTTP 404 "Página não encontrada" serão exibidos; a opção -i é adicionada para ignorar maiúsculas e minúsculas de caracteres:

tail -f /var/logs/apache2/access.log | egrep -i 'HTTP/.*" 404'

Para limpar informações estranhas, a saída deve ser passada para o comando recortar. Este exemplo monitora o log de acesso para consultas que levam ao código de status 404 e, em seguida, usa o método de corte para exibir apenas a data / hora e a página solicitada: Em seguida, para remover colchetes e aspas duplas, você pode direcionar a saída para tr -d ' [] "'.

$ tail -f access.log | egrep --line-buffered 'HTTP/.*" 404' | cut -d' ' -f4-7
[29/Jul/2018:13:10:05 -0400] "GET /test
[29/Jul/2018:13:16:17 -0400] "GET /test.txt
[29/Jul/2018:13:17:37 -0400] "GET /favicon.ico




Nota: a opção --line-buffering do comando egrep é usada aqui. Isso força o egrep a imprimir em stdout toda vez que ocorre uma quebra de linha. Sem esse parâmetro, o buffer ocorrerá e a saída não será enviada ao comando cut até que o buffer esteja cheio. Não queremos esperar tanto tempo. Esta opção permite que o comando egrep escreva cada linha à medida que for encontrada.

BUFFERS DE LINHA DE COMANDO

O que acontece durante o buffer? Imagine que o egrep encontra muitas strings correspondentes ao padrão especificado. Nesse caso, o egrep terá muita saída. Mas a saída (de fato, qualquer entrada ou saída) é muito mais cara (leva mais tempo) do que o processamento de dados (pesquisa de texto). Assim, quanto menos chamadas de E / S, mais eficiente o programa será.

grep , , . . grep . , grep 50 . , 50 , , . 50 !

egrep, , . egrep , , . , , , , . , .

, , tail -f ( ), . , « », . . .

, egrep , . , .


Você pode usar os comandos tail e egrep para monitorar o log e exibir quaisquer entradas que correspondam a padrões conhecidos de atividades suspeitas ou mal-intencionadas, geralmente chamadas de IOC. Você pode criar um sistema simples de detecção de intrusões (IDS). Primeiro, crie um arquivo contendo os padrões de expressão regular para o IOC, conforme mostrado no Exemplo 8.1.

Exemplo 8.1 ioc.txt (1) Este modelo (../) é um indicador de um ataque de diretório indireto: um invasor tenta sair do diretório de trabalho atual e acessar arquivos que não são acessíveis a ele. (2) Os arquivos etc / passwd e etc / shadow do Linux são usados ​​para autenticação do sistema e nunca devem ser acessados ​​através de um servidor web. (3)

\.\./ (1)
etc/passwd (2)
etc/shadow
cmd\.exe (3)
/bin/sh
/bin/bash





Servir os arquivos cmd.exe, / bin / sh ou / bin / bash é uma indicação da conexão reversa retornada pelo servidor da web. Uma conexão reversa geralmente indica uma tentativa bem-sucedida de operação.

Observe que os IOCs devem estar no formato regex, pois serão usados ​​posteriormente pelo comando egrep.

O arquivo ioc.txt pode ser usado com a opção egrep -f. Este parâmetro diz ao egrep para pesquisar os padrões de expressão regular no arquivo especificado. Isso permite que você use o comando tail para monitorar o arquivo de log e, à medida que cada registro é adicionado, a linha de leitura será comparada com todos os modelos no arquivo IOC, exibindo qualquer registro correspondente. Aqui está um exemplo:

tail -f /var/logs/apache2/access.log | egrep -i -f ioc.txt

Além disso, o comando tee pode ser usado para exibir simultaneamente avisos na tela e salvá-los para processamento posterior em seu próprio arquivo: Novamente, a opção --line-buffered é necessária para garantir que não haja problemas causados ​​pelo buffer da saída do comando.

tail -f /var/logs/apache2/access.log | egrep --line-buffered -i -f ioc.txt |
tee -a interesting.txt




Monitoramento de log do Windows


Como já mencionado, você deve usar o comando wevtutil para acessar eventos do Windows. Embora esse comando seja universal, ele não possui uma funcionalidade como cauda, ​​que pode ser usada para recuperar novos registros recebidos. Mas existe uma saída - use um script bash simples que possa fornecer a mesma funcionalidade (Exemplo 8.2).

Exemplo 8.2 wintail.sh

#!/bin/bash -
#
# Bash  
# wintail.sh
#
# :
#    tail   Windows
#
# : ./wintail.sh
#

WINLOG="Application" (1)

LASTLOG=$(wevtutil qe "$WINLOG" //c:1 //rd:true //f:text) (2)

while true
do
      CURRENTLOG=$(wevtutil qe "$WINLOG" //c:1 //rd:true //f:text) (3)
      if [[ "$CURRENTLOG" != "$LASTLOG" ]]
      then
            echo "$CURRENTLOG"
            echo "----------------------------------"
            LASTLOG="$CURRENTLOG"
      fi
done

(1) Essa variável define o log do Windows que você deseja rastrear. Para obter uma lista dos logs atualmente disponíveis no sistema, você pode usar o comando wevtutil el.

(2) Aqui, o wevtutil é executado para solicitar o arquivo de log especificado. O parâmetro c: 1 retorna apenas uma entrada de log. O parâmetro rd: true permite que o comando leia a entrada de log mais recente. Por fim, f: text retorna o resultado em texto sem formatação, não no formato XML, o que facilita a leitura do resultado na tela.

(3)As próximas linhas executam o comando wevtutil novamente e a entrada de log recém-recebida é comparada à última impressa na tela. Se eles diferirem um do outro, isso significa que houve alterações no log. Nesse caso, uma nova entrada é exibida. Se os registros comparados forem os mesmos, nada acontecerá e o comando wevtutil voltará e começará a procurar e comparar novamente.

Criação de histograma em tempo real


O comando tail -f fornece o fluxo de dados atual. Mas e se você quiser contar o número de linhas que foram adicionadas ao arquivo por um determinado período de tempo? Você pode observar esse fluxo de dados, iniciar um cronômetro e realizar a contagem por um período especificado; então a contagem deve ser interrompida e os resultados relatados.

Este trabalho pode ser dividido em dois processos de script: um script lerá as linhas e o outro assistirá o tempo. O temporizador notifica o contador de linha usando um mecanismo de comunicação padrão entre processos POSIX chamado sinal. Um sinal é uma interrupção do software e existem vários tipos de sinais. Alguns deles são fatais - eles levam ao final do processo (por exemplo, uma exceção em uma operação de ponto flutuante). A maioria desses sinais pode ser ignorada ou capturada. A ação é executada quando um sinal é capturado. Muitos desses sinais têm uma finalidade predefinida no sistema operacional. Usaremos um dos dois sinais disponíveis para os usuários. Este é o sinal SIGUSR1 (o outro é SIGUSR2).

Os scripts do shell podem detectar interrupções usando o comando trap interno. Utilizando-o, você pode selecionar um comando que determine qual ação você deseja executar quando um sinal for recebido e uma lista de sinais que acionam uma chamada para este comando. Por exemplo:

trap warnmsg SIGINT

Isso faz com que o comando warnmsg (nosso próprio script ou função) seja chamado sempre que o shell script receber um sinal SIGINT, por exemplo, quando você pressionar Ctrl + C para interromper um processo em execução.

O exemplo 8.3 mostra um script que executa uma contagem.

Exemplo 8.3 looper.sh

#!/bin/bash -
#
# Bash  
# looper.sh
#
# :
#    
#
# : ./looper.sh [filename]
# filename —  ,   ,
#  : log.file
#

function interval ()                                           (1)
{
      echo $(date '+%y%m%d %H%M%S') $cnt                       (2)
      cnt=0
}

declare -i cnt=0
trap interval SIGUSR1                                          (3)

shopt -s lastpipe                                              (4)

tail -f --pid=$$ ${1:-log.file} | while read aline             (5)
do
     let cnt++
done

(1) A função de intervalo será chamada após o recebimento de cada sinal. Obviamente, o intervalo deve ser definido antes que possamos nomeá-lo e usar armadilha em nossa expressão.

(2) O comando date é chamado para fornecer um registro de data e hora para o valor da variável cnt que estamos imprimindo. Depois que o contador é exibido, redefinimos esse valor para 0 para iniciar a contagem regressiva do próximo intervalo.

(3) Agora que o intervalo está definido, podemos indicar que a função é chamada sempre que nosso processo recebe o sinal SIGUSR1.

4)Este é um passo muito importante. Geralmente, quando há um pipeline de comandos (por exemplo, ls-l | grep rwx | wc), partes do pipeline (cada comando) são executadas em sub-redes e cada processo termina com seu próprio identificador de processo. Isso pode ser um problema para esse cenário, porque o loop while estará em um subshell com um identificador de processo diferente. Qualquer que seja o processo iniciado, o script looper.sh não saberá o identificador do processo do loop while para enviar um sinal para ele. Além disso, alterar o valor da variável cnt no subshell não altera o valor cnt no processo principal; portanto, o sinal para o processo principal define o valor a cada vez. Você pode resolver esse problema com o comando shopt, que define o parâmetro (-s) como lastpipe. Diz ao shell para não criar um subshell para o último comando no pipeline,e execute este comando no mesmo processo que o próprio script. No nosso caso, isso significa que o comando tail será executado em um subshell (isto é, em outro processo), e o loop while se tornará parte do processo principal do script. Nota: esta opção de shell está disponível apenas na versão 4.x do bash e superior e apenas para shells não interativos (ou seja, scripts).

(5) Este é o comando tail -f com outro parâmetro --pid. Nós especificamos o identificador do processo, que, após a conclusão deste processo, completará o comando tail. Nós especificamos o ID do processo do script de shell atual $$ a ser exibido. Esta ação permite limpar processos e não deixar o comando tail executado em segundo plano (se, por exemplo, esse script for executado em segundo plano; Exemplo 8.4).

O script tailcount.sh inicia e para o script com um cronômetro (temporizador) e conta os intervalos de tempo.

Exemplo 8.4 tailcount.sh

#!/bin/bash -
#
# Bash  
# tailcount.sh
#
# :
#    n 
#
# : ./tailcount.sh [filename]
#     filename:  looper.sh
#

#  —    
function cleanup ()
{
      [[ -n $LOPID ]] && kill $LOPID          (1)
}

trap cleanup EXIT                             (2)
bash looper.sh $1 &                           (3)
LOPID=$!                                      (4)
#   
sleep 3

while true
do
      kill -SIGUSR1 $LOPID
      sleep 5
done >&2                                      (5)

(1) Como esse script executará outros scripts, ele deverá ser limpo após o trabalho. Se o identificador do processo foi armazenado no LOPID, a variável armazenará o valor; portanto, a função enviará um sinal para esse processo usando o comando kill. Se você não especificar um sinal específico no comando kill, o sinal SIGTERM será enviado por padrão.

(2) O comando EXIT não é um sinal. Este é um caso especial quando a instrução trap diz ao shell para chamar esta função (neste caso, limpeza) se o shell que está executando esse script está prestes a desligar.

(3)Agora o verdadeiro trabalho começa. O script looper.sh é iniciado, o qual será executado em segundo plano: para que esse script funcione durante todo o ciclo (sem esperar pelo comando para concluir o trabalho), ele é desconectado do teclado.

(4) Aqui, o identificador do processo de script que acabamos de iniciar em segundo plano é armazenado.

(5) Esse redirecionamento é simplesmente uma precaução. Todas as saídas provenientes de um loop while ou de declarações kill / sleep (embora não esperemos que elas) não devem ser misturadas com nenhuma saída da função looper.sh, que, embora funcione em segundo plano, ainda as envia para stdout. Portanto, redirecionamos os dados de stdout para stderr.

Para resumir, vemos que, embora a função looper.sh tenha sido colocada em segundo plano, seu identificador de processo é armazenado em uma variável de shell. A cada cinco segundos, o script tailcount.sh envia um sinal SIGUSR1 para esse processo (que é executado na função looper.sh), que, por sua vez, chama o script looper.sh para imprimir o número atual de linhas fixas nele e reiniciar a contagem. Após sair, o script tailcount.sh será limpo enviando um sinal SIGTERM para a função looper.sh para interrompê-lo.

Com a ajuda de dois scripts - um script que executa a contagem de linhas e um script com um cronômetro (timer) que controla o primeiro script - você pode obter a saída (o número de linhas por um determinado período), com base na qual o próximo script criará um histograma. É chamado assim:

bash tailcount.sh | bash livebar.sh

O script livebar.sh lê dados de stdin e imprime a saída em stdout, uma linha para cada linha de entrada (Exemplo 8.5).

Exemplo 8.5 livebar.sh

#!/bin/bash -
#
# Bash  
# livebar.sh
#
# :
#    «» 
#
# :
# <output from other script or program> | bash livebar.sh
#

function pr_bar ()                                         (1)
{
      local raw maxraw scaled
      raw=$1
      maxraw=$2
      ((scaled=(maxbar*raw)/maxraw))
      ((scaled == 0)) && scaled=1 #   
      for((i=0; i<scaled; i++)) ; do printf '#' ; done
      printf '\n'

} # pr_bar

maxbar=60     #         (2)
MAX=60
while read dayst timst qty
do
      if (( qty > MAX ))                                   (3)
      then
           let MAX=$qty+$qty/4    #   
           echo "                      **** rescaling: MAX=$MAX"
      fi
      printf '%6.6s %6.6s %4d:' $dayst $timst $qty         (4)
      pr_bar $qty $MAX
done

(1) A função pr_bar exibe uma sequência de hashtags que são dimensionadas com base nos parâmetros fornecidos para o tamanho máximo. Esse recurso pode parecer familiar, como o usamos anteriormente no script histogram.sh.

(2) Esse é o maior tamanho de linha de hashtag que podemos permitir (sem quebra de linha).

(3)Qual será o tamanho dos valores a serem exibidos? Sem saber disso com antecedência (embora esses dados possam ser fornecidos ao script como argumento), o script rastreará o máximo. Se esse valor máximo for excedido, o valor começará a "escalar" e as linhas que agora são exibidas, e as linhas futuras também serão escaladas para um novo máximo. O script adiciona 25% ao valor máximo, portanto, não é necessário escalar o valor se o próximo novo valor a cada vez aumentar em apenas 1-2%.

4)printf define a largura mínima e máxima dos dois primeiros campos a serem impressos. São carimbos de data e hora que serão truncados se a largura for excedida. Para exibir o valor inteiro, especifique sua largura de quatro caracteres. Nesse caso, apesar das restrições, todos os valores serão impressos. Se o número de caracteres nos valores for menor que quatro, os ausentes serão complementados com espaços.

Como esse script é lido pelo stdin, você pode executá-lo para ver como ele se comporta. Aqui está um exemplo:

$ bash  livebar.sh
201010 1020 20
201010     1020 20:####################
201010 1020 70
                       **** rescaling: MAX=87
201010     1020 70:################################################
201010 1020 75
201010 1020 75:###################################################
^C

Neste exemplo, a entrada é misturada com a saída. Você também pode colocar entrada em um arquivo e redirecioná-lo para um script para ver apenas a saída:

$ bash livebar.sh < testdata.txt
bash livebar.sh < x.data
201010 1020 20:####################
                 **** rescaling: MAX=87
201010 1020 70:################################################
201010 1020 75:###################################################
$

»Mais informações sobre o livro podem ser encontradas no site da editora
» Conteúdo
» Trecho

Para Khabrozhiteley desconto de 25% no cupom - Bash

Após o pagamento da versão impressa do livro, um livro eletrônico é enviado por e-mail.

All Articles