Skip to content

Commit

Permalink
Merge pull request #126 from chrismaddalena/master
Browse files Browse the repository at this point in the history
Ghostwriter v2.0
  • Loading branch information
chrismaddalena authored Nov 20, 2020
2 parents 7d62d1a + f6d4b7c commit 124a9f7
Show file tree
Hide file tree
Showing 168 changed files with 8,433 additions and 3,586 deletions.
35 changes: 0 additions & 35 deletions .envs_template/.local/.django
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,3 @@ DJANGO_ACCOUNT_EMAIL_VERIFICATION=none
# ------------------------------------------------------------------------------
QCLUSTER_NAME=soar
# QCLUSTER_CONNECTION=

# Virustotal
# ------------------------------------------------------------------------------
VIRUSTOTAL_API_KEY=None

# Slack
# ------------------------------------------------------------------------------
SLACK_ENABLE=True
SLACK_EMOJI=:ghost:
SLACK_CHANNEL=#ghostwriter
SLACK_ALERT_TARGET=<!here>
SLACK_USERNAME=ghostwriter
SLACK_URL=https://hooks.slack.com/services/<your_webhook_url>

# Company Info
# ------------------------------------------------------------------------------
COMPANY_NAME=Ghostwriter
COMPANY_TWITTER=@ghostwriter
[email protected]

# Namecheap
# ------------------------------------------------------------------------------
NAMECHEAP_ENABLE=False
NAMECHEAP_API_KEY=
NAMECHEAP_USERNAME=
NAMECHEAP_API_USERNAME=
CLIENT_IP=
NAMECHEAP_PAGE_SIZE=100

# Cloud Services
# ------------------------------------------------------------------------------
ENABLE_CLOUD_MONITOR=False
AWS_KEY=
AWS_SECRET=
DO_API_KEY=
35 changes: 0 additions & 35 deletions .envs_template/.production/.django
Original file line number Diff line number Diff line change
Expand Up @@ -38,38 +38,3 @@ REDIS_URL=redis://redis:6379/0
# ------------------------------------------------------------------------------
QCLUSTER_NAME=soar
# QCLUSTER_CONNECTION=

# Virustotal
# ------------------------------------------------------------------------------
VIRUSTOTAL_API_KEY=None

# Slack
# ------------------------------------------------------------------------------
SLACK_ENABLE=True
SLACK_EMOJI=:ghost:
SLACK_CHANNEL=#ghostwriter
SLACK_ALERT_TARGET=<!here>
SLACK_USERNAME=ghostwriter
SLACK_URL=https://hooks.slack.com/services/<your_webhook_url>

# Company Info
# ------------------------------------------------------------------------------
COMPANY_NAME=Ghostwriter
COMPANY_TWITTER=@ghostwriter
[email protected]

# Namecheap
# ------------------------------------------------------------------------------
NAMECHEAP_ENABLE=False
NAMECHEAP_API_KEY=
NAMECHEAP_USERNAME=
NAMECHEAP_API_USERNAME=
CLIENT_IP=
NAMECHEAP_PAGE_SIZE=100

# Cloud Services
# ------------------------------------------------------------------------------
ENABLE_CLOUD_MONITOR=False
AWS_KEY=
AWS_SECRET=
DO_API_KEY=
53 changes: 53 additions & 0 deletions DOCS/CHANGELOG.RST
Original file line number Diff line number Diff line change
@@ -1,6 +1,59 @@
Changelog
=========

