Code on a computer screen

Replaying Security: From Manual Test Requests to Test Scripts

Preparing for another day

Kalles Group Pen Tester Stan Steenhuis, describes how the investment in constructing custom test requests can be turned into repeatable scripted tests. By adding this process into your pen testing methodology, you can easily develop your existing custom test collection and empower other pen testers on your team to perform these tests.

Discovering a significant new issue in a manual penetration test is traditionally followed by documenting the evidence right after the happy dance and opens the door for the next phase: the creation of a repeatable test recording as a proof of concept for the exploit or finding. Armed with this functional test script you can quickly duplicate the evidence during the out-briefing with the client and the code owners can run the test again without the penetration tester or their fancy tools if the test is scripted in any of the three most common scripting languages: curl, PowerShell or python.

Most of the work is done in manual requestors (crafting a specific POST, PUT or GET) where there is a creation of the offending request that produces the security fail. While I have used the manual request editor in IBM’s Appscan™, OWASP Zap, Charles proxy, Smartbear’s Ready!API (ex-SOAPUI) and POSTMAN; I have found the [Repeater] tab in PortSwigger™’s Burp Suite also has functional support to create the test scripts from the requests in addition to an extensibility extensible API that is extremely rich and powerful where I can code enhancements. The most efficient process in penetration testing is to cast a wide net and sift quickly for rapid discovery by importing the code owners project files (READY!API) or collections (POSTMAN from Google) as well as recorded QA test scripts in Selenium, Fiddler™, or curl from the application owners.

After you have imported a copy of the above-mentioned possible development resources, you can play the tests into your instance of Burp Suite Professional by opening a listener to all interfaces and specify a non-standard port (such as 8081). You can now set your system proxy or, even better, the testing tool’s proxy to use this listener (set to localhost:8081 in the example below)

Proxy configuration screenPlay the traffic from Ready!API, Fiddler™, Postman or the scripts into the burp MITM proxy and then perform your standard manual penetration plan discovery processes and perform an active scan where you configure intelligent entry points for active scanning.

For example, this is the standard test application flow to reproduce an authenticated session security fail below:

Application flow chartThere should be two open tabs in the burp suite repeater at this point when you have found something “interesting”, the open tab for the request which grants authentication and another tab for the subsequent request which produces the failing response. If your application also fails with immortal cookies or bearer tokens that last for years, you can just generate the code for the test request with a right click by using the reissue request scripting extension and ship it off to or replay it for the delivery recipients. This useful extension is found here on Github:

Using this plugin will let you add PowerShell or Python scripting to the already existing curl functionality built in out of the box. Right clicking inside the request body of the authentication request open tab in repeater after installing the extension will create this popup dialog:

Script generator dialogMost likely there will be a need to reestablish authentication to the application when the test script is replayed later, so the process is to generate the code in the tool extension popup for the authentication request, parse the response from the server for either the session cookies or bearer authorization tokens in the header and then patch the second request downstream in the (also generated) code. In python, the code would look something like this:

1. session = requests.Session()
2. response = session.get("http://targetwebapp/", headers=headers)
3. XSRF_TOKEN = response.headers['Set-Cookie'].split(';')[0]
4. SESSION = response.headers['Set-Cookie'].split(';')[3].split(',')[1].replace(" ", "")

Since you generate the code for the authentication and test requests using the utility, the only effort is to supply the code to make the 2nd request have proper authentication. I usually have such snippets sitting around in notepad++ so I can create the two scripts, edit and paste the code for the session management and then add this test script to my security report delivery folder along with screenshots, XLS pivot tables of findings, my logs, etc.

By adding the appropriate error levels and conditions to reflect what happened [set errorlevel=1 or exit 1] ensures that the test scripts are ready for running in automation frameworks like Jenkins.