Giter Site home page Giter Site logo

blacklanternsecurity / writehat Goto Github PK

View Code? Open in Web Editor NEW
1.2K 29.0 224.0 16.09 MB

A pentest reporting tool written in Python. Free yourself from Microsoft Word.

License: GNU General Public License v3.0

Python 40.56% CSS 16.98% JavaScript 27.09% HTML 15.38%

writehat's Introduction

WriteHat WriteHat is a reporting tool which removes Microsoft Word (and many hours of suffering) from the reporting process. Markdown --> HTML --> PDF. Created by penetration testers, for penetration testers - but can be used to generate any kind of report. Written in Django (Python 3).

Features:

  • Effortlessly generate beautiful pentest reports
  • On-the-fly drag-and-drop report builder
  • Markdown support - including code blocks, tables, etc.
  • Crop, annotate, caption, and upload images
  • Customizable report background / footer
  • Assign operators and track statuses for individual report sections
  • Ability to clone and template reports
  • Findings database
  • Supports multiple scoring types (CVSS 3.1, DREAD)
  • Can easily generate multiple reports from the same set of findings
  • Extensible design enables power users to craft highly-customized report sections
  • LDAP integration

writehat_report

Installation Prerequisites:

  • Install docker and docker-compose
    • These can usually be installed using apt, pacman, dnf, etc.
    $ sudo apt install docker.io docker-compose
    

Deploying WriteHat (The quick and easy way, for testing):

WriteHat can be deployed in a single command:

$ git clone https://github.com/blacklanternsecurity/writehat && cd writehat && docker-compose up

Log in at https://127.0.0.1 (default: admin / PLEASECHANGETHISFORHEAVENSSAKE)

Deploying WriteHat (The right way):

  1. Install Docker and Docker Compose

  2. Clone the WriteHat Repo into /opt

    $ cd /opt
    $ git clone https://github.com/blacklanternsecurity/writehat
    $ cd writehat
    
  3. Create Secure Passwords in writehat/config/writehat.conf for:

    • MongoDB (also enter in docker-compose.yml)
    • MySQL (also enter in docker-compose.yml)
    • Django (used for encrypting cookies, etc.)
    • Admin user Note: Nothing else aside from the passwords need to be modified if you are using the default configuration Note: Don't forget to lock down the permissions on writehat/config/writehat.conf and docker-compose.yml: (chown root:root; chmod 600)
  4. Add Your Desired Hostname to allowed_hosts in writehat/config/writehat.conf

  5. (Optional) Replace the self-signed SSL certificates in nginx/:

    • writehat.crt
    • writehat.key
  6. Test That Everything's Working:

    $ docker-compose up --build
    

    Note: If using a VPN, you need to be disconnected from the VPN the first time you run bring up the services with docker-compose. This is so docker can successfully create the virtual network.

  7. Install and Activate the Systemd Service:

    This will start WriteHat automatically upon boot

    $ sudo cp writehat/config/writehat.service /etc/systemd/system/
    $ sudo systemctl enable writehat --now
    
  8. Tail the Service Logs:

    $ sudo journalctl -xefu writehat.service
    
  9. Create Users

    Browse to https://127.0.0.1/admin after logging in with the admin user specified in writehat/config/writehat.conf Note: There are some actions which only an admin can perform (e.g. database backups) An admin user is automatically created from the username and password in writehat/config/writehat.conf, but you can also promote an LDAP user to admin:

    # Enter the app container
    $ docker-compose exec writehat bash
    
    # Promote the user and exit
    $ ./manage.py ldap_promote <ldap_username>
    $ exit
    

Terminology

Here are basic explanations for some WriteHat terms which may not be obvious.

Engagement
 ├─ Customer
 ├─ Finding Group 1
 │   ├─ Finding
 │   └─ Finding
 ├─ Finding Group 2
 │   ├─ Finding
 │   └─ Finding
 ├─ Report 1
 └─ Report 2
     └─ Page Template

Engagement

An Engagement is where content is created for the customer. This is where the work happens - creating reports and entering findings.

Report

A Report is a modular, hierarchical arrangement of Components which can be easily updated via a drag-and-drop interface, then rendered into HTML or PDF. An engagement can have multiple Reports. A Page Template can be used to customize the background and footer. A Report can also be converted into a Report Template.

Report Component

A report Component is a section or module of the report that can be dragged/dropped into place inside the report creator. Examples include "Title Page", "Markdown", "Findings", etc. There are plenty of built-in components, but you can make your own as well. (They're just HTML/CSS + Python, so it's pretty easy. See the guide below)

Report Template

A Report Template can be used as a starting point for a Report (in an Engagement). Reports can also be converted to Report Templates.

