From b1a7ccb7126b5eb50d3d729ced8e065a9bb7414b Mon Sep 17 00:00:00 2001 From: javi Date: Tue, 3 Nov 2020 00:18:59 +0100 Subject: [PATCH] diff operator --- docs/user/advanced.rst | 1 + src/wfuzz/filters/ppfilter.py | 22 +++++++++++++++++----- src/wfuzz/helpers/utils.py | 13 +++++++++++++ src/wfuzz/ui/console/mvc.py | 19 +++---------------- 4 files changed, 34 insertions(+), 21 deletions(-) diff --git a/docs/user/advanced.rst b/docs/user/advanced.rst index 26bc9833..3ab9337e 100644 --- a/docs/user/advanced.rst +++ b/docs/user/advanced.rst @@ -466,6 +466,7 @@ value|replace('what', 'with') value|r('what', 'with') Returns value replacing value|unique() value|u() Returns True if a value is unique. value|startswith('value') value|sw('value') Returns true if the value string starts with param value|gregex('expression') value|gre('exp') Returns first regex group that matches in value +value|diff(expression) Returns diff comparison between value and expression ================================ ======================= ============================================= * When a FuzzResult is available, you could perform runtime introspection of the objects using the following symbols diff --git a/src/wfuzz/filters/ppfilter.py b/src/wfuzz/filters/ppfilter.py index 13032540..1c9ead09 100644 --- a/src/wfuzz/filters/ppfilter.py +++ b/src/wfuzz/filters/ppfilter.py @@ -5,6 +5,7 @@ ) from ..helpers.str_func import value_in_any_list_item from ..helpers.obj_dic import DotDict +from ..helpers.utils import diff import re import collections @@ -64,9 +65,17 @@ def __init__(self, filter_string=None): r"BBB(?:\[(?P(\w|_|-|\.)+)\])?", asMatch=True ).setParseAction(self.__compute_bbb_symbol) + diff_call = Group( + Suppress(Literal("|")) + + Literal("diff") + + Suppress(Literal("(")) + + (fuzz_symbol | res_symbol | bbb_symbol | int_values | quoted_str_value) + + Suppress(")") + ) + fuzz_statement = Group( (fuzz_symbol | res_symbol | bbb_symbol | int_values | quoted_str_value) - + Optional(operator_call, None) + + Optional(diff_call | operator_call, None) ).setParseAction(self.__compute_res_value) operator = oneOf("and or") @@ -127,10 +136,13 @@ def __compute_res_value(self, tokens): if token_tuple: location, operator_match = token_tuple - if operator_match and operator_match.groupdict()["operator"]: - fuzz_val = self._get_operator_value( - location, fuzz_val, operator_match.groupdict() - ) + if location == "diff": + return diff(operator_match, fuzz_val) + else: + if operator_match and operator_match.groupdict()["operator"]: + fuzz_val = self._get_operator_value( + location, fuzz_val, operator_match.groupdict() + ) if isinstance(fuzz_val, list): return [fuzz_val] diff --git a/src/wfuzz/helpers/utils.py b/src/wfuzz/helpers/utils.py index eb6151bb..92576c58 100644 --- a/src/wfuzz/helpers/utils.py +++ b/src/wfuzz/helpers/utils.py @@ -1,4 +1,5 @@ from threading import Lock +import difflib class MyCounter: @@ -20,3 +21,15 @@ def _operation(self, dec): def __call__(self): with self._mutex: return self._count + + +def diff(param1, param2): + delta = difflib.unified_diff( + str(param1).splitlines(False), + str(param2).splitlines(False), + fromfile="prev", + tofile="current", + n=0, + ) + + return "\n".join(delta) diff --git a/src/wfuzz/ui/console/mvc.py b/src/wfuzz/ui/console/mvc.py index 5aa0d70f..37e7bb8e 100644 --- a/src/wfuzz/ui/console/mvc.py +++ b/src/wfuzz/ui/console/mvc.py @@ -1,7 +1,6 @@ import sys from collections import defaultdict import threading -import difflib try: from itertools import zip_longest @@ -162,7 +161,7 @@ def __init__(self, session_options): self.term = Term() self.printed_lines = 0 - def _print_verbose(self, res, print_nres=True, extra_description=None): + def _print_verbose(self, res, print_nres=True): txt_colour = ( Term.noColour if not res.is_baseline or not self.colour else Term.fgCyan ) @@ -179,10 +178,6 @@ def _print_verbose(self, res, print_nres=True, extra_description=None): if "Server" in res.history.headers.response: server = res.history.headers.response["Server"] - description = res.description - if extra_description: - description = "{} | diff:\n{}".format(res.description, extra_description) - rows = [ ("%09d:" % res.nres if print_nres else " |_", txt_colour), ("%.3fs" % res.timer, txt_colour), @@ -195,7 +190,7 @@ def _print_verbose(self, res, print_nres=True, extra_description=None): ("%d Ch" % res.chars, txt_colour), (server, txt_colour), (location, txt_colour), - ('"%s"' % description, txt_colour), + ('"%s"' % res.description, txt_colour), ] self.term.set_colour(txt_colour) @@ -308,15 +303,7 @@ def result(self, res): ): prev_res = res.payload_man.get_payload_content(1) if self.verbose: - delta = difflib.unified_diff( - prev_res.history.raw_content.splitlines(True), - res.history.raw_content.splitlines(True), - fromfile="prev", - tofile="current", - ) - self._print_verbose( - prev_res, print_nres=False, extra_description="".join(delta) - ) + self._print_verbose(prev_res, print_nres=False) else: self._print(prev_res, print_nres=False)