--- /dev/null
+#
+###############################################################################
+#
+# File: icmp6_types
+#
+# Purpose: This file contains all valid icmp6 types and corresponding codes as
+# defined by IANA. If a packet is logged by iptables that does
+# not have a valid type and/or code, then an alert will be generated.
+#
+###############################################################################
+#
+
+# Type
+# Code values
+
+0 Reserved
+1 Destination Unreachable
+ 0 No route to destination
+ 1 Communication with destination administratively prohibited
+ 2 Beyond scope of source address
+ 3 Address unreachable
+ 4 Port unreachable
+ 5 Source address failed ingress/egress policy
+ 6 Reject route to destination
+ 7 Error in Source Routing Header
+
+2 Packet Too Big
+ 0
+
+3 Time Exceeded
+ 0 Hop limit exceeded in transit
+ 1 Fragment reassembly time exceeded
+
+4 Parameter Problem
+ 0 Erroneous header field encountered
+ 1 Unrecognized Next Header type encountered
+ 2 Unrecognized IPv6 option encountered
+
+128 Echo Request
+ 0
+
+129 Echo Reply
+ 0
+
+130 Multicast Listener Query
+ 0
+
+131 Multicast Listener Report
+ 0
+
+132 Multicast Listener Done
+ 0
+
+133 Router Solicitation
+ 0
+
+134 Router Advertisement
+ 0
+
+135 Neighbor Solicitation
+ 0
+
+136 Neighbor Advertisement
+ 0
+
+ 137 Redirect Message
+ 0
+
+138 Router Renumbering
+ 0 Router Renumbering Command
+ 1 Router Renumbering Result
+ 255 Sequence Number Reset
+
+139 ICMP Node Information Query
+ 0 The Data field contains an IPv6 address which is the Subject of this Query.
+ 1 The Data field contains a name which is the Subject of this Query, or is empty, as in the case of a NOOP.
+ 2 The Data field contains an IPv4 address which is the Subject of this Query.
+
+140 ICMP Node Information Response
+ 0 A successful reply. The Reply Data field may or may not be empty.
+ 1 The Responder refuses to supply the answer. The Reply Data field will be empty.
+ 2 The Qtype of the Query is unknown to the Responder. The Reply Data field will be empty.
+
+141 Inverse Neighbor Discovery Solicitation Message
+ 0
+
+142 Inverse Neighbor Discovery Advertisement Message
+ 0
+144 Home Agent Address Discovery Request Message
+ 0
+
+145 Home Agent Address Discovery Reply Message
+ 0
+
+146 Mobile Prefix Solicitation
+ 0
+
+147 Mobile Prefix Advertisement
+ 0
#
###############################################################################
#
-# File: psad_icmp_types
+# File: icmp_types
#
# Purpose: This file contains all valid icmp types and corresponding codes as
# defined in RFC 792. If a packet is logged by iptables that does
0 Echo Reply
0
- NONE
1 Unassigned
4 Source Quench
0
- NONE
5 Redirect
0 Redirect Datagram for the Network (or subnet)
8 Echo
0
- NONE
9 Router Advertisement
0 Normal router advertisement
10 Router Selection
0
- NONE
11 Time Exceeded
0 Time to Live exceeded in Transit
13 Timestamp
0
- NONE
14 Timestamp Reply
0
- NONE
15 Information Request
0
- NONE
16 Information Reply
0
- NONE
17 Address Mask Request
0
- NONE
18 Address Mask Reply
0
- NONE
19 Reserved (for Security)
'signatures' => 'SIGS_FILE',
'auto_dl' => 'AUTO_DL_FILE',
'icmp_types' => 'ICMP_TYPES_FILE',
+ 'icmp6_types' => 'ICMP6_TYPES_FILE',
'posf' => 'POSF_FILE',
'pf.os' => 'P0F_FILE',
'snort_rule_dl' => 'SNORT_RULE_DL_FILE',
&perms_ownership($prod_file, 0600);
### install auto_dl, signatures, icmp_types, posf, and pf.os files
- for my $filename (qw(signatures icmp_types
+ for my $filename (qw(signatures icmp_types icmp6_types
posf auto_dl snort_rule_dl pf.os ip_options)) {
my $file = $config{$file_vars{$filename}};
if (-e $file) {
my %posf_sigs = ();
### cache valid icmp types and corresponding codes
-my %valid_icmp_types = ();
+my %valid_icmp_types = ();
+my %valid_icmp6_types = ();
### Cache snort rule messages unless --no-snort-sids switch was
### given. This is only useful if iptables includes rules
my $no_snort_sids = 0;
my $no_signatures = 0;
my $no_icmp_types = 0;
+my $no_icmp6_types = 0;
my $no_auto_dl = 0;
my $no_posf = 0;
my $no_daemon = 0;
### validate icmp type and code fields against the official values
### in RFC 792. See %inval_type_code for corresponding signature
### message text and danger levels.
- my $type_code_rv = &check_icmp_type($pkt{'itype'},
- $pkt{'icode'});
+ my $type_code_rv = &check_icmp_type(
+ 'icmp', \%valid_icmp_types,
+ $pkt{'itype'}, $pkt{'icode'});
my $update_dl = 0;
- if ($type_code_rv == $BAD_ICMP_TYPE) { ### bad type
+ if ($type_code_rv == $BAD_ICMP_TYPE) {
$scan{$pkt{'src'}}{$pkt{'dst'}}{'icmp'}
{'invalid_type'}{$pkt{'itype'}}
$scan_dl{$pkt{'src'}} = 2;
}
}
+
+ } elsif ($pkt{'proto'} eq 'icmp6') {
+
+ ### validate icmp6 type and code fields against the official values
+ ### defined by IANA. See %inval_type_code for corresponding signature
+ ### message text and danger levels.
+ my $type_code_rv = &check_icmp_type(
+ 'icmp6', \%valid_icmp6_types,
+ $pkt{'itype'}, $pkt{'icode'});
+
+ my $update_dl = 0;
+ if ($type_code_rv == $BAD_ICMP_TYPE) {
+
+ $scan{$pkt{'src'}}{$pkt{'dst'}}{'icmp6'}
+ {'invalid_type'}{$pkt{'itype'}}
+ {$pkt{'chain'}}{'pkts'}++;
+
+ $update_dl = 1;
+
+ } elsif ($type_code_rv == $BAD_ICMP_CODE) {
+
+ $scan{$pkt{'src'}}{$pkt{'dst'}}{'icmp6'}
+ {'invalid_code'}{$pkt{'itype'}}{$pkt{'icode'}}
+ {$pkt{'chain'}}{'pkts'}++;
+
+ $update_dl = 1;
+ }
+
+ if ($update_dl) {
+ if (defined $scan_dl{$pkt{'src'}}) {
+ if ($scan_dl{$pkt{'src'}} < 2) {
+ $scan_dl{$pkt{'src'}} = 2;
+ }
+ } else {
+ $scan_dl{$pkt{'src'}} = 2;
+ }
+ }
}
unless ($no_snort_sids) {
}
$pkt_hr->{'proto'} = 'icmp';
- }
- if ($pkt_hr->{'itype'} == $ICMP_ECHO_REQUEST
- or $pkt_hr->{'itype'} == $ICMP_ECHO_REPLY) {
+ if ($pkt_hr->{'itype'} == $ICMP_ECHO_REQUEST
+ or $pkt_hr->{'itype'} == $ICMP_ECHO_REPLY) {
- ### we expect the ICMP ID and SEQ fields to be populated
- if ($pkt_str =~ /CODE=(\d+)\s+ID=(\d+)\s+SEQ=(\d+)/) {
- $pkt_hr->{'icmp_id'} = $1;
- $pkt_hr->{'icmp_seq'} = $2;
- } else {
- return $PKT_ERROR;
+ ### we expect the ICMP ID and SEQ fields to be populated
+ if ($pkt_str =~ /CODE=(\d+)\s+ID=(\d+)\s+SEQ=(\d+)/) {
+ $pkt_hr->{'icmp_id'} = $1;
+ $pkt_hr->{'icmp_seq'} = $2;
+ } else {
+ return $PKT_ERROR;
+ }
}
}
$top_sigs{$sid}++;
$top_sig_counts{$pkt_hr->{'src'}}++;
}
+
} elsif ($sig_hr->{'proto'} eq 'udp') {
($rv, $sig_match_rv) = &match_snort_udp_keywords($pkt_hr, $sig_hr);
$top_sigs{$sid}++;
$top_sig_counts{$pkt_hr->{'src'}}++;
}
+
} elsif ($sig_hr->{'proto'} eq 'icmp') {
($rv, $sig_match_rv) = &match_snort_icmp_keywords($pkt_hr, $sig_hr);
$top_sigs{$sid}++;
$top_sig_counts{$pkt_hr->{'src'}}++;
}
- }
+ } elsif ($sig_hr->{'proto'} eq 'icmp6') {
+ ### FIXME icmp6 specifc Snort matches?
+ }
}
return $dl, $matched_sig;
}
}
sub check_icmp_type() {
- my ($type, $code) = @_;
+ my ($proto, $valid_types_hr, $type, $code) = @_;
print STDERR " check_icmp_type(type: $type, code: $code)\n" if $debug;
- if (not defined $valid_icmp_types{$type}) {
- print STDERR " BAD_ICMP_TYPE\n" if $debug;
+ if (not defined $valid_types_hr->{$type}) {
+ print STDERR " bad $proto type\n" if $debug;
return $BAD_ICMP_TYPE;
- } elsif (not defined $valid_icmp_types{$type}{'code'}{$code}) {
- print STDERR " BAD_ICMP_CODE\n" if $debug;
+ } elsif (not defined $valid_types_hr->{$type}->{'codes'}->{$code}) {
+ print STDERR " bad $proto code\n" if $debug;
return $BAD_ICMP_CODE;
}
- print STDERR " valid type/code\n" if $debug;
+ print STDERR " valid $proto type/code\n" if $debug;
return 0;
}
### import icmp types and codes from psad_icmp_types; icmp "type"
### and "code" fields will be validated against the values in this
### file.
- &import_icmp_types() unless $no_icmp_types;
+ &import_icmp_types('icmp', \%valid_icmp_types, $config{'ICMP_TYPES_FILE'})
+ unless $no_icmp_types;
+ &import_icmp_types('icmp6', \%valid_icmp6_types,
+ $config{'ICMP6_TYPES_FILE'}) unless $no_icmp6_types;
### import p0f-based passive OS fingerprinting signatures
&import_p0f_ipv4_sigs() unless $no_posf;
}
sub import_icmp_types() {
+ my ($proto, $type_hr, $file) = @_;
- %valid_icmp_types = ();
-
- open TYPES, "< $config{'ICMP_TYPES_FILE'}" or die
- "[*] Could not open $config{'ICMP_TYPES_FILE'}: $!";
- my @lines = <TYPES>;
- close TYPES;
+ open F, "< $file" or die "[*] Could not open $file: $!";
my $icmp_type = -1;
- for my $line (@lines) {
- next if $line =~ /^\s*#/;
- if ($line =~ /^(\d+)\s+(.*)/) {
- $icmp_type = $1;
+ while (<F>) {
+ next if /^\s*#/;
+ if (/^(\d+)\s+(.*)/) {
+ $icmp_type = $1;
my $icmp_type_text = $2;
if ($icmp_type_text =~ /unassigned/i) {
$icmp_type = -1;
}
- $valid_icmp_types{$icmp_type}{'text'} = $icmp_type_text;
+ $type_hr->{$icmp_type}->{'text'} = $icmp_type_text;
+ $type_hr->{$icmp_type}->{'codes'}{-1} = '';
next;
}
- if ($icmp_type > -1 and $line =~ /^\s+(\d+)\s+(.*)/) {
+ if (/^\s+(\d+)\s+(.*)/ and $icmp_type > -1) {
my $icmp_code = $1;
my $icmp_code_text = $2;
next if $icmp_code_text =~ /unassigned/i;
### we validate against the icmp type first (i.e. an invalid
### icmp code is meaningless unless we first have a valid
### icmp type).
- $valid_icmp_types{$icmp_type}{'codes'}{$icmp_code} = '';
+ $type_hr->{$icmp_type}->{'codes'}->{$icmp_code} = '';
}
}
- print STDERR Dumper %valid_icmp_types if $debug and $verbose;
- &sys_log('imported valid icmp types and codes');
+ close F;
+ print STDERR Dumper $type_hr if $debug and $verbose;
+ &sys_log("imported valid $proto types and codes");
return;
}
# fingerprint the remote OS.
'no-signatures' => \$no_signatures, # Disable signature processing.
'no-icmp-types' => \$no_icmp_types, # Disable icmp type/code validation.
+ 'no-icmp6-types' => \$no_icmp6_types, # Disable icmp6 type/code validation.
'no-auto-dl' => \$no_auto_dl, # Disable auto danger level
# assignment.
'no-daemon' => \$no_daemon, # Do not run as a daemon.
ETC_RSYSLOG_CONF IFCFGTYPE ENABLE_WHOIS_FORCE_ASCII
ENABLE_WHOIS_FORCE_SRC_IP ENABLE_IPV6_DETECTION
PERSISTENCE_CTR_THRESHOLD MAX_SCAN_IP_PAIRS INSTALL_ROOT
+ ICMP6_TYPES_FILE
));
&defined_vars(\@required_vars);
return;
DSHIELD_EMAIL_FILE $PSAD_DIR/dshield.email;
SIGS_FILE $PSAD_CONF_DIR/signatures;
ICMP_TYPES_FILE $PSAD_CONF_DIR/icmp_types;
+ICMP6_TYPES_FILE $PSAD_CONF_DIR/icmp6_types;
AUTO_DL_FILE $PSAD_CONF_DIR/auto_dl;
SNORT_RULE_DL_FILE $PSAD_CONF_DIR/snort_rule_dl;
POSF_FILE $PSAD_CONF_DIR/posf;
DSHIELD_EMAIL_FILE $PSAD_DIR/dshield.email;
SIGS_FILE $PSAD_CONF_DIR/signatures;
ICMP_TYPES_FILE $PSAD_CONF_DIR/icmp_types;
+ICMP6_TYPES_FILE $PSAD_CONF_DIR/icmp6_types;
AUTO_DL_FILE $PSAD_CONF_DIR/auto_dl;
SNORT_RULE_DL_FILE $PSAD_CONF_DIR/snort_rule_dl;
POSF_FILE $PSAD_CONF_DIR/posf;
DSHIELD_EMAIL_FILE $PSAD_DIR/dshield.email;
SIGS_FILE $PSAD_CONF_DIR/signatures;
ICMP_TYPES_FILE $PSAD_CONF_DIR/icmp_types;
+ICMP6_TYPES_FILE $PSAD_CONF_DIR/icmp6_types;
AUTO_DL_FILE $PSAD_CONF_DIR/auto_dl;
SNORT_RULE_DL_FILE $PSAD_CONF_DIR/snort_rule_dl;
POSF_FILE $PSAD_CONF_DIR/posf;
DSHIELD_EMAIL_FILE $PSAD_DIR/dshield.email;
SIGS_FILE $PSAD_CONF_DIR/signatures;
ICMP_TYPES_FILE $PSAD_CONF_DIR/icmp_types;
+ICMP6_TYPES_FILE $PSAD_CONF_DIR/icmp6_types;
AUTO_DL_FILE $PSAD_CONF_DIR/auto_dl;
SNORT_RULE_DL_FILE $PSAD_CONF_DIR/snort_rule_dl;
POSF_FILE $PSAD_CONF_DIR/posf;
DSHIELD_EMAIL_FILE $PSAD_DIR/dshield.email;
SIGS_FILE $PSAD_CONF_DIR/signatures;
ICMP_TYPES_FILE $PSAD_CONF_DIR/icmp_types;
+ICMP6_TYPES_FILE $PSAD_CONF_DIR/icmp6_types;
AUTO_DL_FILE $PSAD_CONF_DIR/auto_dl;
SNORT_RULE_DL_FILE $PSAD_CONF_DIR/snort_rule_dl;
POSF_FILE $PSAD_CONF_DIR/posf;
DSHIELD_EMAIL_FILE $PSAD_DIR/dshield.email;
SIGS_FILE $PSAD_CONF_DIR/signatures;
ICMP_TYPES_FILE $PSAD_CONF_DIR/icmp_types;
+ICMP6_TYPES_FILE $PSAD_CONF_DIR/icmp6_types;
AUTO_DL_FILE $PSAD_CONF_DIR/auto_dl;
SNORT_RULE_DL_FILE $PSAD_CONF_DIR/snort_rule_dl;
POSF_FILE $PSAD_CONF_DIR/posf;
DSHIELD_EMAIL_FILE $PSAD_DIR/dshield.email;
SIGS_FILE $PSAD_CONF_DIR/signatures;
ICMP_TYPES_FILE $PSAD_CONF_DIR/icmp_types;
+ICMP6_TYPES_FILE $PSAD_CONF_DIR/icmp6_types;
AUTO_DL_FILE $PSAD_CONF_DIR/auto_dl;
SNORT_RULE_DL_FILE $PSAD_CONF_DIR/snort_rule_dl;
POSF_FILE $PSAD_CONF_DIR/posf;
DSHIELD_EMAIL_FILE $PSAD_DIR/dshield.email;
SIGS_FILE $PSAD_CONF_DIR/signatures;
ICMP_TYPES_FILE $PSAD_CONF_DIR/icmp_types;
+ICMP6_TYPES_FILE $PSAD_CONF_DIR/icmp6_types;
AUTO_DL_FILE $PSAD_CONF_DIR/auto_dl;
SNORT_RULE_DL_FILE $PSAD_CONF_DIR/snort_rule_dl;
POSF_FILE $PSAD_CONF_DIR/posf;
my $ack_scan_file = 'ack_scan_1000_1150';
my $udp_scan_file = 'udp_scan_1000_1150';
my $ipv6_connect_scan_file = 'ipv6_tcp_connect_nmap_default_scan';
+my $ipv6_ping_scan_file = 'ipv6_ping_scan';
my $ignore_ipv4_auto_dl_file = "$conf_dir/auto_dl_ignore_192.168.10.55";
my $ignore_ipv4_subnet_auto_dl_file = "$conf_dir/auto_dl_ignore_192.168.10.0_24";
my $ignore_ipv6_addr_auto_dl_file = "$conf_dir/auto_dl_ignore_ipv6_addr";
},
{
'category' => 'operations',
+ 'detail' => 'IPv6 allow valid ping packets',
+ 'err_msg' => 'generated detection event',
+ 'negative_output_matches' => [
+ qr/SRC\:.*2001\:DB8\:0\:F101\:\:2/],
+ 'match_all' => $MATCH_ALL_RE,
+ 'function' => \&generic_exec,
+ 'cmdline' => "$psadCmd --test-mode -A -m $scans_dir/" .
+ &fw_type() . "/$ipv6_ping_scan_file -c $default_conf",
+ 'exec_err' => $NO,
+ 'fatal' => $NO
+ },
+
+ {
+ 'category' => 'operations',
'detail' => 'IPv6 disabled',
'err_msg' => 'logged IPv6 traffic',
'positive_output_matches' => [qr/\[NONE\]/],