Replay attack bug fix (encryption prefixes)

Ensure that an attacker cannot force a replay attack by intercepting an
SPA packet and the replaying it with the base64 version of "Salted__"
(for Rindael) or the "hQ" prefix (for GnuPG).  This is an important fix.
The following comment was added into the fwknopd code:

/* 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.
*/
This commit is contained in:
Michael Rash
2012-07-29 23:31:15 -04:00
parent fd30a3491d
commit afc71b7df3
4 changed files with 52 additions and 9 deletions
-9
View File
@@ -35,15 +35,6 @@
#include "rijndael.h"
#include "gpgme_funcs.h"
/* Define the consistent prefixes or salt on some ecryption schemes.
* We identify them here so we can remove and reinsert when needed.
*/
#define B64_RIJNDAEL_SALT "U2FsdGVkX1"
#define B64_RIJNDAEL_SALT_STR_LEN 10
#define B64_GPG_PREFIX "hQ"
#define B64_GPG_PREFIX_STR_LEN 2
/* Provide the predicted encrypted data size for given input data based
* on a 16-byte block size (for Rijndael implementation,this also accounts
* for the 16-byte salt as well).
+8
View File
@@ -194,6 +194,14 @@ typedef enum {
#define FKO_DEFAULT_ENCRYPTION FKO_ENCRYPTION_RIJNDAEL
#define FKO_DEFAULT_ENC_MODE MODE_CBC
/* Define the consistent prefixes or salt on some encryption schemes.
*/
#define B64_RIJNDAEL_SALT "U2FsdGVkX1"
#define B64_RIJNDAEL_SALT_STR_LEN 10
#define B64_GPG_PREFIX "hQ"
#define B64_GPG_PREFIX_STR_LEN 2
/* The context holds the global state and config options, as
* well as some intermediate results during processing. This
* is an opaque pointer.
+14
View File
@@ -62,6 +62,20 @@ preprocess_spa_data(fko_srv_options_t *opts, const char *src_ip)
*/
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_NOT_SPA_DATA);
if(pkt_data_len > MIN_GNUPG_MSG_SIZE
&& strncmp(ndx, B64_GPG_PREFIX, B64_GPG_PREFIX_STR_LEN) == 0)
return(SPA_MSG_NOT_SPA_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.
+30
View File
@@ -1452,6 +1452,18 @@ my @tests = (
"$fwknopdCmd $default_server_conf_args $intf_str",
'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",
'fatal' => $NO
},
{
'category' => 'Rijndael SPA',
'subcategory' => 'server',
@@ -1622,6 +1634,19 @@ my @tests = (
'fwknopd_cmdline' => $default_server_gpg_args,
'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_args,
'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopdCmd $default_server_conf_args $intf_str",
'fatal' => $NO
},
{
'category' => 'GnuPG (GPG) SPA',
@@ -1704,6 +1729,7 @@ my %test_keys = (
'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,
@@ -2143,6 +2169,10 @@ sub replay_detection() {
return 0;
}
if ($test_hr->{'pkt_prefix'}) {
$spa_pkt = $test_hr->{'pkt_prefix'} . $spa_pkt;
}
my @packets = (
{
'proto' => 'udp',