├── .gitignore ├── BappDescription.html ├── BappManifest.bmf ├── LICENSE ├── README.md ├── build.gradle ├── images ├── Autowasp1.png ├── Logger Tool.PNG ├── OWASP WSTG.PNG ├── SendfromProxy.gif ├── Setup_jar_file.png ├── Setup_project_resources.png ├── addTargetScope.gif ├── fetchChecklist.gif ├── generateReport.gif ├── mapToCheckList.gif ├── scannerLogic.gif ├── trafficLogging.gif ├── uploadChecklist.gif └── writeComments.gif ├── pom.xml ├── release ├── Autowasp_v1.0.1.jar └── Autowasp_v1.0.jar └── src └── main ├── java ├── autowasp │ ├── Autowasp.java │ ├── ExtenderPanelUI.java │ ├── ProjectWorkspaceFactory.java │ ├── checklist │ │ ├── ChecklistEntry.java │ │ ├── ChecklistLogic.java │ │ ├── ChecklistTable.java │ │ └── ChecklistTableModel.java │ ├── http │ │ ├── ContextMenuFactory.java │ │ ├── ContextMenuInvocation.java │ │ ├── HTTPRequestResponse.java │ │ ├── HTTPService.java │ │ ├── InterceptProxyMessage.java │ │ └── ScanIssue.java │ └── logger │ │ ├── ScannerLogic.java │ │ ├── TrafficEntry.java │ │ ├── TrafficInstance.java │ │ ├── TrafficLogic.java │ │ ├── entryTable │ │ ├── LoggerEntry.java │ │ ├── LoggerTable.java │ │ └── LoggerTableModel.java │ │ └── instancesTable │ │ ├── InstanceEntry.java │ │ ├── InstanceTable.java │ │ └── InstancesTableModel.java └── burp │ ├── .gitignore │ └── BurpExtender.java └── resources ├── META-INF └── MANIFEST.MF └── OWASP_WSTG_local_07Jul2022 /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | out/ 3 | 4 | .idea/ 5 | 6 | target/ 7 | 8 | src/main/.DS_Store 9 | 10 | src/main/java/.DS_Store 11 | 12 | *.iml 13 | 14 | .DS_Store 15 | 16 | src/main/java/burp/ 17 | !src/main/java/burp/BurpExtender.java 18 | !src/main/java/burp/.gitignore 19 | 20 | build/ 21 | 22 | src/main/java/META-INF/ 23 | -------------------------------------------------------------------------------- /BappDescription.html: -------------------------------------------------------------------------------- 1 |

Autowasp, a Burp Suite extension that integrates Burp issues logging, with OWASP Web Security Testing Guide (WSTG), to provide a streamlined web security testing flow for the modern-day penetration tester! This tool will guide new penetration testers to understand the best practices of web application security and automate OWASP WSTG checks.

2 | 3 |

Currently, Autowasp supports the following functionalities:

4 | 9 | 10 |

A general testing workflow using Autowasp would include the following steps:

11 |
    12 |
  1. Display the OWASP checklist in Autowasp for reference.
  2. 13 |
  3. Add the target URL to Scope. The scope function will extract related results from Burp Scanner and listen for insecure web request and responses.
  4. 14 |
  5. Map the scan issues to specific test cases in the checklist. OR
  6. 15 |
  7. Manually explore the website's pages, then click Enable Burp Scanner Logging to display the scanner issues under the Logger tab.
  8. 16 |
  9. Map findings to the checklist.
  10. 17 |
  11. Insert security observations and evidence associated with the logs.
  12. 18 |
  13. Generate a report containing the checklist, logs, evidence, and comments.
  14. 19 |
