Compare os números de ID com os números de revisão em dois arquivos e se o número de referência para o Arquivo A for menor que o Arquivo B substitua a linha com o mais recente rev #?

1

Eu tenho um arquivo de regras. Em cada linha há um sid: number com um rev: number.

Eu quero comparar este arquivo com um arquivo atualizado, mas nem todas as linhas serão atualizadas.

Se uma das linhas com o mesmo sid: number tiver uma maior rev: number eu preciso substituí-la pela maior rev: number.

Este é o tipo de lugar onde estou até agora

grep -oP "sid:[0-9]{0,11}; rev:[0-9]{0,3}" all_rules.rules | 
  while read line; do 
    if grep -q "$line" /home/path/update_rules.rules; then 
      echo updated; 
    else 
      echo > /dev/null; 
    fi
  done

Este é um exemplo de um arquivo all.rules:

alert udp $HOME_NET any -> any 53 (msg:"ET                 
TROJAN CopyKittens? Matryoshka DNS Lookup 1 (winupdate64 . com)"; 
content:"|01 00 00 01 00 00 00 00 00 00|"; depth:10; offset:2; 
content:"|0b|winupdate64|03|com|00|"; nocase; distance:0; fast_pattern; 
reference:url,www.clearskysec.com/wp-
content/uploads/2017/07/Operation_Wilted_Tulip.pdf; classtype:trojan-
activity; sid:2024495; rev:1;)
alert udp $HOME_NET any -> any 53 (msg:"ET 
TROJAN CopyKittens? Matryoshka DNS Lookup 2 (twiter-statics . info)"; 
content:"|01 00 00 01 00 00 00 00 00 00|"; depth:10; offset:2; 
content:"|0e|twiter|2d|statics|04|info|00|"; nocase; distance:0; 
fast_pattern; reference:url,www.clearskysec.com/wp-
content/uploads/2017/07/Operation_Wilted_Tulip.pdf; 
reference:md5,752240cddda5acb5e8d026cef82e2b54; classtype:trojan-
activity; sid:2024496; rev:1;)
alert udp $HOME_NET any -> any 53 (msg:"ET TROJAN CopyKittens? Cobalt 
Strike DNS Lookup (cloudflare-analyse . com)"; content:"|01 00 00 01 00 
00 00 00 00 00|"; depth:10; offset:2; 
content:"|12|cloudflare|2d|analyse|03|com|00|"; nocase; distance:0; 
fast_pattern; threshold:type limit, track by_src, count 1, seconds 60; 
reference:url,www.clearskysec.com/wp-
content/uploads/2017/07/Operation_Wilted_Tulip.pdf; 
reference:md5,752240cddda5acb5e8d026cef82e2b54; classtype:trojan-
activity; sid:2024497; rev:1;)

Aqui está um exemplo do update.rules:

alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (msg:"ET TROJAN Revcode 
RAT CnC"; flow:established,to_server; content:"POST"; http_method; 
content:".php"; http_uri; content:"keyauth="; http_client_body; 
fast_pattern; depth:8; content:"&key="; http_client_body; distance:0; 
content:"&uid="; http_client_body; distance:0; content:!"Referer|3a|"; 
http_header; content:"WinHttpRequest"; http_header; metadata: 
former_category TROJAN; reference:md5,3f652d9bc17a4be3c0e497ea19848344; 
classtype:trojan-activity; sid:2024500; rev:1; metadata:affected_product 
Windows_XP_Vista_7_8_10_Server_32_64_Bit, attack_target Client_Endpoint, 
deployment Perimeter, signature_severity Major, created_at 2017_07_27, 
performance_impact Moderate, updated_at 2017_07_27;)
alert udp $HOME_NET any -> any 53 (msg:"ET TROJAN CopyKittens? Matryoshka 
DNS Lookup 1 (winupdate64 . com)"; content:"|01 00 00 01 00 00 00 00 00 
00|"; depth:10; offset:2; content:"|0b|winupdate64|03|com|00|"; nocase; 
distance:0; fast_pattern; reference:url,www.clearskysec.com/wp-
content/uploads/2017/07/Operation_Wilted_Tulip.pdf; classtype:trojan-
activity; sid:2024495; rev:2;)
alert udp $HOME_NET any -> any 53 (msg:"ET TROJAN CopyKittens Matryoshka DNS 
Lookup 2 (twiter-statics . info)"; content:"|01 00 00 01 00 00 00 00 00 
00|"; depth:10; offset:2; content:"|0e|twiter|2d|statics|04|info|00|"; 
nocase; distance:0; fast_pattern; metadata: former_category TROJAN; 
reference:url,www.clearskysec.com/wp-
content/uploads/2017/07/Operation_Wilted_Tulip.pdf; 
reference:md5,752240cddda5acb5e8d026cef82e2b54; classtype:trojan-activity; 
sid:2024496; rev:2; metadata:affected_product 
Windows_XP_Vista_7_8_10_Server_32_64_Bit, attack_target Client_Endpoint, 
deployment Perimeter, signature_severity Major, created_at 2017_07_25, 
malware_family Matryoshka, performance_impact Moderate, updated_at 
2017_07_25;)
alert udp $HOME_NET any -> any 53 (msg:"ET TROJAN CopyKittens Cobalt Strike 
DNS Lookup (cloudflare-analyse . com)"; content:"|01 00 00 01 00 00 00 00 00 
00|"; depth:10; offset:2; content:"|12|cloudflare|2d|analyse|03|com|00|"; 
nocase; distance:0; fast_pattern; threshold:type limit, track by_src, count 
1, seconds 60; metadata: former_category TROJAN; 
reference:url,www.clearskysec.com/wp-
content/uploads/2017/07/Operation_Wilted_Tulip.pdf; 
reference:md5,752240cddda5acb5e8d026cef82e2b54; classtype:trojan-activity; 
sid:2024497; rev:2; metadata:affected_product 
Windows_XP_Vista_7_8_10_Server_32_64_Bit, attack_target Client_Endpoint, 
deployment Perimeter, signature_severity Major, created_at 2017_07_25, 
malware_family CobaltStrike, performance_impact Moderate, updated_at 
2017_07_26;)
alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (msg:"ET TROJAN 
Win32/BanloadDownloader.XZY Retrieving Payload"; flow:to_server,established; 
content:"GET"; http_method; content:"/sosdoudou_V3/"; http_uri; 
fast_pattern; content:"WinHttp.WinHttpRequest"; http_header; 
content:!"Accept-"; http_header; content:!"Referer|3a 20|"; http_header; 
metadata: former_category TROJAN; 
reference:md5,98376de10118892f0773617da137c2be 
md5,599ea45f5420f948e0836239eb3ce772; classtype:trojan-activity; 
sid:2024499; rev:2; metadata:affected_product 
Windows_XP_Vista_7_8_10_Server_32_64_Bit, attack_target Client_Endpoint, 
deployment Perimeter, signature_severity Major, created_at 2017_07_26, 
malware_family Banload, performance_impact Moderate, updated_at 2017_07_26;)

