def execute(self, name, func): ''' 执行插件,捕获异常 ''' try: func.func_globals.update(log=self.logger.get(name)) func(self.target) except (PluginWarning, TargetWarning), e: cprint('[%s] %s' % (name, e), '*')
def output(target): ''' name: WebServer Parser priority: 8 depends: request ''' if not getattr(target, 'data', None): return server = target.data['headers'].get('server', '') if 'nginx' in server: cprint('testing nginx parsing vulnerability...') path = urlsrc(target.data['content'], target.host) url = target.geturl(path) log.debug('URL: %s' % url) for url in itertools.product([url], ['/.php', '/1.php', '%00.php']): req = urlopen(''.join(url)) if req and not req.history and \ 'text/html' in req.headers['content-type']: cprint('Nginx Parser Vulnerability', '+') break elif 'iis' in server: pass elif 'apache' in server: pass
def output(target): ''' name: CDN Checker priority: 2 depends: request,dns version: 0.2 ''' target.cdn = False if target.redirect: return # 检测CNAME别名 if getattr(target, 'zone', None): cname = map(itemgetter(1), target.zone.get('CNAME', [])) log.debug('CNAME: %s' % ', '.join(cname)) target.cdn = matched(cname, *pattern['cname']) # 检测HTTP头 if not target.cdn and getattr(target, 'data', None): data = str(target.data['headers']).lower() target.cdn = matched(data, *pattern['headers']) # 检测第三方API内容 if not target.cdn and getattr(target, 'raw_build', None): target.cdn = 'CDN Providers' in target.raw_build if target.cdn: cprint('%s has enable CDN' % target.ip, '+')
def output(target): ''' name: Script Guess priority: 8 depends: request version: 0.2 ''' if not getattr(target, 'data', None): return # 检测URL后缀 url = url_extract(target.data['content'], target.host) target.script = check_match(url, 'ext', unicode.endswith) log.debug('URL: %s' % url) if not target.script: # COOKIES target.script = check_match(target.data['cookies'], 'cookie') # 检测buildwith if not target.script: raw_build = getattr(target, 'raw_build', '') match = re.search('framework\/([^"]+)"><', raw_build) if match: log.debug('Match: %s' % match.group(1)) target.script = check_match(match.group(1), 'build') # 检查x-powered-by if not target.script: powered = target.data['headers'].get('x-powered-by', '') log.debug('Powered: %s' % powered) target.script = check_match(powered, 'powered') if target.script: cprint(target.script, '+')
def output(target): ''' name: HTTP Request priority: 1 version: 0.2 ''' req = urlopen(target.geturl()) log.debug("encoding: " + req.encoding) if req is None: raise PluginWarning('target %s connection refused' % target.host) target.data = { 'headers': dict(req.headers.lower_items()), 'cookies': req.cookies.get_dict(), 'content': req.text, 'robots' : urlopen(target.geturl('robots.txt'), attr=('text', '')) } log.debug('Headers: %s' % str(target.data['headers'])) log.debug('Cookies: %s' % str(target.data['cookies'])) if 'server' in req.headers: cprint('Server: %s' % req.headers['server'] , '+') target.raw_build = urlopen('http://builtwith.com/%s' % target.host, attr=('text', ''))
def output(target): ''' name: IP Valider depends: sameip,reverse,domains ''' def ratio_key(x): ''' 根据相似度排序 ''' return SequenceMatcher(None, x[0], target.ip).ratio() data = {1: getattr(target, 'domains', set())} # raw_sameip差集 data[2] = getattr(target, 'raw_sameip', set()) - data[1] data[2].update(getattr(target, 'email_domains', set())) ret = option_input('select extract data subdomain/domains? [1/2] ', [1, 2], '3') domains = set() # 合并数据,删除自身域名 domains.update(*[data[r] for r in ret]) domains.discard(target.tld) pool = multiprocessing.Pool(5) iplist = pool.map(valid_ip, domains) target.sameip = set() # 根据IP相似度排序 iters = filter(itemgetter(0), zip(iplist, domains)) for ip, host in sorted(iters, key=ratio_key, reverse=True): if target.ip == ip: target.sameip.add(host) cprint('%s %s' % (host, ip), '+')
def producer(task, queue): ''' 生产函数 ''' req = urlopen('http://{}:{}'.format(*task)) if req is None: return # 解析请求内容 server, title, banner = parse(req) cprint('%s %s %s [%s]' % (req.url, server, title, banner)) for uri in paths: queue.put((req.url, uri))
def worker(queue): while True: task = queue.get() if task is None: break req = urlopen(urlparse.urljoin(*task)) # 状态码200且不重定向 if req and not req.history: cprint('%s status %d' % (req.url, req.status_code), '+')
def pentest(self): for name, func in self.queue.pop('1', []): self.execute(name, func) if not self.queue.values(): return cprint('testing all plugins from target', '*', True) # {'2' : [...], '3': [...]} items = sorted(self.queue.items()) for name, func in chain(*[vals for _, vals in items]): cprint('testing plugin %s' % name) self.execute(name, func)
def output(target): ''' name: WhatCMS Guess depends: request version: 0.3 ''' if not getattr(target, 'data', None): return if option_input() != 'y': return cms = [] patterns = ['md5', 'type', 'status'] queue = Queue.PriorityQueue() files = glob.glob(os.path.join('plugins/whatcms', '*.json')) for patt in map(json_dict, files): if not patt: continue # 失败时跳过 count = counter(target.data, patt['keyword']) # 统计匹配次数 if count is True: target.cms = patt['name'] break elif count > 0: cms.append(patt['name']) for banner in patt['path']: url = target.geturl(banner.pop('url')) # 计算优先级,算法:patterns顺序 + 匹配次数,越低优先级越高 priority = patterns.index(banner.keys()[0]) + (2 - count) queue.put((priority, patt['name'], url, banner)) if not getattr(target, 'cms', None): # 采集404结果 rand_uuid = str(uuid.uuid4()) status_file = urlopen(target.geturl(rand_uuid + '.js'), attr=('headers', {})) status_dir = urlopen(target.geturl(rand_uuid + '/'), attr=('headers', {})) # 将404的页面长度存入urlcheck中 urlcheck.status_404 = (status_file.get('content-length', 0), status_file.get('content-length', 0)) pool = ThreadPool(processes=3) async_result = pool.apply_async(urlcheck, (queue, )) val = async_result.get() # URL检测失败则尝试从候选列表中获取 if val: target.cms = val elif cms: target.cms = ','.join(cms) if getattr(target, 'cms', None): cprint(target.cms, '+')
def producer(task, queue): req = urlopen('http://{}:{}'.format(*task)) if req is None: return match = re.search( '<[Tt][Ii][Tt][Ll][Ee][^>]*>([^<]*)</[Tt][Ii][Tt][Ll][Ee]>', req.text) title = (match.group(1) if match else '').strip() server = req.headers.get('server', '') banner = 'unknown' if 'servlet' in req.headers.get('x-powered-by', ''): banner = 'servlet' cprint('%s %s %s [%s]' % (req.url, server, title, banner)) for uri in uris: queue.put((req.url, uri))
def output(target): ''' name: Hosting History priority: 8 depends: cdn version: 0.1 ''' if not getattr(target, 'cdn', False): return ipdate = set() for url, regex, fmt in apis_url: content = urlopen(url % target.host, attr=('text', '')) for m in re.finditer(regex, content): date = datetime.strptime(m.group('date'), fmt) ipdate.add((m.group('ip'), date)) for ip, date in sorted(ipdate, key=itemgetter(1)): cprint('%s %s' % (ip, date.strftime('%Y-%m-%d')), '+')
def main(args): cprint('starting at %s\n' % runtime(), '*') try: cprint('testing if the target URL is stable', '*') pe = ProbeEngine(args) # output target ip ip, host = pe.target.ip, pe.target.host cprint('%s (%s)' % (ip, host) if ip != host else ip, '+') pe.pentest() except (TargetError, PluginError), e: cprint('%s' % e, '-')
def output(target): ''' name: AXFR Checker priority: 8 depends: dns version: 0.3 ''' if not getattr(target, 'zone', None): return target.axfr = False # 从zone中提取NS记录并过滤 ns = map(itemgetter(0), target.zone.get('NS', [])) ns = list(filtered(ns, *pattern)) log.debug('NS: %s' % ', '.join(ns)) data = parsedns(target.tld, qtype="AXFR", server=ns, protocol='tcp') if not data: return target.axfr = True target.zone.update(data) cprint('AXFR!!!', '+')
def output(target): ''' name: Nmap Ports Scaner depends: cdn priority: 7 version: 0.1 ''' if getattr(target, 'cdn', True): return nm = nmap.PortScanner() # nm.scan(target.ip, ','.join(map(str, ports)), arguments='-T4 -A') nm.scan(target.ip, ','.join(map(str, ports))) if 'tcp' not in nm[target.ip]: return target.ports = [] # target.os = nm[target.ip]['osmatch'][0]['name'] for key, val in nm[target.ip]['tcp'].items(): target.ports.append(key) target.ports.sort() # cprint('OS: %s' % target.os, '+') cprint('Ports: %s' % ', '.join(map(str, target.ports)), '+')
''' name: Whois priority: 1 version: 0.2 ''' try: resp = get_whois(target.tld) except WhoisException, e: raise PluginWarning(e) for val in resp['contacts'].values(): if val and 'email' in val: emails = [val['email'].lower()]; break else: if 'emails' in resp: emails = map(unicode.lower, resp['emails']) else: return log.debug('Email: %s' % ','.join(emails)) email = next(filtered(emails, *pattern), None) if not email: return expired = resp.get('expiration_date', (None,))[0] target.domain = (email, expired) output = 'Email: %s' % email if expired: output += ', Expired Day: %d' % (expired - datetime.now()).days cprint(output, '+')
parser.add_argument('-s', '--silent', action='store_true', help='silent execution, don\'t ask.') parser.add_argument('-r', '--redirect', action='store_true', help='redirect target hosts ip.') return parser.parse_args() def main(args): cprint('starting at %s\n' % runtime(), '*') try: cprint('testing if the target URL is stable', '*') pe = ProbeEngine(args) # output target ip ip, host = pe.target.ip, pe.target.host cprint('%s (%s)' % (ip, host) if ip != host else ip, '+') pe.pentest() except (TargetError, PluginError), e: cprint('%s' % e, '-') except KeyboardInterrupt: cprint('user quit', '-') finally: cprint('shutting down at %s' % runtime(), '*', True) if __name__ == "__main__": main(get_cmd_args())