From 1ae4f412a0618ba1a0384de9bf1739f54e3520f4 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sat, 17 Feb 2024 19:51:15 +0100 Subject: [PATCH] Add sanity check for size of scan --- src/main.c | 39 +++++++++++++++++------------- src/target-gen.c | 62 ++++++++++++++++++++++++++++++++++++++++-------- src/target.h | 2 ++ 3 files changed, 76 insertions(+), 27 deletions(-) diff --git a/src/main.c b/src/main.c index ef131cb..29bc05f 100644 --- a/src/main.c +++ b/src/main.c @@ -332,23 +332,28 @@ int main(int argc, char *argv[]) r = 0; } else { - // complain about missing args - const char* missing = NULL; - if(is_all_ff(source_mac, 6)) - missing = "--source-mac"; - else if(is_all_ff(router_mac, 6)) - missing = "--router-mac"; - else if(is_all_ff(source_addr, 16)) - missing = "--source-ip"; - else if(ip_type != IP_TYPE_ICMPV6 && !validate_ports(&ports)) - missing = "-p"; - else if(banners && ip_type == IP_TYPE_TCP && source_port == -1) - missing = "--source-port"; - - if(missing) { - printf("Option %s is required but was not given.\n", missing); - r = 1; - } else { + r = target_gen_sanity_check() < 0 ? 1 : 0; + + if (r == 0) { + const char* missing = NULL; + if(is_all_ff(source_mac, 6)) + missing = "--source-mac"; + else if(is_all_ff(router_mac, 6)) + missing = "--router-mac"; + else if(is_all_ff(source_addr, 16)) + missing = "--source-ip"; + else if(ip_type != IP_TYPE_ICMPV6 && !validate_ports(&ports)) + missing = "-p"; + else if(banners && ip_type == IP_TYPE_TCP && source_port == -1) + missing = "--source-port"; + + if(missing) { + printf("Option %s is required but was not given.\n", missing); + r = 1; + } + } + + if (r == 0) { scan_set_general(&ports, max_rate, show_closed, banners); scan_set_network(source_addr, source_port, ip_type); scan_set_output(outfile, outdef); diff --git a/src/target-gen.c b/src/target-gen.c index c62d6f6..3e5167d 100644 --- a/src/target-gen.c +++ b/src/target-gen.c @@ -19,6 +19,7 @@ static uint64_t rand64(); static int popcount(uint32_t x); static void fill_cache(void); static void next_addr(struct targetstate *t, uint8_t *dst); +static void count_total(const struct targetstate *t, uint64_t *total, bool *overflowed); static void progress_single(const struct targetstate *t, uint64_t *total, uint64_t *done); @@ -165,16 +166,7 @@ void target_gen_print_summary(int max_rate, int nports) for(int i = 0; i < targets_i; i++) { const struct targetstate *t = &targets[i]; - uint64_t one = 0, tmp = 0; - progress_single(t, &one, &tmp); - if (one == 0) { // all bits shifted out of the value - total_overflowed = true; - } else { - tmp = total; - total += one; - if (total < tmp) - total_overflowed = true; - } + count_total(t, &total, &total_overflowed); int maskbits = 0; for(int j = 0; j < 4; j++) @@ -239,6 +231,40 @@ void target_gen_print_summary(int max_rate, int nports) } } +int target_gen_sanity_check(void) +{ + uint64_t total = 0; + bool overflowed = false; + for(int i = 0; i < targets_i; i++) { + const struct targetstate *t = &targets[i]; + count_total(t, &total, &overflowed); + } + + const uint64_t limit = UINT64_C(1) << TARGET_SANITY_MAX_BITS; + if (overflowed || total >= limit) { + fprintf(stderr, "Error: You are trying to scan "); + if (overflowed) + fprintf(stderr, "more than 2^64"); + else + fprintf(stderr, "%" PRIu64, total); + fprintf(stderr, " addresses. Refusing.\n" + "\n" + "Even under ideal conditions this would take a tremendous amount of " + "time (check with --print-summary).\nYou were probably expecting to " + "scan an IPv6 subnet exhaustively just like you can with IPv4.\n" + "In practice common sizes like /64 would take more than tens of " + "thousands YEARS to enumerate.\nYou will need to rethink your approach. " + "Good advice on IPv6 scanning can be found on the internet.\n" + "\n" + "In case you were hoping to scan stochastically, note that fi6s " + "IP randomization is not suited for this.\nAs an alternative you can " + "let an external program generate IPs and use --stream-targets.\n" + ); + return -1; + } + return 0; +} + static void shuffle(void *_buf, int stride, int n) { char tmp[stride], *buf = (char*) _buf; @@ -354,6 +380,22 @@ static void next_addr(struct targetstate *t, uint8_t *dst) t->done = 1; } +static void count_total(const struct targetstate *t, uint64_t *total, bool *overflowed) +{ + uint64_t one = 0, tmp = 0; + progress_single(t, &one, &tmp); + // if this target is larger than 2^64 all bits will be shifted off the end + if (one == 0) { + *overflowed = true; + } else { + // add with overflow check + tmp = *total; + *total += one; + if (*total < tmp) + *overflowed = true; + } +} + static void progress_single(const struct targetstate *t, uint64_t *total, uint64_t *done) { uint64_t _total = 0, _done = 0; diff --git a/src/target.h b/src/target.h index 400877d..65cacfc 100644 --- a/src/target.h +++ b/src/target.h @@ -12,11 +12,13 @@ struct targetspec { int target_parse(const char *str, struct targetspec *dst); #define TARGET_RANDOMIZE_SIZE 8192 +#define TARGET_SANITY_MAX_BITS 48 #define TARGET_EVEN_SPREAD 1 // not sure why you would disable this, but you can int target_gen_init(void); void target_gen_set_randomized(int v); void target_gen_set_streaming(FILE *f); +int target_gen_sanity_check(void); void target_gen_fini(void); int target_gen_add(const struct targetspec *s);