Ghostwriter
Ghostwriter is an open-source engagement management platform built by SpecterOps for organizing red team operations, tracking findings, generating professional reports, and managing infrastructure. It provides centralized tracking of clients, projects, findings, and domain/server infrastructure with powerful Jinja2-based report templating.
Installation
Sección titulada «Installation»Docker Compose (Recommended)
Sección titulada «Docker Compose (Recommended)»Clone the repository and deploy using Docker Compose:
git clone https://github.com/GhostManager/Ghostwriter.git
cd Ghostwriter
docker compose up -d
Access the application at http://localhost:8000 after containers start (allow 30-60 seconds for initialization).
Manual Setup Requirements
Sección titulada «Manual Setup Requirements»- Python 3.10+
- PostgreSQL 14+
- Redis
- Node.js 16+
git clone https://github.com/GhostManager/Ghostwriter.git
cd Ghostwriter
pip install -r requirements.txt
npm install
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
Verify Installation
Sección titulada «Verify Installation»docker compose logs -f ghostwriter
curl http://localhost:8000/admin/
Initial Setup
Sección titulada «Initial Setup»Default Admin Credentials
Sección titulada «Default Admin Credentials»Change default admin credentials immediately after deployment:
# Via Django shell
docker compose exec ghostwriter python manage.py shell
from django.contrib.auth.models import User
user = User.objects.get(username='admin')
user.set_password('new_secure_password')
user.save()
Creating Users
Sección titulada «Creating Users»Navigate to Admin Panel > Users or use the API:
# Create user via Django shell
from django.contrib.auth.models import User
User.objects.create_user(
username='operator1',
email='operator@company.com',
password='secure_password'
)
API Token Generation
Sección titulada «API Token Generation»Generate API tokens for automation:
# Via Admin Panel: Profile > API Tokens > Create Token
# Via API:
curl -X POST http://localhost:8000/api/token-auth/ \
-H "Content-Type: application/json" \
-d '{"username":"operator1","password":"secure_password"}'
Store tokens securely in .env files.
Project Management
Sección titulada «Project Management»Creating Clients
Sección titulada «Creating Clients»Add organizational clients to organize engagements:
# Navigation: Clients > Add Client
# Fields:
# - Client Name: Company name
# - Client Timezone: For report generation timing
# - Short Name: Abbreviation (e.g., ACME)
# - Description: Company background/info
Creating Projects
Sección titulada «Creating Projects»Link projects to clients:
# Project Details
Name: "ACME 2026 Pentest"
Client: "ACME Corporation"
Codename: "OPERATION_SWIFT"
Start Date: "2026-04-17"
End Date: "2026-05-17"
Type: "Penetration Test"
Scope: "Internal network, web applications"
Objectives: "Identify vulnerabilities, test defenses"
Setting Engagement Dates and Scope
Sección titulada «Setting Engagement Dates and Scope»# Navigation: Project > Engagement > Edit
Start Date: Planning phase start
End Date: Reporting deadline
On Hold: Check to pause logging/activity
Team: Assign operators and managers
Define scope in the project description or attachments for clarity.
Finding Library
Sección titulada «Finding Library»Creating Reusable Findings
Sección titulada «Creating Reusable Findings»Build a library of pre-configured findings for consistent reporting:
# Navigation: Finding Library > Create Finding
Title: "SQL Injection in Login Form"
Category: "Input Validation"
Finding Type: "Vulnerability"
Severity: "Critical"
CVSS Score: "9.8"
Description: HTML/rich text description
Recommendation: Remediation steps
Severity Ratings and CVSS
Sección titulada «Severity Ratings and CVSS»Severity Levels:
- Info (Informational)
- Low (CVSS: 0.1-3.9)
- Medium (CVSS: 4.0-6.9)
- High (CVSS: 7.0-8.9)
- Critical (CVSS: 9.0-10.0)
Categories and Organization
Sección titulada «Categories and Organization»Organize findings by category:
- Input Validation
- Authentication
- Authorization
- Cryptography
- Configuration
- Sensitive Data Exposure
- Business Logic
- Session Management
- Dependency Usage
- Infrastructure
Report Generation
Sección titulada «Report Generation»DOCX Templates
Sección titulada «DOCX Templates»Ghostwriter generates Word documents using Jinja2 templates:
# Template Structure
templates/
├── report_template.docx
├── executive_summary.docx
├── technical_findings.docx
└── appendix.docx
Jinja2 Template Syntax
Sección titulada «Jinja2 Template Syntax»# Basic variable insertion
{{ report.title }}
{{ project.codename }}
{{ finding.severity }}
# Conditionals
{% if finding.severity == 'Critical' %}
This finding requires immediate attention.
{% endif %}
# Loops
{% for finding in findings %}
Finding: {{ finding.title }}
Severity: {{ finding.severity }}
{% endfor %}
# Filters
{{ report.date|strftime('%B %d, %Y') }}
{{ description|wordcount }}
Common Report Types
Sección titulada «Common Report Types»| Type | Purpose | Includes |
|---|---|---|
| Executive Summary | High-level overview for management | Finding counts, risk ratings, timeline |
| Technical Report | Detailed findings for IT teams | Findings, CVSS scores, evidence, recommendations |
| Detailed Report | Comprehensive assessment | All findings, methodology, testing timeline |
| Summary Report | Brief overview | Top findings, risk summary |
Custom Fields and Variables
Sección titulada «Custom Fields and Variables»Define custom fields in project settings:
# Available in templates:
{{ report.client_name }}
{{ report.project_name }}
{{ report.assessment_type }}
{{ report.assessment_start }}
{{ report.assessment_end }}
{{ report.assessor_name }}
{{ report.company_name }}
{{ findings }}
{{ executive_summary }}
Rich Text Findings and Evidence
Sección titulada «Rich Text Findings and Evidence»Store findings with attachments:
# Findings include:
- HTML/Markdown description
- Code snippets
- Screenshots (embedded as base64 or file references)
- Proof of concept demonstrations
- Evidence artifacts (logs, outputs)
Infrastructure Tracking
Sección titulada «Infrastructure Tracking»Cloud Servers
Sección titulada «Cloud Servers»Track cloud infrastructure used during engagement:
# Navigation: Infrastructure > Servers > Add Server
Name: "C2_Server_01"
IP Address: "10.0.0.5"
Provider: "AWS"
Instance Type: "t3.medium"
Region: "us-east-1"
Purpose: "C2 Infrastructure"
Compromised: Yes/No
Notes: Deployment date, role
Domains
Sección titulada «Domains»Register and track domains for engagement:
# Navigation: Infrastructure > Domains > Add Domain
Name: "example-corp.com"
Type: "Phishing Domain"
Health: Active/Suspended/Taken Down
Registrar: "Namecheap"
Registered Date: "2026-04-10"
Expiration Date: "2027-04-10"
DNS Provider: "Route53"
DNS Records
Sección titulada «DNS Records»Configure DNS for phishing, C2, and communication:
# DNS Record Types
A: 192.168.1.100
CNAME: example.redirect-domain.com
MX: mail.domain.com
TXT: v=spf1 include:sendgrid.net ~all
NS: ns1.provider.com
Domain Health Checks
Sección titulada «Domain Health Checks»Monitor domain reputation and deliverability:
# Automated checks monitor:
- Blacklist status (Spamhaus, Barracuda)
- MX record validation
- SPF/DKIM/DMARC configuration
- SSL certificate validity
- Subdomain enumeration
- DNS resolution
Operation Logging
Sección titulada «Operation Logging»Log activities, commands, and timeline events:
# Navigation: Project > Oplog > Add Entry
Timestamp: "2026-04-17 14:32:00"
Title: "Initial Access via Phishing"
Description: "Deployed phishing email campaign"
Operator: "operator1"
Tool: "Gophish"
Tags: "phishing,initial-access"
Status: "Success"
Tool Tracking
Sección titulada «Tool Tracking»Track tools and commands executed:
Tools:
- name: "Cobalt Strike"
version: "4.7"
beacon_id: "0x1234"
host: "C2_Server_01"
- name: "PowerShell Empire"
listener: "http_listener"
modules_used: ["Invoke-WebRequest", "Get-ADUser"]
Command Logging
Sección titulada «Command Logging»Log specific commands for audit trail:
Command: "Get-ADUser -Filter * -Properties *"
Tool: "PowerShell"
Host: "WORKSTATION-01"
Result: "Retrieved 150 user objects"
Evidence: "output.txt"
Domain and Server Management
Sección titulada «Domain and Server Management»Domain Checkout
Sección titulada «Domain Checkout»Assign domains to team members during engagements:
# Navigation: Infrastructure > Domains > Checkout
Domain: "example-corp.com"
Checked Out By: "operator1"
Start Date: "2026-04-17"
End Date: "2026-05-17"
Purpose: "Phishing domain for engagement"
Notes: "Maintain low profile, monitor traffic"
Categorization Tracking
Sección titulada «Categorization Tracking»Tag infrastructure by purpose and category:
Categories:
- C2 Infrastructure
- Phishing Domain
- Proxy/Relay
- Malware Hosting
- Information Gathering
- Social Engineering
Health Monitoring
Sección titulada «Health Monitoring»Track infrastructure status:
# Status Indicators
- Active: In use
- Dormant: Available but not in use
- Burned: Compromised or flagged
- Retired: End of engagement
- Monitoring: Under observation by defenders
# Health Checks
- DNS Resolution: ✓ Working
- SSL Certificate: ✓ Valid
- Blacklist Status: ✓ Clean
- Network Connectivity: ✓ Online
SSL Certificates
Sección titulada «SSL Certificates»Manage SSL certificates for domains:
# Certificate Details
Domain: "example-corp.com"
Certificate: "self-signed" | "Let's Encrypt" | "Commercial"
Expiration: "2027-04-17"
Common Name: "example-corp.com"
Subject Alt Names: "*.example-corp.com"
Issued By: "DigiCert"
API Usage
Sección titulada «API Usage»GraphQL API
Sección titulada «GraphQL API»Query project data via GraphQL:
import requests
import json
url = "http://localhost:8000/graphql/"
headers = {
"Authorization": "Token YOUR_API_TOKEN",
"Content-Type": "application/json"
}
query = """
{
allProjects {
id
codename
client {
name
}
startDate
endDate
}
}
"""
response = requests.post(
url,
json={"query": query},
headers=headers
)
print(json.dumps(response.json(), indent=2))
REST Endpoints
Sección titulada «REST Endpoints»Common API endpoints:
# Projects
GET /api/projects/
POST /api/projects/
GET /api/projects/{id}/
PATCH /api/projects/{id}/
# Findings
GET /api/findings/
POST /api/findings/
GET /api/findings/{id}/
# Infrastructure
GET /api/servers/
POST /api/servers/
GET /api/domains/
# Oplog
GET /api/oplog/
POST /api/oplog/
Authentication
Sección titulada «Authentication»# Token Auth
curl -H "Authorization: Token YOUR_API_TOKEN" \
http://localhost:8000/api/projects/
# Generate Token
curl -X POST http://localhost:8000/api-token-auth/ \
-d "username=operator1&password=password"
Common Queries
Sección titulada «Common Queries»# Fetch all Critical findings
GET /api/findings/?severity=Critical
# Get project by codename
GET /api/projects/?codename=OPERATION_SWIFT
# List checked out domains
GET /api/domains/?checked_out=true
# Get oplog entries for project
GET /api/oplog/?project=1
Template Customization
Sección titulada «Template Customization»Jinja2 Filters
Sección titulada «Jinja2 Filters»# String Filters
{{ finding.title|upper }}
{{ finding.title|lower }}
{{ finding.description|wordcount }}
# Date Filters
{{ report.date|strftime('%B %d, %Y') }}
{{ report.date|date('Y-m-d') }}
# List Filters
{{ findings|length }}
{{ findings|first }}
{{ findings|rejectattr('severity', 'equalto', 'Info')|list }}
Custom Variables
Sección titulada «Custom Variables»Define custom variables in template context:
# In report generation:
context = {
'company': 'ACME Corp',
'testing_period': '30 days',
'tester_name': 'Red Team',
'custom_rating': 'High Risk',
'findings_count': 42
}
Conditional Sections
Sección titulada «Conditional Sections»{% if findings|length > 0 %}
<h2>Findings</h2>
{% for finding in findings %}
<h3>{{ finding.title }}</h3>
{% endfor %}
{% else %}
<p>No findings identified.</p>
{% endif %}
Loops and Iterations
Sección titulada «Loops and Iterations»{% for finding in findings|dictsort(attribute='severity') %}
<section>
<h3>{{ finding.title }}</h3>
<p>{{ finding.description }}</p>
</section>
{% endfor %}
# Nested loops
{% for project in projects %}
{% for finding in project.findings %}
{{ finding.title }}
{% endfor %}
{% endfor %}
User Management
Sección titulada «User Management»Roles and Permissions
Sección titulada «Roles and Permissions»| Role | Permissions | Access |
|---|---|---|
| Admin | Full access | All projects, users, settings |
| Manager | Manage projects, users | Assigned projects, team management |
| Operator | Execute, log findings | Assigned projects only |
| Viewer | Read-only | Assigned projects, reports |
Assigning Roles
Sección titulada «Assigning Roles»# Navigation: Admin > Users > Select User
Role: Admin | Manager | Operator | Viewer
Projects: Multi-select assigned projects
Teams: Assign to teams
Permissions: Custom permission configuration
Organize operators into teams:
# Navigation: Teams > Create Team
Team Name: "Red Team Alpha"
Members: operator1, operator2, operator3
Projects: Link to relevant projects
Lead: operator1 (team manager)
Troubleshooting
Sección titulada «Troubleshooting»Common Issues
Sección titulada «Common Issues»| Issue | Solution |
|---|---|
| Cannot login | Verify database is running; check POSTGRES_PASSWORD in docker-compose.yml |
| Slow report generation | Reduce findings per report; optimize Jinja2 templates; increase server resources |
| Docker container crashes | Check logs: docker compose logs ghostwriter |
| API token expired | Generate new token; store securely |
| Database migration errors | Run python manage.py migrate --fake-initial |
| Port 8000 already in use | Change port in docker-compose.yml or docker compose -p ghostwriter2 up -d |
Debug Mode
Sección titulada «Debug Mode»# Enable debug logging
DEBUG=True docker compose up
# Check application logs
docker compose logs -f ghostwriter
# Access Django shell
docker compose exec ghostwriter python manage.py shell
Best Practices
Sección titulada «Best Practices»Engagement Organization
Sección titulada «Engagement Organization»- Use consistent codenames across all documents
- Create client-specific templates for branding
- Organize findings by engagement phase (reconnaissance, exploitation, post-exploitation)
- Use tags extensively for filtering and reporting
Finding Management
Sección titulada «Finding Management»- Create reusable findings with generic descriptions
- Include proof-of-concept code in findings
- Document remediation steps clearly
- Assign appropriate CVSS scores consistently
- Use categories to organize finding library
Infrastructure Security
Sección titulada «Infrastructure Security»- Rotate C2 infrastructure regularly
- Monitor domain reputation proactively
- Document all infrastructure assignments
- Use separate infrastructure for different engagement types
- Track SSL certificate expiration dates
Report Generation
Sección titulada «Report Generation»- Test templates with sample data before engagement
- Create role-specific report variations
- Include executive and technical summaries
- Embed evidence and screenshots appropriately
- Use consistent formatting across all reports
Operational Security
Sección titulada «Operational Security»- Limit API token scope to specific operations
- Rotate API tokens regularly
- Audit user access logs monthly
- Archive completed projects and findings
- Use encrypted connections for all API calls
Team Collaboration
Sección titulada «Team Collaboration»- Establish naming conventions for projects and findings
- Create shared finding templates before engagements
- Assign oplog responsibility clearly
- Review and approve findings before finalizing reports
- Maintain team documentation and playbooks
Related Tools
Sección titulada «Related Tools»| Tool | Purpose | Integration |
|---|---|---|
| AttackForge | Engagement management and reporting | Similar functionality; cloud-based |
| PlexTrac | Platform for findings and reporting | Competitor; different UI/workflow |
| Dradis | Security assessment collaboration | Finding collection and reporting |
| DefectDojo | Vulnerability management | Integration with CI/CD pipelines |
| OWASP ZAP | Web application security | Finding import capabilities |
| Nessus | Vulnerability scanning | Scan import and integration |
| Burp Suite | Web penetration testing | Finding export integration |