監査ログの「saddr」フィールドを解釈するには?

監査ログの「saddr」フィールドを解釈するには?

パラメータを記録したいので、connectルールを追加しましたauditctl

audit.log に次の行が表示されます。

タイプ=SOCKADDR msg=audit(1385638181.866:89758729):saddr=16進文字列

それでは、16進文字列の宛先アドレスをどのように解釈する必要がありますか(16進文字列に何が格納されているのかわかりません)。

ベストアンサー1

私はこのPerlスクリプトを見つけました。監査log.plの解析、次のように文字列を解析できる関数を示します。

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";
    }
}

このスクリプトはこれの一部です。CERNウェブサイトのTWikiページ、下にLinuxのサポート。ページのタイトルは次のとおりです。IDSNet接続レコーダー興味のある2つのファイルが含まれています。上記のスクリプトの1つは監査log.plの解析、もう一つはサンプルです監査ログ文書。

スクリプトの実行

これら2つのファイルをダウンロードすると、これがあなたが要求しているものであることがわかります。

はい

$ ./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

パーサーロジック抽出

上記の内容をパーサーで圧縮できますsaddr。これは私のアンインストールバージョンです。

$ 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);

Saddrパーサースクリプトのサンプル実行

次のように実行できます。

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

saddr=..その後、次のコマンドを使用して上記のファイルのすべての行を解析できます。audit.log

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

上記のコードはfamily = 1型を処理しないようにまとめられているため、詳しく見てみる必要がありますsaddr

出力例

$ 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

...

Perlのパッキング/パッキング解凍機能

これらの機能は、その仕組みを理解すると非常に強力です。以前に使ったことがない場合は、チュートリアルを見てみましょう。パーパクトゥット

これらの機能の基本的な概念は、テンプレートをデータ構成構造として使用してデータを受け取り、テンプレートを使用してそのデータを返すことです。

ここにもう一度簡単なPerlスクリプトがあります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]);

次を生成します。

$ ./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

そこに含まれているデータを取得し、Tell関数を$saddr呼び出してunpack()一度に2バイトのデータを取得します(A2)。これを10回繰り返します。最初の4つのブロックA2は実際にはそれぞれ2つの文字で、変数、、、、$f1に格納されます。残りの文字は配列に保存されます。$f2$p1$p2@addr

おすすめ記事