diff options
87 files changed, 1639 insertions, 211 deletions
diff --git a/.gitmodules b/.gitmodules index 2823cad5..b51a2b2e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,12 @@ [submodule "submodules/github/jbalogh/python-irclib"] path = submodules/github/jbalogh/python-irclib url = https://github.com/jbalogh/python-irclib.git +[submodule "Reaktor/repos/gxfr"] + path = Reaktor/repos/gxfr + url = https://github.com/makefu/gxfr.git +[submodule "Reaktor/repos/dnsrecon"] + path = Reaktor/repos/dnsrecon + url = https://github.com/makefu/dnsrecon.git +[submodule "Reaktor/repos/whatweb"] + path = Reaktor/repos/whatweb + url = https://github.com/urbanadventurer/WhatWeb.git diff --git a/Monitoring/plugins/notify_irc b/Monitoring/plugins/notify_irc new file mode 100755 index 00000000..e1de0866 --- /dev/null +++ b/Monitoring/plugins/notify_irc @@ -0,0 +1,87 @@ +#! /usr/bin/env python +# +# Example program using irclib.py. +# +# This program is free without restrictions; do anything you like with +# it. +# +# Joel Rosdahl <joel@rosdahl.net> + +import irclib +import sys +#irclib.DEBUG= True +class IRCCat(irclib.SimpleIRCClient): + def __init__(self, target,msg=""): + irclib.SimpleIRCClient.__init__(self) + self.target = target + self.msg = msg + + def on_welcome(self, connection, event): + if irclib.is_channel(self.target): + connection.join(self.target) + else: + self.send_it() + + def on_join(self, connection, event): + self.send_it() + + def on_disconnect(self, connection, event): + sys.exit(0) + + def send_it(self): + if self.msg: + print "writing given argv privmsg",self.msg + self.connection.privmsg(self.target, self.msg) + else: + print "writing stdin privmsg:" + while 1: + line = sys.stdin.readline() + if not line: + break + print line + self.connection.privmsg(self.target, line) + self.connection.quit("Using irclib.py") +def findGreatNick(prefix='shinken'): + import random + import re + dic="/usr/share/dict/danish" + found=False + while not found: + w = random.choice(list(open(dic))) + found = re.match(r"^[a-zA-Z_-]+$",w) + return prefix +"|"+w.strip() + +def main(): + if len(sys.argv) < 3: + print "Usage: notify_irc <server[:port]> <target> [message]" + print "\ntarget is a nickname or a channel." + sys.exit(1) + + s = sys.argv[1].split(":", 1) + server = s[0] + if len(s) == 2: + try: + port = int(s[1]) + except ValueError: + print "Error: Erroneous port." + sys.exit(1) + else: + port = 6667 + import random + nickname = findGreatNick() + print nickname + target = sys.argv[2] + msg = "" + if len(sys.argv) == 4: + msg = sys.argv[3] + c = IRCCat(target,msg) + try: + print "trying to connect to ",server,port,nickname + c.connect(server, port, nickname ) + except irclib.ServerConnectionError, x: + print x + sys.exit(1) + c.start() + +if __name__ == "__main__": + main() diff --git a/Reaktor/IRC/asybot.py b/Reaktor/IRC/asybot.py index 657cee40..df758ed6 100755 --- a/Reaktor/IRC/asybot.py +++ b/Reaktor/IRC/asybot.py @@ -9,12 +9,14 @@ def is_executable(x): from asynchat import async_chat as asychat from asyncore import loop -from socket import AF_INET, SOCK_STREAM +from socket import AF_INET, SOCK_STREAM,gethostname from signal import SIGALRM, signal, alarm from datetime import datetime as date, timedelta +import shlex +from time import sleep from sys import exit from re import split, search - +from textwrap import TextWrapper import logging,logging.handlers log = logging.getLogger('asybot') hdlr = logging.handlers.SysLogHandler(facility=logging.handlers.SysLogHandler.LOG_DAEMON) @@ -37,6 +39,7 @@ class asybot(asychat): self.set_terminator('\r\n') self.create_socket(AF_INET, SOCK_STREAM) self.connect((self.server, self.port)) + self.wrapper = TextWrapper(subsequent_indent=" ",width=400) # When we don't receive data for alarm_timeout seconds then issue a # PING every hammer_interval seconds until kill_timeout seconds have @@ -105,8 +108,10 @@ class asybot(asychat): def on_privmsg(self, prefix, command, params, rest): def PRIVMSG(text): - msg = 'PRIVMSG %s :%s' % (','.join(params), text) - self.push(msg) + for line in self.wrapper.wrap(text): + msg = 'PRIVMSG %s :%s' % (','.join(params), line) + self.push(msg) + sleep(1) def ME(text): PRIVMSG('ACTION ' + text + '') @@ -125,7 +130,7 @@ class asybot(asychat): from os.path import realpath, dirname, join from subprocess import Popen as popen, PIPE - + from time import time Reaktor_dir = dirname(realpath(dirname(__file__))) public_commands = join(Reaktor_dir, 'public_commands') command = join(public_commands, _command) @@ -133,29 +138,28 @@ class asybot(asychat): if is_executable(command): env = {} + args = [] + start = time() if _argument != None: env['argument'] = _argument - + args = shlex.split(_argument) try: - p = popen([command], stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env) + p = popen([command] + args,bufsize=1, stdout=PIPE, stderr=PIPE, env=env) except OSError, error: ME('brain damaged') log.error('OSError@%s: %s' % (command, error)) return - - stdout, stderr = [ x[:len(x)-1] for x in - [ x.split('\n') for x in p.communicate()]] - code = p.returncode pid = p.pid + for line in iter(p.stdout.readline,""): + PRIVMSG(line) + log.debug('%s stdout: %s' % (pid, line)) + p.wait() + elapsed = time() - start + code = p.returncode + log.info('command: %s -> %s in %d seconds' % (command, code,elapsed)) + [log.debug('%s stderr: %s' % (pid, x)) for x in p.stderr.readlines()] - log.info('command: %s -> %s' % (command, code)) - [log.debug('%s stdout: %s' % (pid, x)) for x in stdout] - [log.debug('%s stderr: %s' % (pid, x)) for x in stderr] - - if code == 0: - [PRIVMSG(x) for x in stdout] - [PRIVMSG(x) for x in stderr] - else: + if code != 0: ME('mimimi') else: @@ -181,8 +185,12 @@ if __name__ == "__main__": lol = logging.DEBUG if env.get('debug',False) else logging.INFO logging.basicConfig(level=lol) - name = getconf1('Name', '/etc/tinc/retiolum/tinc.conf') - hostname = '%s.retiolum' % name + try: + name = getconf1('Name', '/etc/tinc/retiolum/tinc.conf') + hostname = '%s.retiolum' % name + except: + name = gethostname() + hostname = name nick = str(env.get('nick', name)) host = str(env.get('host', 'supernode')) port = int(env.get('port', 6667)) diff --git a/Reaktor/IRC/index b/Reaktor/IRC/index index 24982c76..50022ec9 100755 --- a/Reaktor/IRC/index +++ b/Reaktor/IRC/index @@ -3,5 +3,4 @@ set -xeuf # cd //Reaktor cd $(dirname $(readlink -f $0))/.. - -exec python IRC/asybot.py "$@" +host=irc.freenode.net target='#krebsco' python IRC/asybot.py "$@" diff --git a/Reaktor/Makefile b/Reaktor/Makefile new file mode 100644 index 00000000..2241dba6 --- /dev/null +++ b/Reaktor/Makefile @@ -0,0 +1,23 @@ +submodules = gxfr dnsrecon bxfr whatweb +security_modules = subdomains revip whatweb + +all: init all-mods + +init: init-submodules $(submodules) +init-submodules: + cd ..;git submodule init; git submodule update +$(submodules): + cd repos/$@ ; git checkout master;git pull + +all-mods: $(addprefix public_commands/,$(security_modules)) +public_commands/%:commands/% + ln -s ../$< $@ + +debian-autostart: + useradd reaktor ||: + cp startup/init.d/reaktor-debian /etc/init.d/reaktor + cp startup/conf.d/reaktor /etc/default/ + update-rc.d reaktor defaults +supervisor-autostart: + useradd reaktor ||: + cp startup/supervisor/Reaktor.conf /etc/supervisor/conf.d/ diff --git a/Reaktor/commands/revip b/Reaktor/commands/revip new file mode 120000 index 00000000..e2c3b7ab --- /dev/null +++ b/Reaktor/commands/revip @@ -0,0 +1 @@ +../repos/revip/revip
\ No newline at end of file diff --git a/Reaktor/commands/subdomains b/Reaktor/commands/subdomains new file mode 120000 index 00000000..0489555f --- /dev/null +++ b/Reaktor/commands/subdomains @@ -0,0 +1 @@ +../repos/consolidate_dns/index
\ No newline at end of file diff --git a/Reaktor/commands/whatweb b/Reaktor/commands/whatweb new file mode 100755 index 00000000..84130d5c --- /dev/null +++ b/Reaktor/commands/whatweb @@ -0,0 +1,7 @@ +#!/bin/sh +#wrapper for WhatWeb +here=$(dirname `readlink -f $0`) +whatweb_bin="$here/../repos/whatweb/whatweb" +[ -e "$whatweb_bin" ] || ( echo "!! Whatweb app does not exist" && exit 1 ) +[ "balls$1" = "balls" ] && ( echo "!! no host given" && exit 1) +exec $whatweb_bin -a 3 "$1" diff --git a/Reaktor/repos/bxfr/bxfr.py b/Reaktor/repos/bxfr/bxfr.py new file mode 100644 index 00000000..8e6bd101 --- /dev/null +++ b/Reaktor/repos/bxfr/bxfr.py @@ -0,0 +1,238 @@ +#!/usr/bin/python -tt + +# gxfr replicates dns zone transfers by enumerating subdomains using advanced search engine queries and conducting dns lookups. +# By Tim Tomes (LaNMaSteR53) +# Available for download at http://LaNMaSteR53.com or http://code.google.com/p/gxfr/ + +import sys, os.path, urllib, urllib2, re, time, socket, random, socket + + +def help(): + print """ Syntax: ./gxfr.py domain [options] + + -h, --help this screen + -v enable verbose mode + -t [num of seconds] set number of seconds to wait between queries (default=15) + -q [max num of queries] restrict to maximum number of queries (default=0, indefinite) + --dns-lookup enable dns lookups of all subdomains + --proxy [file|ip:port|-] use a proxy or list of open proxies to send queries (@random w/list) + - [file] must consist of 1 or more ip:port pairs + - replace filename with '-' (dash) to accept stdin + --user-agent ['string'] set custom user-agent string + --timeout [seconds] set socket timeout (default=system default) + --csv [file] + + Examples: + $ ./gxfr.py foxnews.com --dns-lookup -v + $ ./gxfr.py foxnews.com --dns-lookup --proxy open_proxies.txt --timeout 10 + $ ./gxfr.py foxnews.com --dns-lookup -t 5 -q 5 -v --proxy 127.0.0.1:8080 + $ curl http://rmccurdy.com/scripts/proxy/good.txt | ./gxfr.py website.com -v -t 3 --proxy - + """ + sys.exit(2) + +if len(sys.argv) < 2: + help() + +if '-h' in sys.argv or '--help' in sys.argv: + help() + +# declare vars and process arguments +#http://www.bing.com/search?q=site%3agoogle.de&qs=n&filt=all&pq=site%3agoogle.d&sc=8-5&sp=-1&sk=&first=1&FORM=PORE +query_cnt = 0 +csvname = False +domain = sys.argv[1] +sys.argv = sys.argv[2:] +lookup = False +encrypt = True +base_url = 'http://www.bing.com' +base_uri = '/search?qs=n&form=QBRE&sc=0-0&sp=-1&sk=' +base_query = 'site:' + domain +pattern = '//([\.\w-]*)\.%s.+?' % (domain) +proxy = False +user_agent = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; FDM; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 1.1.4322)' +verbose = False +secs = 15 +max_queries = 10 # default = 10 queries +# process command line arguments +if len(sys.argv) > 0: + if '--dns-lookup' in sys.argv: + lookup = True + if '--csv' in sys.argv: + csvname = sys.argv[sys.argv.index('--csv') + 1] + if '--proxy' in sys.argv: + proxy = True + filename = sys.argv[sys.argv.index('--proxy') + 1] + if filename == '-': + proxies = sys.stdin.read().split() + elif os.path.exists(filename): + content = open(filename).read() + proxies = re.findall('\d+\.\d+\.\d+\.\d+:\d+', content) + elif re.match(r'^\d+\.\d+\.\d+\.\d+:\d+$', filename): + proxies = [filename] + else: + help() + if '--timeout' in sys.argv: + timeout = int(sys.argv[sys.argv.index('--timeout') + 1]) + socket.setdefaulttimeout(timeout) + if '--user-agent' in sys.argv: + user_agent = sys.argv[sys.argv.index('--user-agent') + 1] + if '-v' in sys.argv: + verbose = True + if '-t' in sys.argv: + secs = int(sys.argv[sys.argv.index('-t') + 1]) + if '-q' in sys.argv: + max_queries = int(sys.argv[sys.argv.index('-q') + 1]) +subs = [] +new = True +page = 0 + +# --begin-- +print '[-] domain:', domain +print '[-] user-agent:', user_agent +# execute search engine queries and scrape results storing subdomains in a list +print '[-] querying search engine, please wait...' +# loop until no new subdomains are found +while new == True: + try: + query = '' + # build query based on results of previous results + for sub in subs: + query += ' -site:%s.%s' % (sub, domain) + full_query = base_query + query + start_param = '&first=%s' % (str(page*10)) + query_param = '&q=%s&pq=%s' % (urllib.quote_plus(full_query),urllib.quote_plus(full_query)) + if len(base_uri) + len(query_param) + len(start_param) < 2048: + last_query_param = query_param + params = query_param + start_param + else: + params = last_query_param[:2047-len(start_param)-len(base_uri)] + start_param + full_url = base_url + base_uri + params + # note: query character limit is passive in mobile, but seems to be ~794 + # note: query character limit seems to be 852 for desktop queries + # note: typical URI max length is 2048 (starts after top level domain) + if verbose: print '[+] using query: %s...' % (full_url) + # build web request and submit query + request = urllib2.Request(full_url) + # spoof user-agent string + request.add_header('User-Agent', user_agent) + # if proxy is enabled, use the correct handler + if proxy == True: + # validate proxies at runtime + while True: + try: + # select a proxy from list at random + num = random.randint(0,len(proxies)-1) + host = proxies[num] + opener = urllib2.build_opener(urllib2.ProxyHandler({'http': host})) + if verbose: print '[+] sending query to', host + # send query to proxy server + result = opener.open(request).read() + # exit while loop if successful + break + except Exception as inst: + print '[!] %s failed: %s' % (host, inst) + if len(proxies) == 1: + # exit of no proxy servers from list are valid + print '[-] valid proxy server not found' + sys.exit(2) + else: + # remove host from list of proxies and try again + del proxies[num] + else: + opener = urllib2.build_opener(urllib2.HTTPHandler(), urllib2.HTTPSHandler()) + # send query to search engine + try: + result = opener.open(request).read() + except Exception as inst: + print '[!] {0}'.format(inst) + if str(inst).index('503') != -1: print '[!] possible shun: use --proxy or find something else to do for 24 hours :)' + sys.exit(2) + if not verbose: sys.stdout.write('.'); sys.stdout.flush() + #if not verbose: sys.stdout.write('\n'); sys.stdout.flush() + # iterate query count + query_cnt += 1 + sites = re.findall(pattern, result) + # |