Finding Group

A Finding Group is a collection of findings that are scored in the same way (e.g. CVSS or DREAD). You can create multiple finding groups per engagement (e.g. "Technical Findings" and "Treasury Findings"). When inserting the findings into the Report (via the "Findings" Component, for example), you need to select which Finding Group you want to populate that Component.

Page Template

A Page Template lets you customize report background images and footers. You can set one Page Template as the default, and it will be applied globally unless overridden at the Engagement or Report level.

Writing Custom Report Components

report_creation Each report component is made up of the following:

  1. A Python file in writehat/components/
  2. An HTML template in writehat/templates/componentTemplates/
  3. A CSS file in writehat/static/css/component/ (optional)

We recommend referencing the existing files in these directories; they work well as starting points / examples.

A simple custom component would look like this:

components/CustomComponent.py:

from .base import *

class CustomComponentForm(ComponentForm):

    summary = forms.CharField(label='Component Text', widget=forms.Textarea, max_length=50000, required=False)
    field_order = ['name', 'summary', 'pageBreakBefore', 'showTitle']


class Component(BaseComponent):

    default_name = 'Custom Report Component'
    formClass = CustomComponentForm

    # the "templatable" attribute decides whether or not that field
    # gets saved if the report is ever converted into a template
    fieldList = {
        'summary': StringField(markdown=True, templatable=True),
    }

    # make sure to specify the HTML template
    htmlTemplate = 'componentTemplates/CustomComponent.html'

    # Font Awesome icon type + color (HTML/CSS)
    # This is just eye candy in the web app
    iconType = 'fas fa-stream'
    iconColor = 'var(--blue)'

    # the "preprocess" function is executed when the report is rendered
    # use this to perform any last-minute operations on its data
    def preprocess(self, context):

        # for example, to uppercase the entire "summary" field:
        #   context['summary'] = context['summary'].upper()
        return context

Note that fields must share the same name in both the component class and its form. All components must either inherit from BaseComponent or another component. Additionally, each component has built-in fields for name, pageBreakBefore (whether to start on a new page), and showTitle (whether or not to display the name field as a header). So it's not necessary to add those.

componentTemplates/CustomComponent.html:

Fields from the Python module are automatically added to the template context. In this example, we want to render the summary field as markdown, so we add the markdown tag in front of it. Note that you can also access engagement and report-level variables, such as report.name, report.findings, engagement.customer.name, etc.

{% load custom_tags %}
<section class="l{{ level }} component{% if pageBreakBefore %} page-break{% endif %}" id="container_{{ id }}">
  {% include 'componentTemplates/Heading.html' %}
  <div class='markdown-align-justify custom-component-summary'>
    <p>
      {% markdown summary %}
    </p>
  </div>
</section>

componentTemplates/CustomComponent.css (optional):

The filename must match that of the Python file (but with a .css extension instead of .py). It is loaded automatically when the report is rendered.

div.custom-component-summary {
    font-weight: bold;
}

Once the above files are created, simply restart the web app and it the new component will populate automatically.

$ docker-compose restart writehat

Manual DB Update/Migration

If an update is pushed that changes the database schema, Django database migrations are executed automatically when the container is restarted. However, user interaction may sometimes be required. To apply Django migrations manually:

  1. Stop WriteHat (systemctl stop writehat)
  2. cd into the WriteHat directory (/opt/writehat)
  3. Start the docker container
$ docker-compose run writehat bash
  1. Once in the container, apply the migrations as usual:
$ ./manage.py makemigrations
$ ./manage.py migrate
$ exit
  1. Bring down the docker containers and restart the service
$ docker-compose down
$ systemctl start writehat

Manual DB Backup/Restore

Note that there is already in-app functionality for this in the /admin page of the web app. You can use this method if you want to make a file-level backup job via cron, etc.

  1. On the destination system:
    • Follow normal installation steps
    • Stop WriteHat (systemctl stop writehat)
  2. On the source system:
    • Stop WriteHat (systemctl stop writehat)
  3. TAR up the mysql, mongo, and writehat/migrations directories and copy the archive to the destination system (same location):
# MUST RUN AS ROOT
$ sudo tar --same-owner -cvzpf db_backup.tar.gz mongo mysql writehat/migrations
  1. On the destination system, make a backup of the migrations directory
$ mv writehat/migrations writehat/migrations.bak
  1. Extract the TAR archive on the destination
$ sudo tar --same-owner -xvpzf db_backup.tar.gz
  1. Start WriteHat on the new system
$ systemctl start writehat

