*/
spa_pkt->packet_data_len = 0;
+ /* Ignore any SPA packets that contain the Rijndael or GnuPG prefixes
+ * since an attacker might have tacked them on to a previously seen
+ * SPA packet in an attempt to get past the replay check. And, we're
+ * no worse off since a legitimate SPA packet that happens to include
+ * a prefix after the outer one is stripped off won't decrypt properly
+ * anyway because libfko would not add a new one.
+ */
+ if(strncmp(ndx, B64_RIJNDAEL_SALT, B64_RIJNDAEL_SALT_STR_LEN) == 0)
+ return(SPA_MSG_BAD_DATA);
+
+ if(pkt_data_len > MIN_GNUPG_MSG_SIZE
+ && strncmp(ndx, B64_GPG_PREFIX, B64_GPG_PREFIX_STR_LEN) == 0)
+ return(SPA_MSG_BAD_DATA);
+
/* Detect and parse out SPA data from an HTTP request. If the SPA data
* starts with "GET /" and the user agent starts with "Fwknop", then
* assume it is a SPA over HTTP request.
'cmdline' => $default_client_args,
'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopdCmd $default_server_conf_args $intf_str",
+ 'replay_positive_output_matches' => [qr/Replay\sdetected\sfrom\ssource\sIP/],
+ 'fatal' => $NO
+ },
+ {
+ 'category' => 'Rijndael SPA',
+ 'subcategory' => 'client+server',
+ 'detail' => 'replay detection (Rijndael prefix)',
+ 'err_msg' => 'could not detect replay attack',
+ 'function' => \&replay_detection,
+ 'pkt_prefix' => 'U2FsdGVkX1',
+ 'cmdline' => $default_client_args,
+ 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+ "$fwknopdCmd $default_server_conf_args $intf_str",
+ 'replay_positive_output_matches' => [qr/Data\sis\snot\sa\svalid\sSPA\smessage\sformat/],
'fatal' => $NO
},
{
'function' => \&replay_detection,
'cmdline' => $default_client_gpg_args,
'fwknopd_cmdline' => $default_server_gpg_args,
+ 'replay_positive_output_matches' => [qr/Replay\sdetected\sfrom\ssource\sIP/],
+ 'fatal' => $NO
+ },
+ {
+ 'category' => 'GnuPG (GPG) SPA',
+ 'subcategory' => 'client+server',
+ 'detail' => 'replay detection (GnuPG prefix)',
+ 'err_msg' => 'could not detect replay attack',
+ 'function' => \&replay_detection,
+ 'pkt_prefix' => 'hQ',
+ 'cmdline' => $default_client_gpg_args,
+ 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+ "$fwknopdCmd $default_server_conf_args $intf_str",
+ 'replay_positive_output_matches' => [qr/Data\sis\snot\sa\svalid\sSPA\smessage\sformat/],
'fatal' => $NO
},
'fw_rule_created' => $OPTIONAL,
'fw_rule_removed' => $OPTIONAL,
'server_conf' => $OPTIONAL,
+ 'pkt_prefix' => $OPTIONAL,
'positive_output_matches' => $OPTIONAL,
'negative_output_matches' => $OPTIONAL,
'server_positive_output_matches' => $OPTIONAL,
'server_negative_output_matches' => $OPTIONAL,
+ 'replay_positive_output_matches' => $OPTIONAL,
+ 'replay_negative_output_matches' => $OPTIONAL,
);
if ($diff_mode) {
return 0;
}
+ if ($test_hr->{'pkt_prefix'}) {
+ $spa_pkt = $test_hr->{'pkt_prefix'} . $spa_pkt;
+ }
+
my @packets = (
{
'proto' => 'udp',
$rv = 0 unless $server_was_stopped;
- unless (&file_find_regex([qr/Replay\sdetected\sfrom\ssource\sIP/i],
- $MATCH_ALL, $server_test_file)) {
- $rv = 0;
+ if ($test_hr->{'replay_positive_output_matches'}) {
+ $rv = 0 unless &file_find_regex(
+ $test_hr->{'replay_positive_output_matches'},
+ $MATCH_ALL, $server_test_file);
+ }
+
+ if ($test_hr->{'replay_negative_output_matches'}) {
+ $rv = 0 if &file_find_regex(
+ $test_hr->{'replay_negative_output_matches'},
+ $MATCH_ANY, $server_test_file);
}
return $rv;