├── .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 |
5 | - Testing checklist provided by OWASP WSTG
6 | - Logger tool giving penetration testers the ability to extract and consolidate Burp Scanner issues and Proxy/Repeater/Intruder logs.
7 | - Map flagged issues to checklist and generate into excel file
8 |
9 |
10 | A general testing workflow using Autowasp would include the following steps:
11 |
12 | - Display the OWASP checklist in Autowasp for reference.
13 | - Add the target URL to Scope. The scope function will extract related results from Burp Scanner and listen for insecure web request and responses.
14 | - Map the scan issues to specific test cases in the checklist. OR
15 | - Manually explore the website's pages, then click Enable Burp Scanner Logging to display the scanner issues under the Logger tab.
16 | - Map findings to the checklist.
17 | - Insert security observations and evidence associated with the logs.
18 | - Generate a report containing the checklist, logs, evidence, and comments.
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 | [](https://opensource.org/licenses/Apache-2.0)
3 |
4 | 
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 | 
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 | 
27 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
144 |
145 | # Contributing #
146 |
147 | [](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 extends LoggerEntry> c) {
107 | return false;
108 | }
109 |
110 | @Override
111 | public boolean addAll(int index, Collection extends LoggerEntry> 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 extends ChecklistEntry> c) {
292 | return false;
293 | }
294 |
295 | @Override
296 | public boolean addAll(int index, Collection extends ChecklistEntry> 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
--------------------------------------------------------------------------------