Esempio n. 1
0
def main():
    parser = OptionParser(
        usage=
        '%prog url1 [url2 [url3 ... ]]\r\nexample: %prog http://www.victim.org/'
    )
    parser.add_option(
        '-v',
        '--verbose',
        action='count',
        dest='verbose',
        default=0,
        help='Enable verbosity, multiple -v options increase verbosity')
    parser.add_option(
        '-a',
        '--findall',
        action='store_true',
        dest='findall',
        default=False,
        help=
        'Find all WAFs which match the signatures, do not stop testing on the first one'
    )
    parser.add_option('-r',
                      '--noredirect',
                      action='store_false',
                      dest='followredirect',
                      default=True,
                      help='Do not follow redirections given by 3xx responses')
    parser.add_option('-t',
                      '--test',
                      dest='test',
                      help='Test for one specific WAF')
    parser.add_option(
        '-o',
        '--output',
        dest='output',
        help=
        'Write output to csv, json or text file depending on file extension. For stdout, specify - as filename.',
        default=None)
    parser.add_option(
        '-i',
        '--input-file',
        dest='input',
        help=
        'Read targets from a file. Input format can be csv, json or text. For csv and json, a `url` column name or element is required.',
        default=None)
    parser.add_option('-l',
                      '--list',
                      dest='list',
                      action='store_true',
                      default=False,
                      help='List all WAFs that WAFW00F is able to detect')
    parser.add_option(
        '-p',
        '--proxy',
        dest='proxy',
        default=None,
        help=
        'Use an HTTP proxy to perform requests, examples: http://hostname:8080, socks5://hostname:1080, http://user:pass@hostname:8080'
    )
    parser.add_option(
        '--version',
        '-V',
        dest='version',
        action='store_true',
        default=False,
        help='Print out the current version of WafW00f and exit.')
    parser.add_option(
        '--headers',
        '-H',
        dest='headers',
        action='store',
        default=None,
        help=
        'Pass custom headers via a text file to overwrite the default header set.'
    )
    options, args = parser.parse_args()
    logging.basicConfig(level=calclogginglevel(options.verbose))
    log = logging.getLogger('wafw00f')
    if options.output == '-':
        disableStdOut()
    print(randomArt())
    if options.list:
        print('[+] Can test for these WAFs:\r\n')
        attacker = WAFW00F(None)
        try:
            m = [i.replace(')', '').split(' (') for i in wafdetectionsprio]
            print(R + '  WAF Name' + '\t' * 3 + 'Manufacturer\n  ' + '-' * 8 +
                  '\t' * 3 + '-' * 12 + E + '\n')
            for i in m:
                tab, n = '\t', 5
                for j in range(-2, 23, 8):
                    if len(i[0]) < j:
                        print('  ' + Y + i[0] + E + tab * n + W + i[1] + E)
                        break
                    else:
                        n = n - 1
        except Exception:
            return
    if options.version:
        print('[+] The version of WAFW00F you have is %sv%s%s' %
              (B, __version__, E))
        print('[+] WAFW00F is provided under the %s%s%s license.' %
              (C, __license__, E))
        return
    extraheaders = {}
    if options.headers:
        log.info('Getting extra headers from %s' % options.headers)
        extraheaders = getheaders(options.headers)
        if extraheaders is None:
            parser.error(
                'Please provide a headers file with colon delimited header names and values'
            )
    if len(args) == 0 and not options.input:
        parser.error('No test target specified.')
    #check if input file is present
    if options.input:
        log.debug("Loading file '%s'" % options.input)
        try:
            if options.input.endswith('.json'):
                with open(options.input) as f:
                    try:
                        urls = json.loads(f.read())
                    except json.decoder.JSONDecodeError:
                        log.critical(
                            "JSON file %s did not contain well-formed JSON",
                            options.input)
                        sys.exit(1)
                log.info("Found: %s urls to check." % (len(urls)))
                targets = [item['url'] for item in urls]
            elif options.input.endswith('.csv'):
                columns = defaultdict(list)
                with open(options.input) as f:
                    reader = csv.DictReader(f)
                    for row in reader:
                        for (k, v) in row.items():
                            columns[k].append(v)
                targets = columns['url']
            else:
                with open(options.input) as f:
                    targets = [x for x in f.read().splitlines()]
        except FileNotFoundError:
            log.error('File %s could not be read. No targets loaded.',
                      options.input)
            sys.exit(1)
    else:
        targets = args
    results = []
    for target in targets:
        if not target.startswith('http'):
            log.info(
                'The url %s should start with http:// or https:// .. fixing (might make this unusable)'
                % target)
            target = 'http://' + target
        print('[*] Checking %s' % target)
        pret = urlParser(target)
        if pret is None:
            log.critical('The url %s is not well formed' % target)
            sys.exit(1)
        (hostname, port, path, _, _) = pret
        log.info('starting wafw00f on %s' % target)
        proxies = dict()
        if options.proxy:
            proxies = {
                "http": options.proxy,
                "https": options.proxy,
            }
        attacker = WAFW00F(target,
                           port=port,
                           debuglevel=options.verbose,
                           path=path,
                           followredirect=options.followredirect,
                           extraheaders=extraheaders,
                           proxies=proxies)
        global rq
        rq = attacker.normalRequest()
        if rq is None:
            log.error('Site %s appears to be down' % hostname)
            continue
        if options.test:
            if options.test in attacker.wafdetections:
                waf = attacker.wafdetections[options.test](attacker)
                if waf:
                    print('[+] The site %s%s%s is behind %s%s%s WAF.' %
                          (B, target, E, C, options.test, E))
                else:
                    print('[-] WAF %s was not detected on %s' %
                          (options.test, target))
            else:
                print(
                    '[-] WAF %s was not found in our list\r\nUse the --list option to see what is available'
                    % options.test)
            return
        waf = attacker.identwaf(options.findall)
        log.info('Identified WAF: %s' % waf)
        if len(waf) > 0:
            for i in waf:
                results.append(buildResultRecord(target, i))
            print('[+] The site %s%s%s is behind %s%s%s WAF.' %
                  (B, target, E, C, (E + ' and/or ' + C).join(waf), E))
        if (options.findall) or len(waf) == 0:
            print('[+] Generic Detection results:')
            if attacker.genericdetect():
                log.info('Generic Detection: %s' %
                         attacker.knowledge['generic']['reason'])
                print(
                    '[*] The site %s seems to be behind a WAF or some sort of security solution'
                    % target)
                print('[~] Reason: %s' %
                      attacker.knowledge['generic']['reason'])
                results.append(buildResultRecord(target, 'generic'))
            else:
                print('[-] No WAF detected by the generic detection')
                results.append(buildResultRecord(target, None))
        print('[~] Number of requests: %s' % attacker.requestnumber)
    #print table of results
    if len(results) > 0:
        log.info("Found: %s matches." % (len(results)))
    if options.output:
        if options.output == '-':
            enableStdOut()
            print(os.linesep.join(getTextResults(results)))
        elif options.output.endswith('.json'):
            log.debug("Exporting data in json format to file: %s" %
                      (options.output))
            with open(options.output, 'w') as outfile:
                json.dump(results, outfile, indent=2)
        elif options.output.endswith('.csv'):
            log.debug("Exporting data in csv format to file: %s" %
                      (options.output))
            with open(options.output, 'w') as outfile:
                csvwriter = csv.writer(outfile,
                                       delimiter=',',
                                       quotechar='"',
                                       quoting=csv.QUOTE_MINIMAL)
                count = 0
                for result in results:
                    if count == 0:
                        header = result.keys()
                        csvwriter.writerow(header)
                        count += 1
                    csvwriter.writerow(result.values())
        else:
            log.debug("Exporting data in text format to file: %s" %
                      (options.output))
            with open(options.output, 'w') as outfile:
                outfile.write(os.linesep.join(getTextResults(results)))
