def handle_runQuickAnalysis(self): results = '' results_io = StringIO() if not self.qlock.tryLock(): self.framework.debug_log( 'failed to acquire lock for quick analysis') else: original_stdout = sys.stdout sys.stdout = results_io try: python_code = str(self.python_code) scriptLoader = ScriptLoader() global_ns = local_ns = {} script_env = scriptLoader.load_from_string( python_code, global_ns, local_ns) begin_method = script_env.functions.get('begin') if begin_method: res = begin_method() if res: self.append_results(results_io, res) process_request_method = script_env.functions.get( 'process_request') if not process_request_method: raise Exception( 'The "process_request" method is not implemented and is required.' ) factory = RequestResponseFactory.RequestResponseFactory( self.framework, None) for row in self.Data.read_all_responses(self.read_cursor): try: rr = factory.fill_by_row(row) res = process_request_method(rr) if res: self.append_results(results_io, res) except Exception as e: results += '\nEncountered processing error: %s' % (e) end_method = script_env.functions.get('end') if end_method: res = end_method() if res: self.append_results(results_io, res) except Exception as error: self.framework.report_exception(error) results += '\nEncountered processing error: %s' % (error) finally: sys.stdout = original_stdout self.qlock.unlock() if self.callback_object: if results: results += '\n' results += results_io.getvalue() self.callback_object.emit( SIGNAL('runQuickAnalysisFinished(QString)'), results)
def handle_runQuickAnalysis(self): results = '' results_io = StringIO() if not self.qlock.tryLock(): self.framework.debug_log('failed to acquire lock for quick analysis') else: original_stdout = sys.stdout sys.stdout = results_io try: python_code = str(self.python_code) scriptLoader = ScriptLoader() global_ns = local_ns = {} script_env = scriptLoader.load_from_string(python_code, global_ns, local_ns) begin_method = script_env.functions.get('begin') if begin_method: res = begin_method() if res: self.append_results(results_io, res) process_request_method = script_env.functions.get('process_request') if not process_request_method: raise Exception('The "process_request" method is not implemented and is required.') factory = RequestResponseFactory.RequestResponseFactory(self.framework, None) for row in self.Data.read_all_responses(self.read_cursor): try: rr = factory.fill_by_row(row) res = process_request_method(rr) if res: self.append_results(results_io, res) except Exception as e: results += '\nEncountered processing error: %s' % (e) end_method = script_env.functions.get('end') if end_method: res = end_method() if res: self.append_results(results_io, res) except Exception as error: self.framework.report_exception(error) results += '\nEncountered processing error: %s' % (error) finally: sys.stdout = original_stdout self.qlock.unlock() if self.callback_object: if results: results += '\n' results += results_io.getvalue() self.callback_object.emit(SIGNAL('runQuickAnalysisFinished(QString)'), results)
def __init__(self): self.scripts = {} self.scriptLoader = ScriptLoader() self.Data = None
class RaftCmdLine(): # TODO: refactor this definition to be shared with importers FILE_PROCESSOR_DEFINTIONS = { 'raft_capture_xml' : raft_parse_xml, 'burp_log' : burp_parse_log, 'burp_xml' : burp_parse_xml, 'burp_vuln_xml' : burp_parse_vuln_xml, 'burp_state' : burp_parse_state, 'appscan_xml' : appscan_parse_xml, 'webscarab' : webscarab_parse_conversation, 'paros_message' : paros_parse_message, } def __init__(self): self.scripts = {} self.scriptLoader = ScriptLoader() self.Data = None def cleanup(self): if self.Data: self.Data.close() def process_args(self, args): do_create = getattr(args, 'create') do_import = getattr(args, 'import') do_export = getattr(args, 'export') do_parse = getattr(args, 'parse') # was DB file specified? db_filename = getattr(args, 'db') if db_filename is not None: if not db_filename.endswith('.raftdb'): db_filename += '.raftdb' if not os.path.exists(db_filename): if not do_create: sys.stderr.write('\nDB file [%s] does not exist\n' % (db_filename)) return 1 else: sys.stderr.write('\nWill create database: %s\n' %(db_filename)) self.Data = database.Db(__version__, self.report_exception) self.Data.connect(db_filename) sys.stderr.write('\nAttaching database: %s\n' %(db_filename)) else: if do_export or do_import: sys.stderr.write('\nDB file is required\n' % (db_filename)) return 1 # setup any capture filters self.capture_filter_scripts = [] arg = getattr(args, 'capture_filter') if arg is not None: for filearg in arg: self.capture_filter_scripts.append(self.load_script_file(filearg)) # setup any capture filters self.process_capture_scripts = [] arg = getattr(args, 'process_capture') if arg is not None: for filearg in arg: self.process_capture_scripts.append(self.load_script_file(filearg)) if do_export: filename = getattr(args, 'output_file') if filename.endswith('.xml.xz'): fh = lzma.LZMAFile(filename, 'w') elif filename.endswith('.xml.bz2'): fh = bz2.BZ2File(filename, 'w') elif filename.endswith('.xml'): fh = open(filename, 'wb') else: sys.stderr.write('\nUnsupported output file type [%s]\n' % (filename)) return 1 self.export_to_raft_capture(filename, fh) elif do_import: self.run_process_loop(args, self.import_one_file) elif do_parse: self.run_process_loop(args, self.parse_one_file) else: sys.stderr.write('\nNo recognized options\n') return 0 def report_exception(self, error): print(error) def setup_script_initializers(self): for key, script_env in self.scripts.items(): initializer = script_env.functions.get('initialize') if initializer and not script_env['initialized']: initializer() script_env['initialized'] = True def setup_script_finalizers(self): for key, script_env in self.scripts.items(): finalizer = script_env.functions.get('finalize') if finalizer and not script_env['finalized']: finalizer() script_env['finalized'] = True def reset_script_begin_end(self): for key, script_env in self.scripts.items(): script_env['begin_called'] = False script_env['end_called'] = False def call_script_method_with_filename(self, script_env, method, filename): method_func = script_env.functions.get(method) if method_func and not script_env[method + '_called']: method_func(filename) script_env[method + '_called'] = True def run_process_loop(self, args, call_func): self.setup_script_initializers() for name, func in self.FILE_PROCESSOR_DEFINTIONS.items(): arg = getattr(args, name) if arg is None: continue for filearg in arg: if filearg.startswith('~'): filearg = os.path.expanduser(filearg) if '$' in filearg or '%' in filearg: filearg = os.path.expandvars(filearg) if '*' in filearg: file_list = glob.glob(filearg) elif os.path.exists(filearg): file_list = [filearg] for filename in file_list: call_func(filename, func, name) self.setup_script_finalizers() def export_to_raft_capture(self, filename, fhandle): """ Export to RAFT capture format """ sys.stderr.write('\nExporting to [%s]\n' % (filename)) self.reset_script_begin_end() self.setup_script_initializers() filters = [] for script_env in self.capture_filter_scripts: self.call_script_method_with_filename(script_env, 'begin', filename) capture_filter = script_env.functions.get('capture_filter') if capture_filter: filters.append(capture_filter) adapter = ParseAdapter() count = 0 Data = self.Data cursor = Data.allocate_thread_cursor() try: fhandle.write(b'<raft version="1.0">\n') for row in Data.read_all_responses(cursor): capture = RaftDbCapture() capture.populate_by_dbrow(row) skip = False for capture_filter in filters: result = capture_filter(capture) if not result: skip = True break if not skip: fhandle.write(adapter.format_as_xml(capture).encode('utf-8')) count += 1 fhandle.write(b'</raft>') fhandle.close() sys.stderr.write('\nExported [%d] records\n' % (count)) finally: cursor.close() Data.release_thread_cursor(cursor) Data, cursor = None, None for script_env in self.capture_filter_scripts: self.call_script_method_with_filename(script_env, 'end', filename) self.setup_script_finalizers() def import_one_file(self, filename, func, funcname): """ Import one file using specified parser function""" adapter = ParseAdapter() sys.stderr.write('\nImporting [%s]\n' % (filename)) self.reset_script_begin_end() filters = [] for script_env in self.capture_filter_scripts: self.call_script_method_with_filename(script_env, 'begin', filename) capture_filter = script_env.functions.get('capture_filter') if capture_filter: filters.append(capture_filter) count = 0 commit_threshold = 100 Data = self.Data cursor = Data.allocate_thread_cursor() try: Data.set_insert_pragmas(cursor) for result in func(filename): capture = adapter.adapt(result) skip = False for capture_filter in filters: result = capture_filter(capture) if not result: skip = True break if not skip: insertlist = [None, capture.url, capture.request_headers, capture.request_body, capture.response_headers, capture.response_body, capture.status, capture.content_length, capture.elapsed, capture.datetime, capture.notes, None, capture.confirmed, capture.method, capture.hostip, capture.content_type, '%s-%s' % (funcname, capture.origin), capture.host] Data.insert_responses(cursor, insertlist, False) count += 1 if (0 == (count % commit_threshold)): Data.commit() if not (0 == (count % commit_threshold)): Data.commit() sys.stderr.write('\nInserted [%d] records\n' % (count)) except Exception as error: Data.rollback() print(error) # TODO: should continue(?) raise error finally: Data.reset_pragmas(cursor) cursor.close() Data.release_thread_cursor(cursor) Data, cursor = None, None for script_env in self.capture_filter_scripts: self.call_script_method_with_filename(script_env, 'end', filename) def parse_one_file(self, filename, func, funcname): """ Parse one file using specified parser function""" adapter = ParseAdapter() sys.stderr.write('\nProcessing [%s]\n' % (filename)) self.reset_script_begin_end() filters = [] processors = [] for script_env in self.capture_filter_scripts: self.call_script_method_with_filename(script_env, 'begin', filename) capture_filter = script_env.functions.get('capture_filter') if capture_filter: filters.append(capture_filter) for script_env in self.process_capture_scripts: self.call_script_method_with_filename(script_env, 'begin', filename) process_capture = script_env.functions.get('process_capture') if process_capture: processors.append(process_capture) try: for result in func(filename): capture = adapter.adapt(result) skip = False for capture_filter in filters: result = capture_filter(capture) if not result: skip = True break if not skip: for processor in processors: result = processor(capture) except Exception as error: print(error) # TODO: should continue(?) raise error for script_env in self.capture_filter_scripts: self.call_script_method_with_filename(script_env, 'end', filename) for script_env in self.process_capture_scripts: self.call_script_method_with_filename(script_env, 'end', filename) def load_script_file(self, filename): if filename in self.scripts: return self.scripts[filename] script_env = self.scriptLoader.load_from_file(filename) script_env['initialized'] = False script_env['finalized'] = False self.scripts[filename] = script_env return script_env
def start_fuzzing_clicked(self): """ Start the fuzzing attack """ if 'Cancel' == self.mainWindow.wfStdStartButton.text() and self.pending_fuzz_requests is not None: self.cancel_fuzz_requests = True for context, pending_request in self.pending_fuzz_requests.items(): pending_request.cancel() self.pending_fuzz_requests = None self.mainWindow.wfStdStartButton.setText('Start Attack') self.mainWindow.fuzzerStandardProgressBar.setValue(0) return self.pending_fuzz_requests = {} url = str(self.mainWindow.wfStdUrlEdit.text()) templateText = str(self.mainWindow.wfStdEdit.toPlainText()) method = str(self.mainWindow.stdFuzzerReqMethod.currentText()) self.save_standard_configuration() replacements = self.build_replacements(method, url) sequenceId = None if self.mainWindow.wfStdPreChk.isChecked(): sequenceId = self.mainWindow.wfStdPreBox.itemData(self.mainWindow.wfStdPreBox.currentIndex()) postSequenceId = None if self.mainWindow.wfStdPostChk.isChecked(): postSequenceId = self.mainWindow.wfStdPostBox.itemData(self.mainWindow.wfStdPostBox.currentIndex()) # Fuzzing stuff payload_mapping = self.create_payload_map() # print(payload_mapping) self.create_functions() template_definition = TemplateDefinition(templateText) template_items = template_definition.template_items ### print(template_items) parameter_names = template_definition.parameter_names self.global_ns = self.local_ns = {} scriptLoader = ScriptLoader() errors = [] fuzz_payloads = {} for name, payload_info in payload_mapping.items(): if name in parameter_names: payload_type, payload_value, payload_file = payload_info if 'fuzz' == payload_type: filename = payload_value values = self.Attacks.read_data(filename) fuzz_payloads[name] = values elif 'dynamic' == payload_type: target = payload_file # TODO: should this come from saved file or current Scintilla values (?) script_env = scriptLoader.load_from_file(os.path.join(self.functions_dir, target), self.global_ns, self.local_ns) expression = payload_value if not expression.endswith('()'): expression += '()' eval_result = eval(expression, self.global_ns, self.local_ns) fuzz_payloads[name] = [str(v) for v in eval_result] elif 'static' == payload_type: pass elif 'none' == payload_type: # unconfigured payload errors.append(name) test_slots = [] counters = [] tests_count = [] total_tests = 1 for name, payload_info in payload_mapping.items(): if name in parameter_names: payload_type, payload_value, payload_file = payload_info if 'static' == payload_type: # static payload value payloads = [payload_value] elif 'fuzz' == payload_type: payloads = fuzz_payloads[name] elif 'dynamic' == payload_type: payloads = fuzz_payloads[name] total_tests *= len(payloads) test_slots.append((name, payloads)) counters.append(0) tests_count.append(len(payloads)) position_end = len(counters) - 1 position = position_end self.miniResponseRenderWidget.clear_response_render() self.mainWindow.fuzzerStandardProgressBar.setValue(0) self.mainWindow.fuzzerStandardProgressBar.setMaximum(total_tests) finished = False first = True while not finished: data = {} for j in range(0, len(test_slots)): name, payloads = test_slots[j] data[name] = payloads[counters[j]] template_io = StringIO() self.apply_template_parameters(template_io, data, template_items) templateText = template_io.getvalue() context = uuid.uuid4().hex # print('%s%s%s' % ('-'*32, request, '-'*32)) use_global_cookie_jar = self.mainWindow.webFuzzerUseGlobalCookieJar.isChecked() (method, url, headers, body) = self.process_template(url, templateText, replacements) if first: self.mainWindow.wfStdStartButton.setText('Cancel') if use_global_cookie_jar: self.fuzzRequesterCookieJar = self.framework.get_global_cookie_jar() else: self.fuzzRequesterCookieJar = InMemoryCookieJar(self.framework, self) self.requestRunner = RequestRunner(self.framework, self) self.requestRunner.setup(self.fuzzer_response_received, self.fuzzRequesterCookieJar, sequenceId, postSequenceId) first = False self.pending_fuzz_requests[context] = self.requestRunner.queue_request(method, url, headers, body, context) # increment to next test counters[position] = (counters[position] + 1) % (tests_count[position]) while position >= 0 and counters[position] == 0: position -= 1 counters[position] = (counters[position] + 1) % (tests_count[position]) if position == -1: finished = True else: position = position_end
class RaftCmdLine(): # TODO: refactor this definition to be shared with importers FILE_PROCESSOR_DEFINTIONS = { 'raft_capture_xml': raft_parse_xml, 'burp_log': burp_parse_log, 'burp_xml': burp_parse_xml, 'burp_vuln_xml': burp_parse_vuln_xml, 'burp_state': burp_parse_state, 'appscan_xml': appscan_parse_xml, 'webscarab': webscarab_parse_conversation, 'paros_message': paros_parse_message, } def __init__(self): self.scripts = {} self.scriptLoader = ScriptLoader() self.Data = None def cleanup(self): if self.Data: self.Data.close() def process_args(self, args): do_create = getattr(args, 'create') do_import = getattr(args, 'import') do_export = getattr(args, 'export') do_parse = getattr(args, 'parse') # was DB file specified? db_filename = getattr(args, 'db') if db_filename is not None: if not db_filename.endswith('.raftdb'): db_filename += '.raftdb' if not os.path.exists(db_filename): if not do_create: sys.stderr.write('\nDB file [%s] does not exist\n' % (db_filename)) return 1 else: sys.stderr.write('\nWill create database: %s\n' % (db_filename)) self.Data = database.Db(__version__, self.report_exception) self.Data.connect(db_filename) sys.stderr.write('\nAttaching database: %s\n' % (db_filename)) else: if do_export or do_import: sys.stderr.write('\nDB file is required\n' % (db_filename)) return 1 # setup any capture filters self.capture_filter_scripts = [] arg = getattr(args, 'capture_filter') if arg is not None: for filearg in arg: self.capture_filter_scripts.append( self.load_script_file(filearg)) # setup any capture filters self.process_capture_scripts = [] arg = getattr(args, 'process_capture') if arg is not None: for filearg in arg: self.process_capture_scripts.append( self.load_script_file(filearg)) if do_export: filename = getattr(args, 'output_file') if filename.endswith('.xml.xz'): fh = lzma.LZMAFile(filename, 'w') elif filename.endswith('.xml.bz2'): fh = bz2.BZ2File(filename, 'w') elif filename.endswith('.xml'): fh = open(filename, 'wb') else: sys.stderr.write('\nUnsupported output file type [%s]\n' % (filename)) return 1 self.export_to_raft_capture(filename, fh) elif do_import: self.run_process_loop(args, self.import_one_file) elif do_parse: self.run_process_loop(args, self.parse_one_file) else: sys.stderr.write('\nNo recognized options\n') return 0 def report_exception(self, error): print(error) def setup_script_initializers(self): for key, script_env in self.scripts.items(): initializer = script_env.functions.get('initialize') if initializer and not script_env['initialized']: initializer() script_env['initialized'] = True def setup_script_finalizers(self): for key, script_env in self.scripts.items(): finalizer = script_env.functions.get('finalize') if finalizer and not script_env['finalized']: finalizer() script_env['finalized'] = True def reset_script_begin_end(self): for key, script_env in self.scripts.items(): script_env['begin_called'] = False script_env['end_called'] = False def call_script_method_with_filename(self, script_env, method, filename): method_func = script_env.functions.get(method) if method_func and not script_env[method + '_called']: method_func(filename) script_env[method + '_called'] = True def run_process_loop(self, args, call_func): self.setup_script_initializers() for name, func in self.FILE_PROCESSOR_DEFINTIONS.items(): arg = getattr(args, name) if arg is None: continue for filearg in arg: if filearg.startswith('~'): filearg = os.path.expanduser(filearg) if '$' in filearg or '%' in filearg: filearg = os.path.expandvars(filearg) if '*' in filearg: file_list = glob.glob(filearg) elif os.path.exists(filearg): file_list = [filearg] for filename in file_list: call_func(filename, func, name) self.setup_script_finalizers() def export_to_raft_capture(self, filename, fhandle): """ Export to RAFT capture format """ sys.stderr.write('\nExporting to [%s]\n' % (filename)) self.reset_script_begin_end() self.setup_script_initializers() filters = [] for script_env in self.capture_filter_scripts: self.call_script_method_with_filename(script_env, 'begin', filename) capture_filter = script_env.functions.get('capture_filter') if capture_filter: filters.append(capture_filter) adapter = ParseAdapter() count = 0 Data = self.Data cursor = Data.allocate_thread_cursor() try: fhandle.write(b'<raft version="1.0">\n') for row in Data.read_all_responses(cursor): capture = RaftDbCapture() capture.populate_by_dbrow(row) skip = False for capture_filter in filters: result = capture_filter(capture) if not result: skip = True break if not skip: fhandle.write( adapter.format_as_xml(capture).encode('utf-8')) count += 1 fhandle.write(b'</raft>') fhandle.close() sys.stderr.write('\nExported [%d] records\n' % (count)) finally: cursor.close() Data.release_thread_cursor(cursor) Data, cursor = None, None for script_env in self.capture_filter_scripts: self.call_script_method_with_filename(script_env, 'end', filename) self.setup_script_finalizers() def import_one_file(self, filename, func, funcname): """ Import one file using specified parser function""" adapter = ParseAdapter() sys.stderr.write('\nImporting [%s]\n' % (filename)) self.reset_script_begin_end() filters = [] for script_env in self.capture_filter_scripts: self.call_script_method_with_filename(script_env, 'begin', filename) capture_filter = script_env.functions.get('capture_filter') if capture_filter: filters.append(capture_filter) count = 0 commit_threshold = 100 Data = self.Data cursor = Data.allocate_thread_cursor() try: Data.set_insert_pragmas(cursor) for result in func(filename): capture = adapter.adapt(result) skip = False for capture_filter in filters: result = capture_filter(capture) if not result: skip = True break if not skip: insertlist = [ None, capture.url, capture.request_headers, capture.request_body, capture.response_headers, capture.response_body, capture.status, capture.content_length, capture.elapsed, capture.datetime, capture.notes, None, capture.confirmed, capture.method, capture.hostip, capture.content_type, '%s-%s' % (funcname, capture.origin), capture.host ] Data.insert_responses(cursor, insertlist, False) count += 1 if (0 == (count % commit_threshold)): Data.commit() if not (0 == (count % commit_threshold)): Data.commit() sys.stderr.write('\nInserted [%d] records\n' % (count)) except Exception as error: Data.rollback() print(error) # TODO: should continue(?) raise error finally: Data.reset_pragmas(cursor) cursor.close() Data.release_thread_cursor(cursor) Data, cursor = None, None for script_env in self.capture_filter_scripts: self.call_script_method_with_filename(script_env, 'end', filename) def parse_one_file(self, filename, func, funcname): """ Parse one file using specified parser function""" adapter = ParseAdapter() sys.stderr.write('\nProcessing [%s]\n' % (filename)) self.reset_script_begin_end() filters = [] processors = [] for script_env in self.capture_filter_scripts: self.call_script_method_with_filename(script_env, 'begin', filename) capture_filter = script_env.functions.get('capture_filter') if capture_filter: filters.append(capture_filter) for script_env in self.process_capture_scripts: self.call_script_method_with_filename(script_env, 'begin', filename) process_capture = script_env.functions.get('process_capture') if process_capture: processors.append(process_capture) try: for result in func(filename): capture = adapter.adapt(result) skip = False for capture_filter in filters: result = capture_filter(capture) if not result: skip = True break if not skip: for processor in processors: result = processor(capture) except Exception as error: print(error) # TODO: should continue(?) raise error for script_env in self.capture_filter_scripts: self.call_script_method_with_filename(script_env, 'end', filename) for script_env in self.process_capture_scripts: self.call_script_method_with_filename(script_env, 'end', filename) def load_script_file(self, filename): if filename in self.scripts: return self.scripts[filename] script_env = self.scriptLoader.load_from_file(filename) script_env['initialized'] = False script_env['finalized'] = False self.scripts[filename] = script_env return script_env