├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── pages.yml ├── .gitignore ├── BappDescription.html ├── BappManifest.bmf ├── Checklist.CSV ├── DOC ├── API-Mapper.md ├── Checklist.md ├── Config.md ├── README.md ├── Vulnerabilites.md ├── _images │ ├── APIMapper.png │ ├── Burp-Suite-Extender.png │ ├── Checklist.png │ ├── Config.png │ ├── Load.png │ ├── Proxy.png │ ├── Vulnerability.png │ └── Zip.png ├── _sidebar.md ├── index.html └── installation.md ├── LICENSE ├── PentestMapper.py ├── README.md ├── images ├── APIMapper.png ├── APIMapper2.png ├── CheckList.png ├── Config.png ├── Sendreq.png ├── Vulnerability-selection.png ├── proxy.png ├── severity.png └── tt ├── lib └── swingx-all-1.6.4.jar └── pentestmapper ├── APIMapper.py ├── __init__.py ├── autolog.py └── autosave.py /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: Anof-cyber 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/pages.yml: -------------------------------------------------------------------------------- 1 | # Simple workflow for deploying static content to GitHub Pages 2 | name: Deploy static content to Pages 3 | 4 | on: 5 | # Runs on pushes targeting the default branch 6 | push: 7 | branches: ["main"] 8 | 9 | # Allows you to run this workflow manually from the Actions tab 10 | workflow_dispatch: 11 | 12 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 13 | permissions: 14 | contents: read 15 | pages: write 16 | id-token: write 17 | 18 | # Allow one concurrent deployment 19 | concurrency: 20 | group: "pages" 21 | cancel-in-progress: true 22 | 23 | jobs: 24 | # Single deploy job since we're just deploying 25 | deploy: 26 | environment: 27 | name: github-pages 28 | url: ${{ steps.deployment.outputs.page_url }} 29 | runs-on: ubuntu-latest 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v3 33 | - name: Setup Pages 34 | uses: actions/configure-pages@v2 35 | - name: Upload artifact 36 | uses: actions/upload-pages-artifact@v1 37 | with: 38 | # Upload entire repository 39 | path: 'DOC/' 40 | - name: Deploy to GitHub Pages 41 | id: deployment 42 | uses: actions/deploy-pages@v1 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | pentestmapper/vuln.py 2 | pentestmapper/vuln$py.class 3 | pentestmapper/autosave$py.class 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | .jython_cache 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | wheels/ 26 | pip-wheel-metadata/ 27 | share/python-wheels/ 28 | *.egg-info/ 29 | .installed.cfg 30 | *.egg 31 | MANIFEST 32 | 33 | # PyInstaller 34 | # Usually these files are written by a python script from a template 35 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 36 | *.manifest 37 | *.spec 38 | 39 | # Installer logs 40 | pip-log.txt 41 | pip-delete-this-directory.txt 42 | 43 | # Unit test / coverage reports 44 | htmlcov/ 45 | .tox/ 46 | .nox/ 47 | .coverage 48 | .coverage.* 49 | .cache 50 | nosetests.xml 51 | coverage.xml 52 | *.cover 53 | *.py,cover 54 | .hypothesis/ 55 | .pytest_cache/ 56 | 57 | # Translations 58 | *.mo 59 | *.pot 60 | 61 | # Django stuff: 62 | *.log 63 | local_settings.py 64 | db.sqlite3 65 | db.sqlite3-journal 66 | 67 | # Flask stuff: 68 | instance/ 69 | .webassets-cache 70 | 71 | # Scrapy stuff: 72 | .scrapy 73 | 74 | # Sphinx documentation 75 | docs/_build/ 76 | 77 | # PyBuilder 78 | target/ 79 | 80 | # Jupyter Notebook 81 | .ipynb_checkpoints 82 | 83 | # IPython 84 | profile_default/ 85 | ipython_config.py 86 | 87 | # pyenv 88 | .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 98 | __pypackages__/ 99 | 100 | # Celery stuff 101 | celerybeat-schedule 102 | celerybeat.pid 103 | 104 | # SageMath parsed files 105 | *.sage.py 106 | 107 | # Environments 108 | .env 109 | .venv 110 | env/ 111 | venv/ 112 | ENV/ 113 | env.bak/ 114 | venv.bak/ 115 | 116 | # Spyder project settings 117 | .spyderproject 118 | .spyproject 119 | 120 | # Rope project settings 121 | .ropeproject 122 | 123 | # mkdocs documentation 124 | /site 125 | 126 | # mypy 127 | .mypy_cache/ 128 | .dmypy.json 129 | dmypy.json 130 | 131 | # Pyre type checker 132 | .pyre/ 133 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /BappDescription.html: -------------------------------------------------------------------------------- 1 |

Pentest Mapper is a Burp Suite extension that integrates the Burp Suite request logging with a custom application testing checklist. The extension provides a straightforward flow for application penetration testing. The extension includes functionalities to allow users to map the flow of the application for pentesting to better analyse the application and its vulnerabilities. The API calls from each flow can be connected with the function or flow name. The extension allows users to map or connect each flow or API to vulnerability with the custom checklist.

2 | 3 |

Features Summary

4 |
    5 |
  1. Checklist
    6 | Allows you to load the custom checklist 7 |
  2. 8 |
  3. API Mapper
    9 | Allows you to keep track of each API call, Flow and Test Cases for each API calls. 10 |
  4. 11 |
  5. Vulnerability
    12 | Allows to keep track of vulnerabilities, Map each paramter and API call to vulnerability from the Checklist and severity 13 |
  6. 14 |
  7. Config
    15 | 21 |
  8. 22 |
23 | 24 |

Download the demo checklist file CSV file from here

