Como interpretar o campo “saddr” de um log de auditoria?

5

Estou tentando registrar o parâmetro connect , então adicionei uma regra com auditctl .

Agora, em audit.log, recebo linhas como esta:

type=SOCKADDR msg=audit(1385638181.866:89758729): saddr=hex string

Então, como devo interpretar o endereço de destino da string hexadecimal (não tenho certeza do que está armazenado nessa string hexadecimal)?

    
por daisy 28.11.2013 / 12:32

3 respostas

8

Eu encontrei este script Perl, parse -audit-log.pl , que mostra uma função que pode analisar essa cadeia da seguinte forma:

sub parse_saddr
{
    my $sockfd = $_[0];
    my $saddr = $_[1];
    # 0 - sys_bind(), 1 - sys_connect(), 2 - sys_accept()
    my $action = $_[2];

    ($f1, $f2, $p1, $p2, @addr) = unpack("A2A2A2A2A2A2A2A2", $saddr);
    $family = hex2dec($f1) + 256 * hex2dec($f2);
    $port = 256 * hex2dec($p1) + hex2dec($p2);
    $ip1 = hex2dec($addr[0]);
    $ip2 = hex2dec($addr[1]);
    $ip3 = hex2dec($addr[2]);
    $ip4 = hex2dec($addr[3]);
    #print "$saddr\n";
    if ($family eq 2) { #&& $ip1 ne 0) {
        my $dst_addr = "$ip1.$ip2.$ip3.$ip4:$port";
#       print "family=$family $dst_addr\n\n";
        # todo: avoid code duplication
        if ($action eq 0) {
            $sockfd_hash{ $sockfd } = $dst_addr;
        } elsif ($action eq 1) {
            my $src_addr;
            if (exists $sockfd_hash{ $sockfd }) {
                $src_addr = $sockfd_hash{ $sockfd };
            } else {
                $src_addr = "x.x.x.x:x";
            }
            print "$src_addr -> $dst_addr\n";
        } elsif ($action eq 2) {
            my $src_addr;
            if (exists $sockfd_hash{ $sockfd }) {
                $src_addr = $sockfd_hash{ $sockfd };
            } else {
                $src_addr = "x.x.x.x:x";
            }
            print "$dst_addr <- $src_addr\n";
        } else {
            print "unknown action\n";
        }
    } elsif ($family eq 1) {
        $tmp1 = 0;
        ($tmp1, $tmp2) = unpack("A4A*", $saddr);
        my $file = pack("H*", $tmp2);
#       print "family=$family file=$file\n";
    } else {
#       print "$saddr\n";
    }
}

Este script fazia parte desta página do TWiki no site do CERN , sob LinuxSupport . A página intitulada: IDSNetConnectionLogger contém 2 arquivos de interesse. Um dos roteiros que mencionei acima, parse-audit-log.pl e o outro é um exemplo de arquivo audit.log .

Executando o script

Se você fizer o download desses dois arquivos, perceberá que é isso que está perguntando.

Exemplos

$ ./parse-audit-log.pl -l audit.log 
x.x.x.x:x -> 0.0.0.0:22
x.x.x.x:x -> 137.138.32.52:22
137.138.32.52:22 <- x.x.x.x:x
x.x.x.x:x -> 0.0.0.0:22
x.x.x.x:x -> 137.138.32.52:0
x.x.x.x:x -> 137.138.16.5:53
x.x.x.x:x -> 137.138.16.5:53
x.x.x.x:x -> 137.138.16.5:53
x.x.x.x:x -> 137.138.128.158:88
x.x.x.x:x -> 137.138.16.5:53
x.x.x.x:x -> 137.138.16.5:53
x.x.x.x:x -> 137.138.16.5:53
x.x.x.x:x -> 137.138.128.148:750
x.x.x.x:x -> 137.138.16.5:53
x.x.x.x:x -> 137.138.16.5:53
x.x.x.x:x -> 137.138.16.5:53
x.x.x.x:x -> 137.138.128.158:88
x.x.x.x:x -> 137.138.32.52:0
x.x.x.x:x -> 137.138.16.5:53
x.x.x.x:x -> 137.138.16.5:53
x.x.x.x:x -> 137.138.16.5:53
x.x.x.x:x -> 137.138.128.158:88
x.x.x.x:x -> 127.0.0.1:6010

Retirando a lógica do analisador

Podemos condensar o acima, para que seja apenas um saddr do analisador. Aqui está a minha versão simplificada.

$ cat parse_saddr.pl 
#!/usr/bin/perl -w

# Getopt::Std module from the perl package
use Getopt::Std;

my %Options;
getopt('s', \%Options);

if (defined($Options{'s'})) {
    $saddr = $Options{'s'};
} else {
    print "saddr not given\n";
    exit(-1);
}

sub hex2dec($) { return hex $_[0] }

