def run(self, info): m_return = [] if info.has_url_params: #param_dict = info.url_params for k, v in info.url_params.iteritems(): key = to_utf8(k) value = to_utf8(v) for cmd_inject_case in cmd_inject_detect_test_cases: p = payload_muntants(info, payload={ 'k': k, 'pos': 1, 'payload': cmd_inject_case['input'], 'type': 0 }, bmethod=info.method, timeout=30.0) if cmd_inject_case['target'] is not None: if p is not None: __ = re.search(cmd_inject_case['target'], p.data) if __ is not None: logger.log_verbose('[+] found cmd inject!') return m_return if info.has_post_params: #param_dict = info.post_params for k, v in info.post_params.iteritems(): key = to_utf8(k) value = to_utf8(v) for cmd_inject_case in cmd_inject_detect_test_cases: p = payload_muntants(info, payload={ 'k': k, 'pos': 1, 'payload': cmd_inject_case['input'], 'type': 0 }, bmethod=info.method, timeout=30.0) if cmd_inject_case['target'] is not None: if p is not None: __ = re.search(cmd_inject_case['target'], p.data) if __ is not None: logger.log_verbose('[+] found cmd inject!') return m_return # Send the results return m_return
def run(self, info, **kwargs): #if not info.has_url_params and not info.has_post_params: # return m_return = [] if info.has_url_params: ''' cookie_dict = Config.audit_config.cookie print cookie_dict if hasattr(cookie_dict, "iteritems"): cookie_params = { to_utf8(k): to_utf8(v) for k, v in cookie_dict.iteritems() } cookie_param = ';'.join( '%s=%s' % (k ,v) for (k, v) in sorted(cookie_params.iteritems()) ) print cookie_param print "GET" ''' method = kwargs.get('method', None) if method is None or not isinstance(method, str): raise LalascanValueError("run plugin param has not method!") param = kwargs.get('param', None) if param is None or not isinstance(param, dict): raise LalascanValueError("run plugin param has not param!") for any_file_read_case in any_file_read_detect_test_cases: p, payload_resource = payload_muntants( info, payload={ 'k': param['param_key'], 'pos': 1, 'payload': any_file_read_case['input'], 'type': 1 }, bmethod=method) if p is not None: __ = re.search(any_file_read_case['target'], p.data) if __ is not None: vul = WebVulnerability( target=payload_resource, vulparam_point=param['param_key'], method=method, payload=any_file_read_case['input'], injection_type="ANY_FILE_READ") vulresult.put_nowait(vul) logger.log_success( '[!+>>>] found %s reflect xss vulnerable!' % payload_resource.url) return m_return # Send the results return m_return
def delay_for(original_wait_time, delay): time_payload = timing_test_case_dict['input'].replace( "rndstr", rand_str).replace('duration', str(delay)).replace('val', v) delta = original_wait_time * DELTA_PERCENT upper_bound = (delay * 2) + original_wait_time + delta + 1 lower_bound = original_wait_time + delay - delta try: time_sleep_rsp, payload_resource = payload_muntants( url_info=url, payload={ 'k': k, 'pos': 1, 'payload': time_payload, 'type': 0 }, bmethod=method, use_cache=False, timeout=30.0, payload_encode=payload_encode) current_response_wait_time = time_sleep_rsp.elapsed rsp_delay = int(math.ceil(current_response_wait_time)) lower_bound = delay + self.normal_rsp_time_average - TIME_STDEV_COEFF * self.normal_rsp_time_stdev #正态分布 if timing_test_case_dict['case_id'] == 1100020137: print current_response_wait_time print time_payload print delay, rsp_delay, lower_bound rsp_delay_ratio = rsp_delay / delay return rsp_delay >= lower_bound, rsp_delay, rsp_delay_ratio, payload_resource #if upper_bound > current_response_wait_time > lower_bound: # return True except Exception, e: return False, 0, 0
def xss_detect(self, url, method='GET', **kwargs): if not isinstance(url, URL): raise TypeError("Expected url type, type:%s" % type(url)) k = kwargs.get("k", None) if k is None or not isinstance(k, str): raise ValueError("Except param has not key!") v = kwargs.get("v", None) for xss_test_case_dict in xss_reflection_detect_test_cases: #xss_test_case_dict = xss_reflection_detect_test_cases[12] rand_num = 900000000 + randint(1, 9999999) xss_payload = xss_test_case_dict['input'].replace( 'rndstr', str(rand_num)) xss_resp, payload_resource = payload_muntants(url, payload={ 'k': k, 'pos': 1, 'payload': xss_payload, 'type': 1 }, bmethod=method) if xss_resp is None or xss_resp.data is None: return False, None tags_list, flags_list, targets_list = self._get_tags_flags( xss_test_case_dict['tag'], xss_test_case_dict['flag'], xss_test_case_dict['target']) flag_type = xss_test_case_dict['flag_type'] compare = xss_test_case_dict['compare'] for tag in tags_list: result = [] for flag in flags_list: #TODO BUG targets_list must be one try: assert len(targets_list) == 1 target = targets_list[0].replace( 'rndstr', str(rand_num)) #print tag , flag , flag_type , target, compare ret_without_quote, txt_without_quote = self._search_in_html( page=xss_resp.data, tag=tag, flag=flag, flag_type=flag_type, target=target, compare=compare) single_quote_closed = False double_quote_closed = False big_brace_closed = False mid_brace_closed = False if 'rndstr' in targets_list[0]: single_quote_closed, double_quote_closed, big_brace_closed, mid_brace_closed = self._check_whether_quote_closed( txt_without_quote, str(rand_num), xss_test_case_dict['input']) else: single_quote_closed, double_quote_closed, big_brace_closed, mid_brace_closed = self._check_whether_quote_closed( txt_without_quote, targets_list[0], xss_test_case_dict['input']) if txt_without_quote is not None: if compare == 'match': rgx = 'lt;\s*%s\s*>' % tag if re.search( rgx, txt_without_quote ) is not None or single_quote_closed == False or double_quote_closed == False: ret_without_quote = 0 if ret_without_quote > 0: result.append(flag) except AssertionError: logger.log_verbose("targets list length must bu one!") return False if len(result) > 0: vul = WebVulnerability(target=payload_resource, vulparam_point=k, method=method, payload=xss_payload, injection_type="REFLECT_XSS") vulresult.put_nowait(vul) logger.log_success( '[!+>>>] found %s reflect xss vulnerable!' % payload_resource.url) return True return False
def _boolean_sql_detect(self, **kwargs): ''' bool 型注入探测(盲注) :return: ''' k = kwargs.get("k", None) if k is None or not isinstance(k, str): raise ValueError("Except param has not key!") v = kwargs.get("v", None) url = kwargs.get("url", None) if url is None or not isinstance(url, URL): raise ValueError("Except param has not req_uri") method = kwargs.get('method', None) #TODO method str for boolean_test_case_dict in sql_inject_detect_boolean_test_cases: rand_num = randint(10, 9999) true_case = boolean_test_case_dict['true_case'].replace( "val", str(v)).replace("num", str(rand_num)) false_case = boolean_test_case_dict['false_case'].replace( "val", str(v)).replace("num", str(rand_num)) confirm_true_case = boolean_test_case_dict[ 'confirm_true_case'].replace("val", str(v)).replace( "num", str(rand_num)) confirm_false_case = boolean_test_case_dict[ 'confirm_false_case'].replace("val", str(v)).replace( "num", str(rand_num)) body_true_response = "" body_false_response = "" try: body_true_resp, payload_resource = payload_muntants( url_info=url, payload={ 'k': k, 'pos': 1, 'payload': true_case, 'type': 1 }, bmethod=method) if body_true_resp is not None: body_true_response = body_true_resp.data body_false_resp, _ = payload_muntants(url_info=url, payload={ 'k': k, 'pos': 1, 'payload': false_case, 'type': 1 }, bmethod=method) if body_false_resp is not None: body_false_response = body_false_resp.data self.add_normal_rsp_time(body_true_resp.elapsed) except AttributeError: continue if body_true_response == body_false_response: continue compare_diff = False #print 'Comparing body_true_response and body_false_response.' if self.__equal_with_limit(body_true_response, body_false_response, compare_diff): compare_diff = True body_confirm_true_response = "" body_confirm_false_response = "" try: body_confirm_true_resp, _ = payload_muntants( url_info=url, payload={ 'k': k, 'pos': 1, 'payload': confirm_true_case, 'type': 1 }, bmethod=method) body_confirm_true_response = body_confirm_true_resp.data if body_confirm_true_resp is not None else None body_confirm_false_resp, _ = payload_muntants( url_info=url, payload={ 'k': k, 'pos': 1, 'payload': confirm_false_case, 'type': 1 }, bmethod=method) body_confirm_false_response = body_confirm_false_resp.data if body_confirm_false_resp is not None else None except AttributeError: continue if self.__equal_with_limit(body_true_response, body_confirm_false_response, compare_diff): continue if not self.__equal_with_limit(body_confirm_true_response, body_true_response, compare_diff): continue if self.__equal_with_limit(body_confirm_false_response, body_false_response, compare_diff): vulresult.put_nowait( WebVulnerability(target=payload_resource, vulparam_point=k, method=method, payload=true_case, injection_type="SQLI")) logger.log_success( '[!+>>>] found %s boolean sql inject vulnerable!' % payload_resource.url) return True return False
def _union_sql_detect(self, **kwargs): ''' union 注入 :param kwargs: :return: ''' k = kwargs.get("k", None) if k is None or not isinstance(k, str): raise ValueError("Except param has not key!") v = kwargs.get("v", None) url = kwargs.get("url", None) if url is None or not isinstance(url, URL): raise ValueError("Except param has not req_uri") method = kwargs.get('method', None) max_column = 20 orig_rsp = request_muntants(url=url, allow_redirects=False) if orig_rsp is None or orig_rsp.status != '200': return False union_payload = None table_columns = 0 first_union_payload_rsp_data = None for index in range(1, max_column): if index == 1: union_payload = " union select 1" else: union_payload = "{0},{1}".format(union_payload, index) print union_payload union_payload_rsp, payload_resource = payload_muntants( url_info=url, payload={ 'k': k, 'pos': 1, 'payload': union_payload, 'type': 0 }, bmethod=method) if union_payload_rsp is not None: if index == 1: first_union_payload_rsp_data = union_payload_rsp.data else: if (union_payload_rsp.data != first_union_payload_rsp_data ) and (union_payload_rsp.data != orig_rsp.data): #TODO Maybe WAF, union_payload_rsp.data != orig_rsp.data if index == 2: table_columns = [1, 2] else: table_columns = index break else: break if table_columns != 0 and isinstance(table_columns, int): for inject_index in range(table_columns): union_list = [x + 1 for x in range(table_columns)] union_list[inject_index] = ORDER_BY_SIGN union_payload = ' union select {0}'.format(','.join( map(str, union_list))) union_payload_rsp = None try: union_payload_rsp, payload_resource = payload_muntants( url_info=url, payload={ 'k': k, 'pos': 1, 'payload': union_payload, 'type': 0 }, bmethod=method, use_cache=False) if union_payload_rsp is not None and ORDER_BY_MD5_VAL in union_payload_rsp.data: vulresult.put_nowait( WebVulnerability(target=payload_resource, vulparam_point=k, method=method, payload=union_payload, injection_type="SQLI")) logger.log_success( '[!+>>>] found %s union_by sql inject vulnerable!' % payload_resource.url) return True except LalascanAttributeError: return False elif isinstance(table_columns, list): union_payload_list = [ ' union select {0}'.format(ORDER_BY_SIGN), ' union select {0},2'.format(ORDER_BY_SIGN), ' union select 1, {0}'.format(ORDER_BY_SIGN) ] for union_payload in union_payload_list: try: union_payload_rsp, payload_resource = payload_muntants( url_info=url, payload={ 'k': k, 'pos': 1, 'payload': union_payload, 'type': 0 }, bmethod=method, use_cache=False) if union_payload_rsp is not None and ORDER_BY_MD5_VAL in union_payload_rsp.data: vulresult.put_nowait( WebVulnerability(target=payload_resource, vulparam_point=k, method=method, payload=union_payload, injection_type="SQLI")) logger.log_success( '[!+>>>] found %s union_by sql inject vulnerable!' % payload_resource.url) return True except LalascanAttributeError: continue return False
def _orderby_sql_detect(self, **kwargs): ''' order by 注入 :param kwargs: :return: ''' k = kwargs.get("k", None) if k is None or not isinstance(k, str): raise ValueError("Except param has not key!") v = kwargs.get("v", None) url = kwargs.get("url", None) if url is None or not isinstance(url, URL): raise ValueError("Except param has not req_uri") method = kwargs.get('method', None) max_bound = 100 min_bound = -1 lower_index, high_index = 0, max_bound table_column = 0 for keyword in ['or', 'and']: max_order_column_payload = ' {0} 1=2 order by {1}--'.format( keyword, max_bound) min_order_column_payload = ' {0} 1=2 order by {1}--'.format( keyword, min_bound) p = request_muntants(url=url, allow_redirects=False) if p is None or p.status != '200': return False orig_resp_body = p.data max_order_column_payload_rsp, _ = payload_muntants( url_info=url, payload={ 'k': k, 'pos': 1, 'payload': max_order_column_payload, 'type': 0 }, bmethod=method) min_order_column_payload_rsp, _ = payload_muntants( url_info=url, payload={ 'k': k, 'pos': 1, 'payload': min_order_column_payload, 'type': 0 }, bmethod=method) if max_order_column_payload_rsp is not None and min_order_column_payload_rsp is not None: self.add_normal_rsp_time(max_order_column_payload_rsp.elapsed) else: return False if max_order_column_payload_rsp.data != None and min_order_column_payload_rsp.data != None and ( orig_resp_body != max_order_column_payload_rsp.data) and ( orig_resp_body == min_order_column_payload_rsp.data): #maybe exist sql_inject while lower_index <= high_index: #二分法 col = int(math.ceil((lower_index + high_index) / 2)) column_payload = ' order by {0}--'.format(col) print column_payload column_payload_rsp = None column_payload_rsp, _ = payload_muntants( url_info=url, payload={ 'k': k, 'pos': 1, 'payload': column_payload, 'type': 0 }, bmethod=method, use_cache=False) if column_payload_rsp != None and column_payload_rsp.data != orig_resp_body: if (lower_index + 1) == high_index: break high_index = col else: if (lower_index + 1) == high_index: table_column = lower_index print '*' * 50 break elif lower_index == high_index: table_column = high_index break lower_index = col if table_column != 0: logger.log_verbose("[+!>>>] %s maybe has order by inject!" % url.url) for inject_index in range(table_column): union_list = [x + 1 for x in range(table_column)] union_list[inject_index] = ORDER_BY_SIGN union_payload = ' {0} 1=2 union select {1}'.format( keyword, ','.join(map(str, union_list))) union_payload_rsp = None try: union_payload_rsp, payload_resource = payload_muntants( url_info=url, payload={ 'k': k, 'pos': 1, 'payload': union_payload, 'type': 0 }, bmethod=method, use_cache=False) if union_payload_rsp is not None and ORDER_BY_MD5_VAL in union_payload_rsp.data: vulresult.put_nowait( WebVulnerability(target=payload_resource, vulparam_point=k, method=method, payload=union_payload, injection_type="SQLI")) logger.log_success( '[!+>>>] found %s order_by sql inject vulnerable!' % payload_resource.url) return True except LalascanAttributeError: return False return False
def deal_param_payload(self, sql_detect_type, url, method='GET', **kwargs): ''' insert payload into param :return: ''' if not isinstance(sql_detect_type, str): raise TypeError("Expected sql_detect_type string, type:%s" % type(sql_detect_type)) if not isinstance(url, URL): raise TypeError("Expected url type, type:%s" % type(url)) #if not isinstance(param_dict, dict): # raise TypeError("Expected param_dict string, type:%s" % type(param_dict)) #if method == 'GET': # param_dict = url.url_params #elif method == 'POST': # param_dict = url.post_params param_dict = kwargs['param'] is_timing_stable = True short_duration = 1 def __check_if_rsp_stable_on_orig_input(): p = request_muntants(url=url, allow_redirects=False) if p.status != '200': is_timing_stable = False orig_first_time = p.elapsed orig_first_resp_body = p.data time.sleep(2) p = request_muntants(url=url, allow_redirects=False) if p.status != '200': is_timing_stable = False orig_second_time = p.elapsed orig_second_resp_body = p.data min_resp_time = min(orig_first_time, orig_second_time) max_resp_time = max(orig_first_time, orig_second_time) short_duration = max(RSP_SHORT_DURATION, max_resp_time) + 1 long_duration = short_duration * 2 if (max_resp_time - min_resp_time) > short_duration: is_timing_stable = False else: is_timing_stable = True if orig_first_resp_body != orig_second_resp_body: is_timing_stable = False def __check_if_rsp_stable_on_invalid_input(): #TODO judge url is stable is_timing_stable = True #__check_if_rsp_stable_on_orig_input() ''' if sql_detect_type == "ERR_MSG_DETECT": for k,v in param_dict.iteritems(): key = to_utf8(k) value = to_utf8(v) for test_case_dict in sql_inject_detect_err_msg_test_cases: p, payload_resource = payload_muntants(url, payload = {'k': k , 'pos': 1, 'payload':test_case_dict['input'], 'type': 0}, bmethod = method) if self._err_msg_sql_detect(p, test_case_dict['target']): #print '[+] found sql inject in url:{0}, payload:{1}'.format(req_uri, payload_param_dict) vulresult.put_nowait(WebVulnerability(target = payload_resource, vulparam_point = key, method = method, payload = test_case_dict['input'], injection_type = "SQLI")) logger.log_success('[!+>>>] found %s err_msg sql inject vulnerable!' % payload_resource.url) return True elif sql_detect_type == 'ORDER_BY_DETECT': for k, v in param_dict.iteritems(): key = to_utf8(k) value = to_utf8(v) if self._orderby_sql_detect(k = key, v = value , url = url, method = method): return True elif sql_detect_type == "ECHO_DETECT": self._echo_sql_detect() elif sql_detect_type == "BOOLEAN_DETECT": print '----------- BOOLEAN_DETECT -----------------------' for k, v in param_dict.iteritems(): key = to_utf8(k) value = to_utf8(v) if self._boolean_sql_detect(k = key, v = value , url = url, method = method): return True elif sql_detect_type == "TIMING_DETECT": print '-----------TIMING_DETECT -----------------------' if is_timing_stable == True: for k, v in param_dict.iteritems(): key = to_utf8(k) value = to_utf8(v) if self._timing_sql_detect(k = k, v = value, url = url, method = method, short_duration = short_duration): #print '[+] found time_based sql inject!' return True ''' if sql_detect_type == "ERR_MSG_DETECT": for test_case_dict in sql_inject_detect_err_msg_test_cases: p, payload_resource = payload_muntants( url, payload={ 'k': param_dict['param_key'], 'pos': 1, 'payload': test_case_dict['input'], 'type': 0 }, bmethod=method) if self._err_msg_sql_detect(p, test_case_dict['target']): #print '[+] found sql inject in url:{0}, payload:{1}'.format(req_uri, payload_param_dict) vulresult.put_nowait( WebVulnerability( target=payload_resource, vulparam_point=param_dict['param_key'], method=method, payload=test_case_dict['input'], injection_type="SQLI")) logger.log_success( '[!+>>>] found %s err_msg sql inject vulnerable!' % payload_resource.url) return True elif sql_detect_type == "ORDER_BY_DETECT": if self._orderby_sql_detect(k=param_dict['param_key'], v=param_dict['param_value'], url=url, method=method): return True elif sql_detect_type == "UNION_BY_DETECT": if self._union_sql_detect(k=param_dict['param_key'], v=param_dict['param_value'], url=url, method=method): return True elif sql_detect_type == "ECHO_DETECT": self._echo_sql_detect() elif sql_detect_type == "BOOLEAN_DETECT": print '----------- BOOLEAN_DETECT -----------------------' if self._boolean_sql_detect(k=param_dict['param_key'], v=param_dict['param_value'], url=url, method=method): return True elif sql_detect_type == "TIMING_DETECT": print '-----------TIMING_DETECT -----------------------' if self._timing_sql_detect(k=param_dict['param_key'], v=param_dict['param_value'], url=url, method=method, short_duration=short_duration): #print '[+] found time_based sql inject!' return True