LISTEN_ADDRESS = '127.0.0.1' LISTEN_PORT = 5000 BOKEH_LISTEN_ADDRESS = '127.0.0.2' BOKEH_LISTEN_PORT = 8000 IOC_MODE = 'flat'           # flat | logic ## DO NOT USE "logic" for now !!! DEBUG = True USE_SSL = False SSL_KEY_FILE = os.path.join('ssl','server.pem.key') SSL_CERT_FILE = os.path.join('ssl','server.pem.cer') CERTITUDE_DATABASE = "sqlite:///data.db" MIN_SUBMIT_INTERVAL = 300 # min second interval between two submissions of same IP address class Result(Base):
    __tablename__ = 'resultats'

    id = Column(Integer, primary_key=True)
    tache_id = Column(Integer, ForeignKey('queue.id'))
    finished = Column(DateTime, default=datetime.now)

    up = Column(Boolean)
    blocked = Column(Boolean)
    ip = Column(String)
    hostname = Column(String)
    smbreachable = Column(Boolean) class IOCDetection(Base):
    __tablename__ = 'iocdetections'

    id = Column(Integer, primary_key=True)
    result_id = Column(Integer, ForeignKey('resultats.id'))
    resultat = relationship(Result,
        backref='iocdetections',)
    xmlioc_id = Column(Integer)
    indicator_id = Column(String) # Length should be 62
    indicator_data = Column(String) class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    username = Column(String)
    password = Column(String)
    email = Column(String)
    active = Column(Boolean)
    encrypted_master_key = Column(String)
    b64_kdf_salt = Column(String) class ConfigurationProfile(Base):
    __tablename__ = 'configuration_profiles'

    id = Column(Integer, primary_key=True)
    name = Column(String)
    host_confidential = Column(Boolean, default=False)
    ioc_list = Column(String)
    yara_list = Column(String) class WindowsCredential(Base):
    __tablename__ = 'windows_crendentials'

    id = Column(Integer, primary_key=True)
    domain = Column(String)
    login = Column(String)
    encrypted_password = Column(String) class XMLIOC(Base):
    __tablename__ = 'xmliocs'

    id = Column(Integer, primary_key=True)
    name = Column(String)
    date_added = Column(DateTime, default=datetime.now)
    xml_content = Column(String) class Batch(Base):
    __tablename__ = 'batches'

    id = Column(Integer, primary_key = True)
    name = Column(String)
    configuration_profile_id = Column(Integer)
    windows_credential_id = Column(Integer) class GlobalConfig(Base):
    __tablename__ = 'global_config'

    id = Column(Integer, primary_key=True)
    key = Column(String)
    value = Column(String) class YaraRule(Base):
    __tablename__ = 'yararules'

    id = Column(Integer, primary_key=True)
    name = Column(String)
    rules = Column(String)
    content = Column(String)
    date_added = Column(DateTime, default=datetime.now) def hashPassword(password):
    s = sha256()
    s.update(INTERFACE_HASH_SALT)
    s.update(password)

    return s.hexdigest() def checksum(data):
    return sha512(data).hexdigest() def verifyPassword(p):
    if len(p) < 12:
        return False

    MIN = False
    MAJ = False
    NUM = False
    SPEC = False

    for i in range(0, len(p)):
        c = ord(p[i])

        if not c in range(33, 127):
            continue

        if c in range(ord('a'), ord('z')+1):
            MIN = True
        elif c in range(ord('A'), ord('Z')+1):
            MAJ = True
        elif c in range(ord('0'), ord('9')+1):
            NUM = True
        else:
            SPEC = True

    return int(MIN)+int(MAJ)+int(NUM)+int(SPEC)>=3
import atexit
import base64
import datetime
import json
import logging
import os
import ssl
import subprocess
import sys
    import win32event
    import win32security
