Estou testando o regex necessário para criar extração de campo com Splunk para nmap e acho que posso estar perto...
Exemplo de linha completa:
Host: 10.0.0.1 (host) Ports: 21/open|filtered/tcp//ftp///, 22/open/tcp//ssh//OpenSSH 5.9p1 Debian 5ubuntu1 (protocol 2.0)/, 23/closed/tcp//telnet///, 80/open/tcp//http//Apache httpd 2.2.22 ((Ubuntu))/, 10000/closed/tcp//snet-sensor-mgmt/// OS: Linux 2.6.32 - 3.2 Seq Index: 257 IP ID Seq: All zeros
Usei o sublinhado "_" como delimitador porque facilita a leitura.
root@host:/# sed -n -e 's_\([0-9]\{1,5\}\/[^/]*\/[^/]*\/\/[^/]*\/\/[^/]*\/.\)_\n\1_pg' filename
O mesmo regex com os caracteres de escape removidos:
root@host:/# sed -n -e 's_\([0-9]\{1,5\}/[^/]*/[^/]*//[^/]*//[^/]*/.\)_\n\1_pg' filename
Saída:
... ... ...
Host: 10.0.0.1 (host) Ports:
21/open|filtered/tcp//ftp///,
22/open/tcp//ssh//OpenSSH 2.0p1 Debian 2ubuntu1 (protocol 2.0)/,
23/closed/tcp//telnet///,
80/open/tcp//http//Apache httpd 5.4.32 ((Ubuntu))/,
10000/closed/tcp//snet-sensor-mgmt/// OS: Linux 9.8.76 - 7.3 Seq Index: 257 IPID Seq: All zeros
... ... ...
Como você pode ver, a correspondência de padrões parece estar funcionando - embora eu não consiga:
1 - combine o padrão no final da linha (vírgula e branco/tabspace). A última linha contém texto indesejado (neste caso, as informações de tempo do SO e do TCP). Um "OR" booleano para os dois caracteres (vírgula e espaço em branco) parece não corresponder.
...(\,|\s)
e
2 - remova qualquer dado desnecessário - ou seja, imprima apenas o padrão correspondente. Na verdade, está imprimindo a linha inteira. Se eu remover o sinalizador sed -n, o conteúdo restante do arquivo também será impresso. Não consigo localizar uma maneira de imprimir apenas o regex correspondente.
ou seja, por que, quando eu digo explicitamente para não fazer isso, o sed está imprimindo essas linhas? =>
Host: 10.0.0.1 (host) Ports:
e
OS: Linux 2.6.32 - 3.2 Seq Index: 257 IP ID Seq: All zeros
Sendo relativamente novo em sed e regex, qualquer ajuda ou sugestão será muito apreciada!
Responder1
Primeiro, eu encorajo você a dar uma olhada na saída XML do Nmap (disponível com o -oX
sinalizador), que é o formato de saída legível por máquina oficialmente suportado. A saída Greppable ( -oG
ou .gnmap
) está obsoleta e, portanto, não inclui informações úteis de recursos mais recentes do Nmap, como traceroute e scripts NSE.
Para responder diretamente às suas perguntas,
o problema de combinar uma vírgula ou um espaço está causando erros porque o caractere de barra vertical de alternância (
|
) deve ser escapado, não a vírgula. Além disso, você provavelmente sempre desejará corresponder um caractere de espaço em branco, mas apenas às vezes a vírgula. É assim que eu faria isso:,\?\s
Não estou usando agrupamento, pois não há alternância ("ou" pipe).
sed
não está imprimindo "linhas" que você não deseja, está imprimindo o espaço do padrão.A página de informações do sedexplica como o sed funciona e é uma ótima referência para escrever scripts sed. Você basicamente tem 2 espaços para trabalhar e sed imprimirá todo o conteúdo do espaço padrão quando você usar op
comando.
Como exemplo de como você pode fazer isso, aqui está minha opinião sobre um script sed para imprimir apenas as informações da porta de um .gnmap
arquivo:
#!/usr/bin/sed -n
#First, strip the beginning (Host and Ports labels) off
s/.*Ports: //
#Now match a port entry, consuming the optional comma and whitespace
#The comma and whitespace are replaced with a newline
s_\([0-9]\{1,5\}/[^/]*/[^/]*/[^/]*/[^/]*/[^/]*/[^/]*/\),\?\s_\1\n_
#If we made a successful substitution, jump to :matched,
t matched
#otherwise skip to the next input line
d
:matched
#Print the pattern space up to the first newline
P
#Then delete up to the first newline and start over with what's left
D
Todos juntos em uma linha, ficaria mais ou menos assim:
sed -n -e 's/.*Ports: //;s_\([0-9]\{1,5\}/[^/]*/[^/]*/[^/]*/[^/]*/[^/]*/[^/]*/\),\?\s_\1\n_;t matched;d;:matched;P;D' file.gnmap
Observe também que você não pode contar com que alguns campos na especificação da porta estejam sempre vazios. Se a detecção de versão foi feita em um serviço RPC, por exemplo, o campo de informações do SunRPC será preenchido.