Esempio n. 2
0
def main():
    print(randomArt())
    parser = OptionParser(
        usage=
        '%prog url1 [url2 [url3 ... ]]\r\nexample: %prog http://www.victim.org/'
    )
    parser.add_option(
        '-v',
        '--verbose',
        action='count',
        dest='verbose',
        default=0,
        help='Enable verbosity, multiple -v options increase verbosity')
    parser.add_option(
        '-a',
        '--findall',
        action='store_true',
        dest='findall',
        default=False,
        help=
        'Find all WAFs which match the signatures, do not stop testing on the first one'
    )
    parser.add_option('-r',
                      '--noredirect',
                      action='store_false',
                      dest='followredirect',
                      default=True,
                      help='Do not follow redirections given by 3xx responses')
    parser.add_option('-t',
                      '--test',
                      dest='test',
                      help='Test for one specific WAF')
    parser.add_option('-l',
                      '--list',
                      dest='list',
                      action='store_true',
                      default=False,
                      help='List all WAFs that WAFW00F is able to detect')
    parser.add_option(
        '-p',
        '--proxy',
        dest='proxy',
        default=None,
        help=
        'Use an HTTP proxy to perform requests, examples: http://hostname:8080, socks5://hostname:1080, http://user:pass@hostname:8080'
    )
    parser.add_option(
        '--version',
        '-V',
        dest='version',
        action='store_true',
        default=False,
        help='Print out the current version of WafW00f and exit.')
    parser.add_option(
        '--headers',
        '-H',
        dest='headers',
        action='store',
        default=None,
        help=
        'Pass custom headers via a text file to overwrite the default header set.'
    )
    options, args = parser.parse_args()
    logging.basicConfig(level=calclogginglevel(options.verbose))
    log = logging.getLogger('wafw00f')
    if options.list:
        print('[+] Can test for these WAFs:\r\n')
        attacker = WAFW00F(None)
        try:
            m = [i.replace(')', '').split(' (') for i in wafdetectionsprio]
            print(R + '  WAF Name' + '\t' * 3 + 'Manufacturer\n  ' + '-' * 8 +
                  '\t' * 3 + '-' * 12 + E + '\n')
            for i in m:
                tab, n = '\t', 5
                for j in range(-2, 23, 8):
                    if len(i[0]) < j:
                        print('  ' + Y + i[0] + E + tab * n + W + i[1] + E)
                        break
                    else:
                        n = n - 1
        except Exception:
            return
    if options.version:
        print('[+] The version of WAFW00F you have is %sv%s%s' %
              (B, __version__, E))
        print('[+] WAFW00F is provided under the %s%s%s license.' %
              (C, __license__, E))
        return
    extraheaders = {}
    if options.headers:
        log.info('Getting extra headers from %s' % options.headers)
        extraheaders = getheaders(options.headers)
        if extraheaders is None:
            parser.error(
                'Please provide a headers file with colon delimited header names and values'
            )
    if len(args) == 0:
        parser.error('No test target specified.')
    targets = args
    for target in targets:
        if not target.startswith('http'):
            log.info(
                'The url %s should start with http:// or https:// .. fixing (might make this unusable)'
                % target)
            target = 'http://' + target
        print('[*] Checking %s' % target)
        pret = urlParser(target)
        if pret is None:
            log.critical('The url %s is not well formed' % target)
            sys.exit(1)
        (hostname, port, path, _, _) = pret
        log.info('starting wafw00f on %s' % target)
        proxies = dict()
        if options.proxy:
            proxies = {
                "http": options.proxy,
                "https": options.proxy,
            }
        attacker = WAFW00F(target,
                           port=port,
                           debuglevel=options.verbose,
                           path=path,
                           followredirect=options.followredirect,
                           extraheaders=extraheaders,
                           proxies=proxies)
        global rq
        rq = attacker.normalRequest()
        if rq is None:
            log.error('Site %s appears to be down' % hostname)
            continue
        if options.test:
            if options.test in attacker.wafdetections:
                waf = attacker.wafdetections[options.test](attacker)
                if waf:
                    print('[+] The site %s%s%s is behind %s%s%s WAF.' %
                          (B, target, E, C, options.test, E))
                else:
                    print('[-] WAF %s was not detected on %s' %
                          (options.test, target))
            else:
                print(
                    'WAF %s was not found in our list\r\nUse the --list option to see what is available'
                    % options.test)
            return
        waf = attacker.identwaf(options.findall)
        log.info('Identified WAF: %s' % waf)
        if len(waf) > 0:
            print('[+] The site %s%s%s is behind %s%s%s WAF.' %
                  (B, target, E, C, (E + ' and/or ' + C).join(waf), E))
        if (options.findall) or len(waf) == 0:
            print('[+] Generic Detection results:')
            if attacker.genericdetect():
                log.info('Generic Detection: %s' %
                         attacker.knowledge['generic']['reason'])
                print(
                    '[*] The site %s seems to be behind a WAF or some sort of security solution'
                    % target)
                print('[~] Reason: %s' %
                      attacker.knowledge['generic']['reason'])
            else:
                print('[-] No WAF detected by the generic detection')
        print('[~] Number of requests: %s' % attacker.requestnumber)