import netaddr
import helpers.crypto as crypto
import components.scanner.openioc.openiocparser as openiocparser
import helpers.iocscan_modules as ioc_modules
import helpers.hashscan_modules as hash_modules
import xml.etree.ElementTree as ET
from flask import Flask, render_template, request, session, redirect, url_for, Response, abort, escape
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from config import LISTEN_ADDRESS, LISTEN_PORT, BOKEH_LISTEN_ADDRESS, BOKEH_LISTEN_PORT
from config import IOC_MODE, DEBUG, USE_SSL, SSL_KEY_FILE, SSL_CERT_FILE, CERTITUDE_DATABASE, MIN_SUBMIT_INTERVAL
from helpers.queue_models import Task
from helpers.results_models import Result, IOCDetection
from helpers.misc_models import User, ConfigurationProfile, WindowsCredential, XMLIOC, Batch, GlobalConfig
from helpers.yara_models import YaraRule
from helpers.helpers import hashPassword, checksum, verifyPassword
from functools import wraps
from plyara.plyara import PlyaraParser
@requires_auth
def userSwitchActive(userid):
    u = dbsession.query(User).filter_by(id=userid).first()

    if u is None:
        return redirect(app.jinja_env.globals['url_for']('users'))

    u.active = not u.active
    dbsession.commit()

    return redirect(app.jinja_env.globals['url_for']('users'))


# Add a new user
# MASTER_KEY is encrypted for the new user
# Clear text MASTER_KEY is retrieved using the current use's credentials
#
@app.route('/user/add', methods=['GET', 'POST'])
@requires_auth
def userAdd():
    if request.method == 'GET':
        return render_template('user-add.html')
    else:
        success = True
        errors = []

        user_password = request.form['user_password']
        user = dbsession.query(User).filter_by(id=session['user_id']).first()

        # Checks current user password
        if user is None or hashPassword(user_password) != user.password:
            success = False
            errors.append('Your password is incorrect')

        # Someone has messed with the database
        if success:
            mk_cksum = dbsession.query(GlobalConfig).filter_by(key='master_key_checksum').first()
            if not mk_cksum:
                success = False
                errors.append('Database is broken, please create a new one !')

        if success:
            keyFromPassword = crypto.keyFromText(user_password, base64.b64decode(user.b64_kdf_salt))
            MASTER_KEY = crypto.decrypt(user.encrypted_master_key, keyFromPassword)

            # Someone changed the master key...
            if checksum(MASTER_KEY) != mk_cksum.value:
                errors.append('MASTER_KEY may have been altered')
                del MASTER_KEY
                success = False

        # Now check the new user password...
        if success:
            password1, password2 = request.form['password'], request.form['password2']
            if password1 != password2:
                success = False
                errors.append('New user passwords do not match')

        # ... including complexity
        if success:
            if not verifyPassword(password1):
                success = False
                errors.append(
                    'Password is not complex enough (l > 12 and at least three character classes between lowercase, uppercase, numeric and special char)')

        # Encrypt the MASTER_KEY for the user
        if success:
            new_kdf_salt = crypto.randomBytes(crypto.SALT_LENGTH)
            keyFromPassword = crypto.keyFromText(password1, new_kdf_salt)
            emk = crypto.encrypt(MASTER_KEY, keyFromPassword)
            del MASTER_KEY  # safer ?

            u = User(
                username=request.form['username'],
                password=hashPassword(password1),
                email=request.form['email'],
                active=True,
                encrypted_master_key=emk,
                b64_kdf_salt=base64.b64encode(new_kdf_salt))

        if len(request.form['username']) <= 0 or len(request.form['email']) <= 0:
            success = False
            errors.append('No empty fields allowed.')

        if success:
            dbsession.add(u)
            dbsession.commit()
            return redirect(app.jinja_env.globals['url_for']('users'))
        else:
            return render_template('user-add.html', username=request.form['username'], email=request.form['email'],
                                   errors='\n'.join(errors))


# Delete a user
@app.route('/user/<int:userid>/delete', methods=['POST'])
@requires_auth
def userDelete(userid):
    u = dbsession.query(User).filter_by(id=userid).first()

    if u is None:
        return redirect(app.jinja_env.globals['url_for']('users'))

    dbsession.delete(u)
    dbsession.commit()

    return redirect(app.jinja_env.globals['url_for']('users'))



    # CONFIGURATION, IOCs & PROFILES MANAGEMENT


# Configuration homepage
@app.route('/config', )
@requires_auth
def config():
    configuration_profiles = dbsession.query(ConfigurationProfile).order_by(ConfigurationProfile.name.asc())
    windows_credentials = dbsession.query(WindowsCredential).order_by(WindowsCredential.domain.asc(),
                                                                      WindowsCredential.login.asc())
    xmliocs = dbsession.query(XMLIOC).order_by(XMLIOC.date_added.desc())

    yararules = dbsession.query(YaraRule).order_by(YaraRule.date_added.desc())