20 November 2020
----------------
* Tagged release v2.0
* More details: https://posts.specterops.io/ghostwriter-v2-0-release-638cef16deb7
* Upgraded to Django 3 and updated all dependencies
* Initial commit of CommandCenter application and related configuration options
* VirusTotal Configuration
* Global Report Configuration
* Slack Configuration
* Company information
* Namecheap Configuration
* Initial support for adding users to groups for Role-Based Access Controls
* Automated Acitivty Logging (Oplog application) moved out of beta
* Implemented initial "overwatch" notifications
* Domain check-out: alert if domain will expire soon and is not set to auto-renew
* Domain check-out: alert if domain is marked as burned
* Domain check-out: alert if domain has been previously used with selected client
* Updated user interface elements
* New tabbed dashboards for clients, projects, and domains
* New inline forms for creating and managing clients and projects and related items
* New sidebar menu to improve legibility
* Migrated buttons and background tasks to WebSockets and AJAX for a more seamless experience
* Initial release of refactored reporting engine
* New drag-and-drop report management interface
* Added many more options to the WYSIWYG editor's formatting menus
* Initial support for rich text objects for Word documents
* Added new `filter_severity` filter for Word templates
* Closes #89
* Initial support for report template and management
* Upload report tempalte files for Word and PowerPoint
* New template linter to check and verify templates
* Closes #28
* Closes #90
* Security updates and fixes
* Resolved potential stored cross-site scripting in operational logs
* Resolved unvalidated evidence file uploads and new note creation
* Associated user account is now set server-side
* Resolved issues with WebSocket authentication
* Locked-down evidence uploads to close potential loopholes
* Evidence form now only allows specific filetypes: md, txt, log, jpg, jpeg, png
* Requesting an evidence file requires an active user session
* Removed web scraping from domain health checks
* Checks now use VirusTotal and link to the results
* Closes #50
* Closes #84
* Numerous bug fixes and enhancements to address reported issues
* Closes #54
* Closes #55
* Closes #69
* Closes #92
* Closes #93
* Closes #98

25 August 2020
--------------
* Cleaned and refactored each application to improve UI/UX and performance
Expand Down
39 changes: 39 additions & 0 deletions DOCS/examples/post_activity_logs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import requests
import json

# Replace with a URL, API, and ID key for your instance
url = "http://127.0.0.1:8000/oplog/api/entries/"
api_key = "API_KEY"
oplog_id = 1

headers = {
"user-agent": "Python",
"Content-Type": "application/json",
"Authorization": f"Api-Key {api_key}",
}

data = {
"start_date": None,
"end_date": None,
"source_ip": "WIN10VM (10.20.10.10)",
"dest_ip": "127.0.0.1",
"tool": "Beacon",
"user_context": "ADMIN",
"command": "execute_assembly /tmp/Seatbelt.exe logonevents",
"description": "",
"output": "",
"comments": "",
"operator_name": "Benny",
"oplog_id": "1",
}

print("[+] Sending request to Ghostwriter...")

resp = requests.post(url, headers=headers, data=json.dumps(data))

if resp.status_code == 201:
print(f"[+] Received code 201, so log was created: {resp.text}")
else:
print(
f"[!] Received status code {resp.status_code}, so something went wrong: {resp.text}"
)
Binary file modified DOCS/images/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added DOCS/sample_reports/so-con_template.docx
Binary file not shown.
Binary file added DOCS/sample_reports/template.docx
Binary file not shown.
Binary file added DOCS/sample_reports/template.pptx
Binary file not shown.
52 changes: 49 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,54 @@
# Ghostwriter