Observe que há três regras que são as mesmas sid:2024497 , sid:2024496 e sid:2024495 , no entanto, o update.rules contém as revisões de atualização. Eu quero substituir a rev antiga dentro do meu arquivo all.rules com a nova rev da regra em minhas update.rules.

Espero que isso ajude ..

    
por David T. 14.08.2017 / 20:56

3 respostas

0

Isso funciona para mim em testes mínimos:

#!/bin/zsh
typeset -A rule sidrev
while read -r line; do
    sid=${${line/*sid:/}/;*/}
    rev=${${line/*rev:/}/;*/}
    if [[ "$rev" -gt "$sidrev[$sid]" ]]; then
        sidrev[$sid]="$rev"
        rule[$sid]="$line"
    fi
done
echo -E ${(F)rule}

O script lê as regras do snort no stdin e no stdout produz a última revisão de tudo que leu.

    
por 15.08.2017 / 12:56
0

Fiz algumas suposições para obter algum tipo de resposta. Essas suposições sendo:

  1. Atualização unidirecional: update_rules (ou arquivo de entrada 2) é o arquivo de referência para o que está atualizado
  2. O arquivo de referência só conterá a versão mais atualizada ou pelo menos igual à do arquivo a ser atualizado (arquivo de entrada 1). Isso significa que não verificar rev (IF2) é, na verdade, > = rev IF1 como tal. Achtung!
  3. Eu confio em um diff entre IF1 e IF2. Não tenho certeza de quão grande (na contagem de linhas) a diferença entre ambos são, isso pode ter um impacto

Enfim, o suficiente com a blabla, para as partes carnudas

#!/bin/bash
cp "$1" "copy_$1" #backup file we're going to change
#then only extract sid + rev (cut -f cols) + sort
#do that for both file and diff them with RCS format > see output of script for example
#and filter to keep only the sid (prob worth testing without grep to see output)
var=($(diff -n <(egrep -oe "sid:[0-9]{0,11}; rev:[0-9]{0,3}" $1|sort -k2) <(egrep -oe "sid:[0-9]{0,11}; rev:[0-9]{0,3}" $2|sort -k 2) | egrep -oe "sid:[0-9]{0,11};" ))
#Now loop over each SID
for i in ${var[@]}; do
  #Extract line number in IF1
  oldline=$(grep -n $i $1|cut -f1 -d:)
  #Extract replacement line in IF2
  newline=$(grep $i $2.txt)
  #awk magic see (note sed was a pain, couldn't get it to work :/) >> https://sobrelinux.info/questions/4595/how-to-replace-a-string-on-the-5th-line-of-multiple-text-files"$oldline" -v repl="$newline" '(NR==nline){$0=repl}1;' "copy_$1" > "f.tmp" && mv "f.tmp" "copy_$1"
done
#then highlight diff between copy and original // you'll still need to mv "copy_$1" "$1" for it to be applied
diff -n "copy_$1" "$1"

Envolva tudo isso em um script e chame-o:

./my_script.sh all_rules.rules /home/path/update_rules.rules

    
por 15.08.2017 / 03:27
0

Você não mencionou perl , mas suponho que não há problema em usar desde que você mencionou awk , sed e grep . Eu escolhi perl em vez de awk principalmente porque é muito mais fácil trabalhar com matrizes associativas de vários níveis (um "Hash-of-Hashes" ou "HoH" em perl lingo) do que em awk .

#!/usr/bin/perl
use strict;

# array used to keep track of the order each sid was first seen,
# so that they can be printed out in the same order.
# Necessary because perl hashes are inherently un-ordered.
my @order=();

# hashed array to contain the highest rev seen of each sid.
my %S = ();

# count of the number of files we've read completely so far.
my $filenum=0;

while(<>) {
  s/^\s*|\s*$//g;  # strip leading and trailing spaces
  if (m/^$/) { $filenum++ if eof; next }; # skip empty lines

  # extract the sid and the rev
  my ($sid, $rev) = $_ =~ (m/^.*; sid:(\d+); rev:(\d+)/) ;

  # store or update an anonymous hash containing the rev and the entire
  # line in the hash, keyed by the sid.
  if (defined($S{$sid})) {
    $S{$sid} = { rev => $rev, line => $_ } if ( ($rev > $S{$sid}->{rev}) );
  } else {
    next if ($filenum); # only store sid if we're still reading the 1st file.
    push @order, $sid;
    $S{$sid} = { rev => $rev, line => $_ };
  };

  $filenum++ if eof;
};

# if you want output sorted by the sid, comment the first of the next
# two lines and uncomment the second
for my $sid (@order) {
#for my $sid (sort keys %S) {
     print $S{$sid}->{line}, "\n";
};

Salve-o como, por exemplo, ./apply-update.pl e execute-o como ./apply-update.pl all.rules update.rules > out.rules

A saída dos novos arquivos de entrada de amostra será de apenas três linhas (com os sids vistos em all.rules , atualizados por update.rules , ou seja, as versões "rev: 2" em vez de "rev: 1"):

alert udp $home_net any -> any 53 (msg:"et trojan copykittens? matryoshka dns lookup 1 (winupdate64 . com)"; content:"|01 00 00 01 00 00 00 00 00 00|"; depth:10; offset:2; content:"|0b|winupdate64|03|com|00|"; nocase; distance:0; fast_pattern; reference:url,www.clearskysec.com/wp- content/uploads/2017/07/operation_wilted_tulip.pdf; classtype:trojan- activity; sid:2024495; rev:2;)
alert udp $home_net any -> any 53 (msg:"et trojan copykittens matryoshka dns lookup 2 (twiter-statics . info)"; content:"|01 00 00 01 00 00 00 00 00 00|"; depth:10; offset:2; content:"|0e|twiter|2d|statics|04|info|00|"; nocase; distance:0; fast_pattern; metadata: former_category trojan; reference:url,www.clearskysec.com/wp- content/uploads/2017/07/operation_wilted_tulip.pdf; reference:md5,752240cddda5acb5e8d026cef82e2b54; classtype:trojan-activity; sid:2024496; rev:2; metadata:affected_product windows_xp_vista_7_8_10_server_32_64_bit, attack_target client_endpoint, deployment perimeter, signature_severity major, created_at 2017_07_25, malware_family matryoshka, performance_impact moderate, updated_at 2017_07_25;)
alert udp $home_net any -> any 53 (msg:"et trojan copykittens cobalt strike dns lookup (cloudflare-analyse . com)"; content:"|01 00 00 01 00 00 00 00 00 00|"; depth:10; offset:2; content:"|12|cloudflare|2d|analyse|03|com|00|"; nocase; distance:0; fast_pattern; threshold:type limit, track by_src, count 1, seconds 60; metadata: former_category trojan; reference:url,www.clearskysec.com/wp- content/uploads/2017/07/operation_wilted_tulip.pdf; reference:md5,752240cddda5acb5e8d026cef82e2b54; classtype:trojan-activity; sid:2024497; rev:2; metadata:affected_product windows_xp_vista_7_8_10_server_32_64_bit, attack_target client_endpoint, deployment perimeter, signature_severity major, created_at 2017_07_25, malware_family cobaltstrike, performance_impact moderate, updated_at 2017_07_26;)

Isso será muitas vezes mais rápido do que qualquer versão bash - os interpretadores de shell não estão nem um pouco perto do processamento de texto como perl ou awk ou python . Uma linguagem compilada como C seria muito mais rápida novamente, mas escrever algo assim em C seria provavelmente pelo menos 50 ou 60, talvez até algumas centenas, linhas de código C, não 15 linhas de perl (sem contar os comentários). ou linhas em branco).

    
por 15.08.2017 / 14:19