How to Implement a Custom Response Filter Using the `-x` Option in Patator
To implement a custom response filter in Patator, extend the Response_Base class to expose your data, register a new condition keyword in available_conditions, and implement a match_<keyword> method that evaluates the filter logic against module responses.
Patator's flexible brute-forcing framework allows you to define custom response filters using the -x option, which attaches actions like ignore, retry, or skip to conditions evaluated against execution results. This guide walks through the lanjelot/patator source code to show you how to extend the built-in filtering system with your own conditions.
Understanding Patator's Action-Condition Framework
The -x option uses a simple syntax: action:condition=value. For example, -x ignore:code=404 tells Patator to ignore responses with HTTP status 404. This framework relies on three core components in src/patator/patator.py:
- Command-line parsing: The
Controller.usage_parser()method (lines 814-822) defines the-xoption syntax asactions:conditions. - Action storage:
Controller.update_actions()(lines 1011-1030) parses the actions portion and stores conditions inself.ns.actions. - Condition evaluation:
Controller.lookup_actions()(lines 1034-1046) iterates through stored actions and evaluates conditions by callingresp.match(key, val)on theResponseobject.
The Response_Base class (lines 1530-1563) serves as the foundation for all response filtering. It maintains an available_conditions tuple that registers valid filter keywords and implements a generic match() dispatcher (around line 1580) that routes condition checks to specific match_<keyword> methods.
Step-by-Step Implementation Guide
Step 1: Expose Data in the Module Response Class
First, modify the module's Response subclass to capture the data you want to filter. Each module (e.g., HTTP, FTP, SSH) defines its own Response class inheriting from Response_Base.
For example, to filter based on the HTTP Server header, add a server attribute to the HTTP module's response class:
# Inside the HTTP module (e.g., src/patator/http.py)
class Response(Response_Base):
def __init__(self, code, mesg, timing=0, trace=None, server=None):
super().__init__(code, mesg, timing, trace)
self.server = server # New attribute for custom filtering
Ensure this attribute is populated when the module creates the response object during execution.
Step 2: Register the New Condition Keyword
Add your condition to available_conditions in the Response_Base class definition (around line 1556 in patator.py):
class Response_Base:
available_conditions = (
('code', 'match status code'),
('size', 'match size (N or N-M or N- or -N)'),
('time', 'match time (N or N-M or N- or -N)'),
('mesg', 'match message'),
('fgrep', 'search for string in mesg'),
('egrep', 'search for regex in mesg'),
('server','match Server header'), # <-- Your new condition
)
Registration is mandatory—Patator only accepts conditions listed in this tuple when parsing the -x argument.
Step 3: Implement the Matching Logic
Implement a match_<keyword> method in Response_Base to handle the comparison logic. The method receives the value from the command line and returns a boolean:
# In Response_Base class, following existing match methods (around line 1596)
def match_server(self, val):
"""Match the Server header against a substring pattern."""
return self.server and val in self.server
You can implement complex logic here—regex matching, numeric ranges, or case-insensitive comparisons—depending on your filtering requirements. The match() dispatcher automatically calls this method when it encounters the server keyword.
Step 4: Use the Custom Filter
Invoke your custom filter from the command line using the standard -x syntax:
patator http_fuzz url=http://target.com/FUZZ \
-x ignore:server=nginx \
0=wordlist.txt
This configuration ignores any response where the Server header contains "nginx". You can combine multiple conditions using commas: -x ignore:code=404,server=apache.
Code Reference and Architecture
Understanding these specific source locations helps when debugging or extending filters:
- Option definition:
Controller.usage_parser()at line 814 adds the-xflag and builds help text. - Action parsing:
Controller.update_actions()at line 1011 separates actions from conditions. - Condition lookup:
Controller.lookup_actions()at line 1034 triggersresp.match(). - Built-in conditions: Defined in
Response_Base.available_conditionsat line 1556. - Dispatch mechanism:
Response_Base.match()at line 1580 routes tomatch_<keyword>methods.
Module-specific response classes inherit from Response_Base and can override available_conditions or add module-specific match methods, though registering conditions in the base class makes them available globally.
Summary
- Extend
Response_Base: Add your data attribute to the module'sResponseclass constructor. - Register the keyword: Append a tuple to
available_conditionsinResponse_Baseto enable parsing. - Implement
match_<keyword>: Create the evaluation method that returnsTruewhen the condition matches. - Execute with
-x: Use the syntaxaction:keyword=value(e.g.,-x ignore:server=nginx) to activate your filter.
This architecture allows you to filter on any response attribute—from HTTP headers and LDAP error codes to custom protocol fields—without modifying Patator's core execution logic.
Frequently Asked Questions
What is the syntax for the -x option in Patator?
The -x option accepts a string in the format actions:conditions, where actions are comma-separated keywords like ignore, retry, or stop, and conditions use the syntax keyword=value. Multiple condition pairs can be chained with commas: -x ignore:code=200,size=0. The Controller.update_actions() method at line 1011 parses this string into actionable tuples.
Where are the built-in conditions defined in Patator?
Built-in conditions are defined in the available_conditions class attribute of Response_Base at line 1556 in src/patator/patator.py. The default conditions include code (status code), size (response size), time (execution time), mesg (message text), fgrep (substring search), and egrep (regex search). Each condition has a corresponding match_<keyword> method that implements the comparison logic.
Can I use regex patterns in custom response filters?
Yes. While the example above uses simple substring matching, you can implement regex matching by importing the re module and using re.search() inside your match_<keyword> method. The built-in egrep condition demonstrates this pattern in the source code. Ensure your method handles cases where the attribute might be None to avoid attribute errors during execution.
How do I debug a custom filter that isn't matching?
First, verify that your condition keyword appears in Response_Base.available_conditions and that your module's Response class actually populates the attribute you're filtering on. You can temporarily add debug prints to your match_<keyword> method to inspect the self object's attributes. Also confirm that the -x syntax uses the exact keyword you registered—Patator's lookup_actions() method silently skips unrecognized conditions rather than throwing errors.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →