def data(self, value): config = ConfigManager.instance() if self.uuid is None: self.uuid = str(uuid4()) self.byte_size = len(value) with open(config.file_uploads_dir + self.uuid, 'wb') as fp: fp.write(value.encode('base64'))
def __init__(self): self.config = ConfigManager.instance() self.dbsession = dbsession self.cache = pylibmc.Client([self.config.memcached], binary=True) self.epoch = None # Date/time of first snapshot self._load() self.event_manager = EventManager.instance()
def post(self, *args, **kwargs): ''' Update configuration Disabled fields will not be send in the POST, so check for blank values ''' try: config = ConfigManager.instance() config.game_name = self.get_argument('game_name', '') config.restrict_registration = self.get_argument('restrict_registration', '') == 'true' config.public_teams = self.get_argument('public_teams', '') == 'true' config.max_team_size = self.get_argument('max_team_size', '') config.max_password_length = self.get_argument('max_password_length', '') self.config_bots(config) reward = self.get_argument('bot_reward', '') if reward != '': config.bot_reward = reward config.use_black_market = self.get_argument('use_black_market', '') == 'true' upgrade_cost = self.get_argument('password_upgrade_cost', '') if upgrade_cost != '': config.password_upgrade_cost = upgrade_cost bribe_cost = self.get_argument('bribe_cost', '') if bribe_cost != '': config.bribe_cost = bribe_cost config.save() self.render('admin/configuration.html', errors=None, config=self.config) except Exception as error: logging.exception("Configuration update threw an exception") self.render('admin/configuration.html', errors=[str(error)], config=self.config)
def to_xml(self, parent): ''' Convert object to XML ''' box_elem = ET.SubElement(parent, "box") box_elem.set("gamelevel", str(self.game_level.number)) ET.SubElement(box_elem, "name").text = self.name ET.SubElement(box_elem, "operatingsystem").text = self._operating_system ET.SubElement(box_elem, "description").text = self._description ET.SubElement(box_elem, "difficulty").text = self._difficulty ET.SubElement(box_elem, "garbage").text = self.garbage flags_elem = ET.SubElement(box_elem, "flags") flags_elem.set("count", str(len(self.flags))) for flag in self.flags: flag.to_xml(flags_elem) hints_elem = ET.SubElement(box_elem, "hints") hints_elem.set("count", str(len(self.hints))) for hint in self.hints: hint.to_xml(hints_elem) ips_elem = ET.SubElement(box_elem, "ipaddresses") ips_elem.set("count", str(len(self.ips))) for ip in self.ips: ip.to_xml(ips_elem) config = ConfigManager.instance() with open(config.avatar_dir + self.avatar) as favatar: data = favatar.read() ET.SubElement(box_elem, "avatar").text = data.encode('base64')
def score_bots(): ''' Award money for botnets ''' logging.info("Scoring botnets, please wait ...") bot_manager = BotManager.instance() config = ConfigManager.instance() for team in Team.all(): bots = bot_manager.by_team(team.name) reward = 0 for bot in bots: try: reward += config.bot_reward bot.write_message({ 'opcode': 'status', 'message': 'Collected $%d reward' % config.bot_reward }) except: logging.info("Bot at %s failed to respond to score ping" % bot.remote_ip) if 0 < len(bots): logging.info("%s was awarded $%d for controlling %s bot(s)" % ( team.name, reward, len(bots), )) bot_manager.add_rewards(team.name, config.bot_reward) bot_manager.notify_monitors(team.name) team.money += reward dbsession.add(team) dbsession.flush() dbsession.commit()
class StaticFileHandler(DefaultStaticHandler): ''' Same as the normal Tornado StaticFileHandler with a couple overloaded methods. ''' session = None config = ConfigManager.instance() def set_default_headers(self): ''' We need to add the security headers here too, especially the X-Content-Type-Options header, since we whitelist file extenstions. this should prevent anyone from serving html/etc from the static handler ''' self.set_header("Server", "Microsoft-IIS/7.5") self.add_header("X-AspNetMvc-Version", "3.0") self.add_header("X-AspNet-Version", "4.0.30319") self.add_header("X-Powered-By", "ASP.NET") self.add_header("X-Frame-Options", "DENY") self.add_header("X-XSS-Protection", "1; mode=block") self.add_header("X-Content-Type-Options", "nosniff") if self.config.use_ssl: self.add_header("Strict-Transport-Security", 'max-age=31536000; includeSubDomains;') def write_error(self, status_code, **kwargs): ''' Render a generic error page ''' logging.error("Static file request from %s resulted in %d status" % (self.request.remote_ip, status_code)) # Reguardless of error, send a 404 self.render('public/404.html')
def initialize(self): ''' Setup sessions, etc ''' self.session = None self.config = ConfigManager.instance() session_id = self.get_secure_cookie('session_id') if session_id is not None: self.session = self._create_session(session_id) self.session.refresh()
def _registration_post_token(self, form): config_manager = ConfigManager.instance() config_manager.restrict_registration = True form["token"] = "NotARealRegToken" self.post("/registration", data=form)(self.stop) rsp, body = self.wait() assert "Invalid registration token" in body config_manager.restrict_registration = False
def _registration_post_token(self, form): config_manager = ConfigManager.instance() config_manager.restrict_registration = True form['token'] = 'NotARealRegToken' self.post('/registration', data=form)(self.stop) rsp, body = self.wait() assert "Invalid registration token" in body config_manager.restrict_registration = False
def initialize(self): ''' Setup sessions, etc ''' self.session = None self.config = ConfigManager.instance() self.loader = template.Loader("templates/") session_id = self.get_secure_cookie('session_id') if session_id is not None: self.session = self._create_session(session_id) self.session.refresh()
def initialize(self): self.config = ConfigManager.instance() self.bot_manager = BotManager.instance() self.team_name = None if not self.config.use_bots: self.close() else: self.uuid = unicode(uuid4()) self.opcodes = {"auth": self.auth}
def __init__(self): config = ConfigManager.instance() self.botnet = {} # Holds refs to wsockets self.monitors = {} self.sqlite_engine = create_engine(u'sqlite://') setattr(self.sqlite_engine, 'echo', config.bot_sql) Session = sessionmaker(bind=self.sqlite_engine, autocommit=True) self.botdb = Session(autoflush=True) MemoryBaseObject.metadata.create_all(self.sqlite_engine) self.dbsession = dbsession
def render(self, *args, **kwargs): ''' Includes different CSS themes based on user prefs ''' if self.handler.session is not None: return self.render_string("theme/css.html", theme=self.handler.session['theme'] ) else: config = ConfigManager.instance() default_theme = config.default_theme return self.render_string("theme/css.html", theme=default_theme)
def initialize(self): ''' Setup sessions, etc ''' self.session = None self.config = ConfigManager.instance() session_id = self.get_secure_cookie('session_id') if session_id is not None: self.conn = pylibmc.Client([self.config.memcached], binary=True) self.conn.behaviors['no_block'] = 1 # async I/O self.session = self._create_session(session_id) self.session.refresh()
def initialize(self): """ Setup sessions, etc """ self.session = None self._dbsession = dbsession self.new_events = [] self.event_manager = self.application.settings["event_manager"] self.config = ConfigManager.instance() session_id = self.get_secure_cookie("session_id") if session_id is not None: self.session = self._create_session(session_id) self.session.refresh()
def initialize(self): """ Setup sessions, etc """ self.session = None self.manager = EventManager.instance() self.config = ConfigManager.instance() session_id = self.get_secure_cookie("session_id") if session_id is not None: self.conn = pylibmc.Client([self.config.memcached], binary=True) self.conn.behaviors["no_block"] = 1 # async I/O self.session = self._create_session(session_id) self.session.refresh()
def setup_database(db_name): # Setup the test database logging.debug("Setting up the test database connection ...") config_manager = ConfigManager.instance() config_manager.db_connection = 'sqlite:///%s.db' % db_name assert config_manager.db_connection == 'sqlite:///%s.db' % db_name # Create the default tables logging.debug("Creating tables ... ") from setup.create_database import create_tables, engine, metadata create_tables(engine, metadata, False) import setup.bootstrap
def initialize(self): self.bot_manager = BotManager.instance() self.event_manager = EventManager.instance() self.config = ConfigManager.instance() self.team_name = None self.team_uuid = None self.box_uuid = None self.remote_ip = None self.xid = os.urandom(16).encode("hex") if not self.config.use_bots: self.close() else: self.uuid = unicode(uuid4()) self.opcodes = {"interrogation_response": self.interrogation_response}
def avatar(self, image_data): if len(image_data) < (1024 * 1024): ext = imghdr.what("", h=image_data) if ext in ['png', 'jpeg', 'gif', 'bmp']: config = ConfigManager.instance() if self._avatar is not None and os.path.exists(config.avatar_dir + self._avatar): os.unlink(config.avatar_dir + self._avatar) file_path = str(config.avatar_dir + self.uuid + '.' + ext) with open(file_path, 'wb') as fp: fp.write(image_data) self._avatar = self.uuid + '.' + ext else: raise ValueError("Invalid image format, avatar must be: .png .jpeg .gif or .bmp") else: raise ValueError("The image is too large")
def to_xml(self, parent): ''' Admins cannot be exported as XML, not that they would be exported because they're not on a team, but check anyways ''' if not self.has_permission(ADMIN_PERMISSION): user_elem = ET.SubElement(parent, "user") ET.SubElement(user_elem, "handle").text = self.handle ET.SubElement(user_elem, "password").text = self._password bpass_elem = ET.SubElement(user_elem, "bankpassword") bpass_elem.text = self._bank_password bpass_elem.set("algorithm", self.algorithm) config = ConfigManager.instance() with open(config.avatar_dir + self.avatar) as fp: data = fp.read() ET.SubElement(user_elem, "avatar").text = data.encode('base64')
class FirstLoginHandler(BaseHandler): # Terminal JS needs eval() relaxed_csp = "default-src 'self';" + \ "script-src 'self' 'unsafe-eval';" + \ "style-src 'self' 'unsafe-inline';" + \ "font-src 'self';" + \ "img-src 'self';" + \ "connect-src 'self' %s" % ConfigManager.instance().ws_connect @authenticated def get(self, *args, **kwargs): user = self.get_current_user() reward = self.config.bot_reward self.set_header("Content-Security-Policy", self.relaxed_csp) self.render('missions/firstlogin.html', reward=reward, user=user)
def create(): ''' Creates/bootstraps the database ''' from libs.ConfigManager import ConfigManager # Sets up logging print(INFO+'%s : Creating the database ...' % current_time()) from setup.create_database import create_tables, engine, metadata dev = ConfigManager.instance().bootstrap == 'developement' create_tables(engine, metadata, dev) print(INFO+'%s : Bootstrapping the database ...' % current_time()) import setup.bootstrap # Display Details if dev: environ = bold + R + "Developement boot strap" + W details = ", admin password is 'nimda123'." else: environ = bold + "Production boot strap" + W details = '.' print INFO + '%s completed successfully%s' % (environ, details)
def create(): ''' Creates/bootstraps the database ''' from libs.ConfigManager import ConfigManager # Sets up logging print(INFO + '%s : Creating the database ...' % current_time()) from setup.create_database import create_tables, engine, metadata is_devel = ConfigManager.instance().bootstrap.startswith('dev') create_tables(engine, metadata, is_devel) print(INFO + '%s : Bootstrapping the database ...' % current_time()) import setup.bootstrap # Display Details if is_devel: environ = bold + R + "Developement boot strap" + W details = ", admin password is 'nimda123'." else: environ = bold + "Production boot strap" + W details = '.' print(INFO + '%s completed successfully%s' % (environ, details))
def _hash_bank_password(cls, algorithm_name, password): ''' Hashes the password using Md5/Sha1/Sha256/Sha512 only used for the admin accounts. We only allow whitespace/non-ascii. ''' config = ConfigManager.instance() password = filter(lambda char: char in printable[:-6], password) if config.max_password_length < len(password): raise ValueError("Bank password is too long") if algorithm_name is None: algorithm_name = DEFAULT_HASH_ALGORITHM if algorithm_name in cls.algorithms: algo = cls.algorithms[algorithm_name][0]() algo.update(password) return algo.hexdigest() else: raise ValueError("Algorithm %s not supported." % algorithm_name)
def score_bots(): """ Award money for botnets """ logging.info("Scoring botnets, please wait ...") bot_manager = BotManager.instance() config = ConfigManager.instance() for team in Team.all(): bots = bot_manager.by_team(team.name) reward = 0 for bot in bots: try: reward += config.bot_reward bot.write_message({"opcode": "status", "message": "Collected $%d reward" % config.bot_reward}) except: logging.info("Bot at %s failed to respond to score ping" % bot.remote_ip) if 0 < len(bots): logging.info("%s was awarded $%d for controlling %s bot(s)" % (team.name, reward, len(bots))) bot_manager.add_rewards(team.name, config.bot_reward) bot_manager.notify_monitors(team.name) team.money += reward dbsession.add(team) dbsession.flush() dbsession.commit()
def attempt_capture(self, flag, submission): ''' Compares a user provided token to the token in the db ''' user = self.get_current_user() logging.info("%s (%s) capture the flag '%s'" % (user.handle, user.team.name, flag.name)) if submission is not None and flag not in user.team.flags: if flag.capture(submission): user.team.flags.append(flag) user.team.money += flag.value self.dbsession.add(user.team) config = ConfigManager.instance() if config.dynamic_flag_value: flag.value = int(flag.value - ( (flag.value / config.flag_value_decrease) / 100)) self.dbsession.add(flag) self.dbsession.flush() event = self.event_manager.create_flag_capture_event( user, flag) self.new_events.append(event) self._check_level(flag) self.dbsession.commit() return True return False
def get_price(cls, user): ''' Calculate price of next bribe based on history ''' config = ConfigManager.instance() base_price = config.bribe_cost return base_price + (cls.count_completed_by_target_id(user.id) * base_price)
def data(self): config = ConfigManager.instance() with open(config.file_uploads_dir + self.uuid, 'rb') as fp: return fp.read().decode('base64')
def get_organizations_from_file(): ''' Gets the JSON object containing an org list from the configured file ''' config = ConfigManager.instance() with open(config.fb_organization_file, 'r') as f: return json.loads(f.read())
class FlagSubmissionHandler(BaseHandler): # Terminal JS needs eval() relaxed_csp = "default-src 'self';" + \ "script-src 'self' 'unsafe-eval';" + \ "style-src 'self' 'unsafe-inline';" + \ "font-src 'self';" + \ "img-src 'self';" + \ "connect-src 'self' %s" % ConfigManager.instance().ws_connect @authenticated def post(self, *args, **kwargs): ''' Check validity of flag submissions ''' flag = Flag.by_uuid(self.get_argument('uuid', '')) user = self.get_current_user() if flag is not None and flag.game_level in user.team.game_levels: if flag.is_file and 'flag' in self.request.files: submission = self.request.files['flag'][0]['body'] elif not flag.is_file: submission = self.get_argument('token', '') else: submission = None old_reward = flag.value if self.attempt_capture(flag, submission): self.set_header("Content-Security-Policy", self.relaxed_csp) self.render('missions/captured.html', flag=flag, reward=old_reward) else: self.render_page(flag, errors=["Invalid flag submission"]) else: self.render('public/404.html') def attempt_capture(self, flag, submission): ''' Compares a user provided token to the token in the db ''' user = self.get_current_user() logging.info("%s (%s) capture the flag '%s'" % ( user.handle, user.team.name, flag.name )) if submission is not None and flag not in user.team.flags: if flag.capture(submission): user.team.flags.append(flag) user.team.money += flag.value self.dbsession.add(user.team) flag.value = int(flag.value * 0.90) self.dbsession.add(flag) self.dbsession.flush() event = self.event_manager.create_flag_capture_event(user, flag) self.new_events.append(event) self._check_level(flag) self.dbsession.commit() return True return False def _check_level(self, flag): user = self.get_current_user() if len(user.team.level_flags(flag.game_level.number)) == len(flag.game_level.flags): next_level = flag.game_level.next() logging.info("Next level is %r" % next_level) if next_level is not None and next_level not in user.team.game_levels: logging.info("Team completed level, unlocking the next level") user.team.game_levels.append(next_level) self.dbsession.add(user.team) def render_page(self, flag, errors=[]): ''' Wrapper to .render() to avoid duplicate code ''' user = self.get_current_user() box = Box.by_id(flag.box_id) self.render('missions/box.html', box=box, team=user.team, errors=errors, )
def delete_data(self): config = ConfigManager.instance() if os.path.exists(config.file_uploads_dir + self.uuid): os.unlink(config.file_uploads_dir + self.uuid)
def wrapper(self, *args, **kwargs): if ConfigManager.instance().use_black_market: return method(self, *args, **kwargs) else: self.render('public/404.html')
class BaseWebSocketHandler(WebSocketHandler): ''' Handles websocket connections ''' _session = None _memcached = None io_loop = IOLoop.instance() manager = EventManager.instance() config = ConfigManager.instance() @property def memcached(self): ''' Connects to Memcached instance ''' if self._memcached is None: self._memcached = pylibmc.Client([self.config.memcached], binary=True) self._memcached.behaviors['no_block'] = 1 # async I/O return self._memcached @property def session(self): if self._session is None: session_id = self.get_secure_cookie('session_id') if session_id is not None: self._session = self._get_session(session_id) return self._session @session.setter def session(self, new_session): self._session = new_session def _get_session(self, session_id): kwargs = { 'connection': self.memcached, 'session_id': session_id, 'ip_address': self.request.remote_ip, } old_session = MemcachedSession.load(**kwargs) if old_session and not old_session.is_expired(): old_session.refresh() return old_session else: return None def get_current_user(self): ''' Get current user object from database ''' if self.session is not None: try: return User.by_handle(self.session['handle']) except KeyError: logging.exception( "Malformed session: %r" % self.session ) except: logging.exception("Failed call to get_current_user()") return None def open(self): pass def on_message(self, message): pass def on_close(self): pass
def initialize(self): self.config = ConfigManager.instance() if not self.config.use_bots: self.close()
class BaseHandler(RequestHandler): ''' User handlers extend this class ''' csp = { "default-src": set(["'self'"]), "script-src": set(["'self'"]), "connect-src": set(["'self'"]), "frame-src": set(["'self'"]), "img-src": set(["'self'"]), "media-src": set(["'self'"]), "font-src": set(["'self'"]), "object-src": set(["'self'"]), "style-src": set(["'self'"]), } _session = None _dbsession = dbsession _memcached = None new_events = [] io_loop = IOLoop.instance() event_manager = EventManager.instance() config = ConfigManager.instance() def initialize(self): ''' Setup sessions, etc ''' self.add_content_policy('connect-src', self.config.ws_connect) # We need this for a few things, and so far as I know it doesn't present # too much of a security risk - TODO: no longer require inline styles self.add_content_policy('style-src', "'unsafe-inline'") # This add unsafe eval to script src header # -> CSP problem & use of console commands. self.add_content_policy('script-src', "'unsafe-eval'") @property def dbsession(self): return self._dbsession def get_current_user(self): ''' Get current user object from database ''' if self.session is not None: try: return User.by_uuid(self.session['user_uuid']) except KeyError: logging.exception("Malformed session: %r" % self.session) except: logging.exception("Failed call to get_current_user()") return None def start_session(self): ''' Starts a new session ''' self.session = self._create_session() self.set_secure_cookie('session_id', self.session.session_id, expires=self.session.expires, path='/', HttpOnly=True, ) def add_content_policy(self, src, policy): ''' Add to the existing CSP header ''' if src in self.csp: self.csp[src].add(policy) self._refresh_csp() else: raise ValueError("Invalid content source") def clear_content_policy(self, src): ''' Clear a content source in the existing CSP header ''' if src in self.csp: self.csp[src] = set() self._refresh_csp() else: raise ValueError("Invalid content source") def _refresh_csp(self): ''' Rebuild the Content-Security-Policy header ''' _csp = '' for src, policies in self.csp.iteritems(): if len(policies): _csp += "%s %s; " % (src, " ".join(policies)) self.set_header("Content-Security-Policy", _csp) @property def memcached(self): ''' Connects to Memcached instance ''' if self._memcached is None: self._memcached = pylibmc.Client([self.config.memcached], binary=True) self._memcached.behaviors['no_block'] = 1 # async I/O return self._memcached def _create_session(self): ''' Creates a new session ''' kwargs = { 'connection': self.memcached, 'ip_address': self.request.remote_ip, } new_session = MemcachedSession(**kwargs) new_session.save() return new_session @property def session(self): if self._session is None: session_id = self.get_secure_cookie('session_id') if session_id is not None: self._session = self._get_session(session_id) return self._session @session.setter def session(self, new_session): self._session = new_session def _get_session(self, session_id): kwargs = { 'connection': self.memcached, 'session_id': session_id, 'ip_address': self.request.remote_ip, } old_session = MemcachedSession.load(**kwargs) if old_session and not old_session.is_expired(): old_session.refresh() return old_session else: return None def set_default_headers(self): ''' Set security HTTP headers, and add some troll-y version headers ''' self.set_header("Server", "Microsoft-IIS/7.5") self.add_header("X-AspNetMvc-Version", "3.0") self.add_header("X-AspNet-Version", "4.0.30319") self.add_header("X-Powered-By", "ASP.NET") self.add_header("X-Frame-Options", "DENY") self.add_header("X-XSS-Protection", "1; mode=block") self.add_header("X-Content-Type-Options", "nosniff") self._refresh_csp() if self.config.use_ssl: self.add_header("Strict-Transport-Security", '"max-age=31536000; includeSubDomains";') def write_error(self, status_code, **kwargs): ''' Write our custom error pages ''' if not self.config.debug: trace = "".join(traceback.format_exception(*kwargs["exc_info"])) logging.error("Request from %s resulted in an error code %d:\n%s" % ( self.request.remote_ip, status_code, trace )) if status_code in [403]: # This should only get called when the _xsrf check fails, # all other '403' cases we just send a redirect to /403 self.render('public/403.html', locked=False, xsrf=True) else: # Never tell the user we got a 500 self.render('public/404.html') else: # If debug mode is enabled, just call Tornado's write_error() super(BaseHandler, self).write_error(status_code, **kwargs) @property def dbsession(self): return self._dbsession def get(self, *args, **kwargs): ''' Placeholder, incase child class does not impl this method ''' self.render("public/404.html") def post(self, *args, **kwargs): ''' Placeholder, incase child class does not impl this method ''' self.render("public/404.html") def put(self, *args, **kwargs): ''' Log odd behavior, this should never get legitimately called ''' logging.warn( "%s attempted to use PUT method" % self.request.remote_ip ) def delete(self, *args, **kwargs): ''' Log odd behavior, this should never get legitimately called ''' logging.warn( "%s attempted to use DELETE method" % self.request.remote_ip ) def head(self, *args, **kwargs): ''' Ignore it ''' logging.warn( "%s attempted to use HEAD method" % self.request.remote_ip ) def options(self, *args, **kwargs): ''' Log odd behavior, this should never get legitimately called ''' logging.warn( "%s attempted to use OPTIONS method" % self.request.remote_ip ) def on_finish(self, *args, **kwargs): ''' Called after a response is sent to the client ''' self._dbsession.close() if 0 < len(self.new_events): self._event_callbacks() def _event_callbacks(self): ''' Fire any new events ''' for event in self.new_events: self.io_loop.add_callback(event[0], **event[1])
def render(self, *args, **kwargs): config = ConfigManager.instance() if config.recaptcha_enabled: return self.render_string('recaptcha/captcha.html') else: return self.render_string('recaptcha/disabled.html')
def initialize(self): """ Setup sessions, etc """ self._session = None self._dbsession = dbsession self.config = ConfigManager.instance()
def initialize(self): ''' Setup sessions, etc ''' self.config = ConfigManager.instance()
def avatar(self): config = ConfigManager.instance() if self._avatar is not None: return self._avatar else: return "default_avatar.jpeg"
def initialize(self): ''' Setup sessions, etc ''' self._session = None self.config = ConfigManager.instance()
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ''' from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from libs.ConfigManager import ConfigManager from contextlib import contextmanager ### Setup the database session _config = ConfigManager.instance() engine = create_engine(_config.db_connection) setattr(engine, 'echo', False) _Session = sessionmaker(bind=engine) StartSession = lambda: _Session(autoflush=True) dbsession = StartSession() @contextmanager def cxt_dbsession(): ''' Provide a transactional scope around a series of operations. ''' session = StartSession() try: yield session session.commit() except: