@@ -74,6 +74,7 @@ sub run ($self) {
74
74
while (my $msg = $cursor -> next) {
75
75
$index ++;
76
76
$log -> debug(" [$target ] processing message $index of $count " );
77
+ $log -> debug(" msg => " , {filter => \&Dumper, value => $msg });
77
78
if (! defined $msg ) {
78
79
$log -> warn (" [$target ] undefined message encountered, skipping" );
79
80
next ;
@@ -152,19 +153,26 @@ sub process_message ($self, $msg, $target) {
152
153
return 1;
153
154
}
154
155
156
+ $self -> log -> debug(" Target is $target " );
157
+
155
158
return $self -> process_alert($msg ) if ($target eq ' alertgroup' );
156
159
return $self -> process_dispatch($msg ) if ($target eq ' dispatch' );
160
+ return $self -> process_vulnfeed($msg ) if ($target eq ' vulnfeed' or $target eq " vuln_feed" );
157
161
return $self -> process_event($msg ) if ($target eq ' event' );
158
162
159
163
}
160
164
165
+ sub processor_class ($self , $subject ) {
166
+ return " splunk" if $self -> looks_like_splunk($subject );
167
+ return " uba" if $self -> looks_like_uba($subject );
168
+ return " generic" ;
169
+ }
170
+
161
171
sub process_alert ($self , $msg ) {
162
- # 2 types of alerts, from splunk and generic
163
172
my $subject = $msg -> {subject };
164
- $self -> log -> debug(" Looking at message $subject " );
165
- my $json = ($self -> looks_like_splunk($subject ))
166
- ? $self -> process_splunk_alert($msg )
167
- : $self -> process_generic_alert($msg );
173
+ my $class = " process_" .$self -> processor_class($subject )." _alert" ;
174
+ $self -> log -> debug(" Looking at message $subject class $class " );
175
+ my $json = $self -> $class ($msg );
168
176
$self -> filter_msv($json ) if $self -> msv;
169
177
my $status = $self -> create_alertgroup($json );
170
178
if ( $status > 0 ) {
@@ -185,6 +193,11 @@ sub looks_like_splunk ($self, $subject) {
185
193
return undef ;
186
194
}
187
195
196
+ sub looks_like_uba ($self , $subject ) {
197
+ return 1 if ($subject =~ / Splunk UBA/i );
198
+ return undef ;
199
+ }
200
+
188
201
189
202
sub filter_msv ($self , $json ) {
190
203
# this function operates by side-effect
@@ -396,6 +409,40 @@ sub process_splunk_alert ($self, $msg) {
396
409
return wantarray ? %json : \%json ;
397
410
}
398
411
412
+ sub process_uba_alert ($self , $msg ) {
413
+ $self -> log -> debug(" Processing a UBA alert..." );
414
+ my ($html ,
415
+ $plain ,
416
+ $tree ) = $self -> preparse($msg );
417
+ # return $alertname, $backlink, \%data;
418
+ my ($alertname ,
419
+ $backlink ,
420
+ $columns ,
421
+ $data ) = $self -> get_uba_report_info($tree );
422
+ my $alertschema = $self -> build_alert_schema($columns );
423
+
424
+ my %json = (
425
+ owner => ' scot-alerts' ,
426
+ tlp => ' unset' ,
427
+ view_count => 0,
428
+ message_id => $msg -> {message_id },
429
+ subject => $msg -> {subject },
430
+ sources => [qw( email splunk) ],
431
+ tags => [],
432
+ alerts => { data => $data },
433
+ alert_schema => $alertschema ,
434
+ back_refs => $backlink ,
435
+ # additons to discuss with greg
436
+ # (will delete in filter_schema after writing MSV log)
437
+ columns => $columns , # to get column order from splunk
438
+ links => [],
439
+ search => $backlink ,
440
+ );
441
+ $self -> log -> trace(" built json " , {filter => \&Dumper, value => \%json });
442
+
443
+ return wantarray ? %json : \%json ;
444
+ }
445
+
399
446
sub build_alerts ($self , $alerts ) {
400
447
my @new = map { { data => $_ } } @$alerts ;
401
448
return \@new ;
@@ -445,6 +492,57 @@ sub get_splunk_report_info ($self, $tree) {
445
492
return $alertname , $search , \@tags ;
446
493
}
447
494
495
+ sub get_uba_report_info ($self , $tree ) {
496
+ my $alertname = " UBA parse error" ;
497
+ my @tags = (qw( parse_error) );
498
+ my $backlink = ' parse_error' ;
499
+ my %data = ();
500
+ my @columns = ();
501
+
502
+ my $title_element = $tree -> look_down(' _tag' , ' title' );
503
+ if ($title_element ) {
504
+ $alertname = $title_element -> as_text;
505
+ }
506
+
507
+ my $link_element = ($tree -> look_down(' _tag' , ' a' ))[0];
508
+ if ($link_element ) {
509
+ $backlink = $link_element -> attr(' href' );
510
+ }
511
+
512
+ my $table = ($tree -> look_down(' _tag' , ' table' ))[0];
513
+ my @rows = $table -> look_down(' _tag' , ' tr' );
514
+ foreach my $row (@rows ) {
515
+ my ($col1 , $col2 ) = $row -> look_down(' _tag' , ' td' );
516
+ my $colname = $col1 -> as_text;
517
+ push @columns , $colname ;
518
+ my $colval = $col2 -> as_text;
519
+ $data {$colname } = $colval ;
520
+ }
521
+
522
+ # note: this is specified by Kyle Gonzales
523
+ # Looking at the sample, however some of these could be missing
524
+
525
+ my $users_element = ($tree -> look_down(' _tag' ,' ul' ))[0];
526
+ my @li_users = $users_element -> look_down(' _tag' ,' li' );
527
+ foreach my $li (@li_users ) {
528
+ push @{$data {users }}, $li -> as_text;
529
+ }
530
+
531
+ my $devices_element = ($tree -> look_down(' _tag' ,' ul' ))[1];
532
+ my @li_devices = $devices_element -> look_down(' _tag' ,' li' );
533
+ foreach my $li (@li_devices ) {
534
+ push @{$data {devices }}, $li -> as_text;
535
+ }
536
+
537
+ my $domains_element = ($tree -> look_down(' _tag' , ' ul' ))[2];
538
+ my @li_domains = $domains_element -> look_down(' _tag' ,' li' );
539
+ foreach my $li (@li_domains ) {
540
+ push @{$data {domains }}, $li -> as_text;
541
+ }
542
+
543
+ return $alertname , $backlink , \%data ;
544
+ }
545
+
448
546
sub get_alert_results ($self , $tree , $alertname , $search ) {
449
547
my @results = ();
450
548
my @columns = ();
@@ -592,6 +690,35 @@ sub process_dispatch ($self, $msg) {
592
690
return 1;
593
691
}
594
692
693
+ sub process_vulnfeed ($self , $msg ) {
694
+ $self -> log -> debug(" Process a vulnfeed..." );
695
+ my ($html , $plain , $tree ) = $self -> preparse($msg );
696
+ my $tlp = $self -> find_tlp($plain );
697
+ my $entry = $self -> build_entry($tree , $tlp );
698
+
699
+ my %json = (
700
+ vuln_feed => {
701
+ subject => $msg -> {subject },
702
+ message_id => $msg -> {message_id },
703
+ owner => ' scot-vulnfeed' ,
704
+ tags => $self -> build_tags($msg ),
705
+ sources => $self -> build_sources($msg ),
706
+ tlp => $tlp ,
707
+ },
708
+ entry => $entry ,
709
+ );
710
+ $self -> log -> debug(" vulnfeed item = " , {filter => \&Dumper, value => \%json });
711
+ my $resp = $self -> scotapi-> create_vulnfeed(\%json );
712
+
713
+ if (!defined $resp -> {vuln_feed } || !defined $resp -> {entry }) {
714
+ $self -> log -> error(" Error creating either dispatch or entry!" );
715
+ $self -> log -> error(" resp = " ,{filter => \&Dumper, value => $resp });
716
+ return ;
717
+ }
718
+ return 1;
719
+ }
720
+
721
+
595
722
sub process_event ($self , $msg ) {
596
723
$self -> log -> debug(" Processing a event..." );
597
724
my ($html , $plain , $tree ) = $self -> preparse($msg );
@@ -760,6 +887,3 @@ sub find_tlp ($self, $text) {
760
887
761
888
1;
762
889
763
-
764
-
765
-
0 commit comments