sub parse_saddr
{
    my $saddr = $_[0];

    ($f1, $f2, $p1, $p2, @addr) = unpack("A2A2A2A2A2A2A2A2", $saddr);
    $family = hex2dec($f1) + 256 * hex2dec($f2);
    $port = 256 * hex2dec($p1) + hex2dec($p2);
    $ip1 = hex2dec($addr[0]);
    $ip2 = hex2dec($addr[1]);
    $ip3 = hex2dec($addr[2]);
    $ip4 = hex2dec($addr[3]);
    #print "$saddr\n";
    if ($family eq 2) { #&& $ip1 ne 0) {
        my $dst_addr = "$ip1.$ip2.$ip3.$ip4:$port";
        print "family=$family $dst_addr\n\n";
    } elsif ($family eq 1) {
        $tmp1 = 0;
        ($tmp1, $tmp2) = unpack("A4A*", $saddr);
        my $file = pack("H*", $tmp2);
        print "family=$family file=$file\n";
    } else {
        print "$saddr\n";
    }
}

&parse_saddr($saddr);

Exemplo de execução do script do analisador saddr

Podemos executá-lo assim:

$ ./parse_saddr.pl -s 02000035898A1005000000000000000030BED20858D83A0010000000
family=2 137.138.16.5:53

Você poderia então usar um comando como esse para analisar todas as saddr=.. linhas do arquivo audit.log mencionado acima:

$ for i in $(grep saddr audit.log | cut -d"=" -f4);do echo $i; \
    ./parse_saddr.pl -s $i;done | less

O que foi mencionado acima é cortado em conjunto para que ele não manipule a família = 1 tipos de saddr . Você teria que cavar mais, mas isso lhe dá um começo difícil de como lidar com tudo isso.

Exemplo de saída

$ for i in $(grep saddr audit.log | cut -d"=" -f4);do echo $i; \
    ./parse_saddr.pl -s $i;done | less
...
01002F6465762F6C6F67000000000000
family=1 file=/dev/log^@^@^@^@^@^@
...

02000035898A10050000000000000000726E2E6368009A0900000000
family=2 137.138.16.5:53

...
02000058898A809E0000000000000000
family=2 137.138.128.158:88

...
020002EE898A80940000000000000000
family=2 137.138.128.148:750

...
0200177A7F0000010000000000000000
family=2 127.0.0.1:6010

...

Funções de empacotamento / desempacotamento do Perl

Estas são funções muito poderosas quando você entende como elas funcionam. Se você nunca usou antes, eu daria uma olhada no tutorial, perlpacktut .

A ideia por trás dessas funções é que elas pegam dados e usam um modelo para retornar esses dados usando o modelo como uma estrutura de como os dados devem ser organizados.

Novamente aqui está um script Perl simples que mostra a descompactação do saddr .

$ cat unpack.pl
#!/usr/bin/perl

$saddr = "02000035898A1005000000000000000030BED20858D83A0010000000";
($f1, $f2, $p1, $p2, @addr) = unpack("A2A2A2A2A2A2A2A2", $saddr);

printf "org string: $saddr\n";
printf "org values==> f1: %s f2: %s p1: %s p2: %s addr: %s\n",
    $f1,$f2,$p1,$p2,join("",@addr);
printf "new values==> f1: %2s f2: %2s p1: %2s p2: %2s addr: %s.%s.%s.%s\n\n", 
    hex($f1),hex($f2),hex($p1),hex($p2),hex($addr[0]),hex($addr[1]),hex($addr[2]),hex($addr[3]);

O que produz isso:

$ ./unpack.pl 
org string: 02000035898A1005000000000000000030BED20858D83A0010000000
org values==> f1: 02 f2: 00 p1: 00 p2: 35 addr: 898A1005
new values==> f1:  2 f2:  0 p1:  0 p2: 53 addr: 137.138.16.5

Aqui estamos pegando os dados contidos em $saddr e chamando unpack() informando a função para levar os dados 2 bytes de cada vez (A2). Faça isso 10 vezes. Os primeiros 4 A2 blocos, que são realmente apenas 2 caracteres cada, são armazenados nas variáveis: $f1 , $f2 , $p1 , $p2 . Os caracteres restantes são armazenados na matriz @addr .

    
por 28.11.2013 / 22:09
4

Use a opção -i para ausearch

-i, --interpret
Interpret numeric entities into text. For example, uid is converted to account name. The conversion is done using the current resources of the machine where the search is being run. If you have renamed the accounts, or don't have the same accounts on your machine, you could get misleading results.

Isso também decodifica as entradas saddr s em type=SOCKADDR .

    
por 02.09.2014 / 13:23
0

Caso alguém encontre isto e esteja procurando por uma função de análise de saddr do python ...

def parse_saddr(saddr):
    if len(saddr) >= 16 and saddr.startswith('0200'):
        port, ipaddr = struct.unpack('>HL', binascii.unhexlify(saddr[4:16]))
        ip_addr = socket.inet_ntoa(struct.pack('>L', ipaddr))

        print('{}:{}'.format(ip_addr, str(port)))
    
por 13.09.2018 / 06:55

Tags