[![Python Version](https://img.shields.io/badge/Python-3.7-brightgreen.svg)](.) [![License](https://img.shields.io/badge/License-BSD3-darkred.svg)](.) [![Black Hat Arsenal 2019](https://img.shields.io/badge/2019-Black%20Hat%20Arsenal-lightgrey.svg)](.)
[![Python Version](https://img.shields.io/badge/Python-3.8-brightgreen.svg)](.) [![License](https://img.shields.io/badge/License-BSD3-darkred.svg)](.) [![Black Hat Arsenal 2019](https://img.shields.io/badge/2019-Black%20Hat%20Arsenal-lightgrey.svg)](https://www.blackhat.com/us-19/arsenal/schedule/index.html#ghostwriter-15475)

![ghostwriter](https://github.com/GhostManager/Ghostwriter/raw/master/DOCS/images/logo.png)
![GitHub release (latest by date)](https://img.shields.io/github/v/release/GhostManager/Ghostwriter)
![GitHub Release Date](https://img.shields.io/github/release-date/ghostmanager/ghostwriter)

Ghostwriter is a Django project written in Python 3.7 and is designed to be used by a team of operators. The platform is made up of several Django apps that own different roles but work together. See the Wiki for more information.
![ghostwriter](DOCS/images/logo.png)

Ghostwriter is a Django project written in Python 3.8 and is designed to be used by a team of operators. The platform is made up of several Django apps that own different roles but work together.

## Details

Check-out the introductory blogpost: [Introducing Ghostwriter](https://posts.specterops.io/introducing-ghostwriter-part-1-61e7bd014aff)

This blogpost discusses the design and intent behind Ghostwriter: [Introducing Ghostwriter: Part 2](https://posts.specterops.io/introducing-ghostwriter-part-2-f2d8368a1ed6)

## Documentation

The Ghostwriter Wiki contains everything you need to know to use or customize Ghostwriter:

[Ghostwriter Wiki](https://ghostwriter.wiki/)

The wiki covers everything from installation and setup information for first time users to database schemas, the project's code style guide, and how to expand or customie parts of the project to fit your needs.

## Getting Help

[![Slack Status](https://img.shields.io/badge/Slack-%23ghostwriter-blueviolet)](https://bloodhoundgang.herokuapp.com)

The quickest way to get help is Slack. The BloodHound Slack Team has a #ghostwriter channel for discussing this project and requesting assistance. There is also a #reporting channel for discussing various topics related to writing and managing reports and findings.

You can submit an issue. If you do, please use the issue template and provide as much information as possible.

Before submitting an issue, review the [Ghostwriter Wiki](https://ghostwriter.wiki/). Many of the common issues new users encounter stem from missing a step (like loading the seed data to prep the database) or an issue with Docker on their host system.

## Contributing to the Project

Please open issues or submit pull requests! The project team welcomes feedback, new ideas, and external contributions. Before submitting a PR, please check open and closed issues for any previous related discussion. Also, the submitted code must follow the [Code Style Guide](https://ghostwriter.wiki/coding-style-guide/style-guide) to be accepted.

We only ask that you limit PR submissions to those that fix a bug, enhance an existing feature, or add something new.

## Contributions

The following people have contributed much to this project:

* [@covertgeek](https://github.com/covertgeek)
* [@hotnops](https://github.com/hotnops)
* [@andrewchiles](https://github.com/andrewchiles)

These folks kindly submitted feedback and PRs to fix bugs and enhance existing features. Thank you!

* [@fastlorenzo](https://github.com/fastlorenzo)
* [@mattreduce](https://github.com/mattreduce)
* [@dbuentello](https://github.com/dbuentello)
28 changes: 14 additions & 14 deletions compose/local/django/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
FROM python:3.7-alpine
FROM python:3.8-alpine

ENV PYTHONUNBUFFERED 1

RUN apk update \
# psycopg2 dependencies
&& apk add --virtual build-deps gcc python3-dev musl-dev \
&& apk add postgresql-dev \
# Pillow dependencies
&& apk add jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-dev \
# CFFI dependencies
&& apk add libffi-dev py-cffi \
# XLSX dependencies
&& apk add libxml2-dev libxslt-dev \
# Translations dependencies
&& apk add gettext \
# https://docs.djangoproject.com/en/dev/ref/django-admin/#dbshell
&& apk add postgresql-client
# psycopg2 dependencies
&& apk add --virtual build-deps gcc python3-dev musl-dev \
&& apk add postgresql-dev \
# Pillow dependencies
&& apk add jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-dev \
# CFFI dependencies
&& apk add libffi-dev py-cffi \
# XLSX dependencies
&& apk add libxml2-dev libxslt-dev \
# Translations dependencies
&& apk add gettext \
# https://docs.djangoproject.com/en/dev/ref/django-admin/#dbshell
&& apk add postgresql-client

# Requirements are installed here to ensure they will be cached.
COPY ./requirements /requirements
Expand Down
8 changes: 8 additions & 0 deletions compose/local/django/start
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,17 @@ set -o nounset

AVATAR_DIR=/app/ghostwriter/media/user_avatars
EVIDENCE_DIR=/app/ghostwriter/media/evidence
TEMPLATE_DIR=/app/ghostwriter/media/templates

TEMPLATE_PATH_DOCX=/app/ghostwriter/reporting/templates/reports/template.docx
TEMPLATE_PATH_PPTX=/app/ghostwriter/reporting/templates/reports/template.pptx

[[ ! -d "$EVIDENCE_DIR" ]] && mkdir -p "$EVIDENCE_DIR"
[[ ! -d "$AVATAR_DIR" ]] && mkdir -p "$AVATAR_DIR"
[[ ! -d "$TEMPLATE_DIR" ]] && mkdir -p "$TEMPLATE_DIR"

cp -u -p "$TEMPLATE_PATH_DOCX" "$TEMPLATE_DIR"
cp -u -p "$TEMPLATE_PATH_PPTX" "$TEMPLATE_DIR"

python manage.py makemigrations
python manage.py migrate
Expand Down
24 changes: 12 additions & 12 deletions compose/production/django/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
FROM python:3.7-alpine
FROM python:3.8-alpine

ENV PYTHONUNBUFFERED 1

ENV PYTHONPATH="$PYTHONPATH:/app/config"

RUN apk update \
# psycopg2 dependencies
&& apk add --virtual build-deps gcc python3-dev musl-dev \
&& apk add postgresql-dev \
# Pillow dependencies
&& apk add jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-dev \
# CFFI dependencies
&& apk add libffi-dev py-cffi \
# XLSX dependencies
&& apk add libxml2-dev libxslt-dev
# psycopg2 dependencies
&& apk add --virtual build-deps gcc python3-dev musl-dev \
&& apk add postgresql-dev \
# Pillow dependencies
&& apk add jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-dev \
# CFFI dependencies
&& apk add libffi-dev py-cffi \
# XLSX dependencies
&& apk add libxml2-dev libxslt-dev

RUN addgroup -S django \
&& adduser -S -G django django
&& adduser -S -G django django

# Requirements are installed here to ensure they will be cached.
COPY ./requirements /requirements
RUN pip install --no-cache-dir -r /requirements/production.txt \
&& rm -rf /requirements
&& rm -rf /requirements

COPY ./compose/production/django/entrypoint /entrypoint
RUN sed -i 's/\r$//g' /entrypoint
Expand Down
10 changes: 9 additions & 1 deletion compose/production/django/start
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,17 @@ set -o nounset

AVATAR_DIR=/app/ghostwriter/media/user_avatars
EVIDENCE_DIR=/app/ghostwriter/media/evidence
TEMPLATE_DIR=/app/ghostwriter/media/templates

TEMPLATE_PATH_DOCX=/app/ghostwriter/reporting/templates/reports/template.docx
TEMPLATE_PATH_PPTX=/app/ghostwriter/reporting/templates/reports/template.pptx

[[ ! -d "$EVIDENCE_DIR" ]] && mkdir -p "$EVIDENCE_DIR" && chown -R django "$EVIDENCE_DIR"
[[ ! -d "$AVATAR_DIR" ]] && mkdir -p "$AVATAR_DIR" && chown -R django "$AVATAR_DIR"
[[ ! -d "$AVATAR_DIR" ]] && mkdir -p "$AVATAR_DIR" && chown -R django "$AVATAR_DIR"
[[ ! -d "$TEMPLATE_DIR" ]] && mkdir -p "$TEMPLATE_DIR" && chown -R django "$TEMPLATE_DIR"

cp -u -p "$TEMPLATE_PATH_DOCX" "$TEMPLATE_DIR"
cp -u -p "$TEMPLATE_PATH_PPTX" "$TEMPLATE_DIR"

python /app/manage.py collectstatic --noinput
python /app/manage.py migrate
Expand Down
17 changes: 17 additions & 0 deletions config/routing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""This contains all of the WebSocket routes used by the Ghostwriter application."""

# Django & Other 3rd Party Libraries
from django.urls import path
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack

# Ghostwriter Libraries
from ghostwriter.oplog.consumers import OplogEntryConsumer

application = ProtocolTypeRouter(
{
"websocket": AuthMiddlewareStack(
URLRouter([path("ws/oplog/<int:pk>/entries", OplogEntryConsumer)])
)
}
)
Loading

0 comments on commit 124a9f7

Please sign in to comment.