[server] add support for American Fuzzy Lop (ALF) fuzzing
This commit is contained in:
@@ -356,6 +356,7 @@ EXTRA_DIST = \
|
||||
test/tests/rijndael_backwards_compatibility.pl \
|
||||
test/tests/os_compatibility.pl \
|
||||
test/tests/fault_injection.pl \
|
||||
test/tests/afl_fuzzing.pl \
|
||||
test/tests/gpg_hmac.pl \
|
||||
test/tests/gpg_no_pw.pl \
|
||||
test/tests/gpg_no_pw_hmac.pl \
|
||||
|
||||
15
configure.ac
15
configure.ac
@@ -167,6 +167,21 @@ if test "x$want_fuzzing_interfaces" = "xyes"; then
|
||||
AC_DEFINE([FUZZING_INTERFACES], [1], [Define for fuzzing interfaces support])
|
||||
fi
|
||||
|
||||
dnl Decide whether or not to compile in support for the 'American Fuzzy Lop'
|
||||
dnl fuzzer from Michal Zalewski - this is for testing purposes only
|
||||
dnl
|
||||
want_afl_fuzzing_support=no
|
||||
AC_ARG_ENABLE([afl-fuzzing],
|
||||
[AS_HELP_STRING([--enable-afl-fuzzing],
|
||||
[Build fwknop binaries with support for the American Fuzzy Lop fuzzer @<:@default is to disable@:>@])],
|
||||
[want_afl_fuzzing_support=$enableval],
|
||||
[])
|
||||
|
||||
if test "x$want_afl_fuzzing_support" = "xyes"; then
|
||||
AC_DEFINE([AFL_FUZZING], [1], [Define for AFL fuzzing support])
|
||||
AC_DEFINE([FUZZING_INTERFACES], [1], [Define for fuzzing interfaces support])
|
||||
fi
|
||||
|
||||
dnl Decide whether or not to enable UDP server mode (no libpcap dependency)
|
||||
dnl
|
||||
want_udp_server=no
|
||||
|
||||
15
lib/base64.c
15
lib/base64.c
@@ -36,6 +36,7 @@
|
||||
#include "base64.h"
|
||||
#include "fko_common.h"
|
||||
|
||||
#if !AFL_FUZZING
|
||||
static unsigned char map2[] =
|
||||
{
|
||||
0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36,
|
||||
@@ -49,13 +50,24 @@ static unsigned char map2[] =
|
||||
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
|
||||
0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33
|
||||
};
|
||||
#endif
|
||||
|
||||
int
|
||||
b64_decode(const char *in, unsigned char *out)
|
||||
{
|
||||
int i, v;
|
||||
int i;
|
||||
unsigned char *dst = out;
|
||||
#if ! AFL_FUZZING
|
||||
int v;
|
||||
#endif
|
||||
|
||||
#if AFL_FUZZING
|
||||
/* short circuit base64 decoding in AFL fuzzing mode - just copy
|
||||
* data as-is.
|
||||
*/
|
||||
for (i = 0; in[i]; i++)
|
||||
*dst++ = in[i];
|
||||
#else
|
||||
v = 0;
|
||||
for (i = 0; in[i] && in[i] != '='; i++) {
|
||||
unsigned int index= in[i]-43;
|
||||
@@ -68,6 +80,7 @@ b64_decode(const char *in, unsigned char *out)
|
||||
if (i & 3)
|
||||
*dst++ = v >> (6 - 2 * (i & 3));
|
||||
}
|
||||
#endif
|
||||
|
||||
*dst = '\0';
|
||||
|
||||
|
||||
@@ -75,6 +75,10 @@ last_field(char *str)
|
||||
static int
|
||||
verify_digest(char *tbuf, int t_size, fko_ctx_t ctx)
|
||||
{
|
||||
#if AFL_FUZZING
|
||||
return FKO_SUCCESS;
|
||||
#endif
|
||||
|
||||
switch(ctx->digest_type)
|
||||
{
|
||||
case FKO_DIGEST_MD5:
|
||||
@@ -113,6 +117,12 @@ verify_digest(char *tbuf, int t_size, fko_ctx_t ctx)
|
||||
static int
|
||||
is_valid_digest_len(int t_size, fko_ctx_t ctx)
|
||||
{
|
||||
#if AFL_FUZZING
|
||||
ctx->digest_type = FKO_DIGEST_SHA256;
|
||||
ctx->digest_len = t_size;
|
||||
return FKO_SUCCESS;
|
||||
#endif
|
||||
|
||||
switch(t_size)
|
||||
{
|
||||
case MD5_B64_LEN:
|
||||
|
||||
@@ -153,13 +153,14 @@ enum {
|
||||
|
||||
/* Our getopt_long options string.
|
||||
*/
|
||||
#define GETOPTS_OPTION_STRING "a:c:C:d:Dfhi:Kl:O:p:P:RStvV"
|
||||
#define GETOPTS_OPTION_STRING "Aa:c:C:d:Dfhi:Kl:O:p:P:RStvV"
|
||||
|
||||
/* Our program command-line options...
|
||||
*/
|
||||
static struct option cmd_opts[] =
|
||||
{
|
||||
{"access-file", 1, NULL, 'a'},
|
||||
{"afl-fuzzing", 0, NULL, 'A'},
|
||||
{"config-file", 1, NULL, 'c'},
|
||||
{"packet-limit", 1, NULL, 'C'},
|
||||
{"digest-file", 1, NULL, 'd'},
|
||||
|
||||
@@ -1031,6 +1031,14 @@ config_init(fko_srv_options_t *opts, int argc, char **argv)
|
||||
GETOPTS_OPTION_STRING, cmd_opts, &index)) != -1) {
|
||||
|
||||
switch(cmd_arg) {
|
||||
case 'A':
|
||||
#if AFL_FUZZING
|
||||
opts->afl_fuzzing = 1;
|
||||
#else
|
||||
log_msg(LOG_ERR, "[*] fwknopd not compiled with AFL fuzzing support");
|
||||
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
|
||||
#endif
|
||||
break;
|
||||
case 'a':
|
||||
set_config_entry(opts, CONF_ACCESS_FILE, optarg);
|
||||
break;
|
||||
|
||||
@@ -58,11 +58,19 @@ static void setup_pid(fko_srv_options_t *opts);
|
||||
static void init_digest_cache(fko_srv_options_t *opts);
|
||||
static void set_locale(fko_srv_options_t *opts);
|
||||
static pid_t get_running_pid(const fko_srv_options_t *opts);
|
||||
#if AFL_FUZZING
|
||||
static void afl_pkt_from_stdin(fko_srv_options_t *opts);
|
||||
#endif
|
||||
|
||||
#if HAVE_LIBFIU
|
||||
static void enable_fault_injections(fko_srv_options_t * const opts);
|
||||
#endif
|
||||
|
||||
#if AFL_FUZZING
|
||||
#define AFL_MAX_PKT_SIZE 1024
|
||||
#define AFL_DUMP_CTX_SIZE 4096
|
||||
#endif
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@@ -114,7 +122,8 @@ main(int argc, char **argv)
|
||||
/* Make sure we have a valid run dir and path leading to digest file
|
||||
* in case it configured to be somewhere other than the run dir.
|
||||
*/
|
||||
if(! check_dir_path((const char *)opts.config[CONF_FWKNOP_RUN_DIR], "Run", 0))
|
||||
if(!opts.afl_fuzzing
|
||||
&& ! check_dir_path((const char *)opts.config[CONF_FWKNOP_RUN_DIR], "Run", 0))
|
||||
clean_exit(&opts, NO_FW_CLEANUP, EXIT_FAILURE);
|
||||
|
||||
/* Initialize the firewall rules handler based on the fwknopd.conf
|
||||
@@ -175,6 +184,12 @@ main(int argc, char **argv)
|
||||
clean_exit(&opts, NO_FW_CLEANUP, EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
#if AFL_FUZZING
|
||||
/* SPA data from STDIN. */
|
||||
if(opts.afl_fuzzing)
|
||||
afl_pkt_from_stdin(&opts);
|
||||
#endif
|
||||
|
||||
/* Prepare the firewall - i.e. flush any old rules and (for iptables)
|
||||
* create fwknop chains.
|
||||
*/
|
||||
@@ -274,10 +289,69 @@ static void set_locale(fko_srv_options_t *opts)
|
||||
return;
|
||||
}
|
||||
|
||||
#if AFL_FUZZING
|
||||
static void afl_pkt_from_stdin(fko_srv_options_t *opts)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
fko_ctx_t decode_ctx = NULL;
|
||||
unsigned char spa_pkt[AFL_MAX_PKT_SIZE] = {0};
|
||||
int res = 0, es = EXIT_SUCCESS;
|
||||
char dump_buf[AFL_DUMP_CTX_SIZE];
|
||||
|
||||
fp = fdopen(STDIN_FILENO, "r");
|
||||
if(fp != NULL)
|
||||
{
|
||||
if(fgets((char *)spa_pkt, AFL_MAX_PKT_SIZE, fp) == NULL)
|
||||
{
|
||||
fclose(fp);
|
||||
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
fko_new(&decode_ctx);
|
||||
|
||||
res = fko_set_encoded_data(decode_ctx, (char *) spa_pkt,
|
||||
strlen((char *)spa_pkt), 0, FKO_DIGEST_SHA256);
|
||||
|
||||
if(res == FKO_SUCCESS)
|
||||
res = fko_set_spa_data(decode_ctx, (const char *) spa_pkt);
|
||||
if(res == FKO_SUCCESS)
|
||||
res = fko_decode_spa_data(decode_ctx);
|
||||
if(res == FKO_SUCCESS)
|
||||
res = dump_ctx_to_buffer(decode_ctx, dump_buf, sizeof(dump_buf));
|
||||
if(res == FKO_SUCCESS)
|
||||
log_msg(LOG_INFO, "%s", dump_buf);
|
||||
|
||||
fko_destroy(decode_ctx);
|
||||
|
||||
if(res == FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_INFO, "SPA packet decode success: %s", fko_errstr(res));
|
||||
es = EXIT_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_msg(LOG_ERR, "Could not decode SPA packet: %s", fko_errstr(res));
|
||||
es = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
log_msg(LOG_ERR, "Could not acquire SPA packet from stdin.");
|
||||
|
||||
clean_exit(opts, NO_FW_CLEANUP, es);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void init_digest_cache(fko_srv_options_t *opts)
|
||||
{
|
||||
int rp_cache_count;
|
||||
|
||||
#if AFL_FUZZING
|
||||
if(opts->afl_fuzzing)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if(strncasecmp(opts->config[CONF_ENABLE_DIGEST_PERSISTENCE], "Y", 1) == 0)
|
||||
{
|
||||
rp_cache_count = replay_cache_init(opts);
|
||||
@@ -311,6 +385,11 @@ static void setup_pid(fko_srv_options_t *opts)
|
||||
{
|
||||
pid_t old_pid;
|
||||
|
||||
#if AFL_FUZZING
|
||||
if(opts->afl_fuzzing)
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* If we are a new process (just being started), proceed with normal
|
||||
* start-up. Otherwise, we are here as a result of a signal sent to an
|
||||
* existing process and we want to restart.
|
||||
|
||||
@@ -577,6 +577,7 @@ typedef struct fko_srv_options
|
||||
unsigned char fw_list_all; /* List all current firewall rules */
|
||||
unsigned char fw_flush; /* Flush current firewall rules */
|
||||
unsigned char test; /* Test mode flag */
|
||||
unsigned char afl_fuzzing; /* SPA pkts from stdin for AFL fuzzing */
|
||||
unsigned char verbose; /* Verbose mode flag */
|
||||
unsigned char exit_after_parse_config; /* Parse config and exit */
|
||||
unsigned char enable_udp_server; /* Enable UDP server mode */
|
||||
|
||||
50
test/afl/README
Normal file
50
test/afl/README
Normal file
@@ -0,0 +1,50 @@
|
||||
|
||||
The fwknop project supports various fuzzing strategies, and one of the most
|
||||
important is usage of the 'American Fuzzy Lop' (AFL) fuzzer written by Michal
|
||||
Zalewski (see: https://code.google.com/p/american-fuzzy-lop/). Because AFL is
|
||||
not designed to handle encryption schemes (see the README included in the AFL
|
||||
sources for more information on this), a special --enable-afl-fuzzing command
|
||||
line switch is available to the fwknop autoconf configure script. This argument
|
||||
allows encryption and base64 encoding to be bypassed when feeding SPA packet
|
||||
data to fwknopd via stdin. It is the feature that enables AFL fuzzing.
|
||||
|
||||
This directory contains enabling scripts in order to make it easy to fuzz
|
||||
fwknop with AFL. It is assumed that AFL is installed and in your path. The
|
||||
files are in this directory are organized as follows:
|
||||
|
||||
afl-compile.sh - Script to compile fwknop underneath afl-gcc.
|
||||
afl-fuzzing.in - AFL input directory which contains input test cases.
|
||||
afl-fuzzing.out - AFL output directory.
|
||||
afl-run.sh - Script to invoke AFL with proper command line arguments to
|
||||
fwknopd for fuzzing enablement.
|
||||
|
||||
Here is an example of what fwknopd produces when compiled for AFL support when
|
||||
a dummy SPA packet is provided in non-encoded/encrypted form via fwknopd's
|
||||
stdin:
|
||||
|
||||
$ ./fwknopd-stdin-test.sh
|
||||
+ SPA_PKT=1716411011200157:root:1397329899:2.0.1:1:127.0.0.2,tcp/22:AAAAA
|
||||
+ LD_LIBRARY_PATH=../../lib/.libs ../../server/.libs/fwknopd -c ../conf/default_fwknopd.conf -a ../conf/default_access.conf -A -f -t
|
||||
+ echo -n 1716411011200157:root:1397329899:2.0.1:1:127.0.0.2,tcp/22:AAAAA
|
||||
Warning: REQUIRE_SOURCE_ADDRESS not enabled for access stanza source: 'ANY'
|
||||
SPA Field Values:
|
||||
=================
|
||||
Random Value: 1716411011200157
|
||||
Username: root
|
||||
Timestamp: 1397329899
|
||||
FKO Version: 2.0.1
|
||||
Message Type: 1 (Access msg)
|
||||
Message String: 127.0.0.2,tcp/22
|
||||
Nat Access: <NULL>
|
||||
Server Auth: <NULL>
|
||||
Client Timeout: 0
|
||||
Digest Type: 3 (SHA256)
|
||||
HMAC Type: 0 (None)
|
||||
Encryption Type: 1 (Rijndael)
|
||||
Encryption Mode: 2 (CBC)
|
||||
Encoded Data: 1716411011200157:root:1397329899:2.0.1:1:127.0.0.2,tcp/22
|
||||
SPA Data Digest: AAAAA
|
||||
HMAC: <NULL>
|
||||
Final SPA Data: 200157:root:1397329899:2.0.1:1:127.0.0.2,tcp/22:AAAAA
|
||||
|
||||
SPA packet decode success: Success
|
||||
8
test/afl/afl-compile.sh
Executable file
8
test/afl/afl-compile.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh -x
|
||||
|
||||
cd ../../
|
||||
CC=afl-gcc ./extras/apparmor/configure_args.sh --enable-afl-fuzzing
|
||||
make clean
|
||||
make
|
||||
cd test/afl
|
||||
exit
|
||||
1
test/afl/afl-fuzzing.in/spa.start
Normal file
1
test/afl/afl-fuzzing.in/spa.start
Normal file
@@ -0,0 +1 @@
|
||||
1716411011200157:root:1397329899:2.0.1:1:127.0.0.2,tcp/22:AAAAA
|
||||
1
test/afl/afl-fuzzing.in/spa2.start
Normal file
1
test/afl/afl-fuzzing.in/spa2.start
Normal file
@@ -0,0 +1 @@
|
||||
3145808919615481:root:1397329899:2.0.1:0:127.0.0.2,echo fwknoptest > /tmp/fwknoptest:AAAAA
|
||||
1
test/afl/afl-fuzzing.in/spa3.start
Normal file
1
test/afl/afl-fuzzing.in/spa3.start
Normal file
@@ -0,0 +1 @@
|
||||
1716411011200157:root:1397329899:2.0.1:4:127.0.0.2,tcp/22:192.168.10.1,12345:1234:AAAAAA
|
||||
16
test/afl/afl-run.sh
Executable file
16
test/afl/afl-run.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh -x
|
||||
|
||||
OLD_DIR=afl-out-archive
|
||||
OUT_DIR=afl-fuzzing.out
|
||||
|
||||
[ ! -d $OLD_DIR ] && mkdir $OLD_DIR
|
||||
TS=`date +"%m%d%y%H%M%S"`
|
||||
[ -d $OUT_DIR ] && mv $OUT_DIR "$OLD_DIR/$OUT_DIR-$TS"
|
||||
mkdir $OUT_DIR
|
||||
|
||||
### make sure that a basic SPA packet to stdin in fwknopd -A mode works
|
||||
./fwknopd-stdin-test.sh || exit
|
||||
|
||||
LD_LIBRARY_PATH=../../lib/.libs afl-fuzz -i afl-fuzzing.in -o $OUT_DIR ../../server/.libs/fwknopd -c ../conf/default_fwknopd.conf -a ../conf/default_access.conf -A -f -t
|
||||
|
||||
exit
|
||||
6
test/afl/fwknopd-stdin-test.sh
Executable file
6
test/afl/fwknopd-stdin-test.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh -x
|
||||
|
||||
SPA_PKT="1716411011200157:root:1397329899:2.0.1:1:127.0.0.2,tcp/22:AAAAA"
|
||||
#SPA_PKT="1716411011200157:root:1397329899:2.0.1:1:127.0.0.2,tcp/22:A"
|
||||
|
||||
echo -n $SPA_PKT | LD_LIBRARY_PATH=../../lib/.libs ../../server/.libs/fwknopd -c ../conf/default_fwknopd.conf -a ../conf/default_access.conf -A -f -t
|
||||
@@ -103,6 +103,7 @@ my @test_files = (
|
||||
"$tests_dir/rijndael_hmac.pl",
|
||||
"$tests_dir/rijndael_hmac_fuzzing.pl",
|
||||
"$tests_dir/fault_injection.pl",
|
||||
"$tests_dir/afl_fuzzing.pl",
|
||||
"$tests_dir/os_compatibility.pl",
|
||||
"$tests_dir/perl_FKO_module.pl",
|
||||
"$tests_dir/python_fko.pl",
|
||||
@@ -128,6 +129,7 @@ our @rijndael_hmac = (); ### from tests/rijndael_hmac.pl
|
||||
our @rijndael_fuzzing = (); ### from tests/rijndael_fuzzing.pl
|
||||
our @rijndael_hmac_fuzzing = (); ### from tests/rijndael_hmac_fuzzing.pl
|
||||
our @fault_injection = (); ### from tests/fault_injection.pl
|
||||
our @afl_fuzzing = (); ### from tests/alf_fuzzing.pl
|
||||
our @gpg_no_pw = (); ### from tests/gpg_now_pw.pl
|
||||
our @gpg_no_pw_hmac = (); ### from tests/gpg_now_pw_hmac.pl
|
||||
our @gpg = (); ### from tests/gpg.pl
|
||||
@@ -733,6 +735,7 @@ my @tests = (
|
||||
@rijndael_hmac,
|
||||
@rijndael_hmac_fuzzing,
|
||||
@fault_injection,
|
||||
@afl_fuzzing,
|
||||
@os_compatibility,
|
||||
@perl_FKO_module,
|
||||
@python_fko,
|
||||
|
||||
13
test/tests/afl_fuzzing.pl
Normal file
13
test/tests/afl_fuzzing.pl
Normal file
@@ -0,0 +1,13 @@
|
||||
@afl_fuzzing = (
|
||||
### run fwknopd with the -A arg for American Fuzzy Lop support regardless
|
||||
### of whether AFL support has been compiled in - if not, an error is
|
||||
### thrown and is therefore good for code coverage
|
||||
{
|
||||
'category' => 'AFL',
|
||||
'subcategory' => 'FUZZING',
|
||||
'detail' => 'pkt to stdin',
|
||||
'function' => \&generic_exec,
|
||||
'cmdline' => 'echo -n "1716411011200157:root:1397329899:2.0.1:1:127.0.0.2,tcp/22:AAAAA" | ' .
|
||||
"$lib_view_str $valgrind_str $fwknopdCmd $default_server_conf_args -A -f -v",
|
||||
},
|
||||
);
|
||||
Reference in New Issue
Block a user