elespike / burp-cph Goto Github PK
View Code? Open in Web Editor NEWCustom Parameter Handler extension for Burp Suite.
License: MIT License
Custom Parameter Handler extension for Burp Suite.
License: MIT License
Rather than relying on tab order when using cached responses, see if it's possible to reference a tab whose cached response you'd like to use.
This would allow more than one tab to use multiple distinct values from a single cache tab.
Need to consider how to best do this. Regex option? Parse only a literal \r\n and convert it to CRLF?
Switch to saving user config in json format
Save the config files with the ".json" extension
Ensure that "load config" dialogs filter to the new .json config file format
Hi,
I have parameters with unique name + value for each session in the GET request, which look like _portlet_instance_cJ1vzbzA0fql_id=49006de3-de69-4f79-a882-cbff86cfb9b5
I tried to set "Find matches to this expression" to _portlet_instance_([a-zA-Z0-9]{12})_id=([\w-]{36})
and set the same regexp for replacement. However, when I check extender output, I get [INFO] Match index [0]: matched "cJ1vzbzA0fql", replaced with "cJ1vzbzA0fql"
and no further change for the second group (index [1]).
I tried capturing the whole regexp (_portlet_instance_[a-zA-Z0-9]{12}_id=[\w-]{36})
which works.
Are you planning on supporting multiple regexp groups?
If it is possible, we should implement CTRL+Z and CTRL+Y for Undo/Redo. When I accidentally overwrite something I have previously entered, there is no easy way to get it back.
Convert gifs to webm to allow for pausing
My Problem statement : This is what I need and configured so far
Added a Macro to validate session ---> In this have added the PUT request I use in the Intruder
Under Inspect response to determine session validity ---> In this have checked Locations : HTTP headers and Response body : to Look for expression
401 Unauthorized
Now checked if seesion is invalid, perform action below ---> Here I select Run a macro
I have added a macro POST request with username and password to authenticate to the application
Now my problem is how to retrieve the access token send through the above POST response and use the token in the Authorization : Bearer "access-token should be placed here" in this format in the subsequent PUT request in the Intruder when 401 Unauthorized is seen during the attack.
I have Customer Parameter Handler installed and would need steps on how to include and configure CPH when "After running the macro ,invoke a Burp extension action handler " is checked
I always use the Logger++ extension to see what goes out from Burp.
Lately I had to install CPH to "fix" some requests that the Scanner was generating. After enabling CPH I noticed that Logger++ is not showing the requests generated by the scanner in the log anymore.
Is there a way for both extensions to play well together?
Burp's url-encoding callback is creating issues for us; it will encode meaningful url characters like ? and &.
Starts on line 216 in CustomParamHandler.py.
Not sure if it's possible but I'd like to have Burp Scanner injecting inside a JWT in a request authorization header.
Is it possible to do that with the actual features?
Hi, using regex find and replace, when the dynamic value contains a + and a = in the pattern "+(.*)?=", the picker fails to operate.
Test case:
I set up a python simplehttpserver to return a string. If the string matches the pattern +(.*)?= then the entire process fails. Instead of replacing the string, it appends it. EG:
Request header: (found with regex "Basic .*"
Basic replaceme
Obtain string from request:
+=
Replace 'replaceme' with "+=":
Basic replacemeBasic +=
Expected replacement:
Basic +=
This is most noticable when trying to CPH B64 data, which contains + and = in the above pattern.
When the string is =+, it works fine.
Regards,
rgb-rgb
Ctrl+N New tab
Ctrl+Shift+N Clone tab
Ctrl+W Close tab
Ctrl+E Toggle tab (enable/disable)
Ctrl+, Select previous tab
Ctrl+. Select next tab
Ctrl+Shift+, Move tab back
Ctrl+Shift+. Move tab forward
I'm trying to do a simple find/replace on a request. When I set up CPH to replace one word with another, it works find. However, if I use a RegEx to define the target, CPH just doesn't work. See attached. I'm new to pen testing & would appreciate any help you could give. Thank you:) ~Kate; [email protected]
Hello Team
I have read your help doc but couldn't find a relevant info.
Is it possible to use your CPH to
?
Thanks for the great plugin.
The ability to automatically load settings would help when running Burp in headless mode, for automated deployments and the like. See the following post for a potential use case: https://support.portswigger.net/customer/portal/questions/17315873-headless-scan-in-burp-with-bearer-token
It is not a bug, but an inquiry.
Can i accomplish below with CPH?
To authenticate, a user is required to call /authenticate
twice.
POST /authenticate
HTTP 200
{"jwt": [this_is_your_token]}
POST /authenticate
{"jwt": [this_is_your_token], "username": "nino", "password": "password"}
HTTP 200
{"authenticated": "true"}
Before a user sends out username & password, he is required to call the same endpoint without any parameter to obtain a jwt
.
If we add a tab to capture request that match /authenticate
, it seems it would have infinite loop.
Does CPH support this type of request? Thanks.
Put the following string in the expression field which is going to be used to update each field:
/ \@"
The result after the replacement will be:
\/\ \@\"
Commit 1c7ea61 discusses the purpose for the merge script; it would be good to have a summary of that rather long commit message somewhere in the README, such as under a Building Releases section.
Hi,
I see an environment, where in each response, there is a x-request-path:
header, which basically reflects the entire URL. For example: x-request-path: /web/index.hml?param1=2¶mX=Y&csrf=123
.
Is it possible to add support to matching expressions and extracting values within header, body, or both?
For special csrf parameters, when I would try to parse them from HTTP response by some regexp, I have a feeling it matches the header first which uses incorrect value, and only 2nd match = the one in the body would be fresh and valid.
Thanks
Advise along the lines of "if this combobox is empty, ensure previous tab has seen the request at least once"
CPH seems to be ignoring the target host / port for requests and instead using the value in the Host
header.
After using the extension for a while I found that sending this via the repeater:
GET /contact/ HTTP/1.1
Host: andresriancho.com
User-Agent: curl/7.58.0
Accept: */*
Pragma: no-cache
Cache-Control: no-cache, no-transform
Connection: close
With target configured to foo.com
port 443
, will actually send an HTTP request to andresriancho.com
!
This issue also applies to the scanner module. Because of this CPH issue, burp scanner identified a false positive saying Out-of-band resource load (HTTP)
:
GET / HTTP/1.1
Host: gg0r2rg9pyf225f3cyqtigiiu90bszk18rvhj6.burpcollaborator.net
Pragma: no-cache
Cache-Control: no-cache, no-transform
Connection: close
HTTP/1.1 200 OK
Server: Burp Collaborator https://burpcollaborator.net/
X-Collaborator-Version: 4
Content-Type: text/html
Content-Length: 61
<html><body>3es6a1ziwfv5qpn6nkfsu4zjukgkugifigz</body></html>
When the target of that request was foo.com
port 443.
AFAIK this doesn't have anything to do with the rules I configure in CPH, those rules are very simple and do not modify the host header in any way.
Useful when configuring a new tab requires only minor changes to an already-configured tab.
This could either be a button on each tab (presumably at the top, with the move buttons) and/or some sort of control in the Options tab.
Hi,
First, cool tool so thanks.
I'm likely doing this wrong but maybe not.
The goal is to update the request body with an obtained token for any API request that requires a token. Testing in repeater. Everything seems to work okay in debug but the token never gets updated in repeater and an error is thrown.
11:52:54:065 [DEBUG] is_request: 1
11:52:54:065 [DEBUG] rms_type_requests: 1
11:52:54:066 [DEBUG] rms_type_responses: 0
11:52:54:066 [DEBUG] rms_type_both: 0
11:52:54:066 [INFO] Sending request to tab "APILogin" for modification
11:52:54:066 [DEBUG] Extracted match values using this expression: {"token.}
11:52:54:068 [DEBUG] Final match values: [u'{"token":""}']
11:52:54:068 [DEBUG] Initial replace value:
11:52:54:069 [DEBUG] Skipping message received from Extender on account of global tool scope options.
11:52:59:312 [DEBUG] Skipping message received from Extender on account of global tool scope options.
11:52:59:312 [DEBUG] Issued configured request from tab "APILogin" to host "...*"
11:52:59:319 [DEBUG] Got response!
11:52:59:319 [DEBUG] Extracted replace value using this expression: {"token.}
11:52:59:319 [DEBUG] Replace value is now: {"token":"123"}
11:52:59:319 [DEBUG] Final replace value: {"token":"123"}
11:52:59:321 [DEBUG] Searching for "set([u'{"token":"111"}'])", inserting/replacing "{"token":"123"}"
11:52:59:321 [DEBUG] Unfiltered match indices: [0]
11:52:59:321 [DEBUG] Filtered match indices: set([0])
11:52:59:605 [DEBUG] is_request: 0
11:52:59:605 [DEBUG] rms_type_requests: 1
11:52:59:605 [DEBUG] rms_type_responses: 0
11:52:59:607 [DEBUG] rms_type_both: 0
11:52:59:607 [DEBUG] Preliminary scope check negative!
11:52:59:608 [DEBUG] is_request: 1
11:52:59:608 [DEBUG] rms_type_requests: 1
11:52:59:608 [DEBUG] rms_type_responses: 0
11:52:59:608 [DEBUG] rms_type_both: 0
11:52:59:608 [DEBUG] Messages cached for tab APILogin!
Traceback (most recent call last):
File "./bapps/a/CustomParamHandler_merged.py", line 1728, in processHttpMessage
modified_request = self.modify_message(tab, req_as_string)
File "./bapps/a/CustomParamHandler_merged.py", line 1983, in modify_message
substr_indices.extend([m.start() for m in finditer(match_value, original_msg)])
File "/path/burp/jython-standalone-2.7.0.jar/Lib/re.py", line 186, in finditer
File "/path/burp/jython-standalone-2.7.0.jar/Lib/re.py", line 242, in _compile
sre_constants.error: unexpected end of regular expression
at org.python.core.PyException.doRaise(PyException.java:198)
at org.python.core.Py.makeException(Py.java:1337)
at org.python.core.Py.makeException(Py.java:1341)
at re$py._compile$12(/path/burp/jython-standalone-2.7.0.jar/Lib/re.py:246)
at re$py.call_function(/path/burp/jython-standalone-2.7.0.jar/Lib/re.py)
at org.python.core.PyTableCode.call(PyTableCode.java:167)
at org.python.core.PyBaseCode.call(PyBaseCode.java:307)
at org.python.core.PyBaseCode.call(PyBaseCode.java:145)
at org.python.core.PyFunction.__call__(PyFunction.java:423)
at re$py.finditer$7(/path/burp/jython-standalone-2.7.0.jar/Lib/re.py:186)
at re$py.call_function(/path/burp/jython-standalone-2.7.0.jar/Lib/re.py)
at org.python.core.PyTableCode.call(PyTableCode.java:167)
at org.python.core.PyBaseCode.call(PyBaseCode.java:307)
at org.python.core.PyBaseCode.call(PyBaseCode.java:145)
at org.python.core.PyFunction.__call__(PyFunction.java:423)
at org.python.pycode._pyx4.modify_message$108(./bapps/a/CustomParamHandler_merged.py:2012)
at org.python.pycode._pyx4.call_function(./bapps/a/CustomParamHandler_merged.py)
at org.python.core.PyTableCode.call(PyTableCode.java:167)
at org.python.core.PyBaseCode.call(PyBaseCode.java:170)
at org.python.core.PyFunction.__call__(PyFunction.java:434)
at org.python.core.PyMethod.__call__(PyMethod.java:156)
at org.python.pycode._pyx4.processHttpMessage$106(./bapps/a/CustomParamHandler_merged.py:1791)
at org.python.pycode._pyx4.call_function(./bapps/a/CustomParamHandler_merged.py)
at org.python.core.PyTableCode.call(PyTableCode.java:167)
at org.python.core.PyBaseCode.call(PyBaseCode.java:307)
at org.python.core.PyBaseCode.call(PyBaseCode.java:198)
at org.python.core.PyFunction.__call__(PyFunction.java:482)
at org.python.core.PyMethod.instancemethod___call__(PyMethod.java:237)
at org.python.core.PyMethod.__call__(PyMethod.java:228)
at org.python.core.PyMethod.__call__(PyMethod.java:218)
at org.python.core.PyMethod.__call__(PyMethod.java:213)
at org.python.core.PyObject._jcallexc(PyObject.java:3626)
at org.python.core.PyObject._jcall(PyObject.java:3658)
at org.python.proxies.__main__$BurpExtender$19.processHttpMessage(Unknown Source)
at burp.q2b.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Thanks!!!
It is not a bug, but an inquiry.
Can i accomplish below with CPH?
There are three endpoints calls in order:
/getToken
/verify
/confirm
To call /verify
, it requires a valid token from response of /getToken
. In return, the server would return a unique identifier - uniqueId
.
POST /verify
Authorization: my_token
{myorder: 1}
HTTP 200
{"uniqueId": 123}
To call /confirm
, it requires a valid token from response of /getToken
and a uniqueId from response of /verify
.
POST /confirm
Authorization: my_token
{"uniqueId": 123, "myorder": 1}
HTTP 200
Both token and uniqueId are short-live.
The first line of the request is url-encoded every time, even when the path/parameters were not modified. In many cases this results in an improper response from the server. I'd propose the following updates:
Excellent work, thank you.
ensure that monospaced font is obtained for free from messageviewer control, or otherwise implement it
In the modify_message function, when dynamically generating the regex value, special characters are not escaped if they're part of a named group (?P<{}>{}). When executing "match_exp = re_compile(exp + groups_exp)", groups_exp may contain special that will either generate an error or unexpected behavior.
Workaround:
In my case I was extracting a string that sometimes contains a + (base64-ish) with the following regex "token": "(?P<token>[^"]+)
.
I substituted lines 462, 463
match_exp = re_compile(exp + groups_exp)
self.logger.debug('match_exp adjusted to:\n{}'.format(match_exp.pattern))
with
try:
match_exp = re_compile(exp + groups_exp.replace('+','\+'))
except re_error as e:
self.logger.error(exc_invalid_regex.format(ph_target_exp, e))
return msg_as_string
This workaround only fixed my case (+ char in extracted group), groups_exp should be properly escaped for all regex special characters before being recompiled.
Edit: workaround was not so clear.
Hey,
thanks for the great plugin. It was helping me through so many security assessments. Unfortunately, with the newest Burp Pro version v2021.12.1 and with only CPH plugin enabled, the Burp process hangs indefinitely after the active scanning is run for about 15-30 minutes :(
Any help or suggestion?
thanks
Rafal
When a CPH tab uses the "values returned by issuing a single request" the HTTP message editor window has an infinite scrolling issue.
This issue has been reported by Burp Suite to other extensions, including upload scanner:
modzero/mod0BurpUploadScanner#60
We’ve just released a new version of Burp that has some big changes to the HTTP message editor.
Notably, a scroll pane is now implemented inside the message editor.
Unfortunately, this has caused an infinite scrolling issue with your extension. This was reported to us by a user of your BApp, who provided a video of the issue (https://monosnap.com/file/Gqw1tXkXKupRRSAsBSEN3rcjbAYyDw).
If possible, could you remove the scroll pane instance you have implemented, and create a pull request against the PortSwigger branch of your repository so that we can review the changes and update the BApp?
When resizing the Burp window to be more horizontally narrow, the "Determine where.." and "Match indices.." text entry fields (including the RegEx checkbox) can overlap each other, causing relevant data and/or UI controls to be obscured.
Add radio buttons for "first match", "all matches", and "custom".
With First selected, "0" value is in the field and the field is disabled.
With All selected, "0:-1,-1" value is in the field and the field is disabled.
With custom selected, the value does not change from it's previous setting until the user changes it, and the field is enabled.
If there are complex CSRF parameters (e.g. name of the parameter is also of a unique value), currently, native Burp session management doesn't support handling them. When I want to configure it manually, and use as part of Active scanner, there are many more requests in session tracer. Would it be possible to somehow bind this extender to session manager, so that a request would be used only once per valid session? At the moment, when I have 2 tabs of CPH, each of which is set to replace "a value returned by issuing a single request", there are many extra requests made, whereas 1 or 2 per the entire session would be all that is necessary.
Many thanks
Hello!
I propose we add support for back references in the find/replace system. As part of this, we should also closely examine the replacement code because some cases of regex are not supported correctly.
For example: (?<=abc)(def)
on the text "xyzdefabcdef"
with replacement of "ghi"
results in "xyzghiabcghi"
because the system, while it executes the search properly at first, ends up using simplistic search instead because it tries to find matches to values it matched on, which is incorrect behavior.
https://github.com/elespike/burp-cph/blob/master/CustomParamHandler.py#L393-L395
https://github.com/elespike/burp-cph/blob/master/CustomParamHandler.py#L498-L502
Would it be possible to add a global transparent rule to hook into all responses for parsing? As far as I can tell, at this point, CPH needs to create some traffic for parsing. I hope it will be more clear on my API example:
Request 1:
POST /api/v1/CreateNew HTTP/1.1
{"comment":"Just a test", "name":"Johnny"}
Response 1 (a unique identifier is used, which I need to parse and remember):
HTTP/1.1 201 Created
{"Identifier":"123456789"}
Request 2 (note the change in URL, to use parsed value from the last response):
GET /api/v1/GetByID/123456789
Response 2:
HTTP/1.1 200 OK
{"comment":"Just a test", "name":"Johnny", "status":"New", "id":"123456789"}
At this point in time, I'm not aware of any Burp native functionality or Extender, which would allow for Actively scanning 1st request, while changing URL of the 2nd request, so that the scanner would only see 2nd response. I think with CPH I'm not able to do it, because I don't want to issue a request, sequence of requests, nor cached value from previous CPH tab. If there could be a new entry, like "value returned from all responses" it would be awesome:)
If I could create a regexp like "hey CPH, please hook into every single response; parse the latest version by regexp; and then use it to change the request I need to" it would be perfect:)
Sometimes when loading CPH config, the wrong "previous tab cached response" tab is selected.
In order for CPH to cache or modify traffic coming from a Macro test, CPH Tool scope settings must have the Target checkbox selected. This is not readily apparent, and may require some trial and error by a user before they understand why they cannot see Macro testing traffic in CPH. We could add Macros to this checkbox's label to make it read: "Target (incl. Macros)", or similar.
Create a tab or something akin to your usual logger that will show the original request as it came in and the final request that was issued.
This would be especially useful because many of Burp's tools will not update the UI when changes to the requests were made using the HTTPListener interface behind the scenes (which we do all the time).
Lastly, only display requests/responses that were actually modified.
Encountered an issue where the Carriage Return ASCII character (0d in hex, \r) is being stripped from matching lines causing malformed HTTP requests.
Below shows a sample CPH tab configured to replace an Authorization bearer header token that will currently result in a malformed HTTP request. This configuration previously worked. This issue appears to occur when the initial match (box 1) is intended to stop at the end of the line, such as when a header is being replaced.
Below is the final HTTP request sent after CPH replaces the bearer token. The cache-control header is the next header after thee bearer token. Note that the highlighted hex has the line ending character as a Line Feed (0a in hex) without a Carriage Return (0d in hex). HTTP requires both CRLF (0d 0a in hex, \r\n) for line endings.
I have not gone through the code however based on the behaviour observed I belieive the "Find matches to this expression" may now be terminating the line at the Line Feed character \n, capturing the \r in the replacement group, resulting in it being stripped from requests CPH modifies.
The below screenshot shows the current workaround, append the Carriage Return in the "Replace each Target" field if you are getting HTTP 400 Bad Requests.
Similar to how the Labels in the message modification scope change based on which radio button is selected, we should consider doing this for the Match Options label also.
I am having an internal application where I am trying to automate the testing using CPH extension. It handles few parameters dynamically.
From first request, we are extracting few parameters and use those in the subsequent request.
The hurdle we are facing is, we couldn't extract the values of the parameters. And also some help on how to calculate the regex would help.
Attached the demo request for reference as uploading was not allowed.
your help is highly appreciated.
In some cases, more than one parameter needs to be tracked. In my particular use case, it is a CSRF token and object version ID that change for each request. The sequence is:
This could be implemented as tabs under "parameter handling" in each tab of CPH.
Hi Marius! First of all thank you very much for your burp-cph,it helps me a lot ! But i meet a scenario that seems can't be solved by this burpsuite extension
Scenario description likes below:
In this kind of scenario , how could i use this extension to issue a right request!
I read all your document,but it seems can't solve my problem!
I'm looking forward to your reply😊😊😊😊
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.