Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

(Fernando Arnaboldi, IOActive) Found and fixed several DoS/code execu…

…tion 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.
  • Loading branch information...
commit d46ba1c027a11e45821ba897a4928819bccc8f22 1 parent b0bf7f3
@mrash authored
View
5 CREDITS
@@ -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.
View
13 ChangeLog
@@ -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
View
1  Makefile.am
@@ -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 \
View
23 lib/fko_message.c
@@ -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);
}
View
3  lib/fko_message.h
@@ -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);
View
89 server/access.c
@@ -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);
View
4 server/access.h
@@ -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);
View
3  server/fw_util_iptables.c
@@ -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...
*/
View
5 test/conf/disable_aging_fwknopd.conf
@@ -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;
View
413 test/test-fwknop.pl
@@ -48,6 +48,7 @@
'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 @@
{
'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],
@@ -520,6 +521,19 @@
{
'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',
'detail' => 'generate SPA packet',
'err_msg' => 'could not generate SPA packet',
'function' => \&client_send_spa_packet,
@@ -1072,6 +1086,52 @@
{
'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',
'detail' => 'complete cycle (udp/53 dns)',
'err_msg' => 'could not complete SPA cycle',
'function' => \&spa_cycle,
@@ -1154,6 +1214,64 @@
'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',
@@ -1290,6 +1408,24 @@
{
'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',
'detail' => 'complete cycle (udp/53 dns)',
'err_msg' => 'could not complete SPA cycle',
'function' => \&spa_cycle,
@@ -1453,6 +1589,24 @@
{
'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',
'detail' => 'complete cycle (udp/53 dns)',
'err_msg' => 'could not complete SPA cycle',
'function' => \&spa_cycle,
@@ -2112,6 +2266,261 @@ ()
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 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;
Please sign in to comment.
Something went wrong with that request. Please try again.