Roadmap / Potential Future Developments:

  • Change tracking and revisions
  • More in-depth review/feedback functionality
  • Collaborative multi-user editing similar to Google Docs
  • JSON export feature
  • Presentation slide generation
  • More advanced table creator with CSV upload feature
  • More granular permissions / ACLs (beyond just user + admin roles)

Known Bugs / Limitations:

  • Chrome or Chromium is the recommended browser. Others are untested and may experience bugs.
  • "Assignee" field on report components only works with LDAP users, not local ones.
  • Annotations on images sometimes jump slightly when applied. It's a known bug that we're tracking with the JS library: ailon/markerjs#40
  • Visual bugs appear occasionally on page breaks. These can be fixed by manually inserting a page break in the affected markdown (there's a button for it in the editor).

writehat's People

Contributors

aconite33 avatar buildanddestroy avatar cguiraudou avatar kerrymilan avatar r3vn avatar simongurney avatar thejohnbrown avatar thetechromancer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

writehat's Issues

Session timeout

Please can we have functionality to set a session timeout

Findings in TOC

Hi :)
Imho every Finding should automatically be a children of Findings in the TOC( Like this:
3.Findings
  3.1 Finding 1
  3.2 Finding 2
  3.3 Finding 3
)
, so one gets an overview of the findings even by just looking at the TOC.

Could you give me a hint on how I could implement this in the fastest & easiest way ?

Thank you and best regards

connection issue to mysql

I keep getting django.db.utils.OperationalError: (2003, "Can't connect to MySQL server on '127.0.0.1' ([Errno 111] Connection refused)")

I have changed 'mysql' to '127.0.0.1' in the writehat.conf file to try and fix the issue but I get this error either way.

The connection failure happens in the socket.py file

Multilingual findings

Ref. Ghostwriter #130

Another critical feature is having a Multilingual vulnerability database (findings library).

Pentesters from english-speaking countries are maybe the only ones that doesn't need this feature.
But in countries you will need to have a findings library in both English and your native language and some countries also have 2, 3 or more official languages.

PwnDoc is a similar project with Multilingual findings enabled if you need an idea of architecture.

Change font

Hi,
I thought changing the font would be possible in print.css since the font size can also be changed here, but neither changing the preferred font-family changes the font of the html body nor does it work to only specify the wanted font-family.
Only changing it to generic families like sans-serif, monospace etc. works but changing the standard font for these generic families for the browser or the system does not change the used font for these generic families.

Are there any extra steps needed to change the font ?
(Adding the fonts as .otf or .woff to the writehat/writehat/static/admin/fonts folder does not solve this issue either)

Thank you in advance and kind regards :)

unable to start service

On step #7 after copying the writehat.service over to /etc/systemd/system and run sudo systemctl enable writehat --now, I ran service --status-all and writehat.service does not show up. also i have reboot and writehat.service is not started even after service start writehat.service which says unrecognized service.
image

Add support for SAML/OpenID Connect

A lot of companies are moving to SAML or OpenID Connect based authentication for their apps. It allows for use of 2FA, client compliance, security by end-user apps not even passing passwords, etc.

Do you think it would be possible to support at least OpenID Connect through an OAuth library?

Unable to remove uploaded figures from finding

When you add figures to a finding using the "Figures" button on top-right you can't delete them later on.
I added 3 figures like that and now want to remove them again. I click the red "X" on every figure and they disappear from the list.
After saving and reloading, or going back and reentering the finding, the figures are all there again.

Now i have 3 figures printing after my finding which i am unable to remove.

Edit: I am testing on the "quick and dirty" docker-compose up with all default settings

Build Issues with Custom Password Configurations

I've been trying to customize the passwords set in the writehat.conf and docker-compose.yml and run into two behaviors that I can't seem to track down.

  1. Updating the SQL or MongoDB password
    Updating the SQL and/or MongoDB password in writehat.conf and docker-compose.yml causes the build to error out and the writehat container just endlessly restarts with an access denied
    image

After adding a print to the manage.py script I can see it's failing on the first run of the manage.py (manage.py makemigrations writehat).

  1. Assuming I don't change the SQL or MongoDB password and the build finishes the admin_password change in writehat.conf is never reflected in the application. Whatever I put there in the writehat.conf file the password remains the default from the oneliner setup. If I change the admin_username to something like 'superuser' and the admin_password a new admin is created with the custom username/password but the default admin is also still created with the default password.
    image

The only way it seems to change the default admin password is within the application itself after initial setup. If this is working as intended then it should be reflected in the setup/install notes.

Manual file level backup not working

Restoring from a backup created from tarring up the mongo mysql and writehat/migrations folders doesn't seem to work, unless i'm doing something wrong. I created a backup of the folders, made changes to my current application i.e. deleted a report and then tested restoring from this backup by just extracting over the top of my current install. When I went back into the application I could see that the previously deleted report was now restored, however when clicking on the report it would return a 500 error in the browser.