-------------------------------------------------------------------------------- /BappManifest.bmf: -------------------------------------------------------------------------------- 1 | Uuid: b89968942a3e4cab916b6c761beb2003 2 | ExtensionType: 1 3 | Name: Autowasp 4 | RepoName: autowasp 5 | ScreenVersion: 1.0 6 | SerialVersion: 1 7 | MinPlatformVersion: 0 8 | ProOnly: False 9 | Author: Thomas Lim 10 | ShortDescription: Integrates Burp issues logging, with OWASP Web Security Testing Guide (WSTG), to provide a streamlined web security testing flow for the modern-day penetration tester! 11 | EntryPoint: target/autowasp-1.0-SNAPSHOT-jar-with-dependencies.jar 12 | BuildCommand: mvn clean compile assembly:single 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Government Technology Agency 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Autowasp # 2 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 3 | 4 | ![picture](./images/Autowasp1.png) 5 | 6 | Welcome to Autowasp, a Burp Suite extension that integrates Burp issues logging, with OWASP Web Security Testing Guide (WSTG), to provide a streamlined web security testing flow for the modern-day penetration tester! This tool will guide new penetration testers to understand the best practices of web application security and automate OWASP WSTG checks. This README will provide an introduction to the key features of Autowasp, the steps to download and use the tool, and end off by sharing how security researchers and developers can make this tool better! 7 | 8 | # Existing features # 9 | 10 | Currently, Autowasp supports the following functionalities: 11 | 12 | **1. Testing Checklist - Be guided by OWASP!** 13 | 14 | With the ability to fetch the OWASP WSTG checklist, Autowasp aims to aid new penetration testers in conducting penetration testing or web application security research. The testing checklist tab will extract useful information such as: 15 | 16 | * Summary of OWASP WSTG test cases 17 | * How to test – black/white box testing 18 | * Relevant testing tools to aid your test 19 | * Relevant testing tools to aid your test 20 | 21 | ![picture](./images/OWASP%20WSTG.PNG) 22 | 23 | **2. Logger Tool - Log down the Vulns!** 24 | 25 | Autowasp Logger tab gives penetration testers the ability to extract and consolidate Burp Scanner issues. This extender tool will automate and flag vulnerable network traffic issues, allowing users to send vulnerable proxy items from Burp’s `proxy`, `intruder` and `repeater` tab to the extender. These vulnerable issues can then be mapped to WSTG IDs and be used to generate an Excel report upon engaging in a penetration test.on test. 26 | ![picture](./images/Logger%20Tool.PNG) 27 | ![trafficLogging](./images/trafficLogging.gif) 28 | 29 | # Prerequisites # 30 | 31 | - Burp Suite Professional 32 | 33 | # Dependencies # 34 | 35 | - Apache commons collections 4.3 36 | - Apache commons compress 1.18 37 | - GSON 2.8.5 38 | - Jsoup 1.12.1 39 | - Apache POI 4.1.0 40 | - XMLBeans 3.1.0 41 | - Burp Extender APIs 1.7.13 42 | 43 | # Installation # 44 | ## Building the jar 45 | ***Alternatively, you can use the pre-compiled JAR [here](https://github.com/govtech-csg/Autowasp/releases)*** 46 | ### Using IntelliJ IDE 47 | 1. Clone the repository to a location of your choice 48 | ``` 49 | git clone https://github.com/govtech-csg/Autowasp.git 50 | ``` 51 | 2. Open IntelliJ, you can either import Project or Open Project (***File > Open..***) 52 | 3. Head to ***File>Project Structure...*** (***Ctrl+Alt+Shift+S***) 53 | 4. Under Main Class, select ***BurpExtender (burp)*** 54 | 5. Under ***Project Settings***, select ***Artifacts***, click the ***+***, add ***JAR*** and select ***From modules with dependencies..*** 55 | ![picture](./images/Setup_jar_file.png) 56 | 6. Under Main Class, select BurpExtender (burp). Click Ok 57 | 7. Similarly under ***Project Settings**, select ***Modules***, add /src/main/resources as your project resources. 58 | ![picture](./images/Setup_project_resources.png) 59 | 7. Click apply at bottom right and close ***Project Settings*** 60 | 8. Click Build Project (***Build > Build Project***) 61 | 9. The autowasp.jar file will be built in `/Autowasp/out/artifacts/autowasp_jar/autowasp.jar` 62 | 63 | ### Using Command Line 64 | 65 | 1. Clone the repository to a location of your choice 66 | ``` 67 | git clone https://github.com/govtech-csg/Autowasp.git 68 | ``` 69 | 2. Run the following command 70 | ``` 71 | cd Autowasp 72 | mvn clean compile assembly:single 73 | ``` 74 | 3. The autowasp.jar file will be built in `/Autowasp/target/autowasp-1.0-SNAPSHOT-jar-with-dependencies.jar` 75 | 76 | ## Installing the jar 77 | 1. Download the release build [here](https://github.com/govtech-csg/Autowasp/releases). 78 | 2. Open Burp Suite. 79 | - Professional version: 80 | - Either temporary project or new/existing project 81 | - Default/preferred settings 82 | 2. Click on **Extender** located on the top row of tabs. 83 | 3. Under the **Extensions** tab on the second row, click **Add**. 84 | 4. Under **Extension Details**, click **Select file** and select the Autowasp JAR file, then click **Next**. 85 | 5. You should see no output or errors and a new tab labelled Autowasp on the top row. 86 | 87 | # Usage 88 | 89 | ***A general testing workflow using Autowasp would include the following steps:*** 90 | 91 | 1. Display the OWASP checklist in Autowasp for reference. 92 | 2. Add the target URL to **Scope**. The scope function will extract related results from Burp Scanner and listen for insecure web request and responses. 93 | 3. Map the scan issues to specific test cases in the checklist. OR 94 | 4. Manually explore the website's pages, then click **Enable Burp Scanner Logging** to display the scanner issues under the **Logger** tab. 95 | 5. Map findings to the checklist. 96 | 6. Insert security observations and evidence associated with the logs. 97 | 7. Generate a report containing the checklist, logs, evidence, and comments. 98 | 99 | ## **1. Displaying the Testing checklist** ## 100 | 101 | ### First time: ### 102 | 1. Click the **Fetch WSTG Checklist** button to fetch the checklist from the forked [WSTG documentation](https://github.com/GovTech-CSG/www-project-web-security-testing-guide/blob/master/v42/4-Web_Application_Security_Testing/README.md). (Note: this may take a few minutes due to the number of pages) 103 | 2. If you are working in an offline environment, click **Load local checklist** to start your penetration testing work. Do note that local checklist may not be updated frequently. 104 | ![fetchChecklist](./images/fetchChecklist.gif) 105 | 106 | ### Subsequent times: ### 107 | 1. Choose **Load local checklist** to start your penetration testing work. 108 | 2. This should load the checklist almost instantly. 109 | ![uploadChecklist](./images/uploadChecklist.gif) 110 | 111 | ### Excluding Checklist item(s): ### 112 | * If you find test cases that do not apply to your test, you can exclude these items by selecting the checkbox on the right. 113 | 114 | ## **2. Adding to scope and scanning** ## 115 | 1. Add the target URL to scope and perform scan. 116 | ![addTargetScope](./images/addTargetScope.gif) 117 | 118 | 2. Manually explore the website's pages, then click **Enable Burp Scanner Logging** to display the scanner issues under the **Logger** tab. 119 | ![scannerLogic](./images/scannerLogic.gif) 120 | 121 | 3. Note that items from **Proxy -> HTTP History**, **Intruder** & **Repeater** tabs can be sent to Autowasp by right-clicking on them, followed by clicking **Send to Autowasp**. 122 | ![SendfromProxy](./images/SendfromProxy.gif) 123 | 124 | ## **3. Mapping findings to the checklist** ## 125 | 126 | - Click on a specific log in the **Logger** table. 127 | - Click on the empty **Mapped to OWASP WSTG** field on the right side of the table entry. 128 | - Choose a specific test to map the log to using the drop-down list. 129 | * Note that his will only work if you have the checklist already displayed. 130 | ![mapToCheckList](./images/mapToCheckList.gif) 131 | 132 | ## **4. Insert security observations and evidence associated with the logs** ## 133 | 1. Click on a specific log in the **Logger** table. 134 | 2. On the lowest row of tabs, click on either **Pen Tester Comments** or **Evidence**. 135 | 3. Enter what you wish to note down, then click **Save Comments** or **Save Evidence**. 136 | ![writeComments](./images/writeComments.gif) 137 | 138 | ## **5. Report Generation** ## 139 | 140 | 1. Click on **Generate Excel File** and choose a location to save the file to. 141 | 2. Open the excel file and check that the observation, comments, and evidence have been saved beside the associated test case 142 | 3. You can also find the URL pointing to the full article hosted on OWASP's GitHub repository for every test case in the checklist 143 | ![generateReport](./images/generateReport.gif) 144 | 145 | # Contributing # 146 | 147 | [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/govtech-csg/Autowasp/issues) 148 | 149 | Do you have ideas to make Autowasp even more useful? We welcome contributions from developers like yourself to improve the Autowasp tool and highlight any potential problems. Here are some important resources to get you started: 150 | 151 | * [Burp Extender APIs](https://portswigger.net/burp/extender/api/burp/package-summary.html) 152 | * [Singapore Government Developer Portal](https://www.developer.tech.gov.sg/) - leverage on our latest technological solutions, execute your digital projects, and join our community of developers. 153 | * If you find bugs, log us an [issue ticket](https://github.com/govtech-csg/Autowasp/issues) to report them. Do ensure that the bug has not already been reported by searching on GitHub under Issues. 154 | * Have a question but unsure who to contact, log us an [issue ticket](https://github.com/govtech-csg/Autowasp/issues) and we will reach out to you. 155 | 156 | ## Submitting changes 157 | Please send a [GitHub Pull Request to us](https://github.com/govtech-csg/Autowasp/pull/new/master) with a clear list of what you've done (read more about [pull requests](http://help.github.com/pull-requests/)). 158 | 159 | Always write a clear log message for your commits. We accept one-liners for small changes, but bigger changes should include changes and impact: 160 | $ git commit -m "A brief summary of the commit 161 | > 162 | > A paragraph describing what changed and its impact." 163 | 164 | ## Coding conventions 165 | 166 | Start reading our code and you'll get the hang of it. The code serves as an extention module to BurpSuite to extend functionality of web security testing. Autowasp uses the following coding conventions: 167 | 168 | * We use Java for this extender. 169 | * Some of the Burp extender' APIs have been overwritten in order for us to have better control of the extender’s behaviour. Refer to overwritten classes [here](https://github.com/govtech-csg/Autowasp/tree/master/src/main/java/autowasp/http). 170 | * Please do not add additional table listener as it affects the user experience of the extender. That said, we welcome changes to make Autowasp better! 171 | * Add a comment whenever you include a new function so that we can understand your contribution better. 172 | 173 | Autowasp is an open-source software so bear in mind that the open-source community can read your code. Do adhere to our coding conventions detailed in GitHub Readme and keep your codes understandable and easy to follow. Think of it like driving a car: you may love performing doughnuts but you have to consider the well-being of your passengers and make the ride as smooth as possible. That is of course, unless your passengers love the thrill as well. 174 | 175 | 176 | # Authors # 177 | 178 | 👤 **[@imthomas93](https://github.com/imthomas93)** 179 | 180 | 👤 **[@retaric](https://github.com/retaric)** 181 | 182 | 👤 **[@kaiyu92](https://github.com/kaiyu92)** 183 | 184 | 👤 **[@aloy-wee-sious](https://github.com/aloy-wee-sious)** 185 | 186 | 👤 **[@matthewng1996](https://github.com/matthewng1996)** 187 | 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | repositories { 4 | mavenCentral() 5 | } 6 | 7 | dependencies { 8 | compile 'net.portswigger.burp.extender:burp-extender-api:1.7.22' 9 | } 10 | 11 | sourceSets { 12 | main { 13 | java { 14 | srcDir 'src' 15 | } 16 | resources { 17 | srcDir 'resources' 18 | } 19 | } 20 | } 21 | 22 | task fatJar(type: Jar) { 23 | 24 | baseName = project.name + '-all' 25 | from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } 26 | with jar 27 | } 28 | 29 | compileJava { 30 | targetCompatibility '1.8' 31 | sourceCompatibility '1.8' 32 | } 33 | -------------------------------------------------------------------------------- /images/Autowasp1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/images/Autowasp1.png -------------------------------------------------------------------------------- /images/Logger Tool.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/images/Logger Tool.PNG -------------------------------------------------------------------------------- /images/OWASP WSTG.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/images/OWASP WSTG.PNG -------------------------------------------------------------------------------- /images/SendfromProxy.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/images/SendfromProxy.gif -------------------------------------------------------------------------------- /images/Setup_jar_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/images/Setup_jar_file.png -------------------------------------------------------------------------------- /images/Setup_project_resources.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/images/Setup_project_resources.png -------------------------------------------------------------------------------- /images/addTargetScope.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/images/addTargetScope.gif -------------------------------------------------------------------------------- /images/fetchChecklist.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/images/fetchChecklist.gif -------------------------------------------------------------------------------- /images/generateReport.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/images/generateReport.gif -------------------------------------------------------------------------------- /images/mapToCheckList.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/images/mapToCheckList.gif -------------------------------------------------------------------------------- /images/scannerLogic.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/images/scannerLogic.gif -------------------------------------------------------------------------------- /images/trafficLogging.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/images/trafficLogging.gif -------------------------------------------------------------------------------- /images/uploadChecklist.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/images/uploadChecklist.gif -------------------------------------------------------------------------------- /images/writeComments.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/images/writeComments.gif -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 4.0.0 22 | 23 | autowasp 24 | autowasp 25 | jar 26 | 1.0-SNAPSHOT 27 | 28 | 29 | 30 | UTF-8 31 | 1.8 32 | 1.8 33 | 34 | 35 | 36 | 37 | 38 | org.apache.commons 39 | commons-collections4 40 | 4.4 41 | 42 | 43 | 44 | 45 | org.apache.commons 46 | commons-compress 47 | 1.21 48 | 49 | 50 | 51 | 52 | com.google.code.gson 53 | gson 54 | 2.9.0 55 | 56 | 57 | 58 | 59 | org.jsoup 60 | jsoup 61 | 1.14.3 62 | 63 | 64 | 65 | 66 | org.apache.poi 67 | poi 68 | 5.2.2 69 | 70 | 71 | 72 | 73 | org.apache.poi 74 | poi-ooxml 75 | 5.2.2 76 | 77 | 78 | 79 | 80 | org.apache.poi 81 | poi-ooxml-schemas 82 | 4.1.2 83 | 84 | 85 | * 86 | org.bouncycastle 87 | 88 | 89 | 90 | 91 | 92 | 93 | org.apache.xmlbeans 94 | xmlbeans 95 | 5.0.3 96 | 97 | 98 | 99 | 100 | net.portswigger.burp.extender 101 | burp-extender-api 102 | 2.3 103 | 104 | 105 | 106 | 107 | 108 | 109 | maven-assembly-plugin 110 | 3.2.0 111 | 112 | 113 | 114 | burp.BurpExtender 115 | 116 | 117 | 118 | jar-with-dependencies 119 | 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /release/Autowasp_v1.0.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/release/Autowasp_v1.0.1.jar -------------------------------------------------------------------------------- /release/Autowasp_v1.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/release/Autowasp_v1.0.jar -------------------------------------------------------------------------------- /src/main/java/autowasp/Autowasp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp; 18 | 19 | import autowasp.checklist.*; 20 | import autowasp.http.*; 21 | import autowasp.logger.ScannerLogic; 22 | import autowasp.logger.TrafficEntry; 23 | import autowasp.logger.TrafficLogic; 24 | import autowasp.logger.entryTable.LoggerEntry; 25 | import autowasp.logger.entryTable.LoggerTable; 26 | import autowasp.logger.entryTable.LoggerTableModel; 27 | import autowasp.logger.instancesTable.InstanceEntry; 28 | import autowasp.logger.instancesTable.InstanceTable; 29 | import autowasp.logger.instancesTable.InstancesTableModel; 30 | import burp.*; 31 | 32 | import javax.swing.*; 33 | import java.awt.*; 34 | import java.io.PrintWriter; 35 | import java.net.MalformedURLException; 36 | import java.net.URL; 37 | import java.util.ArrayList; 38 | import java.util.Arrays; 39 | import java.util.HashMap; 40 | import java.util.List; 41 | 42 | public class Autowasp implements IBurpExtender, ITab, IMessageEditorController, IScannerListener, IProxyListener { 43 | public IBurpExtenderCallbacks callbacks; 44 | public IExtensionHelpers helpers; 45 | public IBurpCollaboratorClientContext iBurpCollaboratorClientContext; 46 | public PrintWriter stdout; 47 | public PrintWriter stderr; 48 | public TrafficLogic trafficLogic; 49 | public ExtenderPanelUI extenderPanelUI; 50 | public JSplitPane gtScannerSplitPane; 51 | public ChecklistLogic checklistLogic; 52 | public ChecklistTableModel checklistTableModel; 53 | public ChecklistTable checklistTable; 54 | public final List checklistLog = new ArrayList<>(); 55 | public final HashMap checkListHashMap = new HashMap<>(); 56 | public final List trafficLog = new ArrayList<>(); 57 | public LoggerTableModel loggerTableModel; 58 | public InstancesTableModel instancesTableModel; 59 | public LoggerTable loggerTable; 60 | public InstanceTable instanceTable; 61 | public final List loggerList = new ArrayList<>(); 62 | public final List instanceLog = new ArrayList<>(); 63 | public ScannerLogic scannerLogic; 64 | public ProjectWorkspaceFactory projectWorkspace; 65 | public JComboBox comboBox; 66 | public JComboBox comboBox2; 67 | public JComboBox comboBox3; 68 | public int currentEntryRow; 69 | 70 | // Implementing IBurpExtender 71 | @Override 72 | public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks) 73 | { 74 | // keep a reference to our callback object 75 | this.callbacks = callbacks; 76 | 77 | // obtain iBurpCollaborator object 78 | this.iBurpCollaboratorClientContext = callbacks.createBurpCollaboratorClientContext(); 79 | 80 | // obtain an extension helpers object 81 | helpers = callbacks.getHelpers(); 82 | 83 | // set our extension name 84 | callbacks.setExtensionName("Autowasp"); 85 | 86 | stdout = new PrintWriter(callbacks.getStdout(), true); 87 | stderr = new PrintWriter(callbacks.getStderr(), true); 88 | this.extenderPanelUI = new ExtenderPanelUI(this); 89 | 90 | // Initialize variables for logger features 91 | this.instancesTableModel = new InstancesTableModel(instanceLog); 92 | this.instanceTable = new InstanceTable(instancesTableModel, this); 93 | 94 | this.loggerTableModel = new LoggerTableModel(loggerList); 95 | this.loggerTable = new LoggerTable(loggerTableModel, this); 96 | 97 | this.scannerLogic = new ScannerLogic(this); 98 | this.trafficLogic = new TrafficLogic(this); 99 | 100 | // Initialize variables for OWASP checklist feature 101 | this.checklistLogic = new ChecklistLogic(this); 102 | this.checklistTableModel = new ChecklistTableModel(this); 103 | this.checklistTable = new ChecklistTable(checklistTableModel, this); 104 | 105 | // Saving project state feature 106 | this.projectWorkspace = new ProjectWorkspaceFactory(this); 107 | 108 | // Create our IContextMenu 109 | // IContextMenu 110 | ContextMenuFactory contextMenu = new ContextMenuFactory(this); 111 | this.callbacks.registerContextMenuFactory(contextMenu); 112 | 113 | // Bind Issue ComboBox to loggerTable column number 5 114 | this.comboBox = new JComboBox<>(); 115 | this.loggerTable.setUpIssueColumn(loggerTable.getColumnModel().getColumn(4)); 116 | 117 | // Bind Confidence ComboBox to instanceTable column number 2 118 | this.comboBox2 = new JComboBox<>(); 119 | this.instanceTable.generateConfidenceList(); 120 | instanceTable.setUpConfidenceColumn(instanceTable.getColumnModel().getColumn(2)); 121 | 122 | // Bind Severity ComboBox in instanceTable column number 3 123 | this.comboBox3 = new JComboBox<>(); 124 | this.instanceTable.generateSeverityList(); 125 | instanceTable.setupSeverityColumn(instanceTable.getColumnModel().getColumn(3)); 126 | 127 | // create our UI 128 | SwingUtilities.invokeLater(() -> { 129 | extenderPanelUI.run(); 130 | callbacks.registerProxyListener(Autowasp.this); 131 | 132 | // customize our UI components 133 | callbacks.customizeUiComponent(gtScannerSplitPane); 134 | 135 | // add the custom tab to Burp's UI 136 | callbacks.addSuiteTab(Autowasp.this); 137 | }); 138 | } 139 | 140 | // implement ITab 141 | @Override 142 | public String getTabCaption(){ 143 | return "Autowasp"; 144 | } 145 | 146 | @Override 147 | public Component getUiComponent() { 148 | return gtScannerSplitPane; 149 | } 150 | 151 | @Override 152 | public void newScanIssue(IScanIssue Iissue) { 153 | ScanIssue issue = new ScanIssue(Iissue); 154 | if (this.callbacks.isInScope(issue.getUrl()) && !this.scannerLogic.getRepeatedIssue().contains(issue.getIssueName())){ 155 | this.scannerLogic.getRepeatedIssue().add(issue.getIssueName()); 156 | callbacks.issueAlert("New Scan found " + issue.getIssueName()); 157 | // 1. Create a new finding record 158 | scannerLogic.logNewScan(issue); 159 | // 2. Log this instance 160 | scannerLogic.logNewInstance(issue); 161 | } 162 | else if (this.callbacks.isInScope(issue.getUrl()) && this.scannerLogic.getRepeatedIssue().contains(issue.getIssueName())) { 163 | // Identify the finding record is created and log the instance 164 | scannerLogic.logNewInstance(issue); 165 | } 166 | } 167 | 168 | @Override 169 | public void processProxyMessage(boolean messageIsRequest, IInterceptedProxyMessage message) { 170 | try { 171 | InterceptProxyMessage interceptProxyMessage = new InterceptProxyMessage(message); 172 | URL url = new URL(message.getMessageInfo().getHttpService().toString()); 173 | if (callbacks.isInScope(url)){ 174 | if (!messageIsRequest) { 175 | synchronized (trafficLog) { 176 | trafficLogic.classifyTraffic(interceptProxyMessage); 177 | } 178 | } 179 | } 180 | } catch (MalformedURLException e) { 181 | stdout.println("MalformedURLException at processProxyMessage()"); 182 | } 183 | } 184 | 185 | @Override 186 | public IHttpService getHttpService() { 187 | return null; 188 | } 189 | 190 | @Override 191 | public byte[] getRequest() { 192 | return new byte[0]; 193 | } 194 | 195 | @Override 196 | public byte[] getResponse() { 197 | return new byte[0]; 198 | } 199 | } -------------------------------------------------------------------------------- /src/main/java/autowasp/ExtenderPanelUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp; 18 | 19 | import burp.IMessageEditor; 20 | 21 | import java.awt.*; 22 | 23 | import java.net.MalformedURLException; 24 | import java.net.URISyntaxException; 25 | import java.net.URL; 26 | import javax.swing.*; 27 | import javax.swing.border.EmptyBorder; 28 | import javax.swing.event.HyperlinkEvent; 29 | import java.io.IOException; 30 | import java.io.File; 31 | 32 | import java.util.List; 33 | import java.util.concurrent.atomic.AtomicBoolean; 34 | 35 | public class ExtenderPanelUI implements Runnable{ 36 | 37 | private final Autowasp extender; 38 | private JSplitPane gtScannerSplitPane; 39 | public IMessageEditor requestViewer; 40 | public IMessageEditor responseViewer; 41 | private JFileChooser destDirChooser; //This file chooser is now used to choose the directories for both the scan report and the OWASP checklist files 42 | public JLabel scanStatusLabel; 43 | private JTextField hostField; 44 | 45 | // Checklist UI 46 | public JTextPane summaryTextPane; 47 | public JEditorPane howToTestTextPane; 48 | public JTextPane referencesTextPane; 49 | JButton enableScanningButton; 50 | private JButton generateWebChecklistButton; 51 | private Thread thread; 52 | public final AtomicBoolean running = new AtomicBoolean(false); 53 | public JButton cancelFetchButton; 54 | private JButton saveLocalCopyButton; 55 | private JButton generateLocalChecklistButton; 56 | private JButton generateExcelReportButton; 57 | private JFileChooser fileChooser; 58 | private File checklistDestDir; 59 | private final boolean selfUpdateLocal = false; 60 | 61 | // Loggers UI 62 | private JTabbedPane bottomModulesTabs; 63 | public JTextPane penTesterCommentBox; 64 | public JTextPane evidenceBox; 65 | private JButton loadProjectButton; 66 | public JButton deleteEntryButton; 67 | public JButton deleteInstanceButton; 68 | 69 | ExtenderPanelUI(Autowasp extender) { 70 | this.extender = extender; 71 | } 72 | 73 | @Override 74 | public void run() { 75 | // scanner split pane 76 | gtScannerSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); 77 | bottomModulesTabs = new JTabbedPane(); 78 | 79 | setupTopPanel(); 80 | setupCheckListPanel(); 81 | setupLoggerPanel(); 82 | 83 | // Consolidate all modular tabs and set to the scanner bottom pane 84 | gtScannerSplitPane.setRightComponent(bottomModulesTabs); 85 | extender.gtScannerSplitPane = gtScannerSplitPane; 86 | } 87 | 88 | // This method setup the top panel view of Autowasp 89 | private void setupTopPanel() { 90 | //JPanel topPanel = new JPanel(new BorderLayout(10, 10)); 91 | JPanel topPanel = new JPanel(new GridLayout(4, 0)); 92 | topPanel.setBorder(new EmptyBorder(0, 0, 10, 0)); 93 | 94 | JPanel setupPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 10)); 95 | setupPanel.add(new JLabel("Target:", SwingConstants.LEFT), BorderLayout.LINE_START); 96 | hostField = new JTextField("", 15); 97 | JButton addToScopeButton = new JButton("Add Target to Scope"); 98 | addToScopeButton.addActionListener(e -> { 99 | // Filter the URL and add to scope 100 | String url = hostField.getText(); 101 | String sHost; 102 | String host; 103 | String sHost2; 104 | String host2; 105 | if(url.length() == 0) { 106 | return; 107 | } 108 | if(!url.contains("://")) { 109 | sHost = "https://" + url; 110 | host = "http://" + url; 111 | if (!url.contains("www.")){ 112 | sHost2 = "https://www." + url; 113 | host2 = "http://www." + url; 114 | } 115 | else{ 116 | sHost2 = sHost; 117 | host2 = host; 118 | } 119 | } 120 | else { 121 | if (!url.contains("https://")){ 122 | host = url; 123 | String tmp = url.substring(7); 124 | sHost = "https://" + tmp; 125 | if (!url.contains("www.")){ 126 | sHost2 = "https://www." + tmp; 127 | host2 = "http://www." + tmp; 128 | } 129 | else{ 130 | sHost2 = sHost; 131 | host2 = host; 132 | } 133 | } 134 | else { 135 | sHost = url; 136 | String tmp = url.substring(8); 137 | host = "http://" + tmp; 138 | if (!url.contains("www.")){ 139 | sHost2 = "https://www." + tmp; 140 | host2 = "http://www." + tmp; 141 | } 142 | else{ 143 | sHost2 = sHost; 144 | host2 = host; 145 | } 146 | } 147 | } 148 | try { 149 | extender.callbacks.includeInScope(new URL(sHost)); 150 | extender.callbacks.includeInScope(new URL(host)); 151 | extender.callbacks.includeInScope(new URL(sHost2)); 152 | extender.callbacks.includeInScope(new URL(host2)); 153 | scanStatusLabel.setText("Target added to scope: " + url); 154 | if (!enableScanningButton.isEnabled()){ 155 | // Automatically extract scan related to the newly added domain 156 | extender.scannerLogic.extractExistingScan(); 157 | } 158 | this.hostField.setText(""); 159 | } catch (MalformedURLException e1) { 160 | extender.stdout.println("Exception occurred at setupTopPanel"); 161 | } 162 | }); 163 | enableScanningButton = new JButton("Enable Burp Scanner logging"); 164 | enableScanningButton.addActionListener(e -> { 165 | extender.scannerLogic.extractExistingScan(); 166 | enableScanningButton.setEnabled(false); 167 | scanStatusLabel.setText("Extracted Scanner Logs. Passive Scanner logging enabled"); 168 | extender.callbacks.issueAlert("Extracted Scanner Logs. Passive Scanner logging enabled"); 169 | }); 170 | 171 | // Status bar 172 | JPanel scanStatusPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 10)); 173 | scanStatusPanel.add(new JLabel("Status: ", SwingConstants.LEFT)); 174 | scanStatusLabel = new JLabel("Ready to scan", SwingConstants.LEFT); 175 | 176 | //Checklist Panel: [Generate Checklist from Web] [Cancel Fetch] [Generate Checklist from Local Copy] [Save Local Copy] 177 | JPanel testingPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 10)); 178 | testingPanel.add(new JLabel("OWASP CheckList:", SwingConstants.LEFT), BorderLayout.LINE_START); 179 | fileChooser = new JFileChooser(); 180 | fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); //Allows user to load local copy of checklist from a txt file 181 | 182 | //On clicking, fetches checklist data from the web and displays it 183 | generateWebChecklistButton = new JButton("Fetch WSTG Checklist"); 184 | generateWebChecklistButton.addActionListener(e -> { 185 | 186 | extender.callbacks.issueAlert("Fetching checklist now"); 187 | scanStatusLabel.setText("Fetching checklist now"); 188 | generateLocalChecklistButton.setEnabled(false); 189 | cancelFetchButton.setEnabled(true); 190 | generateWebChecklistButton.setEnabled(false); 191 | extender.checklistLog.clear(); //Clears the current checklistLog so there won't be duplicates even if the user clicks on fetch checklist multiple times 192 | running.set(true); 193 | Runnable runnable = () -> { 194 | int counter = 1; 195 | List articleURLs; 196 | articleURLs = extender.checklistLogic.scrapeArticleURLs(); 197 | 198 | while(running.get() && counter < articleURLs.size()){ 199 | for (String url : articleURLs){ 200 | if (running.get()){ 201 | try{ 202 | Thread.sleep(500); 203 | extender.checklistLogic.logNewChecklistEntry(url); 204 | scanStatusLabel.setText("Fetching " + counter + " out of " + articleURLs.size()); 205 | counter++; 206 | } 207 | catch(InterruptedException e1){ 208 | Thread.currentThread().interrupt(); 209 | } 210 | } 211 | else{ 212 | // need to force stop the logging as new checklist entry here. 213 | extender.checklistLog.clear(); //Clears the current checklistLog so there won't be duplicates even if the user clicks on fetch checklist multiple times 214 | break; 215 | } 216 | } 217 | Thread.currentThread().interrupt(); 218 | break; 219 | } 220 | cancelFetchButton.setEnabled(false); 221 | generateExcelReportButton.setEnabled(true); 222 | saveLocalCopyButton.setEnabled(true); // For updating local checklist during development phase 223 | scanStatusLabel.setText("Checklist successfully generated from the web"); 224 | extender.callbacks.issueAlert("Checklist successfully generated from the web"); 225 | extender.loggerTable.generateWSTGList(); 226 | Thread.currentThread().interrupt(); 227 | }; 228 | thread = new Thread(runnable); 229 | thread.start(); 230 | }); 231 | 232 | //On clicking, cancel fetch checklist from web 233 | cancelFetchButton = new JButton("Cancel Fetch"); 234 | cancelFetchButton.addActionListener(e -> { 235 | generateWebChecklistButton.setEnabled(true); 236 | generateLocalChecklistButton.setEnabled(true); 237 | generateExcelReportButton.setEnabled(false); 238 | saveLocalCopyButton.setEnabled(false); 239 | cancelFetchButton.setEnabled(false); 240 | running.set(false); 241 | Thread.currentThread().interrupt(); 242 | extender.callbacks.issueAlert("Fetch checklist cancelled"); 243 | scanStatusLabel.setText("Fetch checklist cancelled"); 244 | }); 245 | 246 | //On clicking, opens a file chooser for the user to upload a local copy of the checklist 247 | generateLocalChecklistButton = new JButton("Upload Local WSTG Checklist"); 248 | generateLocalChecklistButton.addActionListener(e -> { 249 | generateLocalChecklistButton.setEnabled(false); 250 | generateWebChecklistButton.setEnabled(false); 251 | generateExcelReportButton.setEnabled(true); 252 | extender.checklistLogic.loadLocalCopy(); 253 | scanStatusLabel.setText("Local checklist uploaded to Autowasp."); 254 | }); 255 | 256 | //On clicking, opens a file chooser for the user to save a local copy of the checklist in a text file. Note that the contents of the file will be in HTML syntax 257 | saveLocalCopyButton = new JButton("Save a Local WSTG Checklist"); 258 | saveLocalCopyButton.addActionListener(e -> { 259 | //Ensures that the user can only try to save a local copy after fetching data from the web/uploading from an existing local copy 260 | if (extender.checklistLog.size() == 0) { 261 | scanStatusLabel.setText("Please fetch the checklist from the web first"); 262 | extender.callbacks.issueAlert("Please fetch the checklist from the web first"); 263 | } 264 | else { 265 | final int userOption = destDirChooser.showSaveDialog(null); //Returns the integer representation of the user's choice 266 | 267 | if (userOption == JFileChooser.APPROVE_OPTION) { 268 | checklistDestDir = destDirChooser.getSelectedFile(); 269 | try { 270 | extender.checklistLogic.saveLocalCopy(checklistDestDir.getAbsolutePath()); 271 | } catch (IOException ioException) { 272 | extender.stdout.println("IOException at setupTopPanel - saveLocalCopyButton" ); 273 | } 274 | extender.callbacks.issueAlert("Local checklist saved to "+ checklistDestDir.getAbsolutePath()); 275 | scanStatusLabel.setText("Local checklist saved to "+ checklistDestDir.getAbsolutePath()); 276 | } 277 | } 278 | }); 279 | 280 | // On clicking, opens a file chooser for the user to save a local copy of the checklist in an excel file 281 | generateExcelReportButton = new JButton("Generate Excel Report"); 282 | generateExcelReportButton.addActionListener(e -> { 283 | // Ensures that the user can only try to generate an excel file after fetching data from the web/uploading an existing local copy 284 | if (extender.checklistLog.size() == 0) { 285 | scanStatusLabel.setText("Please fetch the checklist from the web first"); 286 | extender.callbacks.issueAlert("Please fetch the checklist from the web first"); 287 | } 288 | else { 289 | final int userOption = destDirChooser.showSaveDialog(null); // Returns the integer representation of the user's choice 290 | 291 | if (userOption == JFileChooser.APPROVE_OPTION) { 292 | checklistDestDir = destDirChooser.getSelectedFile(); 293 | extender.checklistLogic.saveToExcelFile(checklistDestDir.getAbsolutePath()); 294 | } 295 | } 296 | }); 297 | 298 | destDirChooser = new JFileChooser(); 299 | destDirChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 300 | destDirChooser.setApproveButtonText("Select"); 301 | 302 | // On clicking, saving the project config to an XML file. 303 | JButton saveCurrentProjectButton = new JButton("Save Project"); 304 | saveCurrentProjectButton.addActionListener(e -> { 305 | final int userOption = destDirChooser.showSaveDialog(null); //Returns the integer representation of the user's choice 306 | 307 | if (userOption == JFileChooser.APPROVE_OPTION) { 308 | checklistDestDir = destDirChooser.getSelectedFile(); 309 | try { 310 | extender.projectWorkspace.saveFile(checklistDestDir.getAbsolutePath()); 311 | } catch (IOException ioException) { 312 | extender.stdout.println("IOException at setupTopPanel - saveCurrentProjectButton" ); 313 | } 314 | } 315 | }); 316 | 317 | loadProjectButton = new JButton("Load Project"); 318 | loadProjectButton.addActionListener(e -> { 319 | 320 | final int userOption = fileChooser.showOpenDialog(null); //Returns the integer representation of the user's choice 321 | 322 | if (userOption == JFileChooser.APPROVE_OPTION) { 323 | File chosenFile = fileChooser.getSelectedFile(); 324 | 325 | if (!chosenFile.getAbsolutePath().contains("autowasp_project.ser")){ //Note that this contain string must be the same as the save file name though. 326 | scanStatusLabel.setText("Error, this is not the correct project file"); 327 | extender.callbacks.issueAlert("Error, this is not the correct project file"); 328 | }else{ 329 | Runnable runnable = () -> { 330 | extender.projectWorkspace.readFromFile(chosenFile.getAbsolutePath()); 331 | loadProjectButton.setEnabled(false); 332 | }; 333 | Thread thread = new Thread(runnable); 334 | thread.start(); 335 | } 336 | } 337 | }); 338 | 339 | //Misc Panel: [Delete Entries] [Delete Instance] [Save Project] [Load Project] 340 | JPanel miscPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 10)); 341 | miscPanel.add(new JLabel("Misc Actions:", SwingConstants.LEFT), BorderLayout.LINE_START); 342 | 343 | deleteEntryButton = new JButton("Delete Entry"); 344 | deleteEntryButton.addActionListener(e -> extender.loggerTable.deleteEntry()); 345 | 346 | deleteInstanceButton = new JButton("Delete Instance"); 347 | deleteInstanceButton.addActionListener(e -> extender.instanceTable.deleteInstance()); 348 | 349 | setupPanel.add(hostField); 350 | setupPanel.add(addToScopeButton); 351 | setupPanel.add(enableScanningButton); 352 | 353 | scanStatusPanel.add(scanStatusLabel); 354 | 355 | testingPanel.add(generateWebChecklistButton); 356 | testingPanel.add(cancelFetchButton); 357 | testingPanel.add(generateLocalChecklistButton); 358 | if (selfUpdateLocal){ 359 | testingPanel.add(saveLocalCopyButton); 360 | } 361 | testingPanel.add(generateExcelReportButton); 362 | testingPanel.add(saveCurrentProjectButton); 363 | miscPanel.add(deleteEntryButton); 364 | miscPanel.add(deleteInstanceButton); 365 | miscPanel.add(saveCurrentProjectButton); 366 | miscPanel.add(loadProjectButton); 367 | //default both delete buttons are disabled. 368 | disabledInitialButtons(); 369 | 370 | // Add setup panel and status panel to top panel 371 | topPanel.add(setupPanel); 372 | topPanel.add(scanStatusPanel); 373 | topPanel.add(testingPanel); 374 | topPanel.add(miscPanel); 375 | gtScannerSplitPane.setLeftComponent(topPanel); 376 | } 377 | 378 | // This method setup the logger functionality tab 379 | private void setupLoggerPanel() { 380 | // Logger Tab 381 | JTabbedPane loggerTab = new JTabbedPane(); 382 | JTabbedPane instanceLogTab = new JTabbedPane(); 383 | JSplitPane internalLoggerSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); 384 | JSplitPane instancesLogsSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); 385 | JSplitPane internalPenTesterCommentsSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); 386 | JSplitPane internalEvidencesSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); 387 | 388 | // Setting up JTable 389 | JScrollPane loggerScrollPane = new JScrollPane(extender.loggerTable); 390 | loggerScrollPane.setPreferredSize(new Dimension(300, 200)); 391 | loggerScrollPane.setBorder(new EmptyBorder(0, 0, 10, 0)); 392 | JScrollPane instancesScrollPane = new JScrollPane(extender.instanceTable); 393 | instancesScrollPane.setPreferredSize(new Dimension(700, 200)); 394 | instancesScrollPane.setBorder(new EmptyBorder(0, 0, 10, 0)); 395 | 396 | 397 | // Upper half - store Pen testers comments and evidences log 398 | // Comments Pane 399 | penTesterCommentBox = new JTextPane(); 400 | penTesterCommentBox.setContentType("text/plain"); 401 | penTesterCommentBox.setEditable(true); 402 | JScrollPane penTesterCommentBoxScrollPane = new JScrollPane(penTesterCommentBox); 403 | JPanel commentsPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 10)); 404 | JButton clearCommentsButton = new JButton("Clear Comments"); 405 | clearCommentsButton.addActionListener(e -> penTesterCommentBox.setText("")); 406 | JButton saveCommentsButton = new JButton("Save Comments"); 407 | saveCommentsButton.addActionListener(e -> { 408 | //Added a line break to create a space between pentester comments and affected instances 409 | extender.loggerTable.modifyComments(penTesterCommentBox.getText().trim() + "\n"); 410 | }); 411 | commentsPanel.add(saveCommentsButton); 412 | commentsPanel.add(clearCommentsButton); 413 | internalPenTesterCommentsSplitPane.setTopComponent(commentsPanel); 414 | internalPenTesterCommentsSplitPane.setBottomComponent(penTesterCommentBoxScrollPane); 415 | 416 | // Evidence Pane 417 | evidenceBox = new JTextPane(); 418 | evidenceBox.setContentType("text/plain"); 419 | evidenceBox.setEditable(true); 420 | JScrollPane evidenceBoxScrollPane = new JScrollPane(evidenceBox); 421 | JPanel evidencePanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 10)); 422 | JButton clearEvidencesButton = new JButton("Clear Evidence"); 423 | clearEvidencesButton.addActionListener(e -> evidenceBox.setText("")); 424 | JButton saveEvidencesButton = new JButton("Save Evidence"); 425 | saveEvidencesButton.addActionListener(e -> extender.loggerTable.modifyEvidence(evidenceBox.getText().trim())); 426 | evidencePanel.add(saveEvidencesButton); 427 | evidencePanel.add(clearEvidencesButton); 428 | internalEvidencesSplitPane.setTopComponent(evidencePanel); 429 | internalEvidencesSplitPane.setBottomComponent(evidenceBoxScrollPane); 430 | 431 | // Lower half - Instances Tab 432 | requestViewer = extender.callbacks.createMessageEditor(extender, false); 433 | responseViewer = extender.callbacks.createMessageEditor(extender, false); 434 | instanceLogTab.add("Request", requestViewer.getComponent()); 435 | instanceLogTab.add("Response", responseViewer.getComponent()); 436 | instancesLogsSplitPane.setLeftComponent(instancesScrollPane); 437 | instancesLogsSplitPane.setRightComponent(instanceLogTab); 438 | 439 | // Consolidate the final tabs for logger feature 440 | loggerTab.addTab("Affected Instances", instancesLogsSplitPane); 441 | loggerTab.addTab("Pen Tester Comments", internalPenTesterCommentsSplitPane); 442 | loggerTab.addTab("Evidence", internalEvidencesSplitPane); 443 | 444 | internalLoggerSplitPane.setTopComponent(loggerScrollPane); 445 | internalLoggerSplitPane.setBottomComponent(loggerTab); 446 | bottomModulesTabs.add("Logger", internalLoggerSplitPane); 447 | } 448 | 449 | // This method setup the OWASP checklist functionality tab 450 | private void setupCheckListPanel() { 451 | //Checklist internal panel 452 | JSplitPane internalChecklistSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); 453 | 454 | summaryTextPane = new JTextPane(); 455 | summaryTextPane.setEditable(false); 456 | summaryTextPane.setContentType("text/html"); 457 | summaryTextPane.addHyperlinkListener(e -> { 458 | if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { 459 | if(Desktop.isDesktopSupported()) { 460 | try { 461 | Desktop.getDesktop().browse(e.getURL().toURI()); 462 | } 463 | catch (IOException | URISyntaxException e1) { 464 | extender.stdout.println("Exception occurred at setupCheckListPanel"); 465 | } 466 | } 467 | } 468 | } 469 | ); 470 | 471 | 472 | howToTestTextPane = new JEditorPane(); 473 | howToTestTextPane.setEditable(false); 474 | howToTestTextPane.setContentType("text/html"); 475 | howToTestTextPane.addHyperlinkListener(e -> { 476 | if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { 477 | if(Desktop.isDesktopSupported()) { 478 | try { 479 | Desktop.getDesktop().browse(e.getURL().toURI()); 480 | } 481 | catch (IOException | URISyntaxException e1) { 482 | extender.stdout.println("Exception occurred at setupCheckListPanel"); 483 | } 484 | } 485 | } 486 | } 487 | ); 488 | 489 | referencesTextPane = new JTextPane(); 490 | referencesTextPane.setEditable(false); 491 | referencesTextPane.setContentType("text/html"); 492 | referencesTextPane.addHyperlinkListener(e -> { 493 | if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { 494 | if(Desktop.isDesktopSupported()) { 495 | try { 496 | Desktop.getDesktop().browse(e.getURL().toURI()); 497 | } 498 | catch (IOException | URISyntaxException e1) { 499 | extender.stdout.println("Exception occurred at setupCheckListPanel"); 500 | } 501 | } 502 | } 503 | } 504 | ); 505 | 506 | JScrollPane checklistScrollPane = new JScrollPane(extender.checklistTable); 507 | checklistScrollPane.setPreferredSize(new Dimension(300, 200)); 508 | checklistScrollPane.setBorder(new EmptyBorder(0, 0, 10, 0)); 509 | JScrollPane summaryScrollPane = new JScrollPane(summaryTextPane); 510 | JScrollPane howToTestScrollPane = new JScrollPane(howToTestTextPane); 511 | JScrollPane referencesScrollPane = new JScrollPane(referencesTextPane); 512 | JTabbedPane checklistBottomTabs = new JTabbedPane(); 513 | checklistBottomTabs.add("Summary", summaryScrollPane); 514 | checklistBottomTabs.add("How to test", howToTestScrollPane); 515 | checklistBottomTabs.add("References", referencesScrollPane); 516 | internalChecklistSplitPane.setLeftComponent(checklistScrollPane); 517 | internalChecklistSplitPane.setRightComponent(checklistBottomTabs); 518 | bottomModulesTabs.addTab("OWASP Testing Checklist", internalChecklistSplitPane); 519 | gtScannerSplitPane.setRightComponent(bottomModulesTabs); 520 | 521 | } 522 | 523 | // Initial buttons to set to disable by default 524 | public void disabledInitialButtons(){ 525 | this.deleteEntryButton.setEnabled(false); 526 | this.deleteInstanceButton.setEnabled(false); 527 | generateExcelReportButton.setEnabled(false); 528 | saveLocalCopyButton.setEnabled(false); 529 | cancelFetchButton.setEnabled(false); 530 | } 531 | 532 | // To allow instance deletion button only 533 | public void deleteEntryButtonEnabled(){ 534 | this.deleteEntryButton.setEnabled(true); 535 | this.deleteInstanceButton.setEnabled(false); 536 | } 537 | 538 | // To allow entry deletion button only 539 | public void deleteInstanceButtonEnabled(){ 540 | this.deleteEntryButton.setEnabled(false); 541 | this.deleteInstanceButton.setEnabled(true); 542 | } 543 | 544 | } 545 | -------------------------------------------------------------------------------- /src/main/java/autowasp/ProjectWorkspaceFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp; 18 | 19 | import autowasp.logger.entryTable.LoggerEntry; 20 | 21 | import java.io.*; 22 | import java.util.Collection; 23 | import java.util.Iterator; 24 | import java.util.List; 25 | import java.util.ListIterator; 26 | 27 | public class ProjectWorkspaceFactory implements Serializable { 28 | private final Autowasp extender; 29 | 30 | public ProjectWorkspaceFactory(Autowasp extender){ 31 | this.extender = extender; 32 | } 33 | 34 | // Method to save project to file directory 35 | public void saveFile(String absoluteFilePath) throws IOException { 36 | FileOutputStream fileOutputStream = null; 37 | try{ 38 | fileOutputStream = new FileOutputStream(absoluteFilePath + File.separator + "autowasp_project.ser"); 39 | ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream); 40 | for (LoggerEntry loggerEntry : extender.loggerList) { 41 | outputStream.writeObject(loggerEntry); 42 | } 43 | outputStream.close(); 44 | extender.extenderPanelUI.scanStatusLabel.setText("File saved to " + absoluteFilePath + File.separator + "autowasp_project.ser"); 45 | extender.callbacks.issueAlert("File saved to " + absoluteFilePath + File.separator + "autowasp_project.ser"); 46 | } 47 | finally { 48 | if (fileOutputStream !=null){ 49 | safeClose(fileOutputStream); 50 | } 51 | } 52 | } 53 | 54 | // Method to obtain file directory 55 | public void readFromFile(String absoluteFilePath) { 56 | boolean eof = false; 57 | LoggerEntry loggerEntryTemp; 58 | extender.loggerTableModel.clearLoggerList(); 59 | List loggerEntryList = new List() { 60 | @Override 61 | public int size() { 62 | return 0; 63 | } 64 | 65 | @Override 66 | public boolean isEmpty() { 67 | return false; 68 | } 69 | 70 | @Override 71 | public boolean contains(Object o) { 72 | return false; 73 | } 74 | 75 | @Override 76 | public Iterator iterator() { 77 | return null; 78 | } 79 | 80 | @Override 81 | public Object[] toArray() { 82 | return new Object[0]; 83 | } 84 | 85 | @Override 86 | public T[] toArray(T[] a) { 87 | return null; 88 | } 89 | 90 | @Override 91 | public boolean add(LoggerEntry loggerEntry) { 92 | return false; 93 | } 94 | 95 | @Override 96 | public boolean remove(Object o) { 97 | return false; 98 | } 99 | 100 | @Override 101 | public boolean containsAll(Collection c) { 102 | return false; 103 | } 104 | 105 | @Override 106 | public boolean addAll(Collection c) { 107 | return false; 108 | } 109 | 110 | @Override 111 | public boolean addAll(int index, Collection c) { 112 | return false; 113 | } 114 | 115 | @Override 116 | public boolean removeAll(Collection c) { 117 | return false; 118 | } 119 | 120 | @Override 121 | public boolean retainAll(Collection c) { 122 | return false; 123 | } 124 | 125 | @Override 126 | public void clear() { 127 | 128 | } 129 | 130 | @Override 131 | public LoggerEntry get(int index) { 132 | return null; 133 | } 134 | 135 | @Override 136 | public LoggerEntry set(int index, LoggerEntry element) { 137 | return null; 138 | } 139 | 140 | @Override 141 | public void add(int index, LoggerEntry element) { 142 | 143 | } 144 | 145 | @Override 146 | public LoggerEntry remove(int index) { 147 | return null; 148 | } 149 | 150 | @Override 151 | public int indexOf(Object o) { 152 | return 0; 153 | } 154 | 155 | @Override 156 | public int lastIndexOf(Object o) { 157 | return 0; 158 | } 159 | 160 | @Override 161 | public ListIterator listIterator() { 162 | return null; 163 | } 164 | 165 | @Override 166 | public ListIterator listIterator(int index) { 167 | return null; 168 | } 169 | 170 | @Override 171 | public List subList(int fromIndex, int toIndex) { 172 | return null; 173 | } 174 | }; 175 | FileInputStream fileInputStream = null; 176 | try { 177 | fileInputStream = new FileInputStream(absoluteFilePath); 178 | ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); 179 | 180 | while(!eof){ 181 | try { 182 | loggerEntryTemp = (LoggerEntry) objectInputStream.readObject(); 183 | loggerEntryList.add(loggerEntryTemp); 184 | extender.loggerTableModel.addAllLoggerEntry(loggerEntryTemp); 185 | extender.scannerLogic.repeatedIssue.add(loggerEntryTemp.getVulnType()); 186 | } catch (EOFException e) { 187 | eof = true; 188 | } 189 | } 190 | objectInputStream.close(); 191 | } catch (FileNotFoundException e){ 192 | extender.stdout.println("File not found"); 193 | } catch (IOException e){ 194 | extender.stdout.println("Cannot read file"); 195 | } catch (ClassNotFoundException e) 196 | { 197 | extender.stdout.println("LoggerEntry class not found"); 198 | } 199 | finally { 200 | if (fileInputStream != null){ 201 | safeClose(fileInputStream); 202 | } 203 | } 204 | } 205 | 206 | // Method for save closing of FileOutputStream 207 | public void safeClose(FileOutputStream fos) { 208 | if (fos != null) { 209 | try { 210 | fos.close(); 211 | } catch (IOException e) { 212 | extender.stdout.println("FileOutputStream cannot safe close"); 213 | } 214 | } 215 | } 216 | 217 | // Method for save closing of FileInputStream 218 | public void safeClose(FileInputStream fis) { 219 | if (fis != null) { 220 | try { 221 | fis.close(); 222 | } catch (IOException e) { 223 | extender.stdout.println("FileInputStream cannot safe close"); 224 | } 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /src/main/java/autowasp/checklist/ChecklistEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp.checklist; 18 | 19 | import java.io.Serializable; 20 | import java.util.HashMap; 21 | 22 | public class ChecklistEntry implements Serializable { 23 | 24 | public String refNumber; 25 | public String category; 26 | public String testName; 27 | public boolean exclusion; 28 | public boolean testcaseCompleted; 29 | public String summaryHTML; 30 | public String howToTestHTML; 31 | public String referencesHTML; 32 | public final String url; 33 | // Pentester's comments and evidence are sent from the scanner findings to a particular checklist entry when the user maps a finding to an entry 34 | public String pentesterComments; 35 | public String evidence; 36 | public boolean testBoolean; 37 | 38 | // This constructor is used to create new checklist entry objects when fetching new checklist data from the web 39 | public ChecklistEntry(HashMap tableElements, HashMap contentElements, String url) { 40 | this.refNumber = tableElements.get("Reference Number"); 41 | this.category = tableElements.get("Category"); 42 | this.testName = tableElements.get("Test Name"); 43 | this.summaryHTML = contentElements.get("summary"); 44 | this.howToTestHTML = contentElements.get("how to test"); 45 | this.referencesHTML = contentElements.get("references"); 46 | this.exclusion = false; 47 | this.testcaseCompleted = false; 48 | this.url = url; //URL is included for ease of creating the hyperlinks when writing to excel file 49 | this.pentesterComments = ""; 50 | this.evidence = ""; 51 | this.testBoolean = false; 52 | } 53 | 54 | // This constructor is used for re-creating the checklist entry objects when loading data from a local file 55 | public ChecklistEntry(String refNumber, String category, String testName, String summaryHTML, String howToTestHTML, String referencesHTML, String url) { 56 | this.refNumber = refNumber; 57 | this.category = category; 58 | this.testName = testName; 59 | this.summaryHTML = summaryHTML; 60 | this.howToTestHTML = howToTestHTML; 61 | this.referencesHTML = referencesHTML; 62 | this.exclusion = false; 63 | this.testcaseCompleted = false; 64 | this.url = url; //URL is included for ease of creating the hyperlinks when writing to excel file 65 | this.pentesterComments = ""; 66 | this.evidence = ""; 67 | } 68 | 69 | // Used to clean the checklist entry objects to prevent null pointer exceptions when displaying the data in the UI 70 | public void cleanEntry() { 71 | if (refNumber == null) { 72 | this.refNumber = "NIL"; 73 | } 74 | if (category == null) { 75 | this.category = "NIL"; 76 | } 77 | if (testName == null) { 78 | this.testName = "NIL"; 79 | } 80 | if (summaryHTML == null) { 81 | this.summaryHTML = "NIL"; 82 | } 83 | if (howToTestHTML == null) { 84 | this.howToTestHTML = "NIL"; 85 | } 86 | if (referencesHTML == null) { 87 | // This is an empty string because every references panel will have at least the link to the OWASP article 88 | this.referencesHTML = ""; 89 | } 90 | } 91 | 92 | public String getRefNumber() { 93 | return this.refNumber; 94 | } 95 | 96 | public String getTestName() { 97 | return this.testName; 98 | } 99 | 100 | public Boolean isExcluded() {return this.exclusion;} 101 | 102 | public Boolean isTestcaseCompleted(){return this.testcaseCompleted;} 103 | 104 | public void setExclusion(Boolean value){ 105 | this.exclusion = value; 106 | } 107 | 108 | public void setTestCaseCompleted(Boolean value){ this.testcaseCompleted = value;} 109 | 110 | public void setPenTesterComments(String comments) { 111 | // New comments are appended to prevent overwriting existing comments 112 | this.pentesterComments += comments; 113 | } 114 | 115 | public void setEvidence(String evidence) { 116 | // New evidence is appended to prevent overwriting existing evidence 117 | this.evidence += evidence; 118 | } 119 | 120 | public void clearComments(){ 121 | this.pentesterComments = ""; 122 | } 123 | 124 | public void clearEvidences(){ 125 | this.evidence = ""; 126 | } 127 | 128 | public Boolean getTestBool() { return this.testBoolean; } 129 | 130 | public void setTestBoolean(Boolean testBoolean) { 131 | this.testBoolean = testBoolean; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/autowasp/checklist/ChecklistLogic.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp.checklist; 18 | 19 | import autowasp.Autowasp; 20 | import autowasp.logger.entryTable.LoggerEntry; 21 | import autowasp.logger.instancesTable.InstanceEntry; 22 | import org.jsoup.Jsoup; 23 | import org.jsoup.nodes.Document; 24 | import org.jsoup.nodes.Element; 25 | import org.jsoup.parser.Tag; 26 | import org.jsoup.select.Elements; 27 | 28 | import java.io.*; 29 | import java.security.MessageDigest; 30 | import java.security.NoSuchAlgorithmException; 31 | import java.util.*; 32 | import java.util.concurrent.TimeUnit; 33 | 34 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 35 | import org.apache.poi.xssf.usermodel.XSSFSheet; 36 | import org.apache.poi.ss.usermodel.CreationHelper; 37 | import org.apache.poi.ss.usermodel.FillPatternType; 38 | import org.apache.poi.ss.usermodel.Hyperlink; 39 | import org.apache.poi.ss.usermodel.IndexedColors; 40 | import org.apache.poi.xssf.usermodel.XSSFCell; 41 | import org.apache.poi.xssf.usermodel.XSSFCellStyle; 42 | import org.apache.poi.xssf.usermodel.XSSFFont; 43 | import org.apache.poi.xssf.usermodel.XSSFRow; 44 | import org.apache.poi.common.usermodel.HyperlinkType; 45 | 46 | /* Notes: 47 | * 1. The URL for the OWASP content page is currently pointing to our own branch of OWASP's repository. 48 | * 2. The "fetch checklist" function currently takes around 3 minutes to fetch the data. 49 | */ 50 | 51 | public class ChecklistLogic implements Serializable { 52 | 53 | private final Autowasp extender; 54 | private Document anyPage; 55 | public final String GITHUB_REPO_URL = "https://github.com/GovTech-CSG/wstg/blob/master/document/4-Web_Application_Security_Testing/README.md"; 56 | 57 | public ChecklistLogic(Autowasp extender) { 58 | this.extender = extender; 59 | } 60 | 61 | // Returns a list containing the URLs of all the test articles in order of reference number 62 | public List scrapeArticleURLs() { 63 | // Get the URLs located within the main content page, which link to each individual section's content pages 64 | List sectionContentPageURLs = scrapePageURLs(GITHUB_REPO_URL); 65 | sectionContentPageURLs.remove(0); //Removes the link to the introduction page 66 | 67 | // Get the URLs for every individual article within each individual section's content page 68 | List articleURLs = new ArrayList<>(); 69 | for (String url : sectionContentPageURLs) { 70 | List sectionArticleURLs = scrapePageURLs(url); 71 | articleURLs.addAll(sectionArticleURLs); 72 | } 73 | 74 | // Cleans the list of URLs to exclude external links and links to headers within the pages 75 | for (int i = 0; i < articleURLs.size(); i++) { 76 | // do another check to remove "sub" article of a test cases 77 | String[] array = articleURLs.get(i).split("/"); 78 | int subArticleIndex = array[array.length-1].indexOf("."); 79 | // Condition 1 filters out external URLs, 80 | // while condition 2 filters out anchor URLs that link to headers within the article, 81 | // condition 3 filters out README.md and 82 | // condition 4 filters out sub-articles 83 | if (!articleURLs.get(i).contains("https://github.com") || articleURLs.get(i).contains("#") || articleURLs.get(i).contains("README.md") || articleURLs.get(i).contains("00")|| subArticleIndex==2) { 84 | articleURLs.remove(i); 85 | i--; 86 | } 87 | } 88 | return articleURLs; 89 | } 90 | 91 | // A general method to scrape all the URLs that exist on a page and return a list containing them 92 | public List scrapePageURLs(String anyURL) { 93 | // Get the web page specified by the URL as a JSoup Document object 94 | try { 95 | anyPage = Jsoup.connect(anyURL).get(); 96 | // Get the HTML elements of the page body 97 | Elements pageElements = anyPage.getElementsByTag("Article").get(0).children(); 98 | 99 | // Get the list of URLs in the page body 100 | 101 | return pageElements.select("a[href]").eachAttr("abs:href"); 102 | } 103 | catch (IOException e) { 104 | extender.stderr.println("Error 1, Github page not found. Cancel fetch"); 105 | extender.callbacks.issueAlert("Error 1, Github page not found. Cancel fetch"); 106 | extender.extenderPanelUI.scanStatusLabel.setText("Error 1, Github page not found. Cancel fetch"); 107 | } 108 | return null; 109 | 110 | } 111 | 112 | // Gets the Reference Number, Category, and Title of the article saved in a hash map 113 | public HashMap getTableElements(String anyURL) { 114 | // Gets the web page specified by the URL as a JSoup Document object 115 | try { 116 | anyPage = Jsoup.connect(anyURL).get(); 117 | // Get the HTML element of the article that contains the article's file path. Inspect the HTML elements of any article to see this 118 | Elements filePathElements = anyPage.getElementById("blob-path").children(); 119 | Elements filePathElements2 = anyPage.getElementsByTag("td"); 120 | 121 | // Get the required information from the HTML elements and save them into a hash map 122 | String refNumber = filePathElements2.first().text(); // get the ref number from table td tag 123 | 124 | String category = filePathElements.get(6).text().split("-", 2)[1].replace("_", " "); 125 | String testName = filePathElements.get(8).text().split("-", 2)[1].replace("_", " "); 126 | testName = testName.split("[.]", 2)[0]; // To get rid of the .md extension 127 | 128 | HashMap tableElements = new HashMap<>(); 129 | tableElements.put("Reference Number", refNumber); 130 | tableElements.put("Category", category); 131 | tableElements.put("Test Name", testName); 132 | return tableElements; 133 | } 134 | catch (IOException e) { 135 | extender.stderr.println("Error 2, table element not found. Cancel Fetch"); 136 | extender.callbacks.issueAlert("Error 2, table element not found. Cancel Fetch"); 137 | extender.extenderPanelUI.scanStatusLabel.setText("Error 2, table element not found. Cancel Fetch"); 138 | } 139 | return null; 140 | } 141 | 142 | /* Gets the "Summary", "How To Test", and "References" sections of the article saved in a hash map, with HTML format preserved to be rendered 143 | within the Burp UI elements */ 144 | public HashMap getContentElements(String anyURL) { 145 | // Gets the web page specified by the URL as a JSoup Document object 146 | try { 147 | anyPage = Jsoup.connect(anyURL).get(); 148 | Element article = anyPage.getElementsByTag("Article").get(0); 149 | article.append("

Ending marker

"); // To provide an ending marker to stop the while loop later 150 | Elements articleElements = article.children(); 151 | 152 | // replace img tags to href as extender does not pull images 153 | Elements img = article.getElementsByTag("img"); 154 | for (Element e : img){ 155 | String absoluteUrl = e.absUrl("src"); 156 | Element newElement = new Element(Tag.valueOf("a"), ""); 157 | newElement.attr("href", absoluteUrl); 158 | newElement.append("Refer to image here"); 159 | e.replaceWith(newElement); 160 | } 161 | 162 | // Iterates through the list of HTML elements contained within the article, identifying each section title and its 163 | // corresponding body elements, saving the title (String) as the key and the body (String, HTML form) as the value in a hash map 164 | // State 0: A new header is reached 165 | // State 1: Going through the body elements 166 | // State 2: Meets the next header, saves current header and paragraphs into hash map, then move back to state 0 167 | int index = 0; 168 | int state = 0; 169 | String currentHeader = ""; 170 | StringBuilder currentParagraphs = new StringBuilder(); 171 | HashMap contentElements = new HashMap<>(); 172 | 173 | while (index < articleElements.size()) { 174 | switch (state) { 175 | case 0: 176 | currentHeader = articleElements.get(index).text().toLowerCase(); 177 | state = 1; 178 | index++; 179 | break; 180 | case 1: 181 | if (articleElements.get(index).tagName().equals("h2")) { 182 | state = 2; 183 | } 184 | else { 185 | currentParagraphs.append(articleElements.get(index).toString()); 186 | index++; 187 | } 188 | break; 189 | case 2: 190 | contentElements.put(currentHeader, currentParagraphs.toString()); 191 | currentHeader = ""; 192 | currentParagraphs = new StringBuilder(); 193 | state = 0; 194 | break; 195 | } 196 | } 197 | 198 | return contentElements; 199 | } 200 | catch (IOException e) { 201 | extender.stderr.println("Error 3, Content page not found. Cancel fetch"); 202 | extender.callbacks.issueAlert("Error 3, Content page not found. Cancel fetch"); 203 | extender.extenderPanelUI.scanStatusLabel.setText("Error 3, Content page not found. Cancel fetch"); 204 | } 205 | return null; 206 | } 207 | 208 | // Saves a local copy of the checklist in a file called OWASPChecklistData.txt at the directory dictated by the user 209 | public void saveLocalCopy(String absoluteFilePath) throws IOException { 210 | FileOutputStream fileOutputStream = null; 211 | try{ 212 | fileOutputStream = new FileOutputStream(absoluteFilePath + File.separator + "OWASP_WSTG_local"); 213 | ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream); 214 | for (ChecklistEntry entry : extender.checklistLog) { 215 | if (entry.exclusion = true) { 216 | ChecklistEntry tempChecklistEntry = entry; 217 | tempChecklistEntry.exclusion = false; 218 | outputStream.writeObject(tempChecklistEntry); 219 | } else { 220 | outputStream.writeObject(entry); 221 | } 222 | } 223 | outputStream.close(); 224 | 225 | extender.extenderPanelUI.scanStatusLabel.setText("File saved to " + absoluteFilePath + File.separator + "OWASP_WSTG_local"); 226 | extender.callbacks.issueAlert("File saved to " + absoluteFilePath + File.separator + "OWASP_WSTG_local"); 227 | File savedFile = new File(absoluteFilePath + File.separator + "OWASP_WSTG_local"); 228 | } 229 | 230 | finally { 231 | if (fileOutputStream !=null) { 232 | safeClose(fileOutputStream); 233 | } 234 | } 235 | } 236 | 237 | // Re-creates the checklistLog containing ChecklistEntry objects from the uploaded local file 238 | public void loadLocalCopy() { 239 | boolean eof = false; 240 | ChecklistEntry checklistEntryTemp; 241 | extender.checklistLog.clear(); 242 | extender.checkListHashMap.clear(); 243 | 244 | List checklistEntryList = new List() { 245 | @Override 246 | public int size() { 247 | return 0; 248 | } 249 | 250 | @Override 251 | public boolean isEmpty() { 252 | return false; 253 | } 254 | 255 | @Override 256 | public boolean contains(Object o) { 257 | return false; 258 | } 259 | 260 | @Override 261 | public Iterator iterator() { 262 | return null; 263 | } 264 | 265 | @Override 266 | public Object[] toArray() { 267 | return new Object[0]; 268 | } 269 | 270 | @Override 271 | public T[] toArray(T[] a) { 272 | return null; 273 | } 274 | 275 | @Override 276 | public boolean add(ChecklistEntry checklistEntry) { 277 | return false; 278 | } 279 | 280 | @Override 281 | public boolean remove(Object o) { 282 | return false; 283 | } 284 | 285 | @Override 286 | public boolean containsAll(Collection c) { 287 | return false; 288 | } 289 | 290 | @Override 291 | public boolean addAll(Collection c) { 292 | return false; 293 | } 294 | 295 | @Override 296 | public boolean addAll(int index, Collection c) { 297 | return false; 298 | } 299 | 300 | @Override 301 | public boolean removeAll(Collection c) { 302 | return false; 303 | } 304 | 305 | @Override 306 | public boolean retainAll(Collection c) { 307 | return false; 308 | } 309 | 310 | @Override 311 | public void clear() { 312 | 313 | } 314 | 315 | @Override 316 | public boolean equals(Object o) { 317 | return false; 318 | } 319 | 320 | @Override 321 | public int hashCode() { 322 | return 0; 323 | } 324 | 325 | @Override 326 | public ChecklistEntry get(int index) { 327 | return null; 328 | } 329 | 330 | @Override 331 | public ChecklistEntry set(int index, ChecklistEntry element) { 332 | return null; 333 | } 334 | 335 | @Override 336 | public void add(int index, ChecklistEntry element) { 337 | 338 | } 339 | 340 | @Override 341 | public ChecklistEntry remove(int index) { 342 | return null; 343 | } 344 | 345 | @Override 346 | public int indexOf(Object o) { 347 | return 0; 348 | } 349 | 350 | @Override 351 | public int lastIndexOf(Object o) { 352 | return 0; 353 | } 354 | 355 | @Override 356 | public ListIterator listIterator() { 357 | return null; 358 | } 359 | 360 | @Override 361 | public ListIterator listIterator(int index) { 362 | return null; 363 | } 364 | 365 | @Override 366 | public List subList(int fromIndex, int toIndex) { 367 | return null; 368 | } 369 | }; 370 | 371 | InputStream inputStream = getClass().getResourceAsStream("/OWASP_WSTG_local_07Jul2022"); 372 | try{ 373 | ObjectInputStream objectInputStream = new ObjectInputStream(inputStream); 374 | 375 | while(!eof){ 376 | try{ 377 | checklistEntryTemp = (ChecklistEntry) objectInputStream.readObject(); 378 | checklistEntryList.add(checklistEntryTemp); 379 | extender.checkListHashMap.put(checklistEntryTemp.refNumber, checklistEntryTemp); 380 | extender.checklistLogic.loadNewChecklistEntry(checklistEntryTemp); 381 | } catch (EOFException e) { 382 | eof = true; 383 | } 384 | } 385 | extender.loggerTable.generateWSTGList(); 386 | objectInputStream.close(); 387 | } catch (IOException e) { 388 | extender.stdout.println("Cannot read local import file"); 389 | } 390 | catch (ClassNotFoundException e) { 391 | extender.stdout.println("LoggerEntry class not found"); 392 | } 393 | finally { 394 | if (inputStream != null){ 395 | safeClose((FileInputStream) inputStream); 396 | } 397 | } 398 | } 399 | 400 | // Saves a local excel file at the directory specified by the user 401 | @SuppressWarnings("resource") 402 | public void saveToExcelFile(String absoluteFilePath) { 403 | // Populate your excel checklist data 404 | for (LoggerEntry findingEntry: extender.loggerList){ 405 | // Identify findings that was mapped to OWASP checklist 406 | if (findingEntry.getChecklistIssue() == null || findingEntry.getChecklistIssue().isEmpty() || findingEntry.checklistIssue.equals("N.A.")) { 407 | continue; 408 | } 409 | // Extract the refID using substring 410 | int cutIndex = findingEntry.getChecklistIssue().indexOf(" -"); 411 | String findingRefID = findingEntry.getChecklistIssue().substring(0,cutIndex); 412 | ChecklistEntry checklistEntry = extender.checkListHashMap.get(findingRefID); 413 | 414 | // Retrieve findings entry comments, evidences and instances that are not false positive. 415 | StringBuilder comments = new StringBuilder(); 416 | comments.append(findingEntry.getPenTesterComments()); 417 | comments.append("\nAffected Instance include(s):\n"); 418 | for (InstanceEntry instanceEntry : findingEntry.getInstanceList()) { 419 | // Processed instances url that are not marked as false positive 420 | if (!instanceEntry.getConfidence().equals("False Positive")) { 421 | comments.append(instanceEntry.getUrl()).append(" - (").append(instanceEntry.getConfidence()).append(")\n"); 422 | } 423 | } 424 | String evidence = ""; 425 | evidence += findingEntry.getEvidence(); 426 | 427 | // Append break line in case of more findings mapped to similar issue 428 | comments.append("\n\n"); 429 | evidence += "\n\n"; 430 | checklistEntry.setPenTesterComments(comments.toString()); 431 | checklistEntry.setEvidence(evidence); 432 | } 433 | 434 | // Create a new workbook object and a new sheet 435 | XSSFWorkbook checklistWorkbook = new XSSFWorkbook(); 436 | XSSFSheet checklistSheet = checklistWorkbook.createSheet("OWASP Checklist"); 437 | 438 | // Create the style object for the headers (first row) 439 | XSSFCellStyle headerStyle = checklistWorkbook.createCellStyle(); 440 | XSSFFont headerFont = checklistWorkbook.createFont(); 441 | headerFont.setBold(true); 442 | headerStyle.setFont(headerFont); 443 | headerStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex()); 444 | headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); 445 | 446 | // Create the style object for the URL column 447 | XSSFCellStyle urlStyle = checklistWorkbook.createCellStyle(); 448 | urlStyle.setWrapText(true); 449 | XSSFFont urlFont = checklistWorkbook.createFont(); 450 | urlFont.setUnderline(XSSFFont.U_SINGLE); 451 | urlFont.setColor(IndexedColors.BLUE.getIndex()); 452 | urlStyle.setFont(urlFont); 453 | 454 | // Create the style object for the pentester comments and evidence cells 455 | XSSFCellStyle cellStyle = checklistWorkbook.createCellStyle(); 456 | cellStyle.setWrapText(true); 457 | 458 | // Create and style the headers row 459 | XSSFRow columnHeadersRow = checklistSheet.createRow(0); 460 | String[] headerArray = new String[]{"Reference Number", "Category", "Test Name", "Pentester Comments", "Evidence", "URL"}; 461 | for (int i = 0; i < 6; i++) { 462 | XSSFCell cell = columnHeadersRow.createCell(i); 463 | cell.setCellValue(headerArray[i]); 464 | cell.setCellStyle(headerStyle); 465 | } 466 | 467 | // Create and style the content rows 468 | int rowNum = 0; 469 | for (int i = 0; i < extender.checklistLog.size(); i++) { 470 | ChecklistEntry entry = extender.checklistLog.get(i); 471 | String[] contentArray = new String[]{entry.refNumber, entry.category, entry.testName, 472 | entry.pentesterComments.trim(), entry.evidence.trim(), entry.url}; 473 | entry.clearComments(); 474 | entry.clearEvidences(); 475 | 476 | // append "-" to rows that have no entry 477 | if (contentArray[3].equals("")){ 478 | contentArray[3] = "N.A."; 479 | } 480 | if (contentArray[4].equals("")){ 481 | contentArray[4] = "N.A."; 482 | } 483 | 484 | XSSFRow row = checklistSheet.createRow(++rowNum); 485 | for (int j = 0; j < 6; j++) { 486 | XSSFCell cell = row.createCell(j); 487 | cell.setCellValue(contentArray[j]); 488 | // Checks if the cell is the URL cell, which needs to be styled differently 489 | if (j != 5) { 490 | cell.setCellStyle(cellStyle); 491 | } 492 | else { 493 | cell.setCellStyle(urlStyle); 494 | // Adds the hyperlink to the URL cell 495 | CreationHelper helper = checklistWorkbook.getCreationHelper(); 496 | Hyperlink articleLink = helper.createHyperlink(HyperlinkType.URL); 497 | articleLink.setAddress(entry.url); 498 | cell.setHyperlink(articleLink); 499 | } 500 | } 501 | // Sets cell height to excel default value so that word wrap doesn't make the rows super tall 502 | row.setHeight((short)-1); 503 | } 504 | 505 | // Auto-size every column first 506 | for (int i = 0; i <= columnHeadersRow.getPhysicalNumberOfCells(); i++) { 507 | checklistSheet.autoSizeColumn(i); 508 | } 509 | 510 | // Then set a fixed column width of 100 characters (apparently the setColumnWidth method uses 1/256 of a character width as a measurement unit) 511 | checklistSheet.setColumnWidth(3, 25600); 512 | checklistSheet.setColumnWidth(4, 25600); 513 | 514 | // Writes the workbook object into an actual excel file. File.separator is used to ensure cross OS compatibility 515 | try { 516 | FileOutputStream excelWriter = new FileOutputStream(new File(absoluteFilePath + File.separator + "OWASP Checklist.xlsx")); 517 | checklistWorkbook.write(excelWriter); 518 | excelWriter.close(); 519 | extender.callbacks.issueAlert("Excel report generated!"); 520 | extender.extenderPanelUI.scanStatusLabel.setText("Excel report generated!"); 521 | } catch (IOException e) { 522 | extender.callbacks.issueAlert("Error, file not found"); 523 | } 524 | } 525 | 526 | // Constructs a new ChecklistEntry object and adds it to the checklistLog using the setValueAt() method 527 | public void logNewChecklistEntry(String url) { 528 | 529 | int row = this.extender.checklistLog.size(); 530 | try { 531 | TimeUnit.MILLISECONDS.sleep(1000); 532 | } catch (InterruptedException e) { 533 | extender.stdout.println("Error in fetching the url: " + url); 534 | } 535 | ChecklistEntry checklistEntry = new ChecklistEntry(this.getTableElements(url), this.getContentElements(url), url); 536 | checklistEntry.cleanEntry(); 537 | extender.checklistTableModel.addValueAt(checklistEntry, row, row); 538 | extender.checkListHashMap.put(checklistEntry.refNumber,checklistEntry); 539 | } 540 | 541 | // Adds a ChecklistEntry object created from a local saved file to the checklistLog using the setValueAt() method 542 | public void loadNewChecklistEntry(ChecklistEntry entry) { 543 | int row = this.extender.checklistLog.size(); 544 | extender.checklistTableModel.addValueAt(entry, row, row); 545 | } 546 | 547 | // Logic to calculate file hash 548 | public String toHash(File chosenFile) throws NoSuchAlgorithmException { 549 | MessageDigest md; 550 | String result =""; 551 | int readCount; 552 | FileInputStream fis = null; 553 | try { 554 | md = MessageDigest.getInstance("SHA-256"); 555 | fis = new FileInputStream(chosenFile); 556 | byte[] dataBytes = new byte[1024]; 557 | 558 | while ((readCount = fis.read(dataBytes)) != -1) { 559 | md.update(dataBytes, 0, readCount); 560 | } 561 | safeClose(fis); 562 | byte[] mdbytes = md.digest(); 563 | 564 | // convert the byte to hex format method 565 | StringBuilder sb = new StringBuilder(); 566 | for (byte mdbyte : mdbytes) { 567 | sb.append(Integer.toString((mdbyte & 0xff) + 0x100, 16).substring(1)); 568 | } 569 | result = sb.toString(); 570 | } 571 | catch(IOException ioe){ 572 | extender.stderr.println("Error exception at toHash"); 573 | } 574 | finally { 575 | safeClose(fis); 576 | } 577 | 578 | return result; 579 | } 580 | 581 | // Method for save closing of FileOutputStream 582 | public void safeClose(FileOutputStream fos) { 583 | if (fos != null) { 584 | try { 585 | fos.close(); 586 | } catch (IOException e) { 587 | extender.stdout.println("FileOutputStream cannot perform safeClose"); 588 | } 589 | } 590 | } 591 | 592 | private void safeClose(FileInputStream fis){ 593 | if (fis !=null){ 594 | try{ 595 | fis.close(); 596 | } catch (IOException e) { 597 | extender.stdout.println("FileInputStream cannot perform safeClose"); 598 | } 599 | 600 | } 601 | } 602 | } 603 | 604 | -------------------------------------------------------------------------------- /src/main/java/autowasp/checklist/ChecklistTable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp.checklist; 18 | 19 | import autowasp.Autowasp; 20 | 21 | import javax.swing.*; 22 | import javax.swing.table.TableColumn; 23 | import javax.swing.table.TableModel; 24 | 25 | @SuppressWarnings("serial") 26 | public class ChecklistTable extends JTable { 27 | 28 | private final Autowasp extender; 29 | 30 | public ChecklistTable(TableModel tableModel, Autowasp extender) { 31 | super(tableModel); 32 | this.extender = extender; 33 | //Even parameters are default values for each column, odd parameters are max value for that column 34 | //Just need to make sure that the max value >= Default values or things are gonna be abit messy. 35 | setColumnWidths(200, 300, 200, 300, 1350, 1800, 500, 600, 200, 300); 36 | } 37 | 38 | public void setColumnWidths(int... widths) { 39 | for (int i = 0; i < widths.length; i += 2) { 40 | if ((i / 2) < columnModel.getColumnCount()) { 41 | columnModel.getColumn(i / 2).setPreferredWidth(widths[i]); 42 | columnModel.getColumn(i / 2).setMaxWidth(widths[i + 1]); 43 | } 44 | else continue; 45 | } 46 | } 47 | 48 | @Override 49 | public void changeSelection(int row, int col, boolean toggle, boolean extend) { 50 | ChecklistEntry checklistEntry = extender.checklistLog.get(row); 51 | 52 | // Sets the text for each of the bottom tab panes. Setting the caret position to 0 makes sure that the user starts reading from the top 53 | extender.extenderPanelUI.summaryTextPane.setText(checklistEntry.summaryHTML); 54 | extender.extenderPanelUI.summaryTextPane.setCaretPosition(0); 55 | extender.extenderPanelUI.howToTestTextPane.setText(checklistEntry.howToTestHTML.replaceAll("\n", "").replaceAll("\r", "")); 56 | extender.extenderPanelUI.howToTestTextPane.setCaretPosition(0); 57 | extender.extenderPanelUI.referencesTextPane.setText("Link to Article\n" + checklistEntry.referencesHTML); 58 | extender.extenderPanelUI.referencesTextPane.setCaretPosition(0); 59 | 60 | super.changeSelection(row, col, toggle, extend); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/autowasp/checklist/ChecklistTableModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp.checklist; 18 | 19 | import autowasp.*; 20 | import autowasp.logger.entryTable.LoggerEntry; 21 | 22 | import javax.swing.table.AbstractTableModel; 23 | import java.util.List; 24 | 25 | @SuppressWarnings("serial") 26 | public class ChecklistTableModel extends AbstractTableModel { 27 | 28 | private final Autowasp extender; 29 | private final String[] columnNames = { "Reference Number", "Category", "Test Name", "Test Case Completed", "To Exclude" }; 30 | 31 | public ChecklistTableModel(Autowasp extender) { 32 | this.extender = extender; 33 | } 34 | 35 | @Override 36 | public int getColumnCount() { 37 | return columnNames.length; 38 | } 39 | 40 | @Override 41 | public int getRowCount() { 42 | return extender.checklistLog.size(); 43 | } 44 | 45 | public String getColumnName(int columnIndex) { 46 | return columnNames[columnIndex]; 47 | } 48 | 49 | @Override 50 | public Object getValueAt(int rowIndex, int columnIndex) { 51 | ChecklistEntry checklistEntry = extender.checklistLog.get(rowIndex); 52 | if (columnIndex == 0) { 53 | return checklistEntry.refNumber; 54 | } 55 | if (columnIndex == 1) { 56 | return checklistEntry.category; 57 | } 58 | if (columnIndex == 2) { 59 | return checklistEntry.testName; 60 | } 61 | if (columnIndex == 3){ 62 | return checklistEntry.testcaseCompleted; 63 | } 64 | if (columnIndex == 4) { 65 | return checklistEntry.exclusion; 66 | } 67 | return ""; 68 | } 69 | public Class getColumnClass(int column) { 70 | return (getValueAt(0, column).getClass()); 71 | } 72 | 73 | // Method to set value at selected row and column 74 | @Override 75 | public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 76 | ChecklistEntry checklistEntry = extender.checklistLog.get(rowIndex); 77 | if (columnIndex == 3){ 78 | checklistEntry.setTestCaseCompleted((Boolean) aValue); 79 | } 80 | else if (columnIndex == 4) { 81 | checklistEntry.setExclusion((Boolean) aValue); 82 | // Refresh Mapping list for logger tab 83 | extender.loggerTable.resetList(); 84 | } 85 | } 86 | 87 | public void addValueAt(ChecklistEntry entry, int rowIndex, int columnIndex) { 88 | extender.checklistLog.add(entry); 89 | fireTableRowsInserted(rowIndex, columnIndex); 90 | } 91 | 92 | // Method to restrict editable cell to those with dropdown combo. 93 | public boolean isCellEditable(int row, int col) { 94 | if(col == 3 || col == 4){ 95 | return true; 96 | } 97 | return false; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/autowasp/http/ContextMenuFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp.http; 18 | 19 | import autowasp.Autowasp; 20 | import autowasp.logger.entryTable.LoggerEntry; 21 | import autowasp.logger.instancesTable.InstanceEntry; 22 | import burp.IContextMenuFactory; 23 | import burp.IContextMenuInvocation; 24 | 25 | import javax.swing.*; 26 | import java.net.URL; 27 | import java.util.ArrayList; 28 | import java.util.List; 29 | 30 | public class ContextMenuFactory implements IContextMenuFactory { 31 | 32 | private HTTPRequestResponse[] requestResponseArr; 33 | private ContextMenuInvocation contextMenuInvocation; 34 | private Autowasp extender; 35 | 36 | public ContextMenuFactory(Autowasp autowasp){ 37 | this.extender = autowasp; 38 | } 39 | 40 | // Method to create Menu context items. Currently allow users to send request/response from proxy and repeater tab 41 | @Override 42 | public List createMenuItems(IContextMenuInvocation invocation) { 43 | this.contextMenuInvocation = new ContextMenuInvocation(invocation); 44 | ArrayList menu = new ArrayList<>(); 45 | byte ctx = contextMenuInvocation.getInvocationContext(); 46 | JMenuItem item; 47 | 48 | // Context menu for proxy tab 49 | if (ctx == ContextMenuInvocation.CONTEXT_PROXY_HISTORY) { 50 | this.requestResponseArr = contextMenuInvocation.getSelectedMessages(); 51 | item = new JMenuItem("Send proxy finding to Autowasp", null); 52 | item.addActionListener(e -> { 53 | String action = "Sent from Proxy History"; 54 | String comments = requestResponseArr[0].getComment(); 55 | logToAutowasp(action, comments); 56 | }); 57 | menu.add(item); 58 | } 59 | // Context menu for repeater tab 60 | else if ((ctx == ContextMenuInvocation.CONTEXT_MESSAGE_EDITOR_REQUEST) && 61 | (contextMenuInvocation.getToolFlag() == 64)){ 62 | this.requestResponseArr = contextMenuInvocation.getSelectedMessages(); 63 | item = new JMenuItem("Send repeater finding to Autowasp", null); 64 | item.addActionListener(actionEvent -> { 65 | String action = "Sent from Repeater"; 66 | String comments = requestResponseArr[0].getComment(); 67 | logToAutowasp(action, comments); 68 | }); 69 | menu.add(item); 70 | } 71 | // Context menu for intruder tab 72 | else if(ctx == ContextMenuInvocation.CONTEXT_INTRUDER_PAYLOAD_POSITIONS){ 73 | this.requestResponseArr = contextMenuInvocation.getSelectedMessages(); 74 | item = new JMenuItem("Send intruder finding to Autowasp", null); 75 | item.addActionListener(actionEvent -> { 76 | String action = "Sent from Intruder"; 77 | String comments = requestResponseArr[0].getComment(); 78 | logToAutowasp(action, comments); 79 | }); 80 | menu.add(item); 81 | } 82 | return menu; 83 | } 84 | 85 | // Method to log finding(s) to Autowasp 86 | private void logToAutowasp(String action, String comments) { 87 | String host = requestResponseArr[0].getHttpService().getHost(); 88 | 89 | String port = String.valueOf(requestResponseArr[0].getHttpService().getPort()); 90 | 91 | String vulnType = "~"; 92 | String issue = ""; 93 | LoggerEntry findingEntry = new LoggerEntry(host, action, vulnType, issue, comments); 94 | String confidence = ""; 95 | String severity = "~"; 96 | 97 | for (HTTPRequestResponse iHttpRequestResponse : requestResponseArr) { 98 | URL url = extender.helpers.analyzeRequest(iHttpRequestResponse).getUrl(); 99 | extender.callbacks.issueAlert("URL = " + url.toString()); 100 | 101 | InstanceEntry instanceEntry = new InstanceEntry(url, confidence, severity, iHttpRequestResponse); 102 | findingEntry.addInstance(instanceEntry); 103 | } 104 | extender.loggerTableModel.addAllLoggerEntry(findingEntry); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/autowasp/http/ContextMenuInvocation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp.http; 18 | 19 | import burp.IContextMenuInvocation; 20 | import burp.IHttpRequestResponse; 21 | 22 | import java.awt.event.InputEvent; 23 | 24 | public class ContextMenuInvocation implements IContextMenuInvocation { 25 | 26 | private final InputEvent inputEvent; 27 | private final int toolFlag; 28 | private final byte invocationContext; 29 | private final int[] selectionBounds; 30 | private final HTTPRequestResponse[] selectedMessages; 31 | private final ScanIssue[] scanIssues; 32 | 33 | public ContextMenuInvocation(IContextMenuInvocation copy) { 34 | this.inputEvent = copy.getInputEvent(); 35 | this.toolFlag = copy.getToolFlag(); 36 | this.invocationContext = copy.getInvocationContext(); 37 | this.selectionBounds = copy.getSelectionBounds(); 38 | 39 | IHttpRequestResponse[] httpRequestResponses = copy.getSelectedMessages(); 40 | HTTPRequestResponse[] httpRequestResponses1 = new HTTPRequestResponse[httpRequestResponses.length]; 41 | for (int i = 0; i < httpRequestResponses.length; i++) 42 | { 43 | httpRequestResponses1[i] = new HTTPRequestResponse(httpRequestResponses[i]); 44 | } 45 | this.selectedMessages = httpRequestResponses1; 46 | this.scanIssues = (ScanIssue[]) copy.getSelectedIssues(); 47 | } 48 | 49 | /** 50 | * Used to indicate that the context menu is being invoked in a request 51 | * editor. 52 | */ 53 | public static final byte CONTEXT_MESSAGE_EDITOR_REQUEST = 0; 54 | /** 55 | * Used to indicate that the context menu is being invoked in a response 56 | * editor. 57 | */ 58 | public static final byte CONTEXT_MESSAGE_EDITOR_RESPONSE = 1; 59 | /** 60 | * Used to indicate that the context menu is being invoked in a non-editable 61 | * request viewer. 62 | */ 63 | public static final byte CONTEXT_MESSAGE_VIEWER_REQUEST = 2; 64 | /** 65 | * Used to indicate that the context menu is being invoked in a non-editable 66 | * response viewer. 67 | */ 68 | public static final byte CONTEXT_MESSAGE_VIEWER_RESPONSE = 3; 69 | /** 70 | * Used to indicate that the context menu is being invoked in the Target 71 | * site map tree. 72 | */ 73 | public static final byte CONTEXT_TARGET_SITE_MAP_TREE = 4; 74 | /** 75 | * Used to indicate that the context menu is being invoked in the Target 76 | * site map table. 77 | */ 78 | public static final byte CONTEXT_TARGET_SITE_MAP_TABLE = 5; 79 | /** 80 | * Used to indicate that the context menu is being invoked in the Proxy 81 | * history. 82 | */ 83 | public static final byte CONTEXT_PROXY_HISTORY = 6; 84 | /** 85 | * Used to indicate that the context menu is being invoked in the Scanner 86 | * results. 87 | */ 88 | public static final byte CONTEXT_SCANNER_RESULTS = 7; 89 | /** 90 | * Used to indicate that the context menu is being invoked in the Intruder 91 | * payload positions editor. 92 | */ 93 | public static final byte CONTEXT_INTRUDER_PAYLOAD_POSITIONS = 8; 94 | /** 95 | * Used to indicate that the context menu is being invoked in an Intruder 96 | * attack results. 97 | */ 98 | public static final byte CONTEXT_INTRUDER_ATTACK_RESULTS = 9; 99 | /** 100 | * Used to indicate that the context menu is being invoked in a search 101 | * results window. 102 | */ 103 | public static final byte CONTEXT_SEARCH_RESULTS = 10; 104 | 105 | /** 106 | * This method can be used to retrieve the native Java input event that was 107 | * the trigger for the context menu invocation. 108 | * 109 | * @return The InputEvent that was the trigger for the context 110 | * menu invocation. 111 | */ 112 | public InputEvent getInputEvent() { 113 | return inputEvent; 114 | } 115 | 116 | /** 117 | * This method can be used to retrieve the Burp tool within which the 118 | * context menu was invoked. 119 | * 120 | * @return A flag indicating the Burp tool within which the context menu was 121 | * invoked. Burp tool flags are defined in the 122 | * IBurpExtenderCallbacks interface. 123 | */ 124 | public int getToolFlag() { 125 | return toolFlag; 126 | } 127 | 128 | /** 129 | * This method can be used to retrieve the context within which the menu was 130 | * invoked. 131 | * 132 | * @return An index indicating the context within which the menu was 133 | * invoked. The indices used are defined within this interface. 134 | */ 135 | public byte getInvocationContext() { 136 | return invocationContext; 137 | } 138 | 139 | /** 140 | * This method can be used to retrieve the bounds of the user's selection 141 | * into the current message, if applicable. 142 | * 143 | * @return An int[2] array containing the start and end offsets of the 144 | * user's selection in the current message. If the user has not made any 145 | * selection in the current message, both offsets indicate the position of 146 | * the caret within the editor. If the menu is not being invoked from a 147 | * message editor, the method returns null. 148 | */ 149 | public int[] getSelectionBounds() { 150 | if(selectionBounds == null){ 151 | return new int[]{}; 152 | } 153 | return selectionBounds; 154 | } 155 | 156 | /** 157 | * This method can be used to retrieve details of the HTTP requests / 158 | * responses that were shown or selected by the user when the context menu 159 | * was invoked. 160 | * 161 | * Note: For performance reasons, the objects returned from this 162 | * method are tied to the originating context of the messages within the 163 | * Burp UI. For example, if a context menu is invoked on the Proxy intercept 164 | * panel, then the 165 | * IHttpRequestResponse returned by this method will reflect 166 | * the current contents of the interception panel, and this will change when 167 | * the current message has been forwarded or dropped. If your extension 168 | * needs to store details of the message for which the context menu has been 169 | * invoked, then you should query those details from the 170 | * IHttpRequestResponse at the time of invocation, or you 171 | * should use 172 | * IBurpExtenderCallbacks.saveBuffersToTempFiles() to create a 173 | * persistent read-only copy of the 174 | * IHttpRequestResponse. 175 | * 176 | * @return An array of IHttpRequestResponse objects 177 | * representing the items that were shown or selected by the user when the 178 | * context menu was invoked. This method returns null if no 179 | * messages are applicable to the invocation. 180 | */ 181 | public HTTPRequestResponse[] getSelectedMessages() { 182 | if(selectedMessages == null){ 183 | return new HTTPRequestResponse[]{}; 184 | } 185 | return selectedMessages; 186 | } 187 | 188 | /** 189 | * This method can be used to retrieve details of the Scanner issues that 190 | * were selected by the user when the context menu was invoked. 191 | * 192 | * @return An array of IScanIssue objects representing the 193 | * issues that were selected by the user when the context menu was invoked. 194 | * This method returns null if no Scanner issues are applicable 195 | * to the invocation. 196 | */ 197 | public ScanIssue[] getSelectedIssues() { 198 | if(scanIssues == null){ 199 | return new ScanIssue[]{}; 200 | } 201 | return scanIssues; 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /src/main/java/autowasp/http/HTTPRequestResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp.http; 18 | 19 | import burp.IHttpRequestResponse; 20 | import burp.IHttpRequestResponsePersisted; 21 | import burp.IHttpService; 22 | 23 | import java.io.Serializable; 24 | 25 | public class HTTPRequestResponse implements IHttpRequestResponse, Serializable { 26 | 27 | private byte[] request; 28 | private byte[] response; 29 | private String comment; 30 | private String highlight; 31 | private HTTPService httpService; 32 | 33 | public HTTPRequestResponse(IHttpRequestResponse copy) { 34 | this.request = copy.getRequest(); 35 | this.response = copy.getResponse(); 36 | this.comment = copy.getComment(); 37 | this.highlight = copy.getHighlight(); 38 | this.httpService = new HTTPService(copy.getHttpService()); 39 | } 40 | 41 | @Override 42 | public byte[] getRequest() { 43 | if(request == null) { 44 | return new byte[]{}; 45 | } 46 | return request; 47 | } 48 | 49 | @Override 50 | public void setRequest(byte[] message) { 51 | request = message; 52 | } 53 | 54 | @Override 55 | public byte[] getResponse() { 56 | if(response == null) { 57 | return new byte[]{}; 58 | } 59 | return response; 60 | } 61 | 62 | @Override 63 | public void setResponse(byte[] message) { 64 | response = message; 65 | } 66 | 67 | @Override 68 | public String getComment() { 69 | return comment; 70 | } 71 | 72 | @Override 73 | public void setComment(String comment) { 74 | this.comment = comment; 75 | } 76 | 77 | @Override 78 | public String getHighlight() { 79 | return highlight; 80 | } 81 | 82 | @Override 83 | public void setHighlight(String color) { 84 | this.highlight = color; 85 | } 86 | 87 | @Override 88 | public HTTPService getHttpService() { 89 | return httpService; 90 | } 91 | 92 | @Override 93 | public void setHttpService(IHttpService httpService) { 94 | this.httpService = new HTTPService(httpService); 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/autowasp/http/HTTPService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp.http; 18 | 19 | import burp.IHttpService; 20 | 21 | import java.io.Serializable; 22 | 23 | public class HTTPService implements IHttpService, Serializable { 24 | 25 | private final String host; 26 | private final int port; 27 | private final String protocol; 28 | 29 | public HTTPService(IHttpService copy) { 30 | this.host = copy.getHost(); 31 | this.port = copy.getPort(); 32 | this.protocol = copy.getProtocol(); 33 | } 34 | 35 | @Override 36 | public String getHost() { 37 | if(host == null){ 38 | return ""; 39 | } 40 | return host; 41 | } 42 | 43 | @Override 44 | public int getPort() { 45 | return port; 46 | } 47 | 48 | @Override 49 | public String getProtocol() { 50 | if(protocol == null){ 51 | return ""; 52 | } 53 | return protocol; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/autowasp/http/InterceptProxyMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp.http; 18 | 19 | import burp.IInterceptedProxyMessage; 20 | 21 | import java.net.InetAddress; 22 | 23 | public class InterceptProxyMessage implements IInterceptedProxyMessage { 24 | 25 | private int interceptAction; 26 | private final HTTPRequestResponse httpRequestResponse; 27 | private final String listenerInterface; 28 | private final InetAddress clientIPAddr; 29 | private final int msgRef; 30 | 31 | public InterceptProxyMessage(IInterceptedProxyMessage copy){ 32 | this.msgRef = copy.getMessageReference(); 33 | this.interceptAction = copy.getInterceptAction(); 34 | this.httpRequestResponse = new HTTPRequestResponse(copy.getMessageInfo()); 35 | this.listenerInterface = copy.getListenerInterface(); 36 | this.clientIPAddr = copy.getClientIpAddress(); 37 | } 38 | 39 | @Override 40 | public int getMessageReference() { 41 | return msgRef; 42 | } 43 | 44 | @Override 45 | public HTTPRequestResponse getMessageInfo() { 46 | return httpRequestResponse; 47 | } 48 | 49 | @Override 50 | public int getInterceptAction() { 51 | return interceptAction; 52 | } 53 | 54 | @Override 55 | public void setInterceptAction(int interceptAction) { 56 | this.interceptAction = interceptAction; 57 | } 58 | 59 | @Override 60 | public String getListenerInterface() { 61 | return listenerInterface; 62 | } 63 | 64 | @Override 65 | public InetAddress getClientIpAddress() { 66 | return clientIPAddr; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/autowasp/http/ScanIssue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp.http; 18 | 19 | import burp.IHttpRequestResponse; 20 | import burp.IScanIssue; 21 | 22 | import java.net.URL; 23 | 24 | public class ScanIssue implements IScanIssue { 25 | 26 | private final HTTPService httpService; 27 | private final URL url; 28 | private final HTTPRequestResponse[] httpMessages; 29 | private final String detail; 30 | private final String severity; 31 | private final String confidence; 32 | private final String name; 33 | private final String remediation; 34 | 35 | public ScanIssue(IScanIssue copy) 36 | { 37 | this.name = copy.getIssueName(); 38 | this.detail = copy.getIssueDetail(); 39 | this.severity = copy.getSeverity(); 40 | this.httpService = new HTTPService(copy.getHttpService()); 41 | this.url = copy.getUrl(); 42 | IHttpRequestResponse[] iHttpRequestResponse = copy.getHttpMessages(); 43 | HTTPRequestResponse[] allhttpMessages = new HTTPRequestResponse[iHttpRequestResponse.length]; 44 | for (int i = 0; i < iHttpRequestResponse.length; i++) 45 | { 46 | allhttpMessages[i] = new HTTPRequestResponse(iHttpRequestResponse[i]); 47 | } 48 | this.httpMessages = allhttpMessages; 49 | this.confidence = copy.getConfidence(); 50 | this.remediation = copy.getRemediationDetail(); 51 | } 52 | 53 | @Override 54 | public URL getUrl() { 55 | return url; 56 | } 57 | 58 | @Override 59 | public String getIssueName() { 60 | return name; 61 | } 62 | 63 | @Override 64 | public int getIssueType() { 65 | return 0; 66 | } 67 | 68 | @Override 69 | public String getSeverity() { 70 | return severity; 71 | } 72 | 73 | @Override 74 | public String getConfidence() { 75 | return confidence; 76 | } 77 | 78 | @Override 79 | public String getIssueBackground() { 80 | return null; 81 | } 82 | 83 | @Override 84 | public String getRemediationBackground() { 85 | return null; 86 | } 87 | 88 | @Override 89 | public String getIssueDetail() { 90 | return detail; 91 | } 92 | 93 | @Override 94 | public String getRemediationDetail() { 95 | return remediation; 96 | } 97 | 98 | @Override 99 | public HTTPRequestResponse[] getHttpMessages() { 100 | return httpMessages; 101 | } 102 | 103 | @Override 104 | public HTTPService getHttpService() { 105 | return httpService; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/autowasp/logger/ScannerLogic.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp.logger; 18 | 19 | import autowasp.Autowasp; 20 | import autowasp.http.HTTPRequestResponse; 21 | import autowasp.http.ScanIssue; 22 | import autowasp.logger.entryTable.LoggerEntry; 23 | import autowasp.logger.instancesTable.InstanceEntry; 24 | import burp.IScanIssue; 25 | import org.jsoup.Jsoup; 26 | import org.jsoup.nodes.Document; 27 | 28 | import java.net.URL; 29 | import java.util.ArrayList; 30 | 31 | 32 | public class ScannerLogic { 33 | private final Autowasp extender; 34 | public final ArrayList repeatedIssue; 35 | 36 | public ArrayList getRepeatedIssue() { 37 | return repeatedIssue; 38 | } 39 | 40 | public ScannerLogic(Autowasp extender) { 41 | this.extender = extender; 42 | this.repeatedIssue = new ArrayList<>(); 43 | } 44 | 45 | // Method to extract existing scan results 46 | public void extractExistingScan() { 47 | boolean newEntryFlag = true; 48 | IScanIssue[] scannedIssues = this.extender.callbacks.getScanIssues("http"); 49 | for(IScanIssue iScanIssue:scannedIssues) { 50 | ScanIssue issue = castIScanToScan(iScanIssue); 51 | String issueHost = issue.getHttpService().getHost(); 52 | String vulnType = issue.getIssueName(); 53 | if (this.extender.callbacks.isInScope(issue.getUrl())) { 54 | // If issue is new and not in repeated list 55 | if (!this.repeatedIssue.contains(issue.getIssueName())) { 56 | logNewScan(issue); 57 | this.repeatedIssue.add(issue.getIssueName()); 58 | logNewInstance(issue); 59 | } else { 60 | for (LoggerEntry entry : this.extender.loggerList) { 61 | // check if the issue.host and issue.vulnType is equal 62 | if (entry.getHost().equals(issueHost) && entry.getVulnType().equals(vulnType)) { 63 | logNewInstance(issue); 64 | newEntryFlag = false; 65 | } 66 | } 67 | // else new entry. 68 | if (newEntryFlag) { 69 | logNewScan(issue); 70 | logNewInstance(issue); 71 | } 72 | } 73 | } 74 | } 75 | extender.callbacks.registerScannerListener(extender); 76 | } 77 | 78 | public ScanIssue castIScanToScan(IScanIssue iScanIssue){ 79 | ScanIssue scanIssue = new ScanIssue(iScanIssue); 80 | return scanIssue; 81 | } 82 | 83 | // Method to log new instance to a particular issue 84 | public void logNewInstance(ScanIssue issue) { 85 | // form up instances information 86 | URL url = issue.getUrl(); 87 | String confidence = issue.getConfidence(); 88 | String severity = issue.getSeverity(); 89 | HTTPRequestResponse requestResponse = null; 90 | 91 | if(issue.getHttpMessages() != null && issue.getHttpMessages().length !=0) { 92 | requestResponse = issue.getHttpMessages()[0]; 93 | } 94 | InstanceEntry instance = new InstanceEntry(url, confidence, severity, requestResponse); 95 | String issueHost = issue.getHttpService().getHost(); 96 | String issueVulnType = issue.getIssueName(); 97 | 98 | for (LoggerEntry entry : this.extender.loggerList) { 99 | if (entry.getHost().equals(issueHost) && entry.getVulnType().equals(issueVulnType)) { 100 | boolean toAddFlag = true; 101 | for (InstanceEntry ie: entry.getInstanceList()){ 102 | // check if instanceList contain similar URL. 103 | if (ie.getUrl().equals(url.toString())) { 104 | // if url is not unique, set toAddFlag to false 105 | toAddFlag = false; 106 | } 107 | } 108 | // add new instance if toAddFlag is true 109 | if (toAddFlag) { 110 | entry.addInstance(instance); 111 | } 112 | } 113 | } 114 | } 115 | 116 | // Method to log new scan entry 117 | public void logNewScan(ScanIssue issue) { 118 | // Form scan issue information 119 | String host = issue.getHttpService().getHost(); 120 | String action = "Burp Scanner"; 121 | String issueName = ""; 122 | String vulnType = issue.getIssueName(); 123 | String defaultComments = "Burp Scanner detected the following issue type: " + issue.getIssueName(); 124 | String evidences = issue.getIssueDetail(); 125 | if (evidences == null){ 126 | evidences = "Refer to affected instances Request and Response."; 127 | } 128 | Document document = Jsoup.parse(evidences); 129 | evidences = document.text(); 130 | 131 | LoggerEntry entry = new LoggerEntry(host, action, vulnType, issueName); 132 | entry.instancesList.clear(); 133 | entry.setPenTesterComments(defaultComments); 134 | entry.setEvidence(evidences); 135 | extender.loggerTableModel.addAllLoggerEntry(entry); 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/autowasp/logger/TrafficEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package autowasp.logger; 17 | 18 | import autowasp.http.HTTPRequestResponse; 19 | 20 | import java.net.URL; 21 | 22 | public class TrafficEntry { 23 | 24 | public final String flag; 25 | public final HTTPRequestResponse requestResponse; 26 | public final URL url; 27 | public final TrafficInstance affectedInstancesList; 28 | public final String evidence; 29 | public final String trafficMsg; 30 | 31 | TrafficEntry(String flag, HTTPRequestResponse requestResponse, URL url, TrafficInstance affectedInstancesList, String evidence, String trafficMsg){ 32 | this.flag = flag; 33 | this.requestResponse = requestResponse; 34 | this.url = url; 35 | this.affectedInstancesList = affectedInstancesList; 36 | this.evidence = evidence; 37 | this.trafficMsg = trafficMsg; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/autowasp/logger/TrafficInstance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp.logger; 18 | 19 | public class TrafficInstance { 20 | 21 | public boolean isUnencrypted; 22 | public boolean isBase64; 23 | public boolean isXContent; 24 | public final boolean isServerInfoLeaked; 25 | public boolean isServerErrorInfoLeaked; 26 | public boolean isCorHeaders; 27 | public final boolean isUnauthorisedDisclosure; 28 | public final boolean isXSS; 29 | public boolean isCGI; 30 | public boolean isHTTPVerb; 31 | 32 | public TrafficInstance(){ 33 | this.isUnencrypted = false; 34 | this.isBase64 = false; 35 | this.isXContent = false; 36 | this.isServerInfoLeaked = false; 37 | this.isServerErrorInfoLeaked = false; 38 | this.isCorHeaders = false; 39 | this.isUnauthorisedDisclosure = false; 40 | this.isXSS = false; 41 | this.isCGI = false; 42 | this.isHTTPVerb = false; 43 | } 44 | 45 | public void setUnencrypted() { 46 | this.isUnencrypted = true; 47 | } 48 | 49 | public void setServerInfoLeaked() { 50 | this.isServerErrorInfoLeaked = true; 51 | } 52 | 53 | public void setServerErrorInfoLeaked() { 54 | this.isServerErrorInfoLeaked = true; 55 | } 56 | 57 | public void setCGI() { 58 | this.isCGI = true; 59 | } 60 | 61 | public void setBase64() { 62 | this.isBase64 = true; 63 | } 64 | 65 | public void setCorHeaders() { 66 | this.isCorHeaders = true; 67 | } 68 | 69 | public void setHttpVerb() { 70 | this.isHTTPVerb = true; 71 | } 72 | 73 | public void setXContentHeaders() { 74 | this.isXContent = true; 75 | } 76 | } -------------------------------------------------------------------------------- /src/main/java/autowasp/logger/TrafficLogic.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package autowasp.logger; 17 | 18 | import autowasp.Autowasp; 19 | import autowasp.http.HTTPRequestResponse; 20 | import autowasp.http.InterceptProxyMessage; 21 | import autowasp.logger.entryTable.LoggerEntry; 22 | import autowasp.logger.instancesTable.InstanceEntry; 23 | import burp.IRequestInfo; 24 | import burp.IResponseInfo; 25 | 26 | import java.net.MalformedURLException; 27 | import java.net.URL; 28 | import java.nio.charset.StandardCharsets; 29 | import java.util.ArrayList; 30 | import java.util.Arrays; 31 | import java.util.List; 32 | 33 | // The TrafficLogic implements the logic for processing traffic related functions. 34 | public class TrafficLogic { 35 | private final Autowasp extender; 36 | boolean secHeaderFlag = false; 37 | boolean cookieOverallFlag = false; 38 | boolean httpRequestFlag = false; 39 | boolean basicAuthenticationFlag = false; 40 | boolean serverDetailFlag = false; 41 | boolean serverErrorLeakedInfoFlag = false; 42 | boolean corHeadersFlag = false; 43 | boolean unauthorisedDisclosureHostnameFlag = false; 44 | boolean urlManipulationFlag = false; 45 | boolean xssFlag = false; 46 | boolean cgiFlag = false; 47 | boolean cgiUrls = false; 48 | boolean httpVerbFlag = false; 49 | private String evidence; 50 | private String trafficMsg; 51 | private String flag; 52 | private InterceptProxyMessage message; 53 | private HTTPRequestResponse messageInfo; 54 | private IRequestInfo requestInfo; 55 | private IResponseInfo responseInfo ; 56 | private TrafficInstance affectedInstancesList; 57 | private List requestHeaderList = new ArrayList<>(); 58 | private List responseHeaderList = new ArrayList<>(); 59 | public final ArrayList cgiUrlList; 60 | public final String burpCollaboratorHost; 61 | 62 | 63 | final ArrayList httpVerbList = new ArrayList<>(); 64 | 65 | public TrafficLogic(Autowasp extender) { 66 | this.extender = extender; 67 | this.buildHttpVerbList(); 68 | this.cgiUrlList = new ArrayList<>(); 69 | this.burpCollaboratorHost = this.extender.iBurpCollaboratorClientContext.generatePayload(true); 70 | } 71 | 72 | // Method to automate and flag network traffic findings 73 | public void classifyTraffic(InterceptProxyMessage message) { 74 | this.resetLogMsg(); 75 | this.message = message; 76 | messageInfo = this.message.getMessageInfo(); 77 | requestInfo = extender.helpers.analyzeRequest(messageInfo.getHttpService(), messageInfo.getRequest()); 78 | responseInfo = extender.helpers.analyzeResponse(messageInfo.getResponse()); 79 | requestHeaderList = requestInfo.getHeaders(); 80 | responseHeaderList = responseInfo.getHeaders(); 81 | 82 | if(!httpRequestFlag && messageInfo.getHttpService().getProtocol().equals("http")) { 83 | verifyHTTPRequest(); 84 | } 85 | if (!serverDetailFlag) { 86 | verifyServerInfoLeakage(); 87 | } 88 | if (!serverErrorLeakedInfoFlag) { 89 | verifyServerErrorLeakage(); 90 | } 91 | if (!basicAuthenticationFlag) { 92 | verifyBasicAuthentication(); 93 | } 94 | if (!urlManipulationFlag) { 95 | try { 96 | if (responseInfo.getStatusCode() == 302 && messageInfo.getHttpService().getProtocol().equals("http")) { 97 | verifyUrlManipulation(); 98 | } 99 | } catch (Exception e) { 100 | extender.stdout.println("Exception occurred at classifyTraffic()"); 101 | } 102 | } 103 | if (!corHeadersFlag) { 104 | verifyCorHeaders(); 105 | } 106 | if (!httpVerbFlag) { 107 | verifyHttpVerbRequest(); 108 | } 109 | if (!secHeaderFlag) { 110 | verifyXContentHeaders(); 111 | } 112 | 113 | // TODO: Always Monitoring CGI modules 114 | //verifyCGIModules(); 115 | } 116 | 117 | // Method to inspect response content headers 118 | private void verifyXContentHeaders() { 119 | boolean xcontentFlag = false; 120 | this.trafficMsg = ""; 121 | this.evidence = ""; 122 | for (String header : responseHeaderList) { 123 | String[] tokens = header.split(":"); 124 | if(tokens[0].toLowerCase().contains("x-content-type-options")) { 125 | this.trafficMsg = "[+] X-Content-Type-Options header implemented\n"; 126 | this.evidence += header + "\n"; 127 | xcontentFlag = true; 128 | } 129 | if(tokens[0].toLowerCase().contains("x-frame-options")) { 130 | this.trafficMsg = "[+] X-Frame-Options implemented\n"; 131 | this.evidence += header + "\n"; 132 | xcontentFlag = true; 133 | } 134 | if(tokens[0].toLowerCase().contains("x-xss-protection")) { 135 | this.trafficMsg = "[+] X-XSS-Protection implemented\n"; 136 | this.evidence += header + "\n"; 137 | xcontentFlag = true; 138 | } 139 | if(tokens[0].toLowerCase().contains("content-type")) { 140 | this.trafficMsg = "[+] Content-Type implemented\n"; 141 | this.evidence += header + "\n"; 142 | xcontentFlag = true; 143 | } 144 | } 145 | 146 | if (xcontentFlag) { 147 | this.secHeaderFlag = true; 148 | affectedInstancesList.setXContentHeaders(); 149 | this.flag = "Content frame(s) implementation"; 150 | storeTrafficFinding(); 151 | } 152 | 153 | } 154 | 155 | // Method to verify HTTP verb request submission 156 | private void verifyHttpVerbRequest() { 157 | try { 158 | byte[] request = messageInfo.getRequest(); 159 | if (request != null) { 160 | String request_string = extender.helpers.bytesToString(request); 161 | String[] lines = request_string.split("\n"); 162 | 163 | if (lines[0].contains("POST")) { 164 | this.evidence = ""; 165 | 166 | String host = messageInfo.getHttpService().getHost(); 167 | int port = messageInfo.getHttpService().getPort(); 168 | 169 | for (String method: httpVerbList) { 170 | String newRequest_string = request_string.replace("POST", method); 171 | byte[] newRequest = extender.helpers.stringToBytes(newRequest_string); 172 | byte[] newResponse = extender.callbacks.makeHttpRequest(host, port, true, newRequest); 173 | IResponseInfo newResponseInfo = extender.helpers.analyzeResponse(newResponse); 174 | int newStatusCode = newResponseInfo.getStatusCode(); 175 | 176 | if (newStatusCode < 400) { 177 | this.evidence += "Ran method: " + method + " and response status code returns " + newStatusCode + "\n"; 178 | } 179 | } 180 | 181 | if (!this.evidence.equals("")) { 182 | this.trafficMsg = "[+] Possible dangerous HTTP method could be used on this site"; 183 | } 184 | else { 185 | this.trafficMsg = "[+] No dangerous HTTP method could be used on this site"; 186 | } 187 | this.flag = "HTTP verb testing"; 188 | affectedInstancesList.setHttpVerb(); 189 | this.httpVerbFlag = true; 190 | storeTrafficFinding(); 191 | } 192 | } 193 | } 194 | catch(Exception e) { 195 | extender.stdout.println("Exception occurred at verifyHttpVerbRequest()"); 196 | } 197 | } 198 | 199 | // Method to inspect for CORS headers 200 | private void verifyCorHeaders() { 201 | for (String header : responseHeaderList) { 202 | if (header.toLowerCase().contains("access-control-allow-origin: *")) { 203 | this.corHeadersFlag = true; 204 | this.trafficMsg = "[+] Insecure implementation of CORS Header\n"; 205 | this.evidence = header + "\n"; 206 | this.flag = "CORS headers implementation"; 207 | affectedInstancesList.setCorHeaders(); 208 | storeTrafficFinding(); 209 | } 210 | } 211 | } 212 | 213 | // Method to inspect for URL manipulation 214 | private void verifyUrlManipulation() { 215 | if (requestHeaderList.size() != 0) { 216 | try { 217 | String directory = requestHeaderList.get(0).split(" ")[1]; 218 | 219 | // ensure there is no slash behind the URL and a .ext file 220 | if (!directory.endsWith("/") && !directory.contains(".")) { 221 | 222 | this.urlManipulationFlag = true; 223 | int port = 80; 224 | String urlString = "https://" + burpCollaboratorHost + directory; 225 | URL url; 226 | 227 | url = new URL(urlString); 228 | 229 | 230 | byte[] maliciousRequest = extender.helpers.buildHttpRequest(url); 231 | IRequestInfo newRequestInfo = extender.helpers.analyzeRequest(maliciousRequest); 232 | List newRequestHeaderList = newRequestInfo.getHeaders(); 233 | byte[] newResponse = extender.callbacks.makeHttpRequest(burpCollaboratorHost, port, false, maliciousRequest); 234 | IResponseInfo newResponseInfo = extender.helpers.analyzeResponse(newResponse); 235 | List newResponseHeaderList = newResponseInfo.getHeaders(); 236 | 237 | if (newResponseInfo.getStatusCode() == 302) { 238 | for (String header: newResponseHeaderList) { 239 | String location = "location: " + urlString; 240 | if (header.toLowerCase().contains(location)) { 241 | this.trafficMsg = "[+] Manipulation of URL to redirect victim IS possible on this site"; 242 | this.evidence = "MANIPULATED REQUEST\n"; 243 | for (String newHeader: newRequestHeaderList) { 244 | this.evidence += newHeader + "\n"; 245 | } 246 | this.evidence += "\n\nRESPONSE\n"; 247 | for (String newHeader: newResponseHeaderList) { 248 | this.evidence += newHeader + "\n"; 249 | } } 250 | else { 251 | this.trafficMsg = "[+] Manipulation of URL to redirect victim IS NOT possible on this site"; 252 | this.evidence = "MANIPULATED REQUEST\n"; 253 | for (String newHeader: newRequestHeaderList) { 254 | this.evidence += newHeader + "\n"; 255 | } 256 | this.evidence += "\n\nRESPONSE\n"; 257 | for (String newHeader: newResponseHeaderList) { 258 | this.evidence += newHeader + "\n"; 259 | } 260 | } 261 | } 262 | } 263 | else { 264 | this.trafficMsg = "[+] Manipulation of URL to redirect victim IS NOT possible on this site"; 265 | this.evidence = "MANIPULATED REQUEST\n"; 266 | for (String newHeader: newRequestHeaderList) { 267 | this.evidence += newHeader + "\n"; 268 | } 269 | this.evidence += "\n\nRESPONSE\n"; 270 | for (String newHeader: newResponseHeaderList) { 271 | this.evidence += newHeader + "\n"; 272 | } 273 | } 274 | 275 | this.urlManipulationFlag = true; 276 | this.flag = "URL Manipulation"; 277 | storeTrafficFinding(); 278 | } 279 | 280 | } catch (MalformedURLException e) { 281 | extender.stdout.println("MalformedURLException at verifyUrlManipulation()" ); 282 | } 283 | } 284 | } 285 | 286 | // Method to identify the use of basic authentication headers 287 | private void verifyBasicAuthentication() { 288 | for (String header : requestHeaderList) { 289 | if (header.toLowerCase().contains("authorization: basic")) { 290 | String[] tokens = header.split(" "); 291 | String encode = tokens[2]; 292 | byte[] decodeBytes = extender.helpers.base64Decode(encode); 293 | String decode; 294 | decode = new String(decodeBytes , StandardCharsets.UTF_8); 295 | 296 | this.basicAuthenticationFlag = true; 297 | this.flag = "Base64 weak authentication request"; 298 | this.trafficMsg = "[+] Basic Authentication request is being used\n"; 299 | this.trafficMsg += "Encoded found: " + encode + "\n"; 300 | this.trafficMsg += "Decoded found: " + decode + "\n"; 301 | this.evidence = header + "\n"; 302 | this.affectedInstancesList.setBase64(); 303 | storeTrafficFinding(); 304 | } 305 | } 306 | } 307 | 308 | /* 309 | // Method to identify for CGI modules. Still in development. 310 | private void verifyCGIModules() { 311 | String directory = responseHeaderList.get(0).split(" ")[1]; 312 | 313 | if (cgiFlag && directory.contains("cgi") && responseInfo.getStatusCode() == 200) { 314 | String url = requestInfo.getUrl().toString(); 315 | if (cgiUrlList.contains(url)) { 316 | for (TrafficEntry temp : extender.trafficLog) { 317 | if (temp.affectedInstancesList.isCGI) { 318 | temp.evidence += "URL :" + url + " returns : " + responseInfo.getStatusCode() + "\n"; 319 | this.cgiUrlList.add(url); 320 | } 321 | } 322 | } 323 | } 324 | else if (directory.contains("cgi") && responseInfo.getStatusCode() == 200) { 325 | String url = requestInfo.getUrl().toString(); 326 | this.cgiUrlList.add(url); 327 | this.trafficMsg = "[+] CGI modules are enabled on this web server"; 328 | this.evidence = "URL :" + url + " returns : " + responseInfo.getStatusCode() + "\n"; 329 | this.cgiFlag = true; 330 | this.flag = "CGI Modules enabled"; 331 | affectedInstancesList.setCGI(); 332 | storeTrafficFinding(); 333 | } 334 | }*/ 335 | 336 | // Method to inspect for server error leakage 337 | private void verifyServerErrorLeakage() { 338 | try { 339 | String header = responseHeaderList.get(2); 340 | String[] tokens = header.split(":"); 341 | 342 | if (header.toLowerCase().contains("server") && tokens[1].length() != 1 && responseInfo.getStatusCode() >= 500) { 343 | trafficMsg = "[+] Potential Server Details : " + tokens[1] + "from server error page\n"; 344 | 345 | this.serverErrorLeakedInfoFlag = true; 346 | this.flag = "Server response header revealed from error response"; 347 | affectedInstancesList.setServerErrorInfoLeaked(); 348 | this.evidence = header + "\n"; 349 | storeTrafficFinding(); 350 | } 351 | } 352 | catch (Exception e) { 353 | extender.stdout.println("Exception occurred at verifyServerErrorLeakage"); 354 | } 355 | 356 | } 357 | 358 | // Method to inspect for server info 359 | private void verifyServerInfoLeakage() { 360 | boolean toLog = false; 361 | try { 362 | String header = responseHeaderList.get(2); 363 | String[] tokens = header.split(":"); 364 | 365 | if(header.toLowerCase().contains("server") && tokens[1].length() != 1) { 366 | trafficMsg = "[+] Potential Server Details : " + tokens[1] + "\n"; 367 | toLog = true; 368 | } 369 | 370 | if (header.toLowerCase().contains("x-powered-by") && tokens[1].length() != 1) { 371 | trafficMsg = "[+] Web Server powered by : " + tokens[1] + "\n"; 372 | toLog = true; 373 | } 374 | if (toLog) { 375 | this.serverDetailFlag = true; 376 | this.flag = "Server Information Leakage"; 377 | affectedInstancesList.setServerInfoLeaked(); 378 | this.evidence = header + "\n"; 379 | storeTrafficFinding(); 380 | } 381 | } 382 | catch(Exception e) { 383 | extender.stdout.println("Exception occurred at verifyServerInfoLeakage"); 384 | } 385 | } 386 | 387 | // Method to inspect for non-secure network traffic 388 | private void verifyHTTPRequest() { 389 | this.httpRequestFlag = true; 390 | trafficMsg = "[+] A proxy intercepted a request on : " + messageInfo.getHttpService().getHost(); 391 | flag = "Communication over unencrypted channel"; 392 | affectedInstancesList.setUnencrypted(); 393 | 394 | if (responseInfo.getStatusCode() == 200) { 395 | trafficMsg += "\n[+] Server response with " + responseInfo.getStatusCode(); 396 | trafficMsg += "\n[+] Potential sensitive information being transmitted over non-SSL connections"; 397 | } 398 | else if(responseInfo.getStatusCode() == 302 || responseInfo.getStatusCode() == 301 || responseInfo.getStatusCode() == 304) { 399 | trafficMsg += "\n[+] Server response return "+ responseInfo.getStatusCode(); 400 | trafficMsg +="\nRedirection Message from a HTTP Request detected"; 401 | } 402 | evidence = responseHeaderList.get(0) + "\n"; 403 | evidence += responseHeaderList.get(1) + "\n"; 404 | evidence += responseHeaderList.get(2) + "\n"; 405 | evidence += responseHeaderList.get(3) + "\n"; 406 | evidence += responseHeaderList.get(4) + "\n"; 407 | storeTrafficFinding(); 408 | } 409 | 410 | // Method to build HTTP Verb list 411 | private void buildHttpVerbList() { 412 | this.httpVerbList.add("POST"); 413 | this.httpVerbList.add("PUT"); 414 | this.httpVerbList.add("DELETE"); 415 | this.httpVerbList.add("TRACE"); 416 | this.httpVerbList.add("TRACK"); 417 | this.httpVerbList.add("CONNECT"); 418 | this.httpVerbList.add("PROPFIND"); 419 | this.httpVerbList.add("PROPPATCH"); 420 | this.httpVerbList.add("MKCOL"); 421 | this.httpVerbList.add("MOVE"); 422 | this.httpVerbList.add("LOCK"); 423 | this.httpVerbList.add("UNLOCK"); 424 | this.httpVerbList.add("VERSION-CONTROL"); 425 | this.httpVerbList.add("REPORT"); 426 | this.httpVerbList.add("CHECKOUT"); 427 | this.httpVerbList.add("CHECKIN"); 428 | this.httpVerbList.add("UNCHECKOUT"); 429 | this.httpVerbList.add("MKWORKSPACE"); 430 | this.httpVerbList.add("UPDATE"); 431 | this.httpVerbList.add("LABEL"); 432 | this.httpVerbList.add("MERGE"); 433 | this.httpVerbList.add("BASELINE-CONTROL"); 434 | this.httpVerbList.add("MKACTIVITY"); 435 | this.httpVerbList.add("ORDERPATCH"); 436 | this.httpVerbList.add("ACL"); 437 | this.httpVerbList.add("PATCH"); 438 | this.httpVerbList.add("SEARCH"); 439 | this.httpVerbList.add("ARBITARY"); 440 | } 441 | 442 | // Method to clear log message 443 | private void resetLogMsg() { 444 | evidence = null; 445 | trafficMsg = null; 446 | affectedInstancesList = new TrafficInstance(); 447 | message = null; 448 | messageInfo = null; 449 | requestInfo = null; 450 | responseInfo = null; 451 | requestHeaderList.clear(); 452 | responseHeaderList.clear(); 453 | 454 | } 455 | 456 | // Method to store traffic findings to Autowasp 457 | private void storeTrafficFinding() { 458 | String host = messageInfo.getHttpService().getHost(); 459 | String action = "Automated Traffic"; 460 | String vulnType = flag; 461 | String issue = ""; 462 | String comments = "Automated Traffic logging detected the following issue: " + flag; 463 | LoggerEntry findingEntry = new LoggerEntry(host, action, vulnType, issue); 464 | findingEntry.setEvidence(evidence); 465 | 466 | URL url = extender.helpers.analyzeRequest(message.getMessageInfo()).getUrl(); 467 | String confidence = "Certain"; 468 | String severity = "~"; 469 | HTTPRequestResponse requestResponse = new HTTPRequestResponse(message.getMessageInfo()); 470 | InstanceEntry instanceEntry = new InstanceEntry(url, confidence, severity, requestResponse); 471 | findingEntry.addInstance(instanceEntry); 472 | findingEntry.setPenTesterComments(comments + "\n" + trafficMsg); 473 | 474 | extender.loggerTableModel.addAllLoggerEntry(findingEntry); 475 | 476 | this.resetLogMsg(); 477 | } 478 | } 479 | -------------------------------------------------------------------------------- /src/main/java/autowasp/logger/entryTable/LoggerEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package autowasp.logger.entryTable; 17 | 18 | import autowasp.logger.instancesTable.InstanceEntry; 19 | 20 | import java.io.Serializable; 21 | import java.util.ArrayList; 22 | 23 | public class LoggerEntry implements Serializable { 24 | 25 | public final String host; 26 | public final String action; 27 | public final String vulnType; 28 | public String checklistIssue; 29 | public final ArrayList instancesList; 30 | public String penTesterComments; 31 | public String evidences; 32 | public final Integer issueNumber; //Points to the test case in the OWASP checklist that the user maps this particular finding to 33 | 34 | public LoggerEntry(String host, String action, String vulnType, String checklistIssue){ 35 | this.host = host; 36 | this.action = action; 37 | this.vulnType = vulnType; 38 | this.checklistIssue = checklistIssue; 39 | this.issueNumber = null; 40 | instancesList = new ArrayList<>(); 41 | penTesterComments = "Please insert comments"; 42 | evidences = "nil"; 43 | } 44 | 45 | public LoggerEntry(String host, String action, String vulnType, String checklistIssue, String comments){ 46 | this.host = host; 47 | this.action = action; 48 | this.vulnType = vulnType; 49 | this.checklistIssue = checklistIssue; 50 | this.issueNumber = null; 51 | instancesList = new ArrayList<>(); 52 | penTesterComments = comments; 53 | evidences = "Please insert evidences"; 54 | } 55 | 56 | public String getHost(){ return this.host;} 57 | 58 | public String getChecklistIssue() { 59 | return this.checklistIssue; 60 | } 61 | 62 | public void setChecklistIssue(String checklistIssue) { 63 | this.checklistIssue = checklistIssue; 64 | } 65 | 66 | public void setPenTesterComments(String penTesterComments) { 67 | this.penTesterComments = penTesterComments; 68 | } 69 | 70 | public String getPenTesterComments() { 71 | return this.penTesterComments; 72 | } 73 | 74 | public void setEvidence(String evidence) { 75 | this.evidences = evidence; 76 | } 77 | 78 | public String getEvidence() { 79 | return this.evidences; 80 | } 81 | 82 | public ArrayList getInstanceList() { 83 | return this.instancesList; 84 | } 85 | 86 | public void addInstance(InstanceEntry instance) { 87 | this.instancesList.add(instance); 88 | } 89 | 90 | public int getIssueNumber() { 91 | return this.issueNumber; 92 | } 93 | 94 | public String getVulnType() { 95 | return vulnType; 96 | } 97 | 98 | public String toString() { 99 | return "host: " + this.host + ";action: " + this.action + ";issue: " + this.checklistIssue; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/autowasp/logger/entryTable/LoggerTable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package autowasp.logger.entryTable; 17 | 18 | import autowasp.Autowasp; 19 | import autowasp.checklist.ChecklistEntry; 20 | 21 | import javax.swing.DefaultCellEditor; 22 | import javax.swing.JComboBox; 23 | import javax.swing.JTable; 24 | import javax.swing.table.TableColumn; 25 | import javax.swing.table.TableModel; 26 | 27 | @SuppressWarnings("serial") 28 | public class LoggerTable extends JTable { 29 | private final Autowasp extender; 30 | private int currentRow; 31 | 32 | public LoggerTable(TableModel tableModel, Autowasp extender){ 33 | super(tableModel); 34 | this.extender = extender; 35 | setColumnWidths(50, 50, 150, 300, 150, 300, 150, 300, 200, Integer.MAX_VALUE); 36 | } 37 | 38 | public void setColumnWidths(int... widths) { 39 | for (int i = 0; i < widths.length; i += 2) { 40 | if ((i / 2) < columnModel.getColumnCount()) { 41 | columnModel.getColumn(i / 2).setPreferredWidth(widths[i]); 42 | columnModel.getColumn(i / 2).setMaxWidth(widths[i + 1]); 43 | } 44 | else continue; 45 | } 46 | } 47 | 48 | // Method for table view change selection 49 | @Override 50 | public void changeSelection(int row, int col, boolean toggle, boolean extend) { 51 | // show the log entry for the selected row 52 | LoggerEntry loggerEntry = extender.loggerList.get(row); 53 | currentRow = row; 54 | extender.currentEntryRow = row; 55 | extender.extenderPanelUI.penTesterCommentBox.setText(loggerEntry.getPenTesterComments()); 56 | extender.extenderPanelUI.evidenceBox.setText(loggerEntry.getEvidence()); 57 | extender.instancesTableModel.clearInstanceEntryList(); 58 | extender.instancesTableModel.addAllInstanceEntry(loggerEntry.instancesList); 59 | 60 | super.changeSelection(row, col, toggle, extend); 61 | extender.extenderPanelUI.deleteEntryButtonEnabled(); 62 | } 63 | 64 | // Method to modify pentester's comments text field 65 | public void modifyComments(String comments) { 66 | extender.loggerList.get(currentRow).setPenTesterComments(comments); 67 | extender.loggerTableModel.fireTableDataChanged(); 68 | //Checks if finding is mapped to a checklist entry 69 | //If it is, set the pentesterComments variable for that checklist entry 70 | if (extender.loggerList.get(currentRow).issueNumber != null) { 71 | int issueNumber = extender.loggerList.get(currentRow).getIssueNumber(); 72 | String finalComments = comments + "\n"; 73 | extender.checklistLog.get(issueNumber).setPenTesterComments(finalComments); 74 | } 75 | } 76 | 77 | // Method to modify pentester's evidences text field 78 | public void modifyEvidence(String evidences) { 79 | extender.loggerList.get(currentRow).setEvidence(evidences); 80 | extender.loggerTableModel.fireTableDataChanged(); 81 | //Checks if finding is mapped to a checklist entry 82 | //If it is, set the evidence variable for that checklist entry 83 | if (extender.loggerList.get(currentRow).issueNumber != null) { 84 | int issueNumber = extender.loggerList.get(currentRow).getIssueNumber(); 85 | String finalEvidence = evidences + "\n"; 86 | extender.checklistLog.get(issueNumber).setEvidence(finalEvidence); 87 | } 88 | } 89 | 90 | // Method to setup WTSG mapping column with dropdown combo 91 | public void setUpIssueColumn(TableColumn column) { 92 | column.setCellEditor(new DefaultCellEditor(extender.comboBox)); 93 | } 94 | 95 | // Method to setup WTSG mapping column with dropdown combo 96 | public void generateWSTGList() { 97 | JComboBox comboBox = extender.comboBox; 98 | // Add an N.A. to mark finding as false positive 99 | comboBox.addItem("N.A."); 100 | for (ChecklistEntry entry : extender.checklistLog) { 101 | String comboEntry = entry.getRefNumber() + " - " + entry.getTestName(); 102 | comboBox.addItem(comboEntry); 103 | } 104 | } 105 | 106 | // Method to reset WTSG mapping column 107 | public void resetList() { 108 | extender.comboBox.removeAllItems(); 109 | JComboBox comboBox = extender.comboBox; 110 | // Add an N.A. to mark finding as false positive 111 | comboBox.addItem("N.A."); 112 | for (ChecklistEntry entry : extender.checklistLog) { 113 | if (!entry.isExcluded()){ 114 | String comboEntry = entry.getRefNumber() + " - " + entry.getTestName(); 115 | comboBox.addItem(comboEntry); 116 | } 117 | } 118 | } 119 | 120 | // Method to delete logger entry 121 | public void deleteEntry() { 122 | extender.extenderPanelUI.deleteEntryButton.setEnabled(false); 123 | extender.loggerList.remove(currentRow); 124 | // update UI 125 | // Inform user about entry deletion 126 | extender.extenderPanelUI.scanStatusLabel.setText("Entry deleted"); 127 | extender.callbacks.issueAlert("Entry deleted"); 128 | // Repaint logger entries table 129 | extender.loggerTableModel.updateLoggerEntryTable(); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/autowasp/logger/entryTable/LoggerTableModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package autowasp.logger.entryTable; 17 | import javax.swing.table.AbstractTableModel; 18 | import java.util.List; 19 | 20 | @SuppressWarnings("serial") 21 | public class LoggerTableModel extends AbstractTableModel{ 22 | private final List listFindingEntry; 23 | private final String[] columnNames = { "#", "Host", "Action", "Vuln Type", "Mapped to OWASP WSTG" }; 24 | 25 | public LoggerTableModel(List listFindingEntry) { 26 | this.listFindingEntry = listFindingEntry; 27 | } 28 | 29 | // Method to get column count 30 | @Override 31 | public int getColumnCount() { 32 | return columnNames.length; 33 | } 34 | 35 | // Method to get row count 36 | @Override 37 | public int getRowCount() { 38 | return listFindingEntry.size(); 39 | } 40 | 41 | // Method to get column name 42 | public String getColumnName(int columnIndex) { 43 | return columnNames[columnIndex]; 44 | } 45 | 46 | // Method to get value at selected row and column 47 | @Override 48 | public String getValueAt(int rowIndex, int columnIndex) { 49 | String returnValue = ""; 50 | LoggerEntry loggerEntry = listFindingEntry.get(rowIndex); 51 | switch (columnIndex) { 52 | case 0: 53 | returnValue = rowIndex + 1 + ""; 54 | break; 55 | case 1: 56 | returnValue = loggerEntry.host; 57 | break; 58 | case 2: 59 | returnValue = loggerEntry.action; 60 | break; 61 | case 3: 62 | returnValue = loggerEntry.vulnType; 63 | break; 64 | case 4: 65 | returnValue = loggerEntry.checklistIssue; 66 | break; 67 | } 68 | return returnValue; 69 | } 70 | 71 | // Method to set value at selected row and column 72 | @Override 73 | public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 74 | LoggerEntry loggerEntry = listFindingEntry.get(rowIndex); 75 | if (columnIndex == 4) { 76 | loggerEntry.setChecklistIssue((String) aValue); 77 | } 78 | } 79 | 80 | // Method to clear instance entry from table view 81 | public void clearLoggerList() { 82 | this.listFindingEntry.clear(); 83 | } 84 | 85 | // Method to re-add all entry from existing list to table view 86 | public void addAllLoggerEntry(LoggerEntry loggerEntry) { 87 | this.listFindingEntry.add(loggerEntry); 88 | this.fireTableDataChanged(); 89 | } 90 | 91 | // Method to update entry in table view 92 | public void updateLoggerEntryTable() { 93 | this.fireTableDataChanged(); 94 | } 95 | 96 | // Method to restrict editable cell to those with dropdown combo. 97 | public boolean isCellEditable(int row, int col) { 98 | return col == 4; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/autowasp/logger/instancesTable/InstanceEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp.logger.instancesTable; 18 | 19 | import autowasp.http.HTTPRequestResponse; 20 | import burp.IHttpRequestResponse; 21 | 22 | import java.io.Serializable; 23 | import java.net.URL; 24 | 25 | public class InstanceEntry implements Serializable { 26 | public int id = 0; 27 | public final URL url; 28 | public String confidence; 29 | public String severity; 30 | public final HTTPRequestResponse requestResponse; 31 | final boolean falsePositive; 32 | 33 | public InstanceEntry(URL url, String confidence, String severity, HTTPRequestResponse requestResponse){ 34 | this.id = this.id + 1; 35 | this.url = url; 36 | this.confidence = confidence; 37 | this.severity = severity; 38 | this.requestResponse = requestResponse; 39 | this.falsePositive = false; 40 | } 41 | 42 | 43 | public void setConfidence(String confidence) { 44 | this.confidence = confidence; 45 | } 46 | 47 | public String getConfidence() { 48 | return this.confidence; 49 | } 50 | 51 | public void setSeverity(String severity) { 52 | this.severity = severity; 53 | } 54 | 55 | public String getSeverity() { 56 | return severity; 57 | } 58 | 59 | 60 | public IHttpRequestResponse getResReq() { 61 | return this.requestResponse; 62 | } 63 | 64 | public boolean isIHttpRequestResponseNull() { 65 | return this.requestResponse == null; 66 | } 67 | 68 | public String getUrl() { 69 | return url.toString(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/autowasp/logger/instancesTable/InstanceTable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package autowasp.logger.instancesTable; 17 | 18 | import autowasp.Autowasp; 19 | 20 | import javax.swing.DefaultCellEditor; 21 | import javax.swing.JComboBox; 22 | import javax.swing.JTable; 23 | import javax.swing.table.TableColumn; 24 | import javax.swing.table.TableModel; 25 | 26 | @SuppressWarnings("serial") 27 | public class InstanceTable extends JTable { 28 | private final Autowasp extender; 29 | private int currentRow; 30 | 31 | public InstanceTable(TableModel tableModel, Autowasp extender){ 32 | super(tableModel); 33 | this.extender = extender; 34 | setColumnWidths(50, 80, 2500, 350, 150, 300, 150, Integer.MAX_VALUE); 35 | } 36 | 37 | public void setColumnWidths(int... widths) { 38 | for (int i = 0; i < widths.length; i += 2) { 39 | if ((i / 2) < columnModel.getColumnCount()) { 40 | columnModel.getColumn(i / 2).setPreferredWidth(widths[i]); 41 | columnModel.getColumn(i / 2).setMaxWidth(widths[i + 1]); 42 | } 43 | else continue; 44 | } 45 | } 46 | 47 | // Method for table view change selection 48 | @Override 49 | public void changeSelection(int row, int col, boolean toggle, boolean extend){ 50 | // show the log entry for the selected row 51 | currentRow = row; 52 | InstanceEntry instanceEntry = extender.instanceLog.get(row); 53 | if (instanceEntry.isIHttpRequestResponseNull()) { 54 | String toPrint = ""; 55 | byte[] toByte = toPrint.getBytes(); 56 | extender.extenderPanelUI.requestViewer.setMessage(toByte, false); 57 | extender.extenderPanelUI.responseViewer.setMessage(toByte, false); 58 | } 59 | else { 60 | extender.extenderPanelUI.requestViewer.setMessage(instanceEntry.requestResponse.getRequest(), true); 61 | extender.extenderPanelUI.responseViewer.setMessage(instanceEntry.requestResponse.getResponse(), true); 62 | } 63 | super.changeSelection(row, col, toggle, extend); 64 | extender.extenderPanelUI.deleteInstanceButtonEnabled(); 65 | } 66 | 67 | // Method to setup confidence column with dropdown combo 68 | public void setUpConfidenceColumn(TableColumn column) { 69 | DefaultCellEditor dce = new DefaultCellEditor(extender.comboBox2); 70 | column.setCellEditor(dce); 71 | } 72 | 73 | // Method to setup Severity column with dropdown combo 74 | public void setupSeverityColumn(TableColumn column) { 75 | DefaultCellEditor dce = new DefaultCellEditor(extender.comboBox3); 76 | column.setCellEditor(dce); 77 | } 78 | 79 | // Method to prepare confidence dropdown combo 80 | public void generateConfidenceList() { 81 | JComboBox comboBox = extender.comboBox2; 82 | comboBox.addItem("False Positive"); 83 | comboBox.addItem("Certain"); 84 | comboBox.addItem("Firm"); 85 | comboBox.addItem("Tentative"); 86 | } 87 | 88 | // Method to prepare severity dropdown combo 89 | public void generateSeverityList() { 90 | JComboBox comboBox = extender.comboBox3; 91 | comboBox.addItem("High"); 92 | comboBox.addItem("Medium"); 93 | comboBox.addItem("Low"); 94 | comboBox.addItem("Information"); 95 | } 96 | 97 | // Method to delete instance 98 | public void deleteInstance(){ 99 | // delete instance 100 | extender.extenderPanelUI.deleteInstanceButton.setEnabled(false); 101 | extender.loggerList.get(extender.currentEntryRow).getInstanceList().remove(currentRow); 102 | // update UI 103 | // If there are remaining instances 104 | if (extender.loggerList.get(extender.currentEntryRow).getInstanceList().size() != 0){ 105 | // Inform user about instance deletion 106 | extender.extenderPanelUI.scanStatusLabel.setText("Instance deleted"); 107 | extender.callbacks.issueAlert("Instance deleted"); 108 | // Repaint instances table 109 | extender.instancesTableModel.clearInstanceEntryList(); 110 | extender.instancesTableModel.addAllInstanceEntry(extender.loggerList.get(extender.currentEntryRow).instancesList); 111 | } 112 | // Else, no more instances left in entry 113 | else{ 114 | // delete entries instead 115 | extender.loggerTable.deleteEntry(); 116 | } 117 | } 118 | 119 | } -------------------------------------------------------------------------------- /src/main/java/autowasp/logger/instancesTable/InstancesTableModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package autowasp.logger.instancesTable; 18 | 19 | import javax.swing.table.AbstractTableModel; 20 | import java.util.List; 21 | 22 | 23 | @SuppressWarnings("serial") 24 | public class InstancesTableModel extends AbstractTableModel{ 25 | private final List listInstanceEntry; 26 | private final String[] columnNames = { "ID", "Instance URL Path", "Confidence", "Severity" }; 27 | 28 | public InstancesTableModel(List listInstanceEntry) { 29 | this.listInstanceEntry = listInstanceEntry; 30 | } 31 | 32 | // Method to get column count 33 | @Override 34 | public int getColumnCount() { 35 | return columnNames.length; 36 | } 37 | 38 | // Method to get row count 39 | @Override 40 | public int getRowCount() { 41 | return listInstanceEntry.size(); 42 | } 43 | 44 | // Method to get column name 45 | public String getColumnName(int columnIndex) { 46 | return columnNames[columnIndex]; 47 | } 48 | 49 | // Method to get value at selected row and column 50 | @Override 51 | public String getValueAt(int rowIndex, int columnIndex) { 52 | String returnValue = ""; 53 | InstanceEntry instanceEntry = listInstanceEntry.get(rowIndex); 54 | switch (columnIndex) { 55 | case 0: 56 | returnValue = rowIndex + 1 + ""; 57 | break; 58 | case 1: 59 | returnValue = instanceEntry.url.toString(); 60 | break; 61 | case 2: 62 | returnValue = instanceEntry.confidence; 63 | break; 64 | case 3: 65 | returnValue = instanceEntry.severity; 66 | break; 67 | } 68 | 69 | return returnValue; 70 | } 71 | 72 | // Method to set value at selected row and column 73 | @Override 74 | public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 75 | InstanceEntry instanceEntry = listInstanceEntry.get(rowIndex); 76 | if (columnIndex == 2) { 77 | instanceEntry.setConfidence((String) aValue); 78 | } 79 | if (columnIndex == 3){ 80 | instanceEntry.setSeverity((String) aValue); 81 | } 82 | } 83 | 84 | // Method to re-add all instances from existing list to table view 85 | public void addAllInstanceEntry(List listInstanceEntry) { 86 | this.listInstanceEntry.addAll(listInstanceEntry); 87 | this.fireTableDataChanged(); 88 | } 89 | 90 | // Method to clear instance entry from table view 91 | public void clearInstanceEntryList() { 92 | this.listInstanceEntry.clear(); 93 | } 94 | 95 | // Method to restrict editable cell to those with dropdown combo. 96 | public boolean isCellEditable(int row, int col) { 97 | if (col == 2) 98 | return true; 99 | else return col == 3; 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/burp/.gitignore: -------------------------------------------------------------------------------- 1 | # Exclude Burp Interface Classes 2 | 3 | IBurpCollaboratorClientContext.java 4 | IBurpCollaboratorInteraction.java 5 | IBurpExtenderCallbacks.java 6 | IBurpExtender.java 7 | IContextMenuFactory.java 8 | IContextMenuInvocation.java 9 | ICookie.java 10 | IExtensionHelpers.java 11 | IExtensionStateListener.java 12 | IHttpListener.java 13 | IHttpRequestResponse.java 14 | IHttpRequestResponsePersisted.java 15 | IHttpRequestResponseWithMarkers.java 16 | IHttpService.java 17 | IInterceptedProxyMessage.java 18 | IIntruderAttack.java 19 | IIntruderPayloadGeneratorFactory.java 20 | IIntruderPayloadGenerator.java 21 | IIntruderPayloadProcessor.java 22 | IMenuItemHandler.java 23 | IMessageEditorController.java 24 | IMessageEditor.java 25 | IMessageEditorTabFactory.java 26 | IMessageEditorTab.java 27 | IParameter.java 28 | IProxyListener.java 29 | IRequestInfo.java 30 | IResponseInfo.java 31 | IResponseKeywords.java 32 | IResponseVariations.java 33 | IScanIssue.java 34 | IScannerCheck.java 35 | IScannerInsertionPoint.java 36 | IScannerInsertionPointProvider.java 37 | IScannerListener.java 38 | IScanQueueItem.java 39 | IScopeChangeListener.java 40 | ISessionHandlingAction.java 41 | ITab.java 42 | ITempFile.java 43 | ITextEditor.java -------------------------------------------------------------------------------- /src/main/java/burp/BurpExtender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Government Technology Agency 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package burp; 18 | 19 | import autowasp.Autowasp; 20 | 21 | public class BurpExtender extends Autowasp { 22 | public static void main(String [] args){ 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: burp.BurpExtender 3 | 4 | -------------------------------------------------------------------------------- /src/main/resources/OWASP_WSTG_local_07Jul2022: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GovTech-CSG/Autowasp/30c09b37a125520aa68d684f455dd950add69724/src/main/resources/OWASP_WSTG_local_07Jul2022 --------------------------------------------------------------------------------