def __init__(self): app_id = Config.get_value('authentication', 'app_id') app_secret = Config.get_value('authentication', 'app_secret') self.oath_access_token = None if self.oath_access_token is None: self.oath_access_token = utils.get_application_access_token(app_id, app_secret) self.graph = GraphAPI(self.oath_access_token)
def fetch_logintoken(self, url, method, headers, body=None, relogin=None): if method.upper() == "GET": login_request = requests.get(url, headers=headers) elif method.upper() == "POST": login_request = requests.post(url, headers=headers, json=body) logs.logging.info("HTTP response of login API : %s %s %s", login_request.status_code, headers, body) else: print "[-]Invalid request" sys.exit(1) try: login_response = json.loads(login_request.text) except: pass if relogin is not None: print "Session fixation attack won't be tested since it failed to re-login." return auth_names = get_value('config.property', 'login', 'auth_names') auth_type = get_value('config.property', 'login', 'auth_type') auth_names = auth_names.split(',') #auth_header = get_value('config.property','login','auth_header') # Auth types: # 1. Cookie # 2. Basic # 3. Oauth auth_status = False if auth_type == 'cookie': if login_request.headers['Set-Cookie']: auth_cookie = {'cookie': login_request.headers['Set-Cookie']} print "[+]Login successful" update_value('login', 'auth_success', 'Y') update_value('login', 'cookie', auth_cookie) auth_status = True # Basic and oauth auth type code will come here(yet to develop). else: for auth_name in auth_names: if auth_name in login_response: auth_success_token = login_response[auth_name] print "[+]Login successful" update_value('login', 'auth_success', 'Y') update_value('login', 'auth_success_param', auth_name) update_value('login', 'auth_success_token', auth_success_token) auth_status = True break if not auth_status: login_response = raw_input( "Failed to login. Do you want to continue scanning without cookie(y/n)," + self.api_logger.G + url + ': ' + self.api_logger.W) if login_response == 'Y' or login_response == 'y': return elif login_response == 'n' or login_response == 'N': sys.exit(1)
def __init__(self): self.host = get_value('config.property','SMTP','ip') self.email_subject = get_value('config.property','SMTP','email_subject') self.email_message = get_value('config.property','SMTP','email_message') self.email_from = get_value('config.property','SMTP','email_from') # optional try: self.email_cc = get_value('config.property','SMTP','email_cc') except: pass
def session_fixation(url, method, headers, body, scanid): # This function deals with checking session fixation issue. attack_result = {} login_result = get_value('config.property', 'login', 'loginresult') logout_result = get_value('config.property', 'logout', 'logoutresult') if login_result == 'Y' and logout_result == 'Y': login_data, logout_data = get_authdata() if url == login_data['loginurl']: logs.logging.info("Checking for Sesion fixation: %s", url) url, method, headers, body = (logout_data['logouturl'], logout_data['logoutmethod'], logout_data['logoutheaders'], logout_data['logoutbody']) logout_headers, auth_old = add_authheader(headers) try: logout_body = ast.literal_eval(base64.b64decode(body)) except: logout_body = None logs.logging.info("Logout request %s %s %s", url, logout_headers, logout_body) logout_req = req.api_request(url, method, logout_headers, logout_body) if logout_req is None or str(logout_req.status_code)[0] == '4' or \ str(logout_req.status_code)[0] == '5': print "%s[!]Failed to logout. Session fixation attack won't" \ " be tested. Check log file for more information.%s"\ % (api_logger.Y, api_logger.W) return # Try to relogin and check if the application is serving the # previous session login_url, login_method, login_headers, login_body = ( login_data['loginurl'], login_data['loginmethod'], login_data['loginheaders'], login_data['loginbody']) logs.logging.info("Login request %s %s %s", url, headers, body) login_req = api_login.fetch_logintoken( login_url, login_method, ast.literal_eval(login_headers), ast.literal_eval(login_body)) if login_req is True: logs.logging.info("Relogin Successful") auth_new = get_value('config.property', 'login', 'auth') if auth_old == auth_new: attack_result.update({ "id": 5, "scanid": scanid, "url": login_url, "alert": "Session Fixation", "impact": "Medium", "req_headers": login_headers, "req_body": req_body, "res_headers": "NA", "res_body": "NA" }) dbupdate.insert_record(attack_result)
def add_headers(headers): # This function deals with adding custom header and auth value . cookie = get_value('config.property', 'login', 'auth') cookie_dict = ast.literal_eval(cookie) cookie_header = {'Cookie': cookie_dict['cookie']} headers.update(cookie_header) try: custom_header = get_value('config.property', 'login', 'headers') custom_header = ast.literal_eval(custom_header) headers.update(custom_header) except: pass return headers
def send_email_notification(): time.sleep(20) while True: try: schedule = get_value('config.property','SMTP','email_schedule') records = email_db.db.email.find({}) for data in records: notification = data['email_notification'] scan_id = data['scanid'] scan_result = scan_status(scan_id) if notification == 'N' and scan_result == 'Completed': try: email = data['to_email'] email_result = emails.main_email(scan_id,email) if email_result is False: print ("failed to connect to SMTP server") return email_db.db.email.update({'email_notification' : 'N'},{"$set" : {'email_notification' : 'Y'}}) except: pass time.sleep(int(schedule)) except Exception as e: logs.logging.info("Invalid email schedule argument "+str(e)) sys.exit(1)
def brute_force(url,method,headers,body,attack_params,scanid): attack_result = {} failed_set = ['exceed','captcha','too many','rate limit','Maximum login'] if len(attack_params) == 1: # attack_params[0] is a first value from list Ex Pin, password param_value = body[attack_params[0]] # param_value is a value of param. Example: 1234 if type(param_value) == int: length = len(str(param_value)) brute_list = generate_list(length,'int') elif type(param_value) == str or type(param_value) == unicode: length = len(param_value) brute_list = generate_list(length,'str') # Starting brute force attack. count = 0 if brute_list is not None: for value in brute_list: # Mdofiying a json data and update the dictionary. # Example:{"Username":"******",password:"******"} # {"Username":"******",password:"******"} body[attack_params[0]] = value auth_type = get_value('config.property','login','auth_type') if auth_type == "cookie": try: del headers['Cookie'] except: pass brute_request = req.api_request(url,method,headers,body) if brute_request is not None: if count == 0: http_len = len(brute_request.text) count += count if len(brute_request.text) == http_len: if str(brute_request.status_code)[0] == '2' or str(brute_request.status_code)[0] == '4': for failed_name in failed_set: if failed_name in brute_request.text: # Brute force protection detected :-( result = False break else: result = True if result is True: attack_result = { "id" : 7, "scanid":scanid, "url" : url, "alert": "Missing Rate limit", "impact": "High", "req_headers": headers, "req_body" : body, "res_headers": brute_request.headers, "res_body" : brute_request.text } return attack_result
def main(): (collection_type, collection_name, url, headers, method, body, loginurl, loginheaders, logindata) = get_arg(sys.argv[1:]) if loginheaders is None: loginheaders = {'Content-Type': 'application/json'} if (collection_type and collection_name and loginurl and loginmethod and logindata): # Login data is given as an input. api_login.fetch_logintoken(loginurl, loginmethod, loginheaders, logindata) login_require = False elif collection_type and collection_name and loginurl: parse_collection(collection_name, collection_type) try: (loginurl, lognheaders, loginmethod, logidata) = api_login.parse_logindata(loginurl) except: print "[-]%s Failed to detect login API from collection %s " % ( api_logger.R, api_logger.W) sys.exit(1) api_login.fetch_logintoken(loginurl, loginmethod, loginheaders, logindata) login_require = False elif loginurl and loginmethod: api_login.fetch_logintoken(loginurl, loginmethod, loginheaders, logindata) login_require = False elif collection_type and collection_name and headers: # Custom headers update_value('login', 'header', headers) login_require = False elif url and collection_name and headers: # Custom headers update_value('login', 'header', headers) login_require = False elif url: if headers is None: headers = {'Content-Type': 'application/json'} if method is None: method = "GET" login_require = False else: login_require = True if body: body = ast.literal_eval(body) # Configuring ZAP before starting a scan get_auth = get_value('config.property', 'login', 'auth_type') if collection_type and collection_name is not None: scan_core(collection_type, collection_name, url, headers, method, body, loginurl, loginheaders, logindata, login_require) else: scanid = generate_scanid() scan_single_api(url, method, headers, body, "F", scanid) scan_complete()
def check_blacklisted_roles(role): roles_list = get_value('showRoles', 'roles').split(",") for item in roles_list: if role.lower() == item: return True #Role is blacklisted else: continue
def read_scan_policy(): try: scan_policy = get_value('scan.property', 'scan-policy', 'attack') attack = ast.literal_eval(scan_policy) except Exception as e: print e return attack
def add_authheader(auth_headers): # This function reads auth value from config file and add auth header in HTTP request. auth_type = get_value('config.property', 'login', 'auth_type') auth = get_value('config.property', 'login', 'auth') if auth_type == "cookie": auth_headers = ast.literal_eval(auth_headers) if auth_headers['Cookie']: del auth_headers['Cookie'] auth_headers.update({'Cookie': auth}) logs.logging.info("Updated header for session fixation %s", auth_headers) return auth_headers, auth else: logs.logging.info("Updated header for session fixation %s", auth_headers) elif auth_type == "token": # If API is using access token as an auth return headers
def email_start_cron(): email_notification = get_value('config.property','SMTP','email_notification') if email_notification == "y" or email_notification == "Y": # Start the thread #time.sleep(20) t = threading.Thread(target=send_email_notification) t.deamon = True t.start() logs.logging.info("started") else: logs.logging.info("Email notification is not enabled")
def add_headers(headers): # This function deals with adding custom header and auth value . auth_type = get_value('config.property','login','auth_type') if auth_type == 'cookie': cookie = get_value('config.property','login','cookie') if cookie: cookie_dict = ast.literal_eval(cookie) cookie_header = {'Cookie': cookie_dict['cookie']} headers.update(cookie_header) else: auth_success = get_value('config.property','login','auth_success') if auth_success == 'Y': auth_success_token = get_value('config.property','login','auth_success_token') #auth_request_header = get_value('config.property','login','auth_request_token') auth_success_param = get_value('config.property','login','auth_success_param') auth_header = {auth_success_param : auth_success_token } headers.update(auth_header) try: custom_header = get_value('config.property','login','headers') custom_header = ast.literal_eval(custom_header) headers.update(custom_header) except: pass return headers
def jwt_check(url, method, headers, body, scanid): # Main function for JWT test jwt_loc, jwt_key, jwt_token = find_jwt(url, headers) if jwt_loc == None: return jwt_decoded_list = decode_jwt(jwt_token) if jwt_decoded_list: alg = ast.literal_eval(jwt_decoded_list[0])['alg'] jwt_data = ast.literal_eval(jwt_decoded_list[1]) if alg == 'HS256' or alg == 'HS512' or alg == 'HS384': result = jwt_none(url, method, headers, body, jwt_loc, jwt_key, jwt_token, jwt_data) if result is True: pass else: arg = get_value('scan.property', 'modules', 'jwt_brute') if arg == 'Y' or arg == 'y': jwt_brute(url, headers, body, jwt_token, alg, scanid)
def check_whitelisted_ports(ports_list): rval = False whitelisted_ports = get_value('noShowPorts', 'ports').split(',') for item in ports_list: abc = check_port_range(item) if abc is False: if item in whitelisted_ports: rval = True # port is whitelisted else: rval = False # port is not whitelisted break else: #check if it is TCP or UDP if item.startswith('tcp'): abc = ['tcp' + str(s) for s in abc] elif item.startswith('udp'): abc = ['udp' + str(s) for s in abc] return check_whitelisted_ports(abc) return rval
import os import time import re from slackclient import SlackClient import math import ast import json from netaddr import IPAddress import datetime from elasticsearch import Elasticsearch from utils.config import get_value from botFunctions import f_firewall, f_iam, f_operations, f_serviceAccount, f_slackHelper # Get Configuration Value eshost = get_value('Configuration', 'elasticsearch_host') esport = get_value('Configuration', 'elasticsearch_port') bot_token = get_value('Configuration', 'dollhouse_bot_token') running_account = get_value('Configuration', 'running_account') # Get Constant Value RTM_READ_DELAY = int(get_value( 'Constants', 'RTM_READ_DELAY')) # 1 second delay between reading from RTM FIREWALL_DESCRIBE_COMMAND = get_value('Constants', 'FIREWALL_DESCRIBE_COMMAND') IAM_ROLE_DESCRIBE_COMMAND = get_value('Constants', 'IAM_ROLE_DESCRIBE_COMMAND') SERVICEACCONT_IDENTIFY_COMMAND = get_value('Constants', 'SERVICEACCONT_IDENTIFY_COMMAND') WHAT_IS_COMMAND = get_value('Constants', 'WHAT_IS_COMMAND') HELP_COMMAND = get_value('Constants', 'HELP_COMMAND') COMMAND_REGEX = get_value('Constants', 'COMMAND_REGEX') MENTION_REGEX = get_value('Constants', 'MENTION_REGEX') #get group 2 PROJECT_REGEX = get_value('Constants', 'PROJECT_REGEX') #get group 3
def fetch_redirection_names(): # Returns the list of common open redirection param names redirection_names = get_value('scan.property', 'modules', 'open-redirection-names') return redirection_names.split(',')
def fetch_auth_config(name): # Returns the list of common authentication headers names and auth error from config file. auth_config_value = get_value('scan.property', 'modules', name) return auth_config_value.split(',')
def fetch_csrf_names(): # Returns the list of common CSRF token param names from config file. csrf_names = get_value('scan.property', 'modules', 'csrftoken-names') return csrf_names.split(',')
def get_config_value(name): # Return the value from config file. Ex Port, apikey config_value = get_value('config.property', 'Configuration', name) return config_value
def runner(self): """ 死循环不断的更新全局变量(全行交易量以及交易金额) :return: """ while True: log.logger.debug("=========>循环开始<=========") # globalVars = copy.copy(globalVar._global_dict) # mutex.acquire() with acquire(mutex): lastAmount = int(globalVar.get_value("lastAmount")) lastCount = int(globalVar.get_value("lastCount")) lastUpdateTime = int(globalVar.get_value("updateTime")) currAmount = int(globalVar.get_value("totalTransAmount")) currCount = int(globalVar.get_value("totalTransCount")) tempCurrAmount = int(globalVar.get_value("tempTotalTransAmount")) tempCurrCount = int(globalVar.get_value("tempTotalTransCount")) diffNum = tempCurrCount - currCount # mutex.release() log.logger.debug("globalMap:{}".format(json.dumps(globalVar._global_dict))) # 当前值小于上一次值则不进行赋值 if tempCurrAmount <= lastAmount or tempCurrCount <= lastCount: log.logger.warning("!!!!!! 发生了当前总金额或交易笔数小于或等于上一次值的事件,我不赋新值 !!!!!!") time.sleep(self.retryInterval) continue if tempCurrAmount == 0 or tempCurrCount == 0: log.logger.warning("!!!!! totalTransAmount 或 totalTransCount 为空, 进入睡眠状态, 等待SPL接口返回数据 !!!!!") time.sleep(self.retryInterval) continue # 确定上限和下限中间随机数的个数 if diffNum >= self.randomNumRange: size = self.randomNumRange elif diffNum > 0: size = diffNum else: time.sleep(self.retryInterval) continue log.logger.debug("!!!!! 随机数个数:{} !!!!!".format(size)) # 根据随机数创建一批比spl查询结果小的值 amount = [] count = [] for i in range(size): amount.append(self.randomNumber(currAmount, tempCurrAmount)) count.append(self.randomNumber(currCount, tempCurrCount)) # 随机数排下序 amount.sort() count.sort() log.logger.debug("amount:{}, count:{}".format(amount, count)) # 更新全局变量 for i in range(size): # 如果当前随机数等于上次随机数则map缓存数据为上次数据(业务数/总金额) # 检查下当前情况变量情况,如果更新了直接退出循环 if int(globalVar.get_value("updateTime")) != lastUpdateTime: log.logger.warning("!!!!! 发生交易型数据更新, 退出循环 !!!!!") # if mutex.acquire(False): with acquire(mutex): globalVar.set_value("lastAmount", tempCurrAmount) globalVar.set_value("lastCount", tempCurrCount) globalVar.set_value("totalTransAmount", tempCurrAmount) globalVar.set_value("totalTransCount", tempCurrCount) # mutex.release() break else: with acquire(mutex): globalVar.set_value("totalTransAmount", amount[i]) globalVar.set_value("totalTransCount", count[i]) # mutex.release() # 根据随机数个数动态调整休息时间 time.sleep(int(self.splSearchInterval)/self.randomNumRange + 0.5)
import datetime from slackclient import SlackClient from utils.config import get_value import os #get Configurations bot_token = get_value('Configuration', 'dollhouse_bot_token') running_account = get_value('Configuration', 'running_account') #get Constants slack_channel = get_value('Constants', 'SLACK_CHANNEL') slack_client = SlackClient(bot_token) starterbot_id = None def firewall_insert_slack(created_by, operation_type, firewall_name, project_name, allowed, source): currentTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") print('[' + currentTime + '] [*] DEBUG: slack alert sent') slack_client.api_call( "chat.postMessage", channel=slack_channel, text="*" + created_by + "* has just *" + operation_type + "ed* a firewall rule: *" + firewall_name + "* in project *" + project_name + "*. Ports opened by this firewall rule is/are: *" + str(allowed) + "* which can be accessed from *" + str(source) + "*") def firewall_delete_slack(deleted_by, firewall_name, project_name): currentTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")