Steps to reproduce (basically as you have described in the README):

  1. Stop the service systemctl stop writehat
  2. Backup the files sudo tar --same-owner -cvzpf db_backup.tar.gz mongo mysql writehat/migrations
  3. Backup writehat/migrations mv writehat/migrations writehat/migrations.bak
  4. Delete a report in the application
  5. Restore from the backup sudo tar --same-owner -xvpzf db_backup.tar.gz
  6. Start the service again systemctl start writehat

You'll see that the report has been restored but clicking on it returns a 500 status code.

create Reporting Templates error

Hey guys,
I´ve set WH up as written in the README.
When trying to create a new Report Template (btw. the first), we get an Server Error 500.
Also the Admin-Tools link is dead (not found). Any suggestions?

Fresh installed WH on debian 10.9

writehat_1 | 2021-04-09 14:10:17 - DEBUG - views.py: 1260 - enagagementsList (GET) called writehat_1 | [pid: 35|app: 0|req: 7/21] 172.30.0.132 () {46 vars in 843 bytes} [Fri Apr 9 14:10:17 2021] GET /engagements => generated 10639 bytes in 13 msecs (HTTP/1.1 200) 7 headers in 350 bytes (1 switches on core 0) writehat_1 | [pid: 33|app: 0|req: 9/22] 172.30.0.132 () {48 vars in 879 bytes} [Fri Apr 9 14:10:17 2021] GET /validation/whitelists => generated 745 bytes in 7 msecs (HTTP/1.1 200) 6 headers in 172 bytes (1 switches on core 0) writehat_1 | [pid: 35|app: 0|req: 8/23] 172.30.0.132 () {46 vars in 838 bytes} [Fri Apr 9 14:13:30 2021] GET /templates => generated 12763 bytes in 47 msecs (HTTP/1.1 200) 7 headers in 350 bytes (1 switches on core 0) writehat_1 | [pid: 35|app: 0|req: 9/24] 172.30.0.132 () {48 vars in 877 bytes} [Fri Apr 9 14:13:31 2021] GET /validation/whitelists => generated 745 bytes in 7 msecs (HTTP/1.1 200) 6 headers in 172 bytes (1 switches on core 0) writehat_1 | 2021-04-09 14:13:46 - DEBUG - views.py: 1726 - templateNew called; writehat_1 | 2021-04-09 14:13:46 - ERROR - log.py: 224 - Internal Server Error: /templates/new writehat_1 | Traceback (most recent call last): writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/core/handlers/exception.py", line 47, in inner writehat_1 | response = get_response(request) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/core/handlers/base.py", line 181, in _get_response writehat_1 | response = wrapped_callback(request, *callback_args, **callback_kwargs) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/views/decorators/http.py", line 40, in inner writehat_1 | return func(request, *args, **kwargs) writehat_1 | File "./writehat/views.py", line 1728, in templateNew writehat_1 | return render( writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/shortcuts.py", line 19, in render writehat_1 | content = loader.render_to_string(template_name, context, request, using=using) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/loader.py", line 62, in render_to_string writehat_1 | return template.render(context, request) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/backends/django.py", line 61, in render writehat_1 | return self.template.render(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 170, in render writehat_1 | return self._render(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 162, in _render writehat_1 | return self.nodelist.render(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 938, in render writehat_1 | bit = node.render_annotated(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 905, in render_annotated writehat_1 | return self.render(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/loader_tags.py", line 150, in render writehat_1 | return compiled_parent._render(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 162, in _render writehat_1 | return self.nodelist.render(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 938, in render writehat_1 | bit = node.render_annotated(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 905, in render_annotated writehat_1 | return self.render(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/loader_tags.py", line 62, in render writehat_1 | result = block.nodelist.render(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 938, in render writehat_1 | bit = node.render_annotated(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 905, in render_annotated writehat_1 | return self.render(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/loader_tags.py", line 195, in render writehat_1 | return template.render(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 172, in render writehat_1 | return self._render(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 162, in _render writehat_1 | return self.nodelist.render(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 938, in render writehat_1 | bit = node.render_annotated(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 905, in render_annotated writehat_1 | return self.render(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 988, in render writehat_1 | output = self.filter_expression.resolve(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 671, in resolve writehat_1 | obj = self.var.resolve(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 796, in resolve writehat_1 | value = self._resolve_lookup(context) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/template/base.py", line 858, in _resolve_lookup writehat_1 | current = current() writehat_1 | File "./writehat/lib/report.py", line 67, in __init__ writehat_1 | super().__init__(*args, **kwargs) writehat_1 | File "./writehat/models.py", line 63, in __init__ writehat_1 | super().__init__(*args, **kwargs) writehat_1 | File "/usr/local/lib/python3.8/dist-packages/django/db/models/base.py", line 413, in __init__ writehat_1 | raise TypeError('Abstract models cannot be instantiated.') writehat_1 | TypeError: Abstract models cannot be instantiated. writehat_1 | [pid: 35|app: 0|req: 10/25] 172.30.0.132 () {46 vars in 844 bytes} [Fri Apr 9 14:13:46 2021] GET /templates/new => generated 145 bytes in 15 msecs (HTTP/1.1 500) 6 headers in 184 bytes (1 switches on core 0)
grafik
grafik

Package locales has no installation canidate

I am attempting to install writehat on my Kali Virtual Machine version 5.10.0-kali9-amd64 (the most updated version). After changing the passwords etc, upon running docker-compose up I get an error about packages locales and locales-all not being available but referred to by another package. Both packages are already installed on my system however. See attached screenshots. Thanks for the assistance!

info

locales installed

Background Image Dimensions

Hi,
I would like the background image to span over the entire page. I feel like this should be a oneliner, but I can't seem to find the respective parameter.
Any help would be appreciated :)

Thank you!

Export customer data to excel sheet

Hi,
I would like to include some customer data automatically in the excel sheet.
I am a novice at django so I apologize if this a stupid issue.
When trying to export customer data like this:

from writehat.lib.customer import Customer
.
.
.
cell.value = str(Customer.name)

the value in the excel sheet is: <django.db.models.query_utils.DeferredAttribute object at 0x7f41af636c70>

How do I access the data from the customer from the engagement ?

Any help would be greatly appreciated, thank you :)

WriteHat API

Hello,

I have started developing a REST API so I can integrate WriteHat with some other tooling that I use. Has anything similar to this been created internally at Black Lantern as I don't want to duplicate effort?

Thanks.

Network error when downloading PDF

When I generate a PDF report, it opens a new tab and displays the PDF, but when I try to download the PDF I get a network error. I tried using Chrome and Edge browsers and had the same result. To ensure it wasn't actually a network error, I downloaded a report from our Serpico reporting application without error. I have included a screenshot which shows successful download on the left side from Serpico. The three failures to the right of that are from WriteHat.

WriteHat Network Error

Markdown Table Alignment

Markdown tables do not properly align column content based on markdown syntax. The preview attached to the text area you enter into renders correctly, however when rendered in either the preview pane or when rendered to a document the columns are not properly aligned.

To validate, create a table like the following:

Column Name Alpha Column Name Beta Column Name Sigma
A B C

View the table in the text area preview and see that the markdown is shown correctly. Save and render the table in the preview pane and observe that the rendered table is not aligned properly.

Lower half of sentence sometimes cuts off on page breaks

There doesn't seem to be anything I can do to reliably reproduce the issue. It seems to depend on the flow of text and where it splits at the bottom of the page. I've tried adding a newline below the affected line but that didn't change anything. I have highlighted the issue in the screenshot below:

2021-01-14 15_45_58-generatePdf

Page Header

Thank you for the amazing tool!
Is there a consistent way to add a page header to a page template ?

Findings??

I just build this on my box and am navigating around. Are there no findings already in the database?? The wiki doesn't address findings at all (outside explaining finding groups) Do I need to import them from somewhere?? Surely we're not expected to enter every single finding on our own, right?

Toggle Preview on and off when editing

Please can we have a toggle to turn off the preview pane when editing an issue as it isn't required until save time and it takes up a lot of screen space.

Cannot create report template with newest version of MongoDB

Hi, I tried installing writehat today from docker-compose.yml file and I've encountered several issues. The main one was that I was not able to create report template (call failed with http code 500).

Error from docker logs: TypeError: 'Collection' object is not callable. If you meant to call the 'update' method on a 'Collection' object it is failing because no such method exists.

Once I've pulled mongo version 4.4 (or similar) and downgraded pymongo module (in requirements.txt) to version 3.11, the report template started working. Maybe you can lock versions of components to specific ones instead of the latest one.

My CPU is Intel(R) Core(TM) i5-9600K CPU @ 3.70GHz (Coffee Lake) which is a couple of generations newer than Sandy Bridge, that Mongo v5 should support.

Findings custom field

Ref. Ghostwriter #19

The findings/vulnerabilities database is powerful but is lacking of custom fields.

Examples of fields used in pentest report that are not available in the finding model that could be added as custom fields :

  • CVSS score and/or CVSS string
  • CWE
  • OWASP category, or any customer category
  • ID (a unique identifier or reference)
  • Ease of correctness (Easy, Complex, Project, etc.)
  • Priority of correction (Low, Urgent, etc.)
  • Impact Lelvel
  • Any field asked by customer, standard, norm, etc.

So having a way add custom field to the finding model is very useful, for us it's the reason why with stay with PwnDoc even if it less powerful.

In additions to custom fields, having several types of custom field would be nice, input (eg. as title), dictionary (eg. like severity), free text (eg. like description). Also some fields like a custom ID or reference would need a search feature, eg. if you want to assign an internal reference to all findings like INF-00234, WEB-00678, etc. you would like to have a search bar to see that you have already used all ID from WEB-00001 to WEB-00678, so you can create WEB-00679. Some field would also need a uniq switch, eg. CVSS score is not unique but the ID/ref must be.

Once you have several custom fields you also would like to display them in the finding library, it means be able to add columns on the table view (eg. you'd like to add a ref/ID column or CWE, etc.).

Finally, the most important part is being able to have the custom fields available in the template, for this reason I think custom fields name should be enforced to be unique and with only alphanumeric characters + space so it's easy to get {{ finding.cvss_score }} for example.

PwnDoc is a similar project with Custom field enabled if you need an idea of architecture.

/usr/bin/env: ‘python\r’: No such file or directory

When running docker-compose up on the writehat root dir the following error ends up being produced causing the writehat container to exit:

writehat_writehat_1 exited with code 127
writehat_1  | /usr/bin/env: ‘python\r’: No such file or directory

This seems to be caused by how EOL's are encoded. One fix would be to find the file causing this and doing :set ff=unix in vim.

A working solution is to run this in the root dir:

git config core.autocrlf false
git rm --cached -r .         # Don’t forget the dot at the end
git reset --hard

It would be nice to have a permanent solution baked into the repo though.

Bug when creating engagement

When creating a new engagement, if you also create a new customer at the same time it will use the name of the customer for the engagement name, instead of the actual engagement name you specified.

Feature request: additional meta tags

  • Add a {todo} tag. This tag should not display in the rendered report, but should be used to indicate in the review status or report overview page that the section requires attention.
  • Add tags for {findings.criticalCount} and {findings.highCount} for use in summary sections. Optionally scope to a specific finding group or finding type.

Subsections and Numbering

Hi,
first of all: thanks for your incredible work!

Adding subsections in a markdown with the normal ## does not add them to the Table Of Contents and they also do not get a Numbering like X.1 or X.2 etc. Is this intended or is there another way to enable that ?

Kind regards :)

Separate template for the front page?

Hello,

In the last couple of days I have been making small modifications to Writehat. I have mainly been adding a new finding type. This was not trivial as I hoped, mainly because I had to make many small modifications to finding group, engagement findings, findings, the database export and import. This part of the modifications are starting to work but the end result will remain hard to maintain. I am novice at django so that might explain why it took a few days but to me it looks like it would be nice to refactor the code to only have one type of finding group (with a finding type field?). This would remove some of the duplication but I don't know the drawback (perhaps in the database export?). Anyway... I made the modification and I am quite happy about write hat as tool. I also managed to create a script to import code annotations(We often do code review and use a tool to make the annotations) all in all .. quite nice.

I am now trying to modify the title page. I would like to add a background image to it . I am not quite sure how to tackle this. It looks like I would like to be able to select a different page template for this component but I don't understand well enough yet how the report is created. From code inspection it looks like the render method is called on all components (and a htmlTemplate) appear but I don't understand if it would be possible to select a different page template for the titlePage (or even generic Component)

The second way I can imagine is to add an image to the title page component or create my own. Any guidance on how I should modify the code to allow to add a background image to the titlepage without adding this same background to all pages?

Feature Request - Split Customer Address into Fields

When adding a customer the only option is to add a whole address into a single address string field. But this doesn't align with the Customer Information module within a report. It would be helpful to be able to separate address content (street address, state, country, provinces, zip) under the customer management portal.

Build never completes on CentOS 8 Stream

Issue during the build process on CentOS 8 Stream. It gets to this point:

writehat-writehat-1 | WSGI app 0 (mountpoint='') ready in 2 seconds on interpreter 0x55c1e8eec060 pid: 1 (default app)
writehat-writehat-1 | uWSGI running as root, you can use --uid/--gid/--chroot options
writehat-writehat-1 | *** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
writehat-writehat-1 | *** uWSGI is running in multiple interpreter mode ***
writehat-writehat-1 | spawned uWSGI master process (pid: 1)
writehat-writehat-1 | spawned uWSGI worker 1 (pid: 31, cores: 1)
writehat-writehat-1 | spawned uWSGI worker 2 (pid: 32, cores: 1)
writehat-writehat-1 | spawned uWSGI worker 3 (pid: 33, cores: 1)
writehat-writehat-1 | spawned uWSGI worker 4 (pid: 34, cores: 1)
writehat-mongo-1 | {"t":{"$date":"2022-07-04T13:19:12.023+00:00"},"s":"I", "c":"STORAGE", "id":22430, "ctx":"WTCheckpointThread","msg":"WiredTiger message","attr":{"message":"[1656940752:23169][1:0x7f9559cc8700], WT_SESSION.checkpoint: [WT_VERB_CHECKPOINT_PROGRESS] saving checkpoint snapshot min: 3, snapshot max: 3 snapshot count: 0, oldest timestamp: (0, 0) , meta checkpoint timestamp: (0, 0) base write gen: 104"}}
^CGracefully stopping... (press Ctrl+C again to force)

Ctrl + C is the only way out...

Error when importing finding from finding database

I'm getting a "Failed to import finding" error when clicking on "Import Finding" (not a specific finding, just to display the window with the list of findings in the database). The log file has the following in it:

Feb 09 10:35:30 writehat docker-compose[62764]: writehat_1  | 2021-02-09 10:35:30 - WARNING - log.py:  224 - Not Found: /engagements/fgroup/d59f3967-2e3b-40d7-afc9-4051d5e3994f/finding/import/undefined
Feb 09 10:35:30 writehat docker-compose[62764]: nginx_1     | XX.XX.XX.XXX - - [09/Feb/2021:10:35:30 +0000] "GET /engagements/fgroup/d59f3967-2e3b-40d7-afc9-4051d5e3994f/finding/import/undefined HTTP/1.1" 404 179 "https://writehat/engagements/fgroup/d59f3967-2e3b-40d7-afc9-4051d5e3994f/finding/new" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0" "-"
Feb 09 10:35:30 writehat docker-compose[62764]: writehat_1  | [pid: 31|app: 0|req: 385/1153] XX.XX.XX.XXX () {50 vars in 1138 bytes} [Tue Feb  9 10:35:30 2021] GET /engagements/fgroup/d59f3967-2e3b-40d7-afc9-4051d5e3994f/finding/import/undefined => generated 179 bytes in 17 msecs (HTTP/1.1 404) 6 headers in 172 bytes (1 switches on core 0)

All element titles clickable to launch edit.

Hi. Please can we have functionality to make all element titles clickable to launch edit.

Report > Page Template View (list of elements comprising current report under edit e.g. https:///engagements/report//edit )
Make element title (e.g. "Title Page") launchable via double click instead of being required to click the edit icon.

Revision history doesn't work for custom components.

Hello,

I have noticed that the revision history feature does not work for custom components. For example, I have a custom component called Conclusion which is essentially just a two text fields, one for the title and one for the main text. If I make changes to this component and click on the revision history button, it won't have created a new revision and instead just says "Current Text".

Cheers.

Tables within findings

image

I have a finding where it makes more sense for the Affected Resources to be in a table so to include other information relating to where this was found in the host, however putting in a table results in the contents of cells pushing over into the margin. I had this issue with another finding, but it was growing very large and I added the Affected Hosts to an appendix. This will likely come up a lot for web app related findings.

The table also formats like this if I add a table to any other component besides a "Table" component of the report. A lot the fluff sections of my report template are "Table" components because those tables are actually pretty:
image

Selenium docker not working with attached docker-compose

With the attached docker-compose the Selenium docker throws the following when trying to generate a PDF report. This could be my config, but just wanted to check.

chrome_1    | 2020-12-02 17:31:50,549 INFO Included extra file "/etc/supervisor/conf.d/selenium.conf" during parsing
chrome_1    | 2020-12-02 17:31:50,556 INFO supervisord started with pid 8
chrome_1    | 2020-12-02 17:31:51,560 INFO spawned: 'xvfb' with pid 11
chrome_1    | 2020-12-02 17:31:51,563 INFO spawned: 'selenium-standalone' with pid 12
chrome_1    | 2020-12-02 17:31:52,564 INFO success: xvfb entered RUNNING state, process has stayed up for > than 0 seconds (startsecs)
chrome_1    | 2020-12-02 17:31:52,564 INFO success: selenium-standalone entered RUNNING state, process has stayed up for > than 0 seconds (startsecs)
chrome_1    | 17:32:22.356 INFO [GridLauncherV3.parse] - Selenium server version: 3.141.59, revision: e82be7d358
chrome_1    | 17:32:24.024 INFO [GridLauncherV3.lambda$buildLaunchers$3] - Launching a standalone Selenium Server on port 4444
chrome_1    | 2020-12-02 17:32:24.932:INFO::main: Logging initialized @28990ms to org.seleniumhq.jetty9.util.log.StdErrLog
chrome_1    | 17:32:28.782 INFO [WebDriverServlet.<init>] - Initialising WebDriverServlet
chrome_1    | 17:32:30.011 INFO [SeleniumServer.boot] - Selenium Server is up and running on port 4444
chrome_1    | 17:34:40.803 INFO [ActiveSessionFactory.apply] - Capabilities are: {
chrome_1    |   "browserName": "chrome",
chrome_1    |   "goog:chromeOptions": {
chrome_1    |     "extensions": [
chrome_1    |     ],
chrome_1    |     "args": [
chrome_1    |       "--disable-extensions",
chrome_1    |       "--headless",
chrome_1    |       "--no-sandbox",
chrome_1    |       "--disable-dev-shm-usage",
chrome_1    |       "--ignore-certificate-errors",
chrome_1    |       "--allow-running-insecure-content"
chrome_1    |     ]
chrome_1    |   },
chrome_1    |   "version": ""
chrome_1    | }
chrome_1    | 17:34:40.806 INFO [ActiveSessionFactory.lambda$apply$11] - Matched factory org.openqa.selenium.grid.session.remote.ServicedSession$Factory (provider: org.openqa.selenium.chrome.ChromeDriverService)
chrome_1    | Starting ChromeDriver 87.0.4280.20 (c99e81631faa0b2a448e658c0dbd8311fb04ddbd-refs/branch-heads/4280@{#355}) on port 27724
chrome_1    | Only local connections are allowed.
chrome_1    | Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
chrome_1    | ChromeDri[1v6e0r6 9w3a0s4 8s1t.a0r4t2e]d[ SsEuVcEcReEs]s:f ublilnyd.(
chrome_1    | ) failed: Cannot assign requested address (99)
chrome_1    | 17:34:43.136 INFO [ProtocolHandshake.createSession] - Detected dialect: W3C
chrome_1    | 17:34:43.175 INFO [RemoteSession$Factory.lambda$performHandshake$0] - Started new session db65253291c94b8585354b73ef81c881 (org.openqa.selenium.chrome.ChromeDriverService)

Update to django 3.2 ?

Hello,

I started to work on packaging of writehat for Kali (https://bugs.kali.org/view.php?id=6899).
But you use django~=3.1.0 in requirements. In Kali (Debian, Ubuntu) we already have django version 3.2.* as it is the Long Term Support version of Django (support more than 2 years).
And the period of support of the version 3.1 has just ended (on December 7, 2021).

Can you consider to update writehat for django 3.2.? Writehat is not entirely compatible with 3.2.

Thanks

Typos discovered by codespell

Discovered in #19
% codespell --quiet-level=2 --skip="./writehat/static"

./writehat/views.py:209: Sucessfully ==> Successfully
./writehat/views.py:240: Sucessfully ==> Successfully
./writehat/views.py:750: similiar ==> similar
./writehat/views.py:896: retreive ==> retrieve
./writehat/views.py:918: specifiy ==> specify
./writehat/views.py:1060: inheratance ==> inheritance
./writehat/views.py:1271: didnt ==> didn't
./writehat/views.py:1548: sucesfully ==> successfully
./writehat/views.py:1629: similiar ==> similar
./writehat/validation.py:22: hygene ==> hygiene
./writehat/validation.py:165: wasnt ==> wasn't
./writehat/validation.py:186: thats ==> that's
./writehat/lib/dbImport.py:156: probbaly ==> probably
./writehat/lib/findingForm.py:184: Enviromental ==> Environmental
./writehat/lib/findingForm.py:192: Enviromental ==> Environmental
./writehat/lib/findingCategory.py:41: intialize ==> initialize
./writehat/lib/findingCategory.py:57: arent ==> aren't
./writehat/lib/engagementFinding.py:190: heirarchy ==> hierarchy
./writehat/lib/engagementFinding.py:239: heirarchy ==> hierarchy
./writehat/lib/startup.py:112: databse ==> database
./writehat/lib/errors.py:70: exeptions ==> exceptions

https://github.com/codespell-project/codespell

Where does WriteHat store component ownership/status information?

Where does WriteHat store information about the status of a component (Not Started, Writing, Needs Review, Complete) and the user that component is assigned to? I've tried tracing it back in the code but still can't find it. I can see it stores the report and associated report component ids and names in the writehat_report table but can't find the status or assigned owner?

Unable to generate report

Hi,
The repo renders an error every time I try creating a new report. I have installed the test version of the project. Is the issue because of it?
The issue is common across Mozilla and chrome.

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.