(Fernando Arnaboldi, IOActive) Found and fixed several DoS/code execution vulns for authenticated clients

- [server] Fernando Arnaboldi from IOActive found several DoS/code
execution vulnerabilities for malicious fwknop clients that manage to
get past the authentication stage (so a such a client must be in
possession of a valid access.conf encryption key).  These vulnerbilities
manifested themselves in the handling of malformed access requests, and
both the fwknopd server code along with libfko now perform stronger input
validation of access request data.  These vulnerabilities affect
pre-2.0.3 fwknop releases.
- [test suite] Added a new fuzzing capability to ensure proper server-side
input validation.  Fuzzing data is constructed with modified fwknop
client code that is designed to emulate malicious behavior.
This commit is contained in:
Michael Rash
2012-08-24 22:12:19 -04:00
parent b0bf7f3699
commit d46ba1c027
10 changed files with 531 additions and 28 deletions
+5
View File
@@ -53,3 +53,8 @@ Hank Leininger
- For iptables firewalls, suggested a check for the 'comment' match to
ensure the local environment will properly support fwknopd operations.
The result is the new ENABLE_IPT_COMMENT_CHECK functionality.
Fernando Arnaboldi (IOActive)
- Found important buffer overflow conditions for authenticated SPA clients
in the fwknopd server (pre-2.0.3). These findings enabled fixes to be
developed along with a new fuzzing capability in the test suite.
+13
View File
@@ -1,3 +1,16 @@
fwknop-2.0.3 (08//2012):
- [server] Fernando Arnaboldi from IOActive found several DoS/code
execution vulnerabilities for malicious fwknop clients that manage to
get past the authentication stage (so a such a client must be in
possession of a valid access.conf encryption key). These vulnerbilities
manifested themselves in the handling of malformed access requests, and
both the fwknopd server code along with libfko now perform stronger input
validation of access request data. These vulnerabilities affect
pre-2.0.3 fwknop releases.
- [test suite] Added a new fuzzing capability to ensure proper server-side
input validation. Fuzzing data is constructed with modified fwknop
client code that is designed to emulate malicious behavior.
fwknop-2.0.2 (08/18/2012):
- [server] For GPG mode, added a new access.conf variable
"GPG_ALLOW_NO_PW" to make it possible to leverage a server-side GPG key
+1
View File
@@ -149,6 +149,7 @@ EXTRA_DIST = \
test/conf/require_user_access.conf \
test/conf/subnet_source_match_access.conf \
test/conf/local_nat_fwknopd.conf \
test/conf/disable_aging_fwknopd.conf \
test/hardening-check \
test/local_spa.key \
test/test-fwknop.pl \
+15 -8
View File
@@ -200,6 +200,8 @@ validate_access_msg(const char *msg)
do {
ndx++;
res = validate_proto_port_spec(ndx);
if(res != FKO_SUCCESS)
break;
} while((ndx = strchr(ndx, ',')));
return(res);
@@ -208,14 +210,13 @@ validate_access_msg(const char *msg)
int
validate_proto_port_spec(const char *msg)
{
int startlen = strnlen(msg, MAX_SPA_MESSAGE_SIZE);
int startlen = strnlen(msg, MAX_SPA_MESSAGE_SIZE), port_str_len = 0;
const char *ndx = msg;
if(startlen == MAX_SPA_MESSAGE_SIZE)
return(FKO_ERROR_INVALID_DATA);
/* Now check for proto/port string. Currenly we only allow protos
* 'tcp', 'udp', and 'icmp'.
/* Now check for proto/port string.
*/
if(strncmp(ndx, "tcp", 3)
&& strncmp(ndx, "udp", 3)
@@ -224,19 +225,25 @@ validate_proto_port_spec(const char *msg)
return(FKO_ERROR_INVALID_SPA_ACCESS_MSG);
ndx = strchr(ndx, '/');
if(ndx == NULL || (1+(ndx - msg)) >= startlen)
if(ndx == NULL || ((1+(ndx - msg)) > MAX_PROTO_STR_LEN))
return(FKO_ERROR_INVALID_SPA_ACCESS_MSG);
/* Skip over the ',' and make sure we only have digits.
/* Skip over the '/' and make sure we only have digits.
*/
ndx++;
while(*ndx != '\0')
/* Must have at least one digit for the port number
*/
if(isdigit(*ndx) == 0)
return(FKO_ERROR_INVALID_SPA_ACCESS_MSG);
while(*ndx != '\0' && *ndx != ',')
{
if(isdigit(*ndx) == 0)
port_str_len++;
if((isdigit(*ndx) == 0) || (port_str_len > MAX_PORT_STR_LEN))
return(FKO_ERROR_INVALID_SPA_ACCESS_MSG);
ndx++;
}
return(FKO_SUCCESS);
}
+3
View File
@@ -32,6 +32,9 @@
#ifndef FKO_MESSAGE_H
#define FKO_MESSAGE_H 1
#define MAX_PROTO_STR_LEN 4 /* tcp, udp, icmp for now */
#define MAX_PORT_STR_LEN 5
/* SPA message format validation functions.
*/
int validate_cmd_msg(const char *msg);
+73 -16
View File
@@ -168,7 +168,7 @@ add_acc_force_nat(fko_srv_options_t *opts, acc_stanza_t *curr_acc, const char *v
/* Take an IP or Subnet/Mask and convert it to mask for later
* comparisons of incoming source IPs against this mask.
*/
static void
static int
add_source_mask(acc_stanza_t *acc, const char *ip)
{
char *ndx;
@@ -237,7 +237,7 @@ add_source_mask(acc_stanza_t *acc, const char *ip)
free(new_sle);
new_sle = NULL;
return;
return 0;
}
/* Store our mask converted from CIDR to a 32-bit value.
@@ -249,15 +249,17 @@ add_source_mask(acc_stanza_t *acc, const char *ip)
*/
new_sle->maddr = ntohl(in.s_addr) & new_sle->mask;
}
return 1;
}
/* Expand the access SOURCE string to a list of masks.
*/
void
static int
expand_acc_source(acc_stanza_t *acc)
{
char *ndx, *start;
char buf[32];
char buf[ACCESS_BUF_LEN];
int res = 1;
start = acc->source;
@@ -270,8 +272,13 @@ expand_acc_source(acc_stanza_t *acc)
while(isspace(*start))
start++;
if(((ndx-start)+1) >= ACCESS_BUF_LEN)
return 0;
strlcpy(buf, start, (ndx-start)+1);
add_source_mask(acc, buf);
res = add_source_mask(acc, buf);
if(res == 0)
return res;
start = ndx+1;
}
}
@@ -281,15 +288,20 @@ expand_acc_source(acc_stanza_t *acc)
while(isspace(*start))
start++;
if(((ndx-start)+1) >= ACCESS_BUF_LEN)
return 0;
strlcpy(buf, start, (ndx-start)+1);
add_source_mask(acc, buf);
res = add_source_mask(acc, buf);
return res;
}
static int
parse_proto_and_port(char *pstr, int *proto, int *port)
{
char *ndx;
char proto_str[32];
char proto_str[ACCESS_BUF_LEN];
/* Parse the string into its components.
*/
@@ -301,10 +313,24 @@ parse_proto_and_port(char *pstr, int *proto, int *port)
return(-1);
}
strlcpy(proto_str, pstr, (ndx - pstr)+1);
if(((ndx - pstr)+1) >= ACCESS_BUF_LEN)
{
log_msg(LOG_ERR,
"Parse error on access port entry: %s", pstr);
return(-1);
}
strlcpy(proto_str, pstr, (ndx - pstr)+1);
*port = atoi(ndx+1);
if((*port < 0) || (*port > MAX_PORT))
{
log_msg(LOG_ERR,
"Invalid port in access request: %s", pstr);
return(-1);
}
if(strcasecmp(proto_str, "tcp") == 0)
*proto = PROTO_TCP;
else if(strcasecmp(proto_str, "udp") == 0)
@@ -313,7 +339,6 @@ parse_proto_and_port(char *pstr, int *proto, int *port)
{
log_msg(LOG_ERR,
"Invalid protocol in access port entry: %s", pstr);
return(-1);
}
@@ -416,15 +441,15 @@ add_string_list_ent(acc_string_list_t **stlist, const char *str_str)
/* Expand a proto/port access string to a list of access proto-port struct.
*/
void
int
expand_acc_port_list(acc_port_list_t **plist, char *plist_str)
{
char *ndx, *start;
char buf[32];
char buf[ACCESS_BUF_LEN];
start = plist_str;
for(ndx = start; *ndx; ndx++)
for(ndx = start; *ndx != '\0'; ndx++)
{
if(*ndx == ',')
{
@@ -433,6 +458,9 @@ expand_acc_port_list(acc_port_list_t **plist, char *plist_str)
while(isspace(*start))
start++;
if(((ndx-start)+1) >= ACCESS_BUF_LEN)
return 0;
strlcpy(buf, start, (ndx-start)+1);
add_port_list_ent(plist, buf);
start = ndx+1;
@@ -444,9 +472,14 @@ expand_acc_port_list(acc_port_list_t **plist, char *plist_str)
while(isspace(*start))
start++;
if(((ndx-start)+1) >= ACCESS_BUF_LEN)
return 0;
strlcpy(buf, start, (ndx-start)+1);
add_port_list_ent(plist, buf);
return 1;
}
/* Expand a comma-separated string into a simple acc_string_list.
@@ -602,7 +635,11 @@ expand_acc_ent_lists(fko_srv_options_t *opts)
{
/* Expand the source string to 32-bit integer masks foreach entry.
*/
expand_acc_source(acc);
if(expand_acc_source(acc) == 0)
{
acc = acc->next;
continue;
}
/* Now expand the open_ports string.
*/
@@ -1086,9 +1123,9 @@ compare_port_list(acc_port_list_t *in, acc_port_list_t *ac, const int match_any)
int
acc_check_port_access(acc_stanza_t *acc, char *port_str)
{
int res = 1;
int res = 1, ctr = 0;
char buf[32];
char buf[ACCESS_BUF_LEN];
char *ndx, *start;
acc_port_list_t *o_pl = acc->oport_list;
@@ -1101,14 +1138,34 @@ acc_check_port_access(acc_stanza_t *acc, char *port_str)
/* Create our own internal port_list from the incoming SPA data
* for comparison.
*/
for(ndx = start; *ndx; ndx++)
for(ndx = start; *ndx != '\0'; ndx++)
{
if(*ndx == ',')
{
if((ctr >= ACCESS_BUF_LEN)
|| (((ndx-start)+1) >= ACCESS_BUF_LEN))
{
log_msg(LOG_ERR,
"Unable to create acc_port_list from incoming data: %s",
port_str
);
return(0);
}
strlcpy(buf, start, (ndx-start)+1);
add_port_list_ent(&in_pl, buf);
start = ndx+1;
ctr = 0;
}
ctr++;
}
if((ctr >= ACCESS_BUF_LEN)
|| (((ndx-start)+1) >= ACCESS_BUF_LEN))
{
log_msg(LOG_ERR,
"Unable to create acc_port_list from incoming data: %s",
port_str
);
return(0);
}
strlcpy(buf, start, (ndx-start)+1);
add_port_list_ent(&in_pl, buf);
+3 -1
View File
@@ -34,6 +34,8 @@
#define PROTO_TCP 6
#define PROTO_UDP 17
#define ACCESS_BUF_LEN 32
/* Function Prototypes
*/
void parse_access_file(fko_srv_options_t *opts);
@@ -41,7 +43,7 @@ int compare_addr_list(acc_int_list_t *source_list, const uint32_t ip);
int acc_check_port_access(acc_stanza_t *acc, char *port_str);
int acc_check_gpg_remote_id(acc_stanza_t *acc, const char *gpg_id);
void dump_access_list(const fko_srv_options_t *opts);
void expand_acc_port_list(acc_port_list_t **plist, char *plist_str);
int expand_acc_port_list(acc_port_list_t **plist, char *plist_str);
void free_acc_stanzas(fko_srv_options_t *opts);
void free_acc_port_list(acc_port_list_t *plist);
+2 -1
View File
@@ -582,7 +582,8 @@ process_spa_request(const fko_srv_options_t *opts, const acc_stanza_t *acc, spa_
/* Parse and expand our access message.
*/
expand_acc_port_list(&port_list, spadat->spa_message_remain);
if(expand_acc_port_list(&port_list, spadat->spa_message_remain) != 1)
return res;
/* Start at the top of the proto-port list...
*/
+5
View File
@@ -0,0 +1,5 @@
#
# The default fwknopd.conf contains only comments since defaults are defined in
# code and modified via the config file
#
ENABLE_SPA_PACKET_AGING N;
+411 -2
View File
@@ -48,6 +48,7 @@ my %cf = (
'multi_src_access' => "$conf_dir/multi_source_match_access.conf",
'ip_src_match' => "$conf_dir/ip_source_match_access.conf",
'subnet_src_match' => "$conf_dir/ip_source_match_access.conf",
'disable_aging' => "$conf_dir/disable_aging_fwknopd.conf",
);
my $default_digest_file = "$run_dir/digest.cache";
@@ -508,7 +509,7 @@ my @tests = (
{
'category' => 'basic operations',
'subcategory' => 'client',
'detail' => '-A <proto>/<port> specification',
'detail' => '-A <proto>/<port> specification (proto)',
'err_msg' => 'permitted invalid -A <proto>/<port>',
'function' => \&generic_exec,
'positive_output_matches' => [qr/Invalid\sSPA\saccess\smessage/i],
@@ -517,6 +518,19 @@ my @tests = (
"$fwknopCmd -A invalid/22 -a $fake_ip -D $loopback_ip",
'fatal' => $NO
},
{
'category' => 'basic operations',
'subcategory' => 'client',
'detail' => '-A <proto>/<port> specification (port)',
'err_msg' => 'permitted invalid -A <proto>/<port>',
'function' => \&generic_exec,
'positive_output_matches' => [qr/Invalid\sSPA\saccess\smessage/i],
'exec_err' => $YES,
'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopCmd -A tcp/600001 -a $fake_ip -D $loopback_ip",
'fatal' => $NO
},
{
'category' => 'basic operations',
'subcategory' => 'client',
@@ -1069,6 +1083,52 @@ my @tests = (
'fw_rule_removed' => $NEW_RULE_REMOVED,
'fatal' => $NO
},
{
'category' => 'Rijndael SPA',
'subcategory' => 'client+server',
'detail' => 'complete cycle (tcp/60001)',
'err_msg' => 'could not complete SPA cycle',
'function' => \&spa_cycle,
'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopCmd -A tcp/60001 -a $fake_ip -D $loopback_ip --get-key " .
"$local_key_file --verbose --verbose",
'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopdCmd $default_server_conf_args $intf_str",
'fw_rule_created' => $NEW_RULE_REQUIRED,
'fw_rule_removed' => $NEW_RULE_REMOVED,
'fatal' => $NO
},
{
'category' => 'Rijndael SPA',
'subcategory' => 'client+server',
'detail' => 'multi port (tcp/60001,udp/60001)',
'err_msg' => 'could not complete SPA cycle',
'function' => \&spa_cycle,
'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopCmd -A tcp/60001,udp/60001 -a $fake_ip -D $loopback_ip --get-key " .
"$local_key_file --verbose --verbose",
'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopdCmd $default_server_conf_args $intf_str",
'fw_rule_created' => $NEW_RULE_REQUIRED,
'fw_rule_removed' => $NEW_RULE_REMOVED,
'fatal' => $NO
},
{
'category' => 'Rijndael SPA',
'subcategory' => 'client+server',
'detail' => 'multi port (tcp/22,udp/53,tcp/1234)',
'err_msg' => 'could not complete SPA cycle',
'function' => \&spa_cycle,
'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopCmd -A tcp/22,udp/53,tcp/1234 -a $fake_ip -D $loopback_ip --get-key " .
"$local_key_file --verbose --verbose",
'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopdCmd $default_server_conf_args $intf_str",
'fw_rule_created' => $NEW_RULE_REQUIRED,
'fw_rule_removed' => $NEW_RULE_REMOVED,
'fatal' => $NO
},
{
'category' => 'Rijndael SPA',
'subcategory' => 'client+server',
@@ -1154,6 +1214,64 @@ my @tests = (
'replay_positive_output_matches' => [qr/Data\sis\snot\sa\svalid\sSPA\smessage\sformat/],
'fatal' => $NO
},
### fuzzing tests
{
'category' => 'Rijndael SPA',
'subcategory' => 'FUZZING',
'detail' => 'overly long port value',
'err_msg' => 'server crashed or did not detect error condition',
'function' => \&overly_long_port,
'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'fatal' => $NO
},
{
'category' => 'Rijndael SPA',
'subcategory' => 'FUZZING',
'detail' => 'overly long proto value',
'err_msg' => 'server crashed or did not detect error condition',
'function' => \&overly_long_proto,
'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'fatal' => $NO
},
{
'category' => 'Rijndael SPA',
'subcategory' => 'FUZZING',
'detail' => 'negative port value',
'err_msg' => 'server crashed or did not detect error condition',
'function' => \&negative_port,
'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'fatal' => $NO
},
{
'category' => 'Rijndael SPA',
'subcategory' => 'FUZZING',
'detail' => 'null port value',
'err_msg' => 'server crashed or did not detect error condition',
'function' => \&null_port,
'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'fatal' => $NO
},
{
'category' => 'Rijndael SPA',
'subcategory' => 'FUZZING',
'detail' => 'null proto value',
'err_msg' => 'server crashed or did not detect error condition',
'function' => \&null_proto,
'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'fatal' => $NO
},
{
'category' => 'Rijndael SPA',
'subcategory' => 'server',
@@ -1287,6 +1405,24 @@ my @tests = (
'fw_rule_removed' => $NEW_RULE_REMOVED,
'fatal' => $NO
},
{
'category' => 'GPG (no pw) SPA',
'subcategory' => 'client+server',
'detail' => 'complete cycle (tcp/60001)',
'err_msg' => 'could not complete SPA cycle',
'function' => \&spa_cycle,
'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopCmd -A tcp/60001 -a $fake_ip -D $loopback_ip --get-key " .
"$local_key_file --verbose --verbose " .
"--gpg-recipient-key $gpg_server_key " .
"--gpg-signer-key $gpg_client_key " .
"--gpg-home-dir $gpg_client_home_dir_no_pw",
'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
'fw_rule_created' => $NEW_RULE_REQUIRED,
'fw_rule_removed' => $NEW_RULE_REMOVED,
'fatal' => $NO
},
{
'category' => 'GPG (no pw) SPA',
'subcategory' => 'client+server',
@@ -1450,6 +1586,24 @@ my @tests = (
'fw_rule_removed' => $NEW_RULE_REMOVED,
'fatal' => $NO
},
{
'category' => 'GnuPG (GPG) SPA',
'subcategory' => 'client+server',
'detail' => 'complete cycle (tcp/60001)',
'err_msg' => 'could not complete SPA cycle',
'function' => \&spa_cycle,
'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopCmd -A tcp/60001 -a $fake_ip -D $loopback_ip --get-key " .
"$local_key_file --verbose --verbose " .
"--gpg-recipient-key $gpg_server_key " .
"--gpg-signer-key $gpg_client_key " .
"--gpg-home-dir $gpg_client_home_dir",
'fwknopd_cmdline' => $default_server_gpg_args,
'fw_rule_created' => $NEW_RULE_REQUIRED,
'fw_rule_removed' => $NEW_RULE_REMOVED,
'fatal' => $NO
},
{
'category' => 'GnuPG (GPG) SPA',
'subcategory' => 'client+server',
@@ -2112,6 +2266,261 @@ sub altered_non_base64_spa_data() {
return $rv;
}
sub null_proto() {
my $test_hr = shift;
my $rv = 1;
my $server_was_stopped = 0;
my $fw_rule_created = 0;
my $fw_rule_removed = 0;
### this packet was generated with a modified fwknop client via the
### following command line:
#
# LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A /22 \
# -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key \
# --verbose --verbose
#
my $spa_pkt =
'/JT14qxh9P4iy+CuUZahThaQjoEuL2zd46a+jL6sTrBZJSa6faUX4dH5fte/4ZJv+9f' .
'd/diWYKAUvdQ4DydPGlR7mwQa2W+obKpqrsTBz7D4054z6ATAOGpCtifakEVl1XRc2+' .
'hW04WpY8mdUNu9i+PrfPr7/KxqU';
my @packets = (
{
'proto' => 'udp',
'port' => $default_spa_port,
'dst_ip' => $loopback_ip,
'data' => $spa_pkt,
},
);
($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
= &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
$rv = 0 unless $server_was_stopped;
if ($fw_rule_created) {
&write_test_file("[-] new fw rule created.\n", $current_test_file);
$rv = 0;
} else {
&write_test_file("[+] new fw rule not created.\n", $current_test_file);
}
unless (&file_find_regex([qr/Args\scontain\sinvalid\sdata/],
$MATCH_ALL, $server_test_file)) {
$rv = 0;
}
return $rv;
}
sub null_port() {
my $test_hr = shift;
my $rv = 1;
my $server_was_stopped = 0;
my $fw_rule_created = 0;
my $fw_rule_removed = 0;
### this packet was generated with a modified fwknop client via the
### following command line:
#
# LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/ \
# -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key \
# --verbose --verbose
#
my $spa_pkt =
'94nu7hvq6V/3A27GzjHwfPnPCQfs44ySlraIFYHOAqy5YqjkrBS67nH35tX55N1BrYZ' .
'07zvcT03keUhLE1Uo7Wme1nE7BfTOG5stmIK1UQI85sL52//lDHu+xCqNcL7GUKbVRz' .
'ekw+EUscVvUkrsRcVtSvOm+fCNo';
my @packets = (
{
'proto' => 'udp',
'port' => $default_spa_port,
'dst_ip' => $loopback_ip,
'data' => $spa_pkt,
},
);
($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
= &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
$rv = 0 unless $server_was_stopped;
if ($fw_rule_created) {
&write_test_file("[-] new fw rule created.\n", $current_test_file);
$rv = 0;
} else {
&write_test_file("[+] new fw rule not created.\n", $current_test_file);
}
unless (&file_find_regex([qr/Args\scontain\sinvalid\sdata/],
$MATCH_ALL, $server_test_file)) {
$rv = 0;
}
return $rv;
}
sub negative_port() {
my $test_hr = shift;
my $rv = 1;
my $server_was_stopped = 0;
my $fw_rule_created = 0;
my $fw_rule_removed = 0;
### this packet was generated with a modified fwknop client via the
### following command line:
#
# LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A \
# tcp/-33 -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key \
# --verbose --verbose
#
my $spa_pkt =
'/weoc+pEuQknZo8ImWTQBB+/PwSJ2/TcrmFoSkxpRXX4+jlUxoJakHrioxh8rhLmAD9' .
'8E4lMnq+EbM2XYdhs2alpZ5bovAFojMsYRWwr/BvRO4Um4Fmo9z9sY3DR477TXNYXBR' .
'iGXWxSL4u+AWSSePK3qiiYoRQVw';
my @packets = (
{
'proto' => 'udp',
'port' => $default_spa_port,
'dst_ip' => $loopback_ip,
'data' => $spa_pkt,
},
);
($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
= &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
$rv = 0 unless $server_was_stopped;
if ($fw_rule_created) {
&write_test_file("[-] new fw rule created.\n", $current_test_file);
$rv = 0;
} else {
&write_test_file("[+] new fw rule not created.\n", $current_test_file);
}
unless (&file_find_regex([qr/Args\scontain\sinvalid\sdata/],
$MATCH_ALL, $server_test_file)) {
$rv = 0;
}
return $rv;
}
sub overly_long_proto() {
my $test_hr = shift;
my $rv = 1;
my $server_was_stopped = 0;
my $fw_rule_created = 0;
my $fw_rule_removed = 0;
### this packet was generated with a modified fwknop client via the
### following command line:
#
# LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A \
# "tcp`perl -e '{print "A"x"28"}'`/1" -a 127.0.0.2 -D 127.0.0.1 \
# --get-key local_spa.key --verbose --verbose
#
# This problem was found by Fernando Arnaboldi of IOActive and exploits
# a buffer overflow in the fwknopd servers prior to 2.0.3 from
# authenticated clients.
#
my $spa_pkt =
'/im5MiJQmOdzqrdWXv+AjEtAm/HsLrdaTFcSw3ZskqpGOdDIrSCz3VXbFfv7qDkc5Y4' .
'q/k1mRXl9SGzpug87U5dZSyCdAr30z7/2kUFEPTGOQBi/x+L1t1pvdkm4xg13t09ldm' .
'5OD8KiV6qzqLOvN4ULJjvvJJWBZ9qvo/f2Q9Wf67g2KHiwS6EeCINAuMoUw/mNRQMa4' .
'oGnOXu3/DeWHJAwtSeh7EAr4';
my @packets = (
{
'proto' => 'udp',
'port' => $default_spa_port,
'dst_ip' => $loopback_ip,
'data' => $spa_pkt,
},
);
($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
= &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
$rv = 0 unless $server_was_stopped;
if ($fw_rule_created) {
&write_test_file("[-] new fw rule created.\n", $current_test_file);
$rv = 0;
} else {
&write_test_file("[+] new fw rule not created.\n", $current_test_file);
}
unless (&file_find_regex([qr/Args\scontain\sinvalid\sdata/],
$MATCH_ALL, $server_test_file)) {
$rv = 0;
}
return $rv;
}
sub overly_long_port() {
my $test_hr = shift;
my $rv = 1;
my $server_was_stopped = 0;
my $fw_rule_created = 0;
my $fw_rule_removed = 0;
### this packet was generated with a modified fwknop client via the
### following command line:
#
# LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A \
# "tcp/`perl -e '{print "1"x"40"}'`" -a 127.0.0.2 -D 127.0.0.1 \
# --get-key local_spa.key --verbose --verbose
#
# This problem was found by Fernando Arnaboldi of IOActive and exploits
# a buffer overflow in the fwknopd servers prior to 2.0.3 from
# authenticated clients.
#
my $spa_pkt =
'+JzxeTGlc6lwwzbJSrYChKx8bonWBIPajwGfEtGOaoglcMLbTY/GGXo/nxqiN1LykFS' .
'lDFXgrkyx2emJ7NGzYqQPUYZxLdZRocR9aRIptvXLLIPBcIpJASi/TUiJlw7CDFMcj0' .
'ptSBJJUZi0tozpKHETp3AgqfzyOy5FNs38aZsV5/sDl3Pt+kF7fTZJ+YLbmYY4yCUz2' .
'ZUYoCaJ7X78ULyJTi5eT7nug';
my @packets = (
{
'proto' => 'udp',
'port' => $default_spa_port,
'dst_ip' => $loopback_ip,
'data' => $spa_pkt,
},
);
($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
= &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
$rv = 0 unless $server_was_stopped;
if ($fw_rule_created) {
&write_test_file("[-] new fw rule created.\n", $current_test_file);
$rv = 0;
} else {
&write_test_file("[+] new fw rule not created.\n", $current_test_file);
}
unless (&file_find_regex([qr/Args\scontain\sinvalid\sdata/],
$MATCH_ALL, $server_test_file)) {
$rv = 0;
}
return $rv;
}
sub altered_base64_spa_data() {
my $test_hr = shift;
@@ -2357,7 +2766,7 @@ sub server_ignore_small_packets() {
}
sub client_server_interaction() {
my ($test_hr, $pkts_hr, $spa_client_flag, $fw_rules_flag) = @_;
my ($test_hr, $pkts_hr, $spa_client_flag) = @_;
my $rv = 1;
my $server_was_stopped = 1;