25 | -------------------------------------------------------------------------------- /BappManifest.bmf: -------------------------------------------------------------------------------- 1 | Uuid: af490ae7e79546fa81a28d8d0b90874e 2 | ExtensionType: 2 3 | Name: Pentest Mapper 4 | RepoName: pentest-mapper 5 | ScreenVersion: 1.5 6 | SerialVersion: 4 7 | MinPlatformVersion: 0 8 | ProOnly: False 9 | Author: Anof-cyber 10 | ShortDescription: Integrates logging with a custom application testing checklist. 11 | EntryPoint: PentestMapper.py 12 | BuildCommand: 13 | SupportedProducts: Pro, Community 14 | -------------------------------------------------------------------------------- /Checklist.CSV: -------------------------------------------------------------------------------- 1 | 1,Parameter Tampering 2 | 2,SQL Injection 3 | 3,Reflected Cross Site Scripting 4 | 4,IDOR 5 | 5,Privledge Esclation 6 | 6,Code Tapering 7 | 7,DOM Cross Site Scripting 8 | 8,Stored Cross Site Scripting 9 | 9,Rate Liming 10 | 10,CORS 11 | 11,Verbose Error 12 | 12,Options Method Enabled 13 | 13,Forced Browsing 14 | 14,Missing HSTS Header 15 | 15,Missing X-Frame Header 16 | 16,OTP Bypass with Response Modification 17 | 17,Directory Listing Enabled 18 | 18,Hard-Coded Sensitive Information 19 | 19,SSL not Enabled 20 | 20,SSL not Enforced 21 | 21,Weak Password Policy 22 | 22,Cookie without Secure Flag 23 | 23,Cookie without HTTP Only Flag 24 | 24,Sensitive Information in URL 25 | 25,User Enumeration 26 | 26,Long Password DOS 27 | 27,Insufficient Account Verification 28 | 28,Open Redirect 29 | 29,2FA Bypass 30 | 30,CSRF 31 | 31,Insufficient Session Expiry after Logout 32 | 32,Insufficient Session Expiry after Change or Forget password 33 | 33,Command Injection 34 | 34,Local Storage not Cleaned 35 | 35,Host Header Injection 36 | 36,OTP Valid for more than one time 37 | 37,Password Reset Link is not expired 38 | 38,Password Reset Link Poision 39 | 39,Password Reset Token is predictable 40 | 40,File Path Traversal 41 | 41,LFI 42 | 42,RFI 43 | 43,SSRF 44 | 44,XPath Injection 45 | 45,No SQL Injection 46 | 46,HTTP Request Smuggling 47 | 47,XMLPRC Enabled 48 | 48,DEBUG Method Enabled 49 | 49,View State Not Encrypted 50 | 50,Captcha Bypass 51 | 51,Price Manipulation 52 | 52,Internal IP Disclosed 53 | 53,Login Bypass 54 | -------------------------------------------------------------------------------- /DOC/API-Mapper.md: -------------------------------------------------------------------------------- 1 | # API Mapper 2 | 3 | The API Mapper allow users to Map the API with HTTP request and response. They can even write test cases or comments for each request. 4 | The idea is to allow the pentester to test each API and URL at a time with test cases which he can write for each API. Also, the pentester can keep track of API like which API is completed, Pending. 5 | 6 | ![picture](_images/APIMapper.png) 7 | 8 | ## Overview 9 | 10 | ### Search 11 | 12 | At the top of the API Mapper tab, we have a search button same as a checklist which allows us to filter the data from the table. 13 | 14 | ### Save Project 15 | 16 | Since the BurpSuite doesn't allow extension to save the extension data within the burp suite project file. We have the option to save the API Mapper output in a CSV file. 17 | You can click on the Save project button and select the directory and it will create a CSV file for you. 18 | 19 | ### Load Project 20 | 21 | Once you save your API Mapper Data you also have the option to load that data again in the extension with the Load Project button. 22 | You can click on the button, select the CSV file and it will load the data in the API Mapper 23 | 24 | ### API Mapper Table 25 | 26 | Now we have a table with multiple columns. 27 | - The 1st column `SR ` will show the row number for the table. 28 | - The 2nd column `URL` will show the full URL of the request. 29 | - The 3rd column `Method` will show the HTTP method used for that request. 30 | - The 4th column `Post Body` will show the Post request Body for that request. 31 | - The 5th column `Functionality Name` is like a text box where the user can specify the name of the Functionality the request belong. Like if this request is for login or profile etc. If you double click it will allow you to edit. 32 | - The 6th column `Status` will allow users to select the Pentest Status for the specific URL or API. Where he can select if the select API is completed for testing or pending etc. 33 | 34 | 35 | 36 | ### Adding Data to API Mapper Table 37 | 38 | Since our table is empty we can add the request from BurpSuite Target, Proxy History, Repeater, Intruder etc. You can right-click on any selected request, and select extension --> Pentest Mapper --> API Mapper. Now you can view the request inside the table. 39 | 40 | ![picture](_images/Proxy.png) 41 | 42 | ### Test Cases 43 | 44 | Once you click on any row in the table, You can view the request and response below the table. We also have a Test case tab where we can write the test cases for the selected API. Once we are done we can click on the save test cases button to save. 45 | 46 | ### Menu 47 | 48 | You can select any row in the table and right-click. A menu will pop up. 49 | - Add to Vulnerabilities - You can send the selected requests to the Vulnerabilities tab to map the particular request to vulnerability. 50 | - Send to Repeater - You can send the selected request to the repeater tab. 51 | - Delete - Lastly we have the option to delete the selected row. 52 | 53 | You can also select multiple rows to perform the actions. 54 | -------------------------------------------------------------------------------- /DOC/Checklist.md: -------------------------------------------------------------------------------- 1 | # CheckList 2 | 3 | The extension comes with 4 different tabs inside it. The checklist tab allows users to load a custom vulnerability checklist. The checklist file will later be used while mapping the API to the vulnerabilities. 4 | You can download the demo checklist from [here](https://github.com/Anof-cyber/Pentest-Mapper/blob/main/Checklist.CSV). 5 | 6 | ![picture](_images/Checklist.png) 7 | 8 | ## Overview 9 | 10 | 11 | ### Search 12 | The first thing in the checklist is the search text box and button which allows you to filter and search the vulnerabilities from the table. 13 | 14 | ### Import Checklist 15 | 16 | You also have an import button which allows you to load your checklist CSV file into the table. This button will be removed in future updates so you can ignore this button. 17 | To load the checklist you can go to the config tab. 18 | 19 | ### Create Checklist 20 | 21 | You have a create button once you click on that button it will show you a text box which allows you to create a new test case or add a new vulnerability in your table. 22 | This creates button is useful if you need to add a new vulnerability to your checklist table. 23 | 24 | **Note:** If you add a new vulnerability using create button, it will only add to your table but your CSV file which you have imported will not be updated. 25 | This is only valid if you load the checklist from the import checklist button. If you load the checklist from the config tab it will update the CSV file if you create a new vulnerability with create button. 26 | 27 | ``` 28 | 29 | - It's recommended that you load the checklist from the config tab. 30 | 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /DOC/Config.md: -------------------------------------------------------------------------------- 1 | # Config 2 | 3 | Lastly we have an Configuration tab where we can set multiple options for our extension. 4 | 5 | ![picture](_images/Config.png) 6 | 7 | ## OverVIew 8 | 9 | ### Auto Save Config 10 | 11 | The extension allows users to store API Mapper and Vulnerabilities output individually. The problem arises here when for some reason burp or system is closed without saving the output. 12 | We have the AutoSave method. The Autosave need to be configured, you have to select the output directory and time. Once done you can click on the Save Config button. 13 | 14 | Every time you load the extension or open the burp suite the saved setting will not be removed since ita stored in your burp configuration. 15 | 16 | The Autosave will run after every 10 minutes ( default time ), and will create two files in the output directory as ```vulnerability.csv``` and ```APIMapper.csv```. 17 | Each time the extension tries to save it will overwrite the files so make sure you import the data first before the auto-save start or change the directory. 18 | 19 | ### Auto Load Checklist 20 | 21 | You can select your checklist file from here. If you load the checklist from here. The file path will be stored and each time extension is loaded the checklist will autoload. 22 | Also once you add a new vulnerability in the checklist tab with create button. the data will also be updated in the CSV file. 23 | 24 | ### One Click Import Export 25 | 26 | You can import or export the API Mapper and vulnerability data with a single button. The extension will try to check if the autosave directory is selected and saved and then it will look for the ```vulnerability.csv``` and ```APIMapper.csv```files in that directory to import. 27 | To export only the autosave directory should be saved. 28 | 29 | ### Auto Logging 30 | 31 | The extension will add each request from the proxy to API Mapper if the Auto Logging is set to ON. it will only add the data in API Mapper if the URL is in scope from the Burp Suite Target tab. 32 | You can also select the excluded files. The default setting is set to OFF. 33 | 34 | ### Auto Save 35 | 36 | By default, the Auto Save is off. You can turn on Auto Save. 37 | -------------------------------------------------------------------------------- /DOC/README.md: -------------------------------------------------------------------------------- 1 | # Pentest Mapper 2 | 3 | Pentest Mapper is a Burp Suite extension that integrates the Burp Suite request logging with a custom application testing checklist. 4 | The extension provides a straightforward flow for application penetration testing. The extension includes functionalities to allow users to map the flow of the application for pentesting to better analyse the application and its vulnerabilities. 5 | The API calls from each flow can be connected with the function or flow name. The extension allows users to map or connect each flow or API to vulnerability with the custom checklist. 6 | 7 | 8 | 9 | # Documentation 10 | - [Installation](installation.md) 11 | - [Checklist](Checklist.md) 12 | - [API Mapper](API-Mapper.md) 13 | - [Vulnerabilites](Vulnerabilites.md) 14 | - [Config](Config.md) 15 | 16 | 17 | # Features 18 | 19 | - Allow you to load a custom checklist 20 | - Map Each API and HTTP request to keep track of progress 21 | - Connect the Mapped API with flow and functionalities 22 | - Write Pentesting test cases for each HTTP request and APIs 23 | - Map Each Vulnerable API to vulnerabilitst based on severity and parameter 24 | - Set Auto save and checklist and Auto Map 25 | -------------------------------------------------------------------------------- /DOC/Vulnerabilites.md: -------------------------------------------------------------------------------- 1 | # Vulnerabilites 2 | 3 | The Vulnerabilities tab allows you to keep track of each vulnerability found during the testing of the application. You can add the URL, Parameter, severity and name of the vulnerability. 4 | 5 | ![picture](_images/Vulnerability.png) 6 | 7 | ## Overview 8 | 9 | ### Search 10 | 11 | At the top of the Vulnerabilities tab, we have a search button same as a checklist which allows us to filter the data from the table. 12 | 13 | 14 | ### Export Vulnerabilities 15 | 16 | Since the BurpSuite doesn't allow extension to save the extension data within the burp suite project file. We have the option to save the vulnerability output in a CSV file. 17 | You can click on the Export Vulnerabilities button and select the directory and it will create a CSV file for you. 18 | 19 | ### Import Vulnerabilities 20 | 21 | Once you save your Vulnerabilitesr Data you also have the option to load that data again in the extension with the Import Vulnerabilities button. 22 | You can click on the button, select the CSV file and it will load the data in the Vulnerabilities. 23 | 24 | ### Vulnerabilities Table 25 | 26 | Now we have a table with multiple columns. 27 | 28 | - The 1st column `URL ` will show the full URL of the request. 29 | - The 2nd column `Parameter` will allow you to enter the vulnerable parameter name. You can double-click and edit the cell 30 | - The 3rd column `Vulnerability` will show a drop-down list from the checklist tab. You can select the vulnerability to which the particular API is vulnerable. 31 | - The 4th column `severity` will again show a drop-down list where you can select if the vulnerability is Critical, High, Medium, Low or Informational. 32 | 33 | 34 | ### Adding Data to Vulnerabilities Table 35 | 36 | Same as API Mapper you can add the data in the Vulnerabilities table from BurpSuite Target, Proxy History, Repeater, Intruder etc. You can right-click on any selected request, 37 | and select extension --> Pentest Mapper --> API Mapper. Now you can view the request inside the table. 38 | 39 | You can also right-click on any row in API MApper and select send to vulnerability to add the data here. 40 | -------------------------------------------------------------------------------- /DOC/_images/APIMapper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/DOC/_images/APIMapper.png -------------------------------------------------------------------------------- /DOC/_images/Burp-Suite-Extender.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/DOC/_images/Burp-Suite-Extender.png -------------------------------------------------------------------------------- /DOC/_images/Checklist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/DOC/_images/Checklist.png -------------------------------------------------------------------------------- /DOC/_images/Config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/DOC/_images/Config.png -------------------------------------------------------------------------------- /DOC/_images/Load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/DOC/_images/Load.png -------------------------------------------------------------------------------- /DOC/_images/Proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/DOC/_images/Proxy.png -------------------------------------------------------------------------------- /DOC/_images/Vulnerability.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/DOC/_images/Vulnerability.png -------------------------------------------------------------------------------- /DOC/_images/Zip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/DOC/_images/Zip.png -------------------------------------------------------------------------------- /DOC/_sidebar.md: -------------------------------------------------------------------------------- 1 | - [Installation](installation.md) 2 | - [Checklist](Checklist.md) 3 | - [API Mapper](API-Mapper.md) 4 | - [Vulnerabilites](Vulnerabilites.md) 5 | - [Config](Config.md) 6 | -------------------------------------------------------------------------------- /DOC/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Pentest Mapper 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /DOC/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | You need to add the Jython in your burp Suite before your start installing the extension. You can use the BurpSuite guide to complete the process from [Here](https://burpsuite.guide/runtimes/python/). 4 | 5 | ## Burp Suite Extender 6 | 7 | You can download the Pentest Mapper within the BurpSuite extender. 8 | 9 | ![picture](_images/Burp-Suite-Extender.png) 10 | - GO to the Extender tab in the Burp Suite 11 | - Click on BApp Store 12 | - Search `Pentest Mapper` and Click on the install button 13 | 14 | ## Manual 15 | The manual installation process is simple. You need to download the repository and load the `PentestMapper.py` file in the burp Suite. 16 | 17 | 18 | 19 | - You can download the repository as a git clone or you can download the zip file as well. 20 | 21 | ``` 22 | git clone https://github.com/Anof-cyber/Pentest-Mapper 23 | ``` 24 | 25 | ![picture](_images/Zip.png) 26 | 27 | ![picture](_images/Load.png) 28 | 29 | - Open your BurpSuite Click on the Extender Tab. 30 | - Click on Add button and select python from the dropdown list 31 | - Click on the select file button and select the `pentestmapper.py` file 32 | 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /PentestMapper.py: -------------------------------------------------------------------------------- 1 | from burp import (IBurpExtender, ITab, IContextMenuFactory, IContextMenuInvocation, 2 | IHttpService, IParameter, IMessageEditorController, IHttpRequestResponse, IProxyListener, 3 | IMessageEditorTabFactory, IMessageEditorTab, IExtensionStateListener ) 4 | 5 | from java.awt import (BorderLayout, FlowLayout , Dimension, Font, Color, Cursor) 6 | 7 | from javax.swing import (JMenuItem, JTable, JButton, JTextField, GroupLayout, JTabbedPane, JTextPane, RowFilter 8 | ,JScrollPane, JSplitPane, JLabel, JPopupMenu, JComboBox, DefaultCellEditor, JToggleButton, JTextArea, DefaultComboBoxModel 9 | ,JPanel, JFileChooser, JSeparator, Box ) 10 | 11 | from javax.swing.event import ListSelectionListener 12 | 13 | from javax.swing.table import ( DefaultTableModel, AbstractTableModel, TableRowSorter ,TableCellEditor) 14 | from javax.swing.SwingConstants import VERTICAL 15 | from java.lang import Short 16 | import javax.swing.Box 17 | from javax.swing.filechooser import FileNameExtensionFilter 18 | from urlparse import urlparse 19 | import time, csv, sys, os, base64, zlib 20 | from threading import Lock 21 | 22 | 23 | from pentestmapper.autolog import Autologclas 24 | from pentestmapper.APIMapper import LogEntry, Table, CustomTableModel 25 | from pentestmapper.autosave import Autosaveclas 26 | 27 | sys.path.append("./lib/swingx-all-1.6.4.jar") 28 | from org.jdesktop.swingx.autocomplete import AutoCompleteDecorator 29 | 30 | 31 | 32 | csv.field_size_limit(sys.maxsize) 33 | 34 | 35 | 36 | 37 | # Creating Burp Extend Class 38 | class BurpExtender(IBurpExtender, ITab, IContextMenuFactory, AbstractTableModel, IMessageEditorController, IExtensionStateListener): 39 | 40 | 41 | def registerExtenderCallbacks(self, callbacks): 42 | self.callbacks = callbacks 43 | self.helpers = callbacks.getHelpers() 44 | 45 | # Allowing debugging 46 | sys.stdout = callbacks.getStdout() 47 | sys.stderr = callbacks.getStderr() 48 | 49 | # Informing Burp suite the name of the extension 50 | callbacks.setExtensionName("Pentest Mapper") 51 | 52 | #adding extension state listner if extenion loaded on unloaded 53 | callbacks.registerExtensionStateListener(self) 54 | 55 | 56 | # Creating a output after loading 57 | callbacks.printOutput("Author: Sourav Kalal Aka AnoF") 58 | callbacks.printOutput("Version: 1.7.3") 59 | callbacks.printOutput("https://github.com/Anof-cyber/Pentest-Mapper") 60 | 61 | callbacks.registerContextMenuFactory(self) 62 | 63 | self.tab = JPanel(BorderLayout()) 64 | self.tabbedPane = JTabbedPane() 65 | self.tab.add("Center", self.tabbedPane) 66 | 67 | self._log = list() 68 | self._vuln = list() 69 | self._lock = Lock() 70 | 71 | # Creating Another Tab in the extension tab 72 | # Creating the First tab named as CheckList 73 | self.firstTab = JPanel() 74 | self.firstTab.layout = BorderLayout() 75 | self.tabbedPane.addTab("CheckList", self.firstTab) 76 | callbacks.addSuiteTab(self) 77 | 78 | # Creating a Import button in CheckList Tab 79 | self.ChecklistbuttonPanel = JPanel() 80 | self.searchchecklist = JTextField('', 15) 81 | self.ChecklistbuttonPanel.add(self.searchchecklist) 82 | self.ChecklistbuttonPanel.add(JButton("Search", actionPerformed=self.searchinchecklist)) 83 | 84 | 85 | # adding the import button with onclick action which refers to the function below 86 | self.ChecklistbuttonPanel.add(JButton( 87 | "Import CheckList", actionPerformed=self.importchecklist)) 88 | self.createchecklistbutton = JButton("Create CheckList", actionPerformed=self.createtestcases) 89 | #self.ChecklistbuttonPanel.add(JButton("Create CheckList", actionPerformed=self.createtestcases)) 90 | self.ChecklistbuttonPanel.add(self.createchecklistbutton) 91 | self.firstTab.add(self.ChecklistbuttonPanel, BorderLayout.PAGE_START) 92 | 93 | 94 | # Creating a tab in CheckList tab which will show the data from the import checlist 95 | self.tablePanel = JPanel() 96 | self.colNames = ('Sr', 'Test-Cases') 97 | self.dataModel = CustomDefaultTableModelHosts(None, self.colNames) 98 | self.table = JTable(self.dataModel) 99 | self.table.getTableHeader().setReorderingAllowed(False) 100 | self.table.setAutoCreateRowSorter(True) 101 | self.scrollPane = JScrollPane(self.table) 102 | self.sorter = TableRowSorter(self.dataModel); 103 | 104 | self.table.setRowSorter(self.sorter) 105 | X_BASE2 = 200 # send to leff 106 | # 3rd one send to right 107 | 108 | self.scrollPane.getViewport().setView((self.table)) 109 | self.firstTab.add(self.scrollPane, BorderLayout.CENTER) 110 | 111 | # Creating Second Tab 112 | self.secondTab = JPanel() 113 | self.secondTab.layout = BorderLayout() 114 | self.tabbedPane.addTab("API Mapper", self.secondTab) 115 | 116 | 117 | # creating UI for button and button in api mapper tab 118 | self.APIMapperButtonPanel = JPanel() 119 | self.searchapimapper = JTextField('', 15) 120 | self.APIMapperButtonPanel.add(self.searchapimapper) 121 | self.APIMapperButtonPanel.add(JButton("Search", actionPerformed=self.searchinapimapper)) 122 | 123 | # adding the import button with onclick action which refers to the function below 124 | self.APIMapperButtonPanel.add(JButton( 125 | "Save Project", actionPerformed=self.savelogger)) 126 | self.APIMapperButtonPanel.add(JButton( 127 | "Load Project", actionPerformed=self.importlogger)) 128 | self.secondTab.add(self.APIMapperButtonPanel, BorderLayout.PAGE_START) 129 | 130 | 131 | # Creating a UI for table in api mapper tab 132 | self.tablePanel2 = JPanel() 133 | 134 | 135 | ''' 136 | creating a menu which will be added with the table in api mapper for right click 137 | also assigning a fumction to handle the event when click 138 | ''' 139 | popupMenu = JPopupMenu() 140 | sendVulneraility = JMenuItem("Add to Vulnerabilities", actionPerformed=self.sendVulnItem) 141 | sendRepeaterItem = JMenuItem("Send request to Repeater", actionPerformed=self.sendRepeaterItem) 142 | deleterow = JMenuItem("Delete Row", actionPerformed=self.deleterow) 143 | popupMenu.add(sendVulneraility) 144 | popupMenu.add(sendRepeaterItem) 145 | popupMenu.add(deleterow) 146 | 147 | self.comboBox1 = JComboBox() 148 | self.comboBox1.addItem(None) 149 | self.comboBox1.addItem("Pending") 150 | self.comboBox1.addItem("In Progress") 151 | self.comboBox1.addItem("Completed") 152 | 153 | 154 | # creating a message editor from burp to show request 155 | self.requestViewer = callbacks.createMessageEditor(None, True) 156 | self.responseViewer = callbacks.createMessageEditor(None, True) 157 | 158 | # creating a table with custom model for api mapper 159 | 160 | 161 | self.apimappertable = CustomTableModel(self) 162 | 163 | self.logTable = Table(self, self.apimappertable) 164 | 165 | 166 | # allowed colum size for api mapper tab/table 167 | self.logTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF) 168 | self.logTable.getTableHeader().setReorderingAllowed(False) 169 | self.logTable.getColumnModel().getColumn(0).setPreferredWidth(25) 170 | self.logTable.getColumnModel().getColumn(1).setPreferredWidth(400) 171 | self.logTable.getColumnModel().getColumn(2).setPreferredWidth(50) 172 | self.logTable.getColumnModel().getColumn(3).setPreferredWidth(750) 173 | self.logTable.getColumnModel().getColumn(4).setPreferredWidth(142) 174 | self.logTable.setRowSelectionAllowed(True) 175 | 176 | comboColumn1 = self.logTable.getColumnModel().getColumn(5) 177 | comboColumn1.setCellEditor(DefaultCellEditor(self.comboBox1)) 178 | 179 | #adding a right click menu in the table in api mapper 180 | self.logTable.setComponentPopupMenu(popupMenu) 181 | 182 | 183 | 184 | # Creating a scroller for table in api mapper and also width hight for table 185 | self.scrollPane2 = JScrollPane(self.logTable) 186 | 187 | self.scrollPane2.getViewport().setView((self.logTable)) 188 | self.sorter2 = TableRowSorter(self.apimappertable); 189 | self.logTable.setRowSorter(self.sorter2) 190 | 191 | 192 | # creating a save test case button and UI and a split pane 193 | self.CommentsSplitPane = JSplitPane(JSplitPane.VERTICAL_SPLIT); 194 | self.bottomviewpanel = JPanel() 195 | self.SaveTestCasePanel = JPanel(FlowLayout(FlowLayout.LEADING, 10, 10)) 196 | self.SaveTestCasePanel.add(JButton( 197 | "Save TestCases", actionPerformed=self.SaveTestCases)) 198 | 199 | 200 | #crearting a text box for test cases 201 | self.testcases = JTextPane() 202 | self.testcases.setContentType("text/plain"); 203 | self.testcases.setEditable(True) 204 | penTesterCommentBoxScrollPane = JScrollPane(self.testcases) 205 | 206 | # creating a split in test cases to add button and text box 207 | self.CommentsSplitPane.setTopComponent(self.SaveTestCasePanel) 208 | self.CommentsSplitPane.setBottomComponent(penTesterCommentBoxScrollPane); 209 | 210 | 211 | 212 | 213 | 214 | 215 | #adding the tapped pane to create request and test cases 216 | self.editor_view = JTabbedPane() 217 | self.editor_view.addTab("Request", self.requestViewer.getComponent()) 218 | self.editor_view.addTab("Response", self.responseViewer.getComponent()) 219 | self.editor_view.addTab('Test Cases', self.CommentsSplitPane) 220 | 221 | 222 | 223 | # creating a split in api mapper with split size 224 | spl = JSplitPane(JSplitPane.VERTICAL_SPLIT) 225 | 226 | 227 | # adding the UI for split pane in api mapper tab 228 | 229 | 230 | spl.setLeftComponent(self.scrollPane2) 231 | spl.setRightComponent(self.editor_view) 232 | 233 | # adding the spilt part to api mapper tab 234 | self.secondTab.add(spl) 235 | 236 | # addinG the burp Defalut UI customization for the api mapper tab 237 | self.callbacks.customizeUiComponent(spl) 238 | self.callbacks.customizeUiComponent(self.logTable) 239 | self.callbacks.customizeUiComponent(self.scrollPane2) 240 | self.callbacks.customizeUiComponent(self.editor_view) 241 | 242 | 243 | # creating a new tab 244 | self.ThirdTab = JPanel() 245 | self.ThirdTab.layout = BorderLayout() 246 | self.tabbedPane.addTab("Vulnerabilities", self.ThirdTab) 247 | 248 | 249 | # creating the button and button location and width in vulnerability tab 250 | self.VulnerabilityButtonPanel = JPanel() 251 | 252 | # Search For Vulnerability UI 253 | self.searchvulnerability = JTextField('', 15) 254 | self.VulnerabilityButtonPanel.add(self.searchvulnerability) 255 | self.VulnerabilityButtonPanel.add(JButton("Search", actionPerformed=self.searchinvulnerability)) 256 | 257 | # adding the import button with onclick action which refers to the function below 258 | 259 | self.VulnerabilityButtonPanel.add(JButton( 260 | "Export Vulnerabilities", actionPerformed=self.exportvulnerability)) 261 | self.VulnerabilityButtonPanel.add(JButton( 262 | "Import Vulnerabilities", actionPerformed=self.importvulnerability)) 263 | 264 | # adding the button in vulnerability tab 265 | self.ThirdTab.add(self.VulnerabilityButtonPanel, BorderLayout.PAGE_START) 266 | 267 | 268 | 269 | # creating the UI pannel for vulnerability tab --> table 270 | self.tablePanel3 = JPanel() 271 | 272 | # Creating a jcombobox that will show the selection option, and adding and none or empty item for selection 273 | self.comboBox = JComboBox() 274 | self.comboBox.addItem(None) 275 | self.comboBox.setEditable(True) 276 | self.combolist = [] 277 | #self.comboBox.addActionListener(self.seachincombobox) 278 | 279 | AutoCompleteDecorator.decorate(self.comboBox) 280 | 281 | 282 | # Creating a seelction list for Severity on vulnerability table 283 | self.comboBox2 = JComboBox() 284 | self.comboBox2.addItem(None) 285 | self.comboBox2.addItem('Critical') 286 | self.comboBox2.addItem('High') 287 | self.comboBox2.addItem('Medium') 288 | self.comboBox2.addItem('Low') 289 | self.comboBox2.addItem('Informational') 290 | 291 | 292 | 293 | 294 | # creating the table to vulnerability tab 295 | #self.colNames3 = ['URL', 'Parameters','Vulnerability','Severity','Request','Response'] 296 | #self.dataModel2 = CustomDefaultTableModelHosts2(None,self.colNames3) 297 | self.dataModel2 = CustomTableModelVuln(self) 298 | 299 | 300 | 301 | self.table3 = JTable(self.dataModel2) 302 | self.table3.setAutoCreateRowSorter(True) 303 | self.table3.getColumnModel().getColumn(2).setPreferredWidth(0) 304 | self.table3.getColumnModel().getColumn(1).setPreferredWidth(0) 305 | self.table3.getTableHeader().setReorderingAllowed(False) 306 | 307 | 308 | 309 | #comboColumn = self.table3.getColumnModel().getColumn(2) 310 | #comboColumn.setCellEditor(DefaultCellEditor(self.comboBox)) 311 | 312 | 313 | self.editor = AutocompleteTableCellEditor(self.combolist,self.table3) 314 | comboColumn = self.table3.getColumnModel().getColumn(2) 315 | comboColumn.setCellEditor(self.editor) 316 | 317 | 318 | 319 | 320 | 321 | comboColumn2 = self.table3.getColumnModel().getColumn(3) 322 | comboColumn2.setCellEditor(DefaultCellEditor(self.comboBox2)) 323 | 324 | #self.table3.removeColumn(self.table3.getColumnModel().getColumn(5)); 325 | #self.table3.removeColumn(self.table3.getColumnModel().getColumn(4)); 326 | self.table3.getColumnModel().getColumn(4).setMinWidth(0); 327 | self.table3.getColumnModel().getColumn(4).setMaxWidth(0); 328 | self.table3.getColumnModel().getColumn(4).setWidth(0); 329 | self.table3.getColumnModel().getColumn(5).setMinWidth(0); 330 | self.table3.getColumnModel().getColumn(5).setMaxWidth(0); 331 | self.table3.getColumnModel().getColumn(5).setWidth(0); 332 | 333 | 334 | 335 | 336 | # Adding a right click menu for Vulnerability 337 | popupMenu2 = JPopupMenu() 338 | deletevulnerability = JMenuItem("Delete Vulnerability", actionPerformed=self.deletevuln) 339 | popupMenu2.add(deletevulnerability) 340 | self.table3.setComponentPopupMenu(popupMenu2) 341 | 342 | 343 | 344 | # adding the table size, width, location and will add the scroller to the table 345 | self.scrollPane3 = JScrollPane(self.table3) 346 | X_BASE3 = 1 # send to leff 347 | # 3rd one send to right 348 | self.scrollPane3.setBounds(X_BASE3 + 10, 20, 1900, 850) 349 | self.scrollPane3.setPreferredSize(Dimension(1500, 700)) 350 | self.scrollPane3.getViewport().setView((self.table3)) 351 | self.tablePanel3.add(self.scrollPane3) 352 | 353 | 354 | self.requestViewer1 = callbacks.createMessageEditor(None, True) 355 | self.responseViewer1 = callbacks.createMessageEditor(None, True) 356 | 357 | self.editor_view1 = JTabbedPane() 358 | self.editor_view1.addTab("Request", self.requestViewer1.getComponent()) 359 | self.editor_view1.addTab("Response", self.responseViewer1.getComponent()) 360 | spl1 = JSplitPane(JSplitPane.VERTICAL_SPLIT) 361 | 362 | spl1.setLeftComponent(self.scrollPane3) 363 | spl1.setRightComponent(self.editor_view1) 364 | 365 | #listener = CustomSelectionListener(self.dataModel2, self.requestViewer1, self.responseViewer1) 366 | #self.table3.getSelectionModel().addListSelectionListener(listener) 367 | 368 | listener = CustomSelectionListener(self.table3, self.requestViewer1, self.responseViewer1) 369 | self.table3.getSelectionModel().addListSelectionListener(listener) 370 | 371 | 372 | 373 | 374 | 375 | # adding the table UI to vulnerability tab 376 | self.ThirdTab.add(spl1, BorderLayout.CENTER) 377 | #self.ThirdTab.add(self.scrollPane3, BorderLayout.CENTER) 378 | 379 | 380 | # Config Tab 381 | self.FourthTab = JPanel() 382 | self.FourthTab.layout = BorderLayout() 383 | self.tabbedPane.addTab("Config", self.FourthTab) 384 | self.buttonPanel5 = JPanel() 385 | 386 | layout = GroupLayout(self.buttonPanel5) 387 | self.buttonPanel5.setLayout(layout) 388 | 389 | 390 | 391 | 392 | jButton1 = JButton("Choose Directory", actionPerformed=self.Autosavepath) 393 | jLabel1 = JLabel() 394 | self.autosavepath = JLabel(); 395 | self.autosavepath.setForeground(Color(255, 102, 51)) 396 | self.timeperid = JLabel(); 397 | self.timerbox = JTextField(5); 398 | jLabel4 = JLabel(); 399 | button2 = JButton("Choose File", actionPerformed=self.Autosavepath2) 400 | self.Checklistfilepath = JLabel() 401 | self.Checklistfilepath.setForeground(Color(255, 102, 51)) 402 | Savechecklistfileconfig = JButton("Save Path", actionPerformed=self.saveautoconfigdata2) 403 | Savechecklistfileconfig.setBackground(Color(255, 102, 51)) 404 | Savechecklistfileconfig.setFont(Font("Segoe UI", 1, 12)) 405 | Savechecklistfileconfig.setForeground(Color(255, 255, 255)) 406 | 407 | self.saveconfigbutton = JButton("Save Config", actionPerformed=self.saveautoconfigdata) 408 | self.saveconfigbutton.setBackground(Color(255, 102, 51)); 409 | self.saveconfigbutton.setFont(Font("Segoe UI", 1, 12)) 410 | self.saveconfigbutton.setForeground(Color(255, 255, 255)) 411 | jLabel1.setText("Select the Auto Save Output Directory :") 412 | 413 | self.timeperid.setText("Set Time for Auto Save :") 414 | 415 | self.timerbox.setText("self.timerbox"); 416 | 417 | self.timeerror = JLabel(); 418 | self.timeerror.setForeground(Color(204, 0, 0)) 419 | importall = JButton("Import All", actionPerformed=self.autoimportall) 420 | jSeparator1 = JSeparator() 421 | jSeparator2 = JSeparator() 422 | jSeparator1.setPreferredSize(Dimension(50, 100)) 423 | 424 | 425 | jSeparator2.setPreferredSize(Dimension(50, 100)) 426 | 427 | AutoSaveConfigHeading = JLabel() 428 | AutoSaveConfigHeading.setFont(Font("Segoe UI", 1, 14)) 429 | AutoSaveConfigHeading.setToolTipText("") 430 | AutoloadChecklistHeading = JLabel(); 431 | AutoloadChecklistHeading.setFont(Font("Segoe UI", 1, 14)) 432 | AutoloadChecklistHeading.setToolTipText("") 433 | Exportall = JButton("Export All", actionPerformed=self.autoexportall); 434 | AutoSaveConfigHeading.setFont(Font("Segoe UI", 1, 14)); 435 | AutoSaveConfigHeading.setText("Auto Save Config"); 436 | AutoSaveConfigHeading.setToolTipText(""); 437 | 438 | AutoloadChecklistHeading.setFont(Font("Segoe UI", 1, 14)) 439 | AutoloadChecklistHeading.setText("Auto Load Checklist"); 440 | AutoloadChecklistHeading.setToolTipText("") 441 | 442 | 443 | jLabel4.setText("Select Auto Load Checklist File :") 444 | OneclickImportExportLabel = JLabel() 445 | OneclickImportExportLabel.setText("Import and Export API Mapper and Vulnerabilities from Above Selected Directory") 446 | Singleclickfilename = JLabel() 447 | Singleclickfilename.setForeground(Color(204, 0, 0)) 448 | Singleclickfilename.setText("Note: File Name should be APIMapper.csv & Vulnerability.csv") 449 | jSeparator3 = JSeparator() 450 | jSeparator3.setPreferredSize(Dimension(50, 100)) 451 | AutologLabel = JLabel() 452 | AutologLabel.setText("Auto Log from Proxy to API Mapper :") 453 | AutologHeading1 = JLabel() 454 | AutologHeading1.setFont(Font("Segoe UI", 1, 14)) 455 | AutologHeading1.setText("Auto Logging"); 456 | AutologHeading1.setToolTipText("") 457 | self.AutoLoggingtoggle = JToggleButton() 458 | self.AutoLoggingtoggle.addItemListener(self.AutoLogtogglelistener) 459 | self.AutoLoggingtoggle.setBackground(Color(128, 128, 128)); 460 | self.AutoLoggingtoggle.setFont(Font("Segoe UI", 1, 14)) 461 | self.AutoLoggingtoggle.setText("ON"); 462 | self.AutoLoggingtoggle.setCursor(Cursor(Cursor.DEFAULT_CURSOR)) 463 | self.ToggleStatus = JLabel() 464 | self.ToggleStatus.setForeground(Color(255, 102, 51)) 465 | self.ToggleStatus.setText("Current Status: OFF") 466 | oneclickimportexportHeading = JLabel() 467 | oneclickimportexportHeading.setFont(Font("Segoe UI", 1, 14)) 468 | oneclickimportexportHeading.setText("One Click Import Export") 469 | oneclickimportexportHeading.setToolTipText("") 470 | self.SingleclickimportMapper = JLabel() 471 | self.SingleclickimportMapper.setForeground(Color(255, 102, 51)); 472 | 473 | self.SingleclickimportVulnerabilities = JLabel() 474 | self.SingleclickimportVulnerabilities.setForeground(Color(255, 102, 51)); 475 | 476 | self.SingleclickexportMapper = JLabel() 477 | self.SingleclickexportMapper.setForeground(Color(255, 102, 51)) 478 | 479 | self.SingleclickexportVulnerabilities = JLabel() 480 | self.SingleclickexportVulnerabilities.setForeground(Color(255, 102, 51)) 481 | 482 | Excludefilelabel = JLabel() 483 | Excludefilelabel.setText("Exclude Files :") 484 | Excludefilebutton = JButton("Save", actionPerformed=self.excludefilebuttonclick) 485 | Excludefilebutton.setBackground(Color(255, 102, 51)) 486 | Excludefilebutton.setFont(Font("Segoe UI", 1, 12)) 487 | Excludefilebutton.setForeground(Color(255, 255, 255)) 488 | AutosaveHeading3 = JLabel() 489 | AutosaveHeading3.setFont(Font("Segoe UI", 1, 14)) 490 | AutosaveHeading3.setText("Auto Save") 491 | AutosaveHeading3.setToolTipText("") 492 | self.AutoSavetoggle = JToggleButton() 493 | self.AutoSavetoggle.setBackground(Color(128, 128, 128)) 494 | self.AutoSavetoggle.setFont(Font("Segoe UI", 1, 14)) 495 | self.AutoSavetoggle.setText("ON")#, itemStateChanged = self.AutoSavetogglelistener) 496 | self.AutoSavetoggle.addItemListener(self.AutoSavetogglelistener) 497 | self.AutoSavetoggle.setCursor(Cursor(Cursor.DEFAULT_CURSOR)) 498 | self.Autosavechecker = False 499 | AutoSaveLabel = JLabel() 500 | AutoSaveLabel.setText("Auto Save API Mapper and Vulnerability :") 501 | self.AutoSaveToggleStatus = JLabel() 502 | self.AutoSaveToggleStatus.setForeground(Color(255, 102, 51)) 503 | self.AutoSaveToggleStatus.setText("Current Status: OFF") 504 | self.AutoSaveErrorlabel = JLabel() 505 | self.AutoSaveErrorlabel.setBackground(Color(0, 0, 0)) 506 | self.AutoSaveErrorlabel.setForeground(Color(204, 0, 0)) 507 | #AutoSaveErrorlabel.setText("Auto Save Requires Auto Save Config with Valid Directory Selected") 508 | jScrollPane1 = JScrollPane() 509 | self.Excludefiletextfield = JTextArea() 510 | self.Excludefiletextfield.setColumns(20) 511 | self.Excludefiletextfield.setRows(1) 512 | self.Excludefiletextfield.setTabSize(6) 513 | self.Excludefiletextfield.setText("SCRIPT,JPEG,CSS,PNG,IMAGE,APP") 514 | jScrollPane1.setViewportView(self.Excludefiletextfield) 515 | jSeparator5 = JSeparator() 516 | jSeparator5.setOrientation(VERTICAL) 517 | 518 | 519 | 520 | layout.setHorizontalGroup( 521 | layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 522 | .addGroup(layout.createSequentialGroup() 523 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 524 | .addGroup(layout.createSequentialGroup() 525 | .addGap(26, 26, 26) 526 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 527 | .addGroup(layout.createSequentialGroup() 528 | .addComponent(AutologHeading1) 529 | .addGap(125, 125, 125) 530 | .addComponent(jSeparator3, javax.swing.GroupLayout.PREFERRED_SIZE, 180, javax.swing.GroupLayout.PREFERRED_SIZE)) 531 | .addComponent(oneclickimportexportHeading) 532 | .addComponent(Singleclickfilename) 533 | .addComponent(OneclickImportExportLabel) 534 | .addGroup(layout.createSequentialGroup() 535 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 536 | .addComponent(jLabel1) 537 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) 538 | .addComponent(AutoloadChecklistHeading) 539 | .addComponent(self.timeperid)) 540 | .addComponent(jLabel4)) 541 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 542 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 543 | .addGroup(layout.createSequentialGroup() 544 | .addComponent(button2) 545 | .addGap(37, 37, 37) 546 | .addComponent(self.Checklistfilepath)) 547 | .addGroup(layout.createSequentialGroup() 548 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 549 | .addComponent(jButton1) 550 | .addComponent(self.timerbox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 551 | .addComponent(self.saveconfigbutton)) 552 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 553 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 554 | .addComponent(self.timeerror) 555 | .addComponent(self.autosavepath))) 556 | .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 180, javax.swing.GroupLayout.PREFERRED_SIZE) 557 | .addComponent(Savechecklistfileconfig) 558 | .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 180, javax.swing.GroupLayout.PREFERRED_SIZE))) 559 | .addGroup(layout.createSequentialGroup() 560 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 561 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, False) 562 | .addGroup(layout.createSequentialGroup() 563 | .addComponent(Exportall) 564 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) 565 | .addComponent(self.SingleclickexportMapper)) 566 | .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() 567 | .addComponent(importall) 568 | .addGap(18, 18, 18) 569 | .addComponent(self.SingleclickimportMapper))) 570 | .addGroup(layout.createSequentialGroup() 571 | .addComponent(AutologLabel) 572 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 573 | .addComponent(self.AutoLoggingtoggle, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE))) 574 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 575 | .addGroup(layout.createSequentialGroup() 576 | .addGap(24, 24, 24) 577 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 578 | .addComponent(self.SingleclickimportVulnerabilities) 579 | .addComponent(self.SingleclickexportVulnerabilities))) 580 | .addGroup(layout.createSequentialGroup() 581 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 582 | .addGroup(layout.createSequentialGroup() 583 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 584 | .addComponent(self.ToggleStatus)) 585 | .addGroup(layout.createSequentialGroup() 586 | .addGap(52, 52, 52) 587 | .addComponent(Excludefilebutton))) 588 | .addGap(45, 45, 45) 589 | .addComponent(jSeparator5, javax.swing.GroupLayout.PREFERRED_SIZE, 12, javax.swing.GroupLayout.PREFERRED_SIZE) 590 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 591 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 592 | .addComponent(self.AutoSaveErrorlabel) 593 | .addComponent(AutoSaveLabel) 594 | .addGroup(layout.createSequentialGroup() 595 | .addComponent(self.AutoSavetoggle, javax.swing.GroupLayout.PREFERRED_SIZE, 73, javax.swing.GroupLayout.PREFERRED_SIZE) 596 | .addGap(18, 18, 18) 597 | .addComponent(self.AutoSaveToggleStatus)) 598 | .addComponent(AutosaveHeading3))))) 599 | .addGroup(layout.createSequentialGroup() 600 | .addComponent(Excludefilelabel) 601 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 602 | .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))) 603 | .addGroup(layout.createSequentialGroup() 604 | .addGap(35, 35, 35) 605 | .addComponent(AutoSaveConfigHeading))) 606 | .addContainerGap(133, Short.MAX_VALUE)) 607 | ); 608 | layout.setVerticalGroup( 609 | layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 610 | .addGroup(layout.createSequentialGroup() 611 | .addContainerGap() 612 | .addComponent(AutoSaveConfigHeading) 613 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) 614 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 615 | .addComponent(jLabel1) 616 | .addComponent(jButton1) 617 | .addComponent(self.autosavepath)) 618 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) 619 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 620 | .addComponent(self.timeperid) 621 | .addComponent(self.timerbox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 622 | .addComponent(self.timeerror)) 623 | .addGap(18, 18, 18) 624 | .addComponent(self.saveconfigbutton) 625 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 626 | .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE) 627 | .addGap(2, 2, 2) 628 | .addComponent(AutoloadChecklistHeading) 629 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) 630 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 631 | .addComponent(jLabel4) 632 | .addComponent(button2) 633 | .addComponent(self.Checklistfilepath)) 634 | .addGap(18, 18, 18) 635 | .addComponent(Savechecklistfileconfig) 636 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 637 | .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE) 638 | .addGap(1, 1, 1) 639 | .addComponent(oneclickimportexportHeading) 640 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) 641 | .addComponent(OneclickImportExportLabel) 642 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) 643 | .addComponent(Singleclickfilename) 644 | .addGap(18, 18, 18) 645 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 646 | .addComponent(importall) 647 | .addComponent(self.SingleclickimportMapper) 648 | .addComponent(self.SingleclickimportVulnerabilities)) 649 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) 650 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 651 | .addComponent(Exportall) 652 | .addComponent(self.SingleclickexportMapper) 653 | .addComponent(self.SingleclickexportVulnerabilities)) 654 | .addGap(18, 18, 18) 655 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 656 | .addGroup(layout.createSequentialGroup() 657 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 658 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 659 | .addComponent(AutologHeading1) 660 | .addComponent(AutosaveHeading3)) 661 | .addComponent(jSeparator3, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)) 662 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) 663 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 664 | .addComponent(AutologLabel) 665 | .addComponent(self.AutoLoggingtoggle, javax.swing.GroupLayout.PREFERRED_SIZE, 34, javax.swing.GroupLayout.PREFERRED_SIZE) 666 | .addComponent(self.ToggleStatus)) 667 | .addGap(18, 18, 18) 668 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 669 | .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 670 | .addComponent(Excludefilelabel) 671 | .addComponent(Excludefilebutton)) 672 | .addGap(0, 0, Short.MAX_VALUE)) 673 | .addGroup(layout.createSequentialGroup() 674 | .addGap(22, 22, 22) 675 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 676 | .addGroup(layout.createSequentialGroup() 677 | .addComponent(AutoSaveLabel) 678 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) 679 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 680 | .addComponent(self.AutoSavetoggle, javax.swing.GroupLayout.PREFERRED_SIZE, 38, javax.swing.GroupLayout.PREFERRED_SIZE) 681 | .addComponent(self.AutoSaveToggleStatus)) 682 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 683 | .addComponent(self.AutoSaveErrorlabel)) 684 | .addComponent(jSeparator5, javax.swing.GroupLayout.PREFERRED_SIZE, 134, javax.swing.GroupLayout.PREFERRED_SIZE)) 685 | .addContainerGap(187, Short.MAX_VALUE)))) 686 | ) 687 | 688 | 689 | 690 | self.FourthTab.add(self.buttonPanel5)#,BorderLayout.NORTH) 691 | 692 | 693 | # Loading auto save time,path and auto load checklist and auto log exclude files from burp config 694 | self.path = callbacks.loadExtensionSetting('path') 695 | self.time = callbacks.loadExtensionSetting('time') 696 | self.loadexcludefiles = callbacks.loadExtensionSetting('excludefilestolog') 697 | self.checklistpath = callbacks.loadExtensionSetting('checklistpath') 698 | self.timerbox.setText(self.time) 699 | self.autosavepath.setText(self.path) 700 | 701 | 702 | 703 | self.autoloadchecklist = 0 704 | self.autosavelocation = 0 705 | self.extensionload = True 706 | 707 | 708 | # Validing the content og extension loaded config 709 | if self.loadexcludefiles == None: 710 | self.loadexcludefiles = "SCRIPT,JPEG,CSS,PNG,IMAGE,APP".upper() 711 | else: 712 | self.Excludefiletextfield.setText(self.loadexcludefiles) 713 | 714 | if self.time == None: 715 | self.time = 10 716 | self.timerbox.setText(str(self.time)) 717 | else: 718 | pass 719 | 720 | if self.path == None: 721 | self.path = "Please select the Directory" 722 | self.autosavepath.setText(self.path) 723 | else: 724 | pass 725 | 726 | self.callbacks.printOutput("\nAuto Save Time = " + str(self.time)) 727 | self.callbacks.printOutput("Auto Save Path = " + self.path +"\n") 728 | 729 | 730 | # Loading the checkling if auto load checklist configured 731 | if self.checklistpath == None: 732 | self.callbacks.printOutput(str(self.checklistpath)) 733 | self.Checklistfilepath.setText("Select the Checklist file") 734 | else: 735 | self.comboBox.removeAllItems() 736 | self.comboBox.addItem(None) 737 | self.dataModel.setRowCount(0) 738 | with open(self.checklistpath, 'rb') as f: 739 | reader2 = csv.reader(f, delimiter=',') 740 | for rows in reader2: 741 | SR = rows[0] 742 | title = rows[1] 743 | obj = [SR,title] 744 | self.dataModel.addRow(obj) 745 | #self.comboBox.addItem(str(title)) 746 | self.combolist.append(str(title)) 747 | combo_model = DefaultComboBoxModel(self.combolist) 748 | self.editor.comboBox.setModel(combo_model) 749 | f.close() 750 | self.Checklistfilepath.setText(self.checklistpath) 751 | 752 | 753 | 754 | 755 | 756 | # Validating if extension is unloaded to stop all running process ( Auto Save and Auto Log) 757 | def extensionUnloaded(self): 758 | self.extensionload = False 759 | self.Autosavechecker = False 760 | self.Autologcheck = False 761 | 762 | 763 | # Listner to validate if auto Log is on or off 764 | def AutoLogtogglelistener(self,e): 765 | self.AutoLoggingtoggle = e.getItem() 766 | if self.AutoLoggingtoggle.isSelected(): 767 | self.AutoLoggingtoggle.setText("OFF") 768 | self.AutoLoggingtoggle.setBackground(Color(255, 255, 255)) 769 | self.ToggleStatus.setText("Current Status: ON") 770 | self.Autologcheck = True 771 | self.callbacks.registerProxyListener(Autologclas(self)) 772 | #Autologclas(self) 773 | 774 | 775 | else: 776 | self.AutoLoggingtoggle.setText("ON") 777 | self.AutoLoggingtoggle.setBackground(Color(128, 128, 128)) 778 | self.ToggleStatus.setText("Current Status: OFF") 779 | self.Autologcheck = False 780 | self.callbacks.removeProxyListener(Autologclas(self)) 781 | 782 | 783 | 784 | # Listner to validate if auto Save is on or off 785 | def AutoSavetogglelistener(self, e): 786 | self.AutoSavetoggle = e.getItem() 787 | t = Autosaveclas(self) 788 | #p = multiprocessing.Process(target=t.run) 789 | 790 | if self.AutoSavetoggle.isSelected(): 791 | if not os.path.isdir(str(self.path)): 792 | self.AutoSavetoggle.setBackground(Color(128, 128, 128)) 793 | self.AutoSaveErrorlabel.setText("Auto Save Requires Auto Save Config with Valid Directory Selected") 794 | self.Autosavechecker = False 795 | else: 796 | 797 | self.AutoSavetoggle.setText("OFF") 798 | self.AutoSavetoggle.setBackground(Color(255, 255, 255)) 799 | self.AutoSaveToggleStatus.setText("Current Status: ON") 800 | self.AutoSaveErrorlabel.setText("") 801 | 802 | self.Autosavechecker = True 803 | t.start() 804 | 805 | else: 806 | self.AutoSavetoggle.setText("ON") 807 | self.AutoSaveToggleStatus.setText("Current Status: OFF") 808 | self.AutoSavetoggle.setBackground(Color(128, 128, 128)) 809 | self.AutoSaveErrorlabel.setText("") 810 | self.Autosavechecker = False 811 | t.stop() 812 | 813 | 814 | # Import All data if Import button clicked from config Tab 815 | def autoimportall(self,e): 816 | if os.path.isdir(str(self.path)): 817 | fname = "APIMapper"+"."+"csv" 818 | fnameWithPath = os.path.join(self.path,fname) 819 | if os.path.exists(fnameWithPath): 820 | with open(fnameWithPath, 'rb') as f: 821 | reader2 = csv.reader(f, delimiter=',') 822 | for rows in reader2: 823 | SR = rows[0] 824 | url = rows[1] 825 | method = rows[2] 826 | body = zlib.decompress(base64.b64decode(rows[3])) 827 | functionname = rows[4] 828 | request = zlib.decompress(base64.b64decode(rows[5])) 829 | testcases = rows[6] 830 | try: 831 | response = zlib.decompress(base64.b64decode(rows[7])) 832 | status = rows[8] 833 | except IndexError: 834 | response = None 835 | status = None 836 | self._log.append(LogEntry(SR,url, method,body,request,functionname,testcases,response,status)) 837 | 838 | f.close() 839 | self.fireTableDataChanged() 840 | self.SingleclickimportMapper.setText("API Mapper Import Completed") 841 | fname2 = "Vulnerability"+"."+"csv" 842 | fnameWithPath2 = os.path.join(self.path,fname2) 843 | if os.path.exists(fnameWithPath2): 844 | with open(fnameWithPath2, 'rb') as f: 845 | reader2 = csv.reader(f, delimiter=',') 846 | for rows in reader2: 847 | URL = rows[0] 848 | Parameter = rows[1] 849 | Vulnerability = rows[2] 850 | try: 851 | Severity = rows[3] 852 | Request = zlib.decompress(base64.b64decode(rows[4])) 853 | Response = zlib.decompress(base64.b64decode(rows[5])) 854 | except IndexError: 855 | Severity = None 856 | Request = None 857 | Response = None 858 | obj = [URL,Parameter,Vulnerability,Severity,Request,Response] 859 | self.dataModel2.addRow(obj) 860 | f.close() 861 | self.SingleclickimportVulnerabilities.setText("Vulnerabilities Import Completed") 862 | else: 863 | self.autosavepath.setText("Output Directory doesn't exist") 864 | self.SingleclickimportVulnerabilities.setText("Vulnerabilities Import Failed") 865 | self.SingleclickimportMapper.setText("API Mapper Import Failed") 866 | 867 | 868 | 869 | 870 | 871 | # Export All data if Export button clicked from config Tab 872 | def autoexportall(self,e): 873 | if os.path.isdir(str(self.path)): 874 | if self.logTable.getRowCount() > 0: 875 | fname = "APIMapper"+"."+"csv" 876 | fnameWithPath = os.path.join(self.path,fname) 877 | if os.path.exists(fnameWithPath): 878 | os.remove(fnameWithPath) 879 | self.callbacks.printOutput("Saving the API Mapper output") 880 | with open(fnameWithPath, 'wb') as loggerdata: 881 | writer = csv.writer(loggerdata) 882 | for logEntry in self._log: 883 | writer.writerow([str(logEntry._sr), str(logEntry._url) ,str(logEntry._method) , base64.b64encode(zlib.compress(logEntry._postbody.encode('utf-8'))) ,str(logEntry._FunctionalityName) , base64.b64encode(zlib.compress(logEntry._requestResponse.encode('utf-8'))) ,str(logEntry._TestCases), base64.b64encode(zlib.compress(logEntry._response.encode('utf-8'))) ,str(logEntry._status)]) 884 | loggerdata.close() 885 | self.SingleclickexportMapper.setText("API Mapper Export Completed") 886 | else: 887 | self.callbacks.printOutput("Skipping the API Mapper, Table is empty") 888 | 889 | self.SingleclickexportMapper.setText("API Mapper Export Failed. Empty Table") 890 | if self.dataModel2.getRowCount() > 0: 891 | 892 | fname2 = "Vulnerability"+"."+"csv" 893 | fnameWithPath2 = os.path.join(self.path,fname2) 894 | if os.path.exists(fnameWithPath2): 895 | os.remove(fnameWithPath2) 896 | self.callbacks.printOutput("Saving the Vulnerability output") 897 | totalrow = self.dataModel2.getRowCount() 898 | with open(fnameWithPath2, 'wb') as vulnerabilitydata: 899 | writer = csv.writer(vulnerabilitydata) 900 | for row in range (0, totalrow): 901 | url = self.dataModel2.getValueAt(row,0) 902 | paramter = self.dataModel2.getValueAt(int(row),1) 903 | Vulnerability = self.dataModel2.getValueAt(int(row),2) 904 | Severity = self.dataModel2.getValueAt(int(row),3) 905 | Request = self.dataModel2.getValueAt(int(row),4) 906 | Response = self.dataModel2.getValueAt(int(row),5) 907 | 908 | 909 | writer.writerow([str(url), str(paramter) ,str(Vulnerability),str(Severity),base64.b64encode(zlib.compress(Request.encode('utf-8'))),base64.b64encode(zlib.compress(Response.encode('utf-8')))]) 910 | vulnerabilitydata.close() 911 | self.SingleclickexportVulnerabilities.setText("Vulnerabilities Export Completed") 912 | else: 913 | self.callbacks.printOutput("Skipping the Vulnerability, Table is empty") 914 | self.SingleclickexportVulnerabilities.setText("Vulnerabilities Export Failed. Empty Table") 915 | else: 916 | self.autosavepath.setText("Output Directory doesn't exist") 917 | self.SingleclickexportVulnerabilities.setText("Vulnerabilities Export Failed") 918 | self.SingleclickexportMapper.setText("API Mapper Export Failed") 919 | 920 | 921 | # Listner if Save button clicked from config tab to modify the auto log excluded files 922 | def excludefilebuttonclick(self,e): 923 | #Excludefiletextfield.getText() 924 | self.callbacks.saveExtensionSetting("excludefilestolog", self.Excludefiletextfield.getText().upper()) 925 | self.Excludefiletextfield.setText(self.Excludefiletextfield.getText().upper()) 926 | 927 | 928 | 929 | #Allowing users to select the auto save DIRECTORIES 930 | def Autosavepath(self,e): 931 | chooseFile = JFileChooser() 932 | chooseFile.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY) 933 | returnedFile = chooseFile.showDialog(self.VulnerabilityButtonPanel, "Output Path") 934 | if returnedFile == JFileChooser.APPROVE_OPTION: 935 | fileLoad1 = chooseFile.getSelectedFile() 936 | self.autosavelocation = fileLoad1.getPath() 937 | return str(self.autosavelocation) 938 | 939 | 940 | # Allowing users to select the checklist CSV file to auto load it everytime extension is reloaded 941 | def Autosavepath2(self,e): 942 | chooseFile = JFileChooser() 943 | filter = FileNameExtensionFilter("csv files", ["csv"]) 944 | chooseFile.addChoosableFileFilter(filter) 945 | 946 | ret = chooseFile.showDialog(self.tab, "Choose file") 947 | if ret == JFileChooser.APPROVE_OPTION: 948 | fileLoad = chooseFile.getSelectedFile() 949 | self.autoloadchecklist = fileLoad.getAbsolutePath() 950 | return str(self.autoloadchecklist) 951 | 952 | 953 | # Allowing users to set auto save time 954 | def saveautoconfigdata(self,e): 955 | if self.autoloadchecklist == 0: 956 | self.autoloadchecklist = None 957 | if self.autosavelocation == 0: 958 | if str(self.timerbox.getText()) == "0": 959 | self.timeerror.setText("Invalid time") 960 | else: 961 | self.path = self.callbacks.loadExtensionSetting('path') 962 | if os.path.isdir(str(self.path)): 963 | self.autosavepath.setText(self.path) 964 | self.callbacks.saveExtensionSetting("time", self.timerbox.getText()) 965 | self.time = self.callbacks.loadExtensionSetting('time') 966 | else: 967 | self.callbacks.printOutput(str(self.autosavelocation)) 968 | self.autosavepath.setText("Please select the valid path!") 969 | else: 970 | if str(self.timerbox.getText()) == "0": 971 | 972 | self.timeerror.setText("Invalid time") 973 | 974 | 975 | else: 976 | self.callbacks.saveExtensionSetting("path", str(self.autosavelocation)) 977 | self.callbacks.saveExtensionSetting("time", self.timerbox.getText()) 978 | self.autosavepath.setText(str(self.autosavelocation)) 979 | self.path = self.callbacks.loadExtensionSetting('path') 980 | self.time = self.callbacks.loadExtensionSetting('time') 981 | 982 | 983 | # Allow users to save the auto load checklist path 984 | def saveautoconfigdata2(self,e): 985 | if self.autoloadchecklist == 0: 986 | self.Checklistfilepath.setText("Select the checklist file") 987 | else: 988 | self.callbacks.saveExtensionSetting("checklistpath", str(self.autoloadchecklist)) 989 | self.Checklistfilepath.setText(self.autoloadchecklist) 990 | self.Checklistfilepath.setText(str(self.autoloadchecklist)) 991 | 992 | 993 | # this will send the selected row in api mapper to vulnerability tab 994 | def sendVulnItem(self,event): 995 | row = self.logTable.getSelectedRows() 996 | for rows in row: 997 | modelRowIndex = self.logTable.convertRowIndexToModel(rows) 998 | logEntry = self._log[modelRowIndex] 999 | self.url = logEntry._url 1000 | self.requestinst = logEntry._requestResponse 1001 | self.responseinst = logEntry._response 1002 | obj = [str(self.url), None,'','',self.requestinst,self.responseinst] 1003 | self.dataModel2.addRow(obj) 1004 | 1005 | # function will handle to send the selected row to repeater 1006 | def sendRepeaterItem(self,event): 1007 | row = self.logTable.getSelectedRows() 1008 | for rows in row: 1009 | modelRowIndex = self.logTable.convertRowIndexToModel(rows) 1010 | logEntry = self._log[modelRowIndex] 1011 | fullurl = logEntry._url 1012 | url = urlparse(str(fullurl)) 1013 | hostname = url.hostname 1014 | #port = url.port 1015 | port = url.port if url.port is not None else 443 1016 | protocol = url.scheme 1017 | request = self.helpers.stringToBytes(logEntry._requestResponse) 1018 | func = logEntry._FunctionalityName 1019 | if protocol == "https": 1020 | self.callbacks.sendToRepeater(hostname,port, True, request, func) 1021 | else: 1022 | self.callbacks.sendToRepeater(hostname,port, False, request, func) 1023 | 1024 | 1025 | # function will handle, delete the row from api mapper 1026 | def deleterow(self,event): 1027 | row = self.logTable.getSelectedRows() 1028 | 1029 | 1030 | for rows in sorted(row, reverse=True): 1031 | modelRowIndex = self.logTable.convertRowIndexToModel(rows) 1032 | self._log.pop(modelRowIndex) 1033 | self.fireTableDataChanged() 1034 | 1035 | # delete row from the vulnerability table 1036 | def deletevuln(self,e): 1037 | totalvulnrows = self.table3.getSelectedRows() 1038 | for rows in sorted(totalvulnrows, reverse=True): 1039 | modelRowIndex = self.table3.convertRowIndexToModel(rows) 1040 | self.dataModel2.removeRow(modelRowIndex) 1041 | 1042 | 1043 | # allow users to search vulnerablity from select vulnerablity list in vulnerability table 1044 | ''' 1045 | def seachincombobox(self,event): 1046 | Combo = event.getSource() 1047 | searchedvalue = Combo.getSelectedItem() 1048 | self.comboBox.removeAllItems() 1049 | self.comboBox.addItem(None) 1050 | for items in self.combolist: 1051 | if searchedvalue in items: 1052 | self.comboBox.addItem(items) 1053 | 1054 | 1055 | 1056 | def seachincombobox(self, event): 1057 | Combo = event.getSource() 1058 | searchedValue = Combo.getEditor().getItem() 1059 | model = Combo.getModel() 1060 | model.removeAllElements() 1061 | model.addElement(None) 1062 | for item in self.combolist: 1063 | if not searchedValue or searchedValue.lower() in item.lower(): 1064 | model.addElement(item) 1065 | ''' 1066 | 1067 | 1068 | #function that will show a option to send request to extension in proxy/repeater etc 1069 | def createMenuItems(self, invocation): 1070 | ctx = invocation.getInvocationContext() 1071 | menu = [] 1072 | menu.append(JMenuItem("Send To API Mapper", None,actionPerformed=lambda x, inv=invocation: self.getTabledataa(inv))) 1073 | menu.append(JMenuItem("Send To Vulnerability", None,actionPerformed=lambda x, inv=invocation: self.getVulnerabilitydataa(inv))) 1074 | 1075 | if menu == []: 1076 | return 1077 | else: 1078 | return menu 1079 | 1080 | 1081 | # function will be called when user send any request to vulnerabilites tab, it will give the selected message 1082 | def getVulnerabilitydataa(self,invocation): 1083 | reqRes = invocation.getSelectedMessages() 1084 | for items in reqRes: 1085 | self.url = items.getUrl() 1086 | req = self.helpers.analyzeRequest(items) 1087 | gettingrequest = items.getRequest() 1088 | self.requestinst = self.helpers.bytesToString(gettingrequest) 1089 | self.responseinbytes = items.getResponse() 1090 | self.responseinst = self.helpers.bytesToString(self.responseinbytes) 1091 | obj = [str(self.url), None,'','',self.requestinst,self.responseinst] 1092 | 1093 | self.dataModel2.addRow(obj) 1094 | 1095 | 1096 | 1097 | # function will be called when user send any request to the extension, function will get the required data from the request that is send and will add it to the list 1098 | def getTabledataa(self, invocation): 1099 | reqRes = invocation.getSelectedMessages() 1100 | for items in reqRes: 1101 | req = self.helpers.analyzeRequest(items) 1102 | self.method = req.getMethod() 1103 | paramter = req.getParameters() 1104 | self.url = items.getUrl() 1105 | gettingrequest = items.getRequest() 1106 | self.requestinst = self.helpers.bytesToString(gettingrequest) 1107 | self.responseinbytes = items.getResponse() 1108 | self.responseinst = self.helpers.bytesToString(self.responseinbytes) 1109 | getody = req.getBodyOffset() 1110 | self.body = self.requestinst[getody:len(self.requestinst)] 1111 | rowss = self.logTable.getRowCount() 1112 | self.sr2 = str((rowss + 1)) 1113 | self._lock.acquire() 1114 | row = len(self._log) 1115 | column = self.logTable.getColumnCount() 1116 | self._log.append(LogEntry(self.sr2, self.url, self.method, self.body, self.requestinst, '', '', self.responseinst, '')) 1117 | self.logTable.getModel().fireTableRowsInserted(row, row) 1118 | self._lock.release() 1119 | 1120 | 1121 | # Returning the tab name to Burp Suite 1122 | def getTabCaption(self): 1123 | return "Pentest Mapper" 1124 | 1125 | 1126 | # Returning the UI to the extension tab - Returning the new taB insite the extension tab 1127 | def getUiComponent(self): 1128 | return self.tabbedPane 1129 | 1130 | # function will export the table data when clicked on save button in api mapper tab 1131 | def savelogger(self,e): 1132 | currenttime = str(time.strftime('%Y-%m-%d,%H:%M:%S', time.localtime(time.time()))) 1133 | chooseFile = JFileChooser() 1134 | chooseFile.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY) 1135 | returnedFile = chooseFile.showDialog(self.APIMapperButtonPanel, "Output Path") 1136 | if returnedFile == JFileChooser.APPROVE_OPTION: 1137 | fileLoad = chooseFile.getSelectedFile() 1138 | self.filepath = fileLoad.getPath() 1139 | fname = "APIMapper"+str(time.time())+"."+"csv" 1140 | fnameWithPath = os.path.join(self.filepath,fname) 1141 | with open(fnameWithPath, 'wb') as loggerdata: 1142 | writer = csv.writer(loggerdata) 1143 | for logEntry in self._log: 1144 | writer.writerow([str(logEntry._sr), str(logEntry._url) ,str(logEntry._method) , base64.b64encode(zlib.compress(logEntry._postbody.encode('utf-8'))) ,str(logEntry._FunctionalityName) , base64.b64encode(zlib.compress(logEntry._requestResponse.encode('utf-8'))) ,str(logEntry._TestCases), base64.b64encode(zlib.compress(logEntry._response.encode('utf-8'))) ,str(logEntry._status)]) 1145 | loggerdata.close() 1146 | 1147 | 1148 | # function to handle event to import table data in api mapper tab 1149 | def importlogger(self,e): 1150 | chooseFile = JFileChooser() 1151 | filter = FileNameExtensionFilter("csv files", ["csv"]) 1152 | chooseFile.addChoosableFileFilter(filter) 1153 | ret = chooseFile.showDialog(self.tab, "Choose file") 1154 | if ret == JFileChooser.APPROVE_OPTION: 1155 | fileLoad = chooseFile.getSelectedFile() 1156 | self.filepath = fileLoad.getAbsolutePath() 1157 | with open(self.filepath, 'rb') as f: 1158 | reader2 = csv.reader(f, delimiter=',') 1159 | for rows in reader2: 1160 | SR = rows[0] 1161 | url = rows[1] 1162 | method = rows[2] 1163 | body = zlib.decompress(base64.b64decode(rows[3])) 1164 | functionname = rows[4] 1165 | request = zlib.decompress(base64.b64decode(rows[5])) 1166 | testcases = rows[6] 1167 | try: 1168 | response = zlib.decompress(base64.b64decode(rows[7])) 1169 | status = rows[8] 1170 | except IndexError: 1171 | response = None 1172 | status = None 1173 | self._log.append(LogEntry(SR,url, method,body,request,functionname,testcases,response,status)) 1174 | f.close() 1175 | self.fireTableDataChanged() 1176 | 1177 | 1178 | ## Search text in checklist tab 1179 | def searchinchecklist(self,e): 1180 | checklistsearchstring = self.searchchecklist.getText() 1181 | if checklistsearchstring == "": 1182 | self.sorter.setRowFilter(None) 1183 | else: 1184 | self.sorter.setRowFilter(RowFilter.regexFilter("(?i)" + checklistsearchstring)); 1185 | 1186 | 1187 | ## Search text in APIMapper tab 1188 | def searchinapimapper(self,e): 1189 | apimappersearchstring = self.searchapimapper.getText() 1190 | if apimappersearchstring == "": 1191 | self.sorter2.setRowFilter(None) 1192 | else: 1193 | self.sorter2.setRowFilter(RowFilter.regexFilter("(?i)" + apimappersearchstring)); 1194 | 1195 | ## Search text in APIMapper tab 1196 | def searchinvulnerability(self,e): 1197 | vulnerabilitysearchstring = self.searchvulnerability.getText() 1198 | if vulnerabilitysearchstring == "": 1199 | self.sorter3.setRowFilter(None) 1200 | else: 1201 | self.sorter3.setRowFilter(RowFilter.regexFilter("(?i)" + vulnerabilitysearchstring)); 1202 | 1203 | 1204 | #Function that will be called when user click on import in checklist tab 1205 | def importchecklist(self, e): 1206 | chooseFile = JFileChooser() 1207 | filter = FileNameExtensionFilter("csv files", ["csv"]) 1208 | chooseFile.addChoosableFileFilter(filter) 1209 | ret = chooseFile.showDialog(self.tab, "Choose file") 1210 | if ret == JFileChooser.APPROVE_OPTION: 1211 | fileLoad = chooseFile.getSelectedFile() 1212 | self.filepath = fileLoad.getAbsolutePath() 1213 | self.comboBox.removeAllItems() 1214 | self.comboBox.addItem(None) 1215 | self.dataModel.setRowCount(0) 1216 | with open(self.filepath, 'rb') as f: 1217 | reader2 = csv.reader(f, delimiter=',') 1218 | for rows in reader2: 1219 | SR = rows[0] 1220 | title = rows[1] 1221 | obj = [SR,title] 1222 | self.dataModel.addRow(obj) 1223 | self.comboBox.addItem(str(title)) 1224 | self.combolist.append(str(title)) 1225 | combo_model = DefaultComboBoxModel(self.combolist) 1226 | self.editor.comboBox.setModel(combo_model) 1227 | f.close() 1228 | 1229 | 1230 | # creating a function that will be called when user clicks on the create button this function will show the input field in UI for checklist taB 1231 | def createtestcases(self, e): 1232 | self.createchecklistbutton.setEnabled(False) 1233 | self.textfield1 = JTextField('', 15) 1234 | self.ChecklistbuttonPanel.add(self.textfield1) 1235 | self.ChecklistbuttonPanel.add(JButton( 1236 | "Submit", actionPerformed=self.addrow)) 1237 | self.ChecklistbuttonPanel.add(Box.createVerticalGlue()) 1238 | 1239 | # this function will be called as soon as user click on suBmit Button of add row UI input 1240 | def addrow(self, e): 1241 | rowsss = self.dataModel.getRowCount() 1242 | sr = (rowsss + 1) 1243 | title = self.value = self.textfield1.getText() 1244 | obj = [sr, title] 1245 | self.comboBox.addItem(str(title)) 1246 | self.combolist.append(str(title)) 1247 | combo_model = DefaultComboBoxModel(self.combolist) 1248 | self.editor.comboBox.setModel(combo_model) 1249 | self.dataModel.addRow(obj) 1250 | if not self.checklistpath == None: 1251 | # Writing the new entry in file 1252 | with open(self.checklistpath, 'a') as writechecklist: 1253 | writer = csv.writer(writechecklist) 1254 | writer.writerow([str(sr), str(title)]) 1255 | writechecklist.close() 1256 | else: 1257 | self.callbacks.printOutput("Auto add to csv file only work if auto checklist load is configured") 1258 | 1259 | 1260 | # function to handel event when save button clicked on test cases 1261 | def SaveTestCases(self,e): 1262 | selectedrow = self.logTable.getSelectedRow() 1263 | modelRowIndex = self.logTable.convertRowIndexToModel(selectedrow) 1264 | if modelRowIndex >= 0: 1265 | logEntry = self._log[modelRowIndex] 1266 | Value = self.testcases.getText() 1267 | logEntry._TestCases = Value 1268 | 1269 | 1270 | # function will handle to event once the export button clicked on vulnerablity tab 1271 | def exportvulnerability(self,e): 1272 | totalrow = self.dataModel2.getRowCount() 1273 | self.callbacks.printOutput(str(totalrow)) 1274 | chooseFile = JFileChooser() 1275 | chooseFile.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY) 1276 | returnedFile = chooseFile.showDialog(self.VulnerabilityButtonPanel, "Output Path") 1277 | if returnedFile == JFileChooser.APPROVE_OPTION: 1278 | fileLoad1 = chooseFile.getSelectedFile() 1279 | self.filepath2 = fileLoad1.getPath() 1280 | fname2 = "Vulnerability"+str(time.time())+"."+"csv" 1281 | fnameWithPath = os.path.join(self.filepath2,fname2) 1282 | 1283 | #self.filepath2 = fileLoad1.getAbsolutePath() 1284 | with open(fnameWithPath, 'wb') as vulnerabilitydata: 1285 | writer = csv.writer(vulnerabilitydata) 1286 | for row in range (0, totalrow): 1287 | url = self.dataModel2.getValueAt(row,0) 1288 | paramter = self.dataModel2.getValueAt(int(row),1) 1289 | Vulnerability = self.dataModel2.getValueAt(int(row),2) 1290 | Severity = self.dataModel2.getValueAt(int(row),3) 1291 | Request = self.dataModel2.getValueAt(int(row),4) 1292 | Response = self.dataModel2.getValueAt(int(row),5) 1293 | writer.writerow([str(url), str(paramter) ,str(Vulnerability),str(Severity),base64.b64encode(zlib.compress(Request.encode('utf-8'))),base64.b64encode(zlib.compress(Response.encode('utf-8')))]) 1294 | vulnerabilitydata.close() 1295 | 1296 | 1297 | 1298 | # function will handle to event once the import button clicked on vulnerablity tab 1299 | def importvulnerability(self,e): 1300 | chooseFile = JFileChooser() 1301 | filter = FileNameExtensionFilter("csv files", ["csv"]) 1302 | chooseFile.addChoosableFileFilter(filter) 1303 | ret = chooseFile.showDialog(self.tab, "Choose file") 1304 | if ret == JFileChooser.APPROVE_OPTION: 1305 | fileLoad = chooseFile.getSelectedFile() 1306 | self.filepath = fileLoad.getAbsolutePath() 1307 | 1308 | with open(self.filepath, 'rb') as f: 1309 | reader2 = csv.reader(f, delimiter=',') 1310 | #self.data1 = list(reader) 1311 | for rows in reader2: 1312 | URL = rows[0] 1313 | Parameter = rows[1] 1314 | Vulnerability = rows[2] 1315 | try: 1316 | Severity = rows[3] 1317 | Request = rows[4] 1318 | Response = rows[5] 1319 | except IndexError: 1320 | Severity = None 1321 | Request = None 1322 | Response = None 1323 | obj = [URL,Parameter,Vulnerability,Severity,zlib.decompress(base64.b64decode(Request)),zlib.decompress(base64.b64decode(Response))] 1324 | self.dataModel2.addRow(obj) 1325 | f.close() 1326 | 1327 | 1328 | # extending the default table model to remove the editable column from the checklist taB table 1329 | class CustomDefaultTableModelHosts(DefaultTableModel): 1330 | 1331 | # override isCellEditable method 1332 | def isCellEditable(self, row, column): 1333 | return 0 1334 | 1335 | 1336 | 1337 | 1338 | class CustomSelectionListener(ListSelectionListener): 1339 | def __init__(self, table, request_viewer, response_viewer): 1340 | self.table = table 1341 | self.request_viewer = request_viewer 1342 | self.response_viewer = response_viewer 1343 | 1344 | def valueChanged(self, event): 1345 | if not event.getValueIsAdjusting(): 1346 | selected_row = self.table.getSelectedRow() 1347 | if selected_row != -1: 1348 | request_data = self.table.getValueAt(selected_row, 4) 1349 | response_data = self.table.getValueAt(selected_row, 5) 1350 | self.request_viewer.setMessage(request_data, True) 1351 | self.response_viewer.setMessage(response_data, True) 1352 | 1353 | 1354 | 1355 | 1356 | 1357 | # Vulnerability Table vulnerability selection autocompletion 1358 | class AutocompleteTableCellEditor(TableCellEditor): 1359 | def __init__(self, items,table3): 1360 | self.items = items 1361 | self.comboBox = JComboBox(items) 1362 | self.comboBox.setEditable(True) 1363 | AutoCompleteDecorator.decorate(self.comboBox) 1364 | self.listeners = [] 1365 | self.table3 = table3 1366 | 1367 | 1368 | def getCellEditorValue(self): 1369 | return self.comboBox.getSelectedItem() 1370 | 1371 | def getTableCellEditorComponent(self, table, value, isSelected, row, column): 1372 | self.comboBox = JComboBox(self.items) 1373 | self.comboBox.setEditable(True) 1374 | AutoCompleteDecorator.decorate(self.comboBox) 1375 | self.comboBox.setSelectedItem(value) 1376 | return self.comboBox 1377 | 1378 | def isCellEditable(self, event): 1379 | return True 1380 | 1381 | def addCellEditorListener(self, listener): 1382 | self.listeners.append(listener) 1383 | 1384 | def removeCellEditorListener(self, listener): 1385 | self.listeners.remove(listener) 1386 | 1387 | def shouldSelectCell(self, event): 1388 | return True 1389 | 1390 | def stopCellEditing(self): 1391 | selected_value = self.comboBox.getSelectedItem() 1392 | selected_row = self.table3.convertRowIndexToModel(self.table3.getEditingRow()) 1393 | selected_column = self.table3.convertColumnIndexToModel(self.table3.getEditingColumn()) 1394 | self.table3.getModel().setValueAt(selected_value, selected_row, selected_column) 1395 | 1396 | return True 1397 | 1398 | def cancelCellEditing(self): 1399 | return True 1400 | 1401 | 1402 | 1403 | class RowData: 1404 | def __init__(self, url="", parameters="", vulnerability="", severity="", request="", response=""): 1405 | self.url = url 1406 | self.parameters = parameters 1407 | self.vulnerability = vulnerability 1408 | self.severity = severity 1409 | self.request = request 1410 | self.response = response 1411 | 1412 | 1413 | 1414 | class CustomTableModelVuln(AbstractTableModel): 1415 | def __init__(self, extender): 1416 | self.vulndata = extender._vuln 1417 | self.callbacks = extender.callbacks 1418 | 1419 | 1420 | def getRowCount(self): 1421 | try: 1422 | return len(self.vulndata) 1423 | except: 1424 | return 0 1425 | 1426 | 1427 | def getColumnCount(self): 1428 | return 6 1429 | 1430 | def getColumnName(self, columnIndex): 1431 | if columnIndex == 0: 1432 | return "URL" 1433 | if columnIndex == 1: 1434 | return "Parameters" 1435 | if columnIndex == 2: 1436 | return "Vulnerability" 1437 | if columnIndex == 3: 1438 | return "Severity" 1439 | if columnIndex == 4: 1440 | return "Request" 1441 | if columnIndex == 5: 1442 | return "Response" 1443 | return "" 1444 | 1445 | 1446 | def getValueAt(self, rowIndex, columnIndex): 1447 | if rowIndex < self.getRowCount() and columnIndex < self.getColumnCount(): 1448 | vulnEntry = self.vulndata[rowIndex] 1449 | 1450 | if columnIndex == 0: 1451 | return vulnEntry.url 1452 | elif columnIndex == 1: 1453 | return vulnEntry.parameters 1454 | elif columnIndex == 2: 1455 | return vulnEntry.vulnerability 1456 | elif columnIndex == 3: 1457 | return vulnEntry.severity 1458 | elif columnIndex == 4: 1459 | return vulnEntry.request 1460 | elif columnIndex == 5: 1461 | return vulnEntry.response 1462 | 1463 | 1464 | def getColumnClass(self, col): 1465 | return str 1466 | 1467 | def isCellEditable(self, row, col): 1468 | return True 1469 | 1470 | def setValueAt(self, value, row, col): 1471 | rowData = self.vulndata[row] 1472 | if col == 0: 1473 | rowData.url = value 1474 | elif col == 1: 1475 | rowData.parameters = value 1476 | elif col == 2: 1477 | rowData.vulnerability = value 1478 | elif col == 3: 1479 | rowData.severity = value 1480 | elif col == 4: 1481 | rowData.request = value 1482 | elif col == 5: 1483 | rowData.response = value 1484 | self.fireTableCellUpdated(row, col) 1485 | 1486 | 1487 | 1488 | def setValueAt(self, value, rowIndex, columnIndex): 1489 | 1490 | if rowIndex < self.getRowCount() and columnIndex == 1: 1491 | vulEntry = self.vulndata[rowIndex] 1492 | vulEntry.parameters = value 1493 | 1494 | if rowIndex < self.getRowCount() and columnIndex == 2: 1495 | vulEntry = self.vulndata[rowIndex] 1496 | vulEntry.vulnerability = value 1497 | 1498 | if rowIndex < self.getRowCount() and columnIndex == 3: 1499 | vulEntry = self.vulndata[rowIndex] 1500 | vulEntry.severity = value 1501 | else: 1502 | self.callbacks.printError("Table is empty") 1503 | 1504 | def addRow(self, obj): 1505 | row_data = RowData(*obj) 1506 | self.vulndata.append(row_data) 1507 | self.fireTableRowsInserted(len(self.vulndata) - 1, len(self.vulndata) - 1) 1508 | 1509 | 1510 | 1511 | 1512 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pentest Mapper # 2 | 3 | Pentest Mapper is a Burp Suite extension that integrates the Burp Suite request logging with a custom application testing checklist. The extension provides a straightforward flow for application penetration testing. The extension includes functionalities to allow users to map the flow of the application for pentesting to better analyse the application and its vulnerabilities. The API calls from each flow can be connected with the function or flow name. The extension allows users to map or connect each flow or API to vulnerability with the custom checklist. 4 | 5 | # Installation 6 | 7 | - Extension is available on Burp Suite BApp Store 8 | 9 | # Documentation 10 | 11 | https://anof-cyber.github.io/Pentest-Mapper/ 12 | 13 | # Features Summary 14 | **1. Checklist** 15 | 16 | Allows to load the custom checklist 17 | 18 | **2. API Mapper** 19 | 20 | Allow to keep track of each API call, Flow and Test Cases for each API calls. 21 | 22 | **3. Vulnerability** 23 | 24 | Allows to keep track of vulnerabilities, Map each paramter and API call to vulnerability from the Checklist and severity 25 | 26 | **4. Config** 27 | 28 | Allow to set Auto save the project or extension data and auto load the checklist. Also import and export all data with one click 29 | 30 | 31 | 32 | # Features 33 | 34 | **1. Checklist** 35 | 36 | The checklist allows users to create or upload the custom checklist to map each API call to the vulnerability from the custom uploaded checklist. 37 | 38 | ![picture](./images/CheckList.png) 39 | 40 | 41 | **2. API Mapper** 42 | 43 | The API Mapper tab allows logging the HTTP request from the poxy or repeater tab and mapping the request with the flow and sorting the request based on the flow. Also, the tab allows users to write the comment or test cases for each API call logged into the extension. The tab allows mapping each API with the vulnerability from the checklist. 44 | 45 | ![picture](./images/APIMapper.png) 46 | 47 | ![picture](./images/APIMapper2.png) 48 | 49 | 50 | **3. Vulnerabilities** 51 | 52 | The tab stores the URL and parameters and allows users to map the selected API to the vulnerabilities. 53 | 54 | ![picture](./images/Vulnerability-selection.png) 55 | ![picture](./images/severity.png) 56 | 57 | **4. Config** 58 | 59 | The config tab allow you to set time for auto save after specific time peried and select the output location. You can also set the auto load the checklist file and Import and export data with one click. You can also turn on off the Auto Save and Auto Logging request from proxy for scope domain 60 | 61 | ![picture](./images/Config.png) 62 | 63 | **Sending Request** 64 | 65 | ![picture](./images/Sendreq.png) 66 | 67 | ___ 68 | 69 | # TBD 70 | 71 | * ~~Single Click Import and Export~~ 72 | * ~~Auto Save the project Data~~ 73 | * ~~Auto Logging Scope APIs and requests with Optional mode~~ 74 | * ~~Seach option for all 3 tables to manage long table~~ 75 | * ~~Solving long checklist selection from vulnerability~~ 76 | * ~~Updating checklist file automatically~~ 77 | * ~~Map Vulnerabilities with Severity~~ 78 | * Custom and Default CVSS score generation 79 | * Multiple row selection for API Mapper 80 | * ~~Turn on off auto save from config~~ 81 | * ~~Optimization of code~~ 82 | * ~~Allowing individual request to mark as completed~~ 83 | * ~~Allowing Request and Response for Vulnerability~~ 84 | 85 | -------------------------------------------------------------------------------- /images/APIMapper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/images/APIMapper.png -------------------------------------------------------------------------------- /images/APIMapper2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/images/APIMapper2.png -------------------------------------------------------------------------------- /images/CheckList.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/images/CheckList.png -------------------------------------------------------------------------------- /images/Config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/images/Config.png -------------------------------------------------------------------------------- /images/Sendreq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/images/Sendreq.png -------------------------------------------------------------------------------- /images/Vulnerability-selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/images/Vulnerability-selection.png -------------------------------------------------------------------------------- /images/proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/images/proxy.png -------------------------------------------------------------------------------- /images/severity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/images/severity.png -------------------------------------------------------------------------------- /images/tt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /lib/swingx-all-1.6.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/lib/swingx-all-1.6.4.jar -------------------------------------------------------------------------------- /pentestmapper/APIMapper.py: -------------------------------------------------------------------------------- 1 | from javax.swing import JTable 2 | from java.lang import Integer, String 3 | from javax.swing.table import AbstractTableModel 4 | 5 | 6 | #logger entry <- Class based python list to store the data for API Mapper tab/tabble 7 | class LogEntry: 8 | def __init__(self, sr, url, method, postbody, requestResponse, FunctionalityName, TestCases, response, status): 9 | self._sr = sr 10 | self._url = url 11 | self._method = method 12 | self._postbody = postbody 13 | self._requestResponse = requestResponse 14 | self._FunctionalityName = FunctionalityName 15 | self._TestCases = TestCases 16 | self._response = response 17 | self._status = status 18 | 19 | 20 | 21 | # Extedning the JTable for API Mapper TaB 22 | class Table(JTable): 23 | def __init__(self, extender,tablemodel): 24 | self._extender = extender 25 | self.setModel(tablemodel) 26 | self.setRowSelectionAllowed(True) 27 | self.setAutoCreateRowSorter(True) 28 | 29 | def getColumnClass(self, column): 30 | columnClasses = [Integer, String, String, String, String,String] 31 | return columnClasses[column] 32 | 33 | # Only last colum is allowed for editing 34 | def isCellEditable(self, row, column): 35 | if column == 4 or 5: 36 | return 1 37 | else: 38 | return 0 39 | 40 | # function that will change the request and test case for selected row 41 | def changeSelection(self, row, col, toggle, extend): 42 | self.modelRowIndex = self.convertRowIndexToModel(row) 43 | self._extender._currentlySelectedLogTableRow = self.modelRowIndex 44 | logEntry = self._extender._log[int(self.modelRowIndex)] 45 | self._extender.requestViewer.setMessage( 46 | logEntry._requestResponse, True) 47 | self._extender.responseViewer.setMessage( 48 | logEntry._response, True) 49 | text = logEntry._TestCases 50 | self._extender.testcases.setText(logEntry._TestCases) 51 | self._extender._currentlyDisplayedItem = logEntry._requestResponse 52 | JTable.changeSelection(self, row, col, toggle, extend) 53 | 54 | 55 | 56 | 57 | 58 | 59 | class CustomTableModel(AbstractTableModel): 60 | 61 | def __init__(self, extender): 62 | self._log = extender._log 63 | self.callbacks = extender.callbacks 64 | #self.logTable = extender.logTable 65 | 66 | # part of custom table model to get total number of row in the table, it will check the data in the list amd will return when called 67 | def getRowCount(self): 68 | try: 69 | return len(self._log) 70 | except: 71 | return 0 72 | 73 | # this is required to work with AbstractTableModel, this will show return the total columns in API Mapper 74 | def getColumnCount(self): 75 | return 6 76 | 77 | # this is required to work with AbstractTableModel, this will show the columns Name for API Mapper table 78 | def getColumnName(self, columnIndex): 79 | if columnIndex == 0: 80 | return "SR" 81 | if columnIndex == 1: 82 | return "URL" 83 | if columnIndex == 2: 84 | return "Method" 85 | if columnIndex == 3: 86 | return "Post Body" 87 | if columnIndex == 4: 88 | return "Functionality Name" 89 | if columnIndex == 5: 90 | return "Status" 91 | return "" 92 | 93 | # this is required to work with AbstractTableModel, this will show the data in the columns from the list for API Mapper table 94 | def getValueAt(self, rowIndex, columnIndex): 95 | #self.totalrow = self.logTable.getRowCount() 96 | if rowIndex < self.getRowCount() and columnIndex < self.getColumnCount(): 97 | logEntry = self._log[rowIndex] 98 | if columnIndex == 0: 99 | return str(rowIndex + 1) 100 | if columnIndex == 1: 101 | return logEntry._url 102 | if columnIndex == 2: 103 | return logEntry._method 104 | if columnIndex == 3: 105 | return logEntry._postbody 106 | if columnIndex == 4: 107 | return logEntry._FunctionalityName 108 | if columnIndex == 5: 109 | return logEntry._status 110 | return "" 111 | else: 112 | self.callbacks.printError("Table is empty") 113 | 114 | ''' 115 | part of custom table for api mapper, it will get the edited value from function column and will save it in the class based list 116 | for the selected row 117 | 118 | ''' 119 | def setValueAt(self, value, rowIndex, columnIndex): 120 | 121 | if rowIndex < self.getRowCount() and columnIndex == 4: 122 | logEntry = self._log[rowIndex] 123 | logEntry._FunctionalityName = value 124 | 125 | if rowIndex < self.getRowCount() and columnIndex == 5: 126 | logEntry = self._log[rowIndex] 127 | logEntry._status = value 128 | 129 | 130 | else: 131 | self.callbacks.printError("Table is empty") 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /pentestmapper/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anof-cyber/Pentest-Mapper/e519f144738bdebae4a6e3597324489649ca186c/pentestmapper/__init__.py -------------------------------------------------------------------------------- /pentestmapper/autolog.py: -------------------------------------------------------------------------------- 1 | from burp import IProxyListener 2 | 3 | from pentestmapper.APIMapper import LogEntry 4 | 5 | # Class to handle auto log requests from proxy 6 | class Autologclas(IProxyListener): 7 | def __init__(self,handlingoutput): 8 | self._handlingoutput = handlingoutput 9 | #self._handlingoutput.callbacks.registerHttpListener(self) 10 | 11 | 12 | def processProxyMessage(self,messageIsRequest, message): 13 | 14 | if self._handlingoutput.Autologcheck == True: 15 | if not messageIsRequest: 16 | if self._handlingoutput.callbacks.isInScope(self._handlingoutput.helpers.analyzeRequest(message.getMessageInfo()).getUrl()): 17 | 18 | req = self._handlingoutput.helpers.analyzeRequest(message.getMessageInfo()) 19 | self.url = self._handlingoutput.helpers.analyzeRequest(message.getMessageInfo()).getUrl() 20 | response = message.getMessageInfo().getResponse() 21 | responseInfo = self._handlingoutput.helpers.analyzeResponse(response) 22 | 23 | # Find out if image 24 | self.responsetype = responseInfo.getInferredMimeType() 25 | self.responsetype2 = responseInfo.getStatedMimeType() 26 | self.exludelist = self._handlingoutput.Excludefiletextfield.getText().split(",") 27 | 28 | if (self.responsetype.upper() not in self.exludelist) and (self.responsetype2.upper() not in self.exludelist): 29 | #if self.responsetype.upper() not in self.exludelist: 30 | 31 | self.method = req.getMethod() 32 | self.requestinst = self._handlingoutput.helpers.bytesToString(message.getMessageInfo().getRequest()) 33 | getody = req.getBodyOffset() 34 | self.body = self.requestinst[getody:len(self.requestinst)] 35 | self.responseinst = self._handlingoutput.helpers.bytesToString(message.getMessageInfo().getResponse()) 36 | rowss = self._handlingoutput.logTable.getRowCount() 37 | self.sr2 = str((rowss + 1)) 38 | 39 | self._handlingoutput._lock.acquire() 40 | row = len(self._handlingoutput._log) 41 | self._handlingoutput._log.append(LogEntry(self.sr2, self.url, self.method, self.body, self.requestinst, '', '', self.responseinst,'')) 42 | self._handlingoutput.fireTableRowsInserted(row, row) 43 | self._handlingoutput._lock.release() 44 | 45 | else: 46 | self._handlingoutput.callbacks.removeProxyListener(self) 47 | -------------------------------------------------------------------------------- /pentestmapper/autosave.py: -------------------------------------------------------------------------------- 1 | from threading import Thread, Event 2 | import os 3 | import csv, zlib,time 4 | import base64 5 | 6 | 7 | ##Class to handle auto save 8 | class Autosaveclas(Thread): 9 | def __init__(self,handlingoutput): 10 | self._handlingoutput = handlingoutput 11 | 12 | Thread.__init__(self) 13 | self._stop = Event() 14 | 15 | def run(self): 16 | 17 | #self._handlingoutput = handlingoutput 18 | while not self.stopped(): 19 | if self._handlingoutput.Autosavechecker == True: 20 | 21 | if os.path.isdir(str(self._handlingoutput.path)): 22 | 23 | if self._handlingoutput.logTable.getRowCount() > 0: 24 | #self.path = fileLoad.getPath() 25 | fname = "APIMapper"+"."+"csv" 26 | fnameWithPath = os.path.join(self._handlingoutput.path,fname) 27 | if os.path.exists(fnameWithPath): 28 | os.remove(fnameWithPath) 29 | self._handlingoutput.callbacks.printOutput("Saving the API Mapper output") 30 | with open(fnameWithPath, 'wb') as loggerdata: 31 | writer = csv.writer(loggerdata) 32 | for logEntry in self._handlingoutput._log: 33 | writer.writerow([str(logEntry._sr), str(logEntry._url) ,str(logEntry._method) , base64.b64encode(zlib.compress(logEntry._postbody.encode('utf-8'))) ,str(logEntry._FunctionalityName) , base64.b64encode(zlib.compress(logEntry._requestResponse.encode('utf-8'))) ,str(logEntry._TestCases), base64.b64encode(zlib.compress(logEntry._response.encode('utf-8'))) ,str(logEntry._status)]) 34 | 35 | loggerdata.close() 36 | else: 37 | self._handlingoutput.callbacks.printOutput("Skipping the API Mapper, Table is empty") 38 | if self._handlingoutput.dataModel2.getRowCount() > 0: 39 | fname2 = "Vulnerability"+"."+"csv" 40 | fnameWithPath2 = os.path.join(self._handlingoutput.path,fname2) 41 | if os.path.exists(fnameWithPath2): 42 | os.remove(fnameWithPath2) 43 | self._handlingoutput.callbacks.printOutput("Saving the Vulnerability output") 44 | totalrow = self._handlingoutput.dataModel2.getRowCount() 45 | with open(fnameWithPath2, 'wb') as vulnerabilitydata: 46 | writer = csv.writer(vulnerabilitydata) 47 | for row in range (0, totalrow): 48 | url = self._handlingoutput.dataModel2.getValueAt(row,0) 49 | paramter = self._handlingoutput.dataModel2.getValueAt(int(row),1) 50 | Vulnerability = self._handlingoutput.dataModel2.getValueAt(int(row),2) 51 | Severity = self._handlingoutput.dataModel2.getValueAt(int(row),3) 52 | Request = self._handlingoutput.dataModel2.getValueAt(int(row),4) 53 | Response = self._handlingoutput.dataModel2.getValueAt(int(row),5) 54 | #self.callbacks.printOutput(str(url)) 55 | 56 | #self.callbacks.printOutput(str(logEntry._sr)) 57 | writer.writerow([str(url), str(paramter) ,str(Vulnerability),str(Severity),base64.b64encode(zlib.compress(Request.encode('utf-8'))),base64.b64encode(zlib.compress(Response.encode('utf-8')))]) 58 | vulnerabilitydata.close() 59 | else: 60 | self._handlingoutput.callbacks.printOutput("Skipping the Vulnerability, Table is empty") 61 | else: 62 | self._handlingoutput.autosavepath.setText("Output Directory doesn't exist") 63 | time.sleep(int(self._handlingoutput.time) * 60) 64 | 65 | def stop(self): 66 | self._stop.set() 67 | 68 | def stopped(self): 69 | return self._stop.isSet() --------------------------------------------------------------------------------