chore: auto-commit 2026-04-24 20:11
This commit is contained in:
parent
3915fa975f
commit
816e056ba1
13 changed files with 2711 additions and 77 deletions
157
AttackSurface/README.md
Normal file
157
AttackSurface/README.md
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
# AASD — API Attack Surface Discovery
|
||||||
|
|
||||||
|
Interactive booth application for GITEX 2026. Visitors enter a corporate email, and AASD runs a full attack surface discovery pipeline:
|
||||||
|
|
||||||
|
**Email → Domain Discovery → GoTestWAF Scan → AI Resilience Report**
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
Visitor Email
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ /start (POST) │ Email validation + domain extraction
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ domain-scan │ Passive subdomain enumeration (15s timeout)
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ GoTestWAF │ WAF penetration test against Wallarm endpoint (120s)
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ DeepSeek AI │ Generate resilience narrative from scan results
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ HTML Report │ Static report served at /reports/<token>.html
|
||||||
|
└─────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tech Stack
|
||||||
|
|
||||||
|
| Component | Technology |
|
||||||
|
|-----------|-----------|
|
||||||
|
| Backend | Go 1.25 — Gin web framework |
|
||||||
|
| Frontend | HTML, JavaScript, Tailwind CSS (CDN) |
|
||||||
|
| WAF Scanner | GoTestWAF |
|
||||||
|
| Domain Discovery | domain-scan |
|
||||||
|
| AI Narrative | DeepSeek API |
|
||||||
|
| Email | SMTP (OpenXchange) |
|
||||||
|
|
||||||
|
## Quick Start (Development)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Option 1: Deploy via install script
|
||||||
|
cd AttackSurface
|
||||||
|
sudo bash install.sh
|
||||||
|
|
||||||
|
# Option 2: Run from dist/ directly
|
||||||
|
cd AttackSurface/dist
|
||||||
|
./aasd
|
||||||
|
|
||||||
|
# Option 3: Build from source
|
||||||
|
cd AttackSurface/src
|
||||||
|
go build -o ../dist/aasd ./cmd/aasd/
|
||||||
|
cd ../dist
|
||||||
|
./aasd
|
||||||
|
```
|
||||||
|
|
||||||
|
## Endpoints
|
||||||
|
|
||||||
|
| Path | Description | Auth |
|
||||||
|
|------|-------------|------|
|
||||||
|
| `/` | Frontend landing page (email entry) | Public |
|
||||||
|
| `/start` (POST) | Submit email, trigger scan pipeline | Public |
|
||||||
|
| `/analysing` | Scan progress visualization | Public |
|
||||||
|
| `/simulation` | Legacy alias for `/analysing` | Public |
|
||||||
|
| `/scan-status/:token` | Poll scan status (JSON) | Public |
|
||||||
|
| `/qrcode?text=...` | QR code generator | Public |
|
||||||
|
| `/admin-dashboard` | Consultant dashboard | Basic Auth |
|
||||||
|
| `/email-report` (POST) | Send report via email | Public |
|
||||||
|
| `/reports/*` | Generated static reports | Public |
|
||||||
|
| `/report-data/:token` | Raw scan result JSON | Public |
|
||||||
|
| `/api/scans` | Scan summaries (JSON) | Public |
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Edit `dist/config.yaml` (or `/opt/aasd/config.yaml` after install) with your values:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
ai:
|
||||||
|
api_key: "sk-..." # DeepSeek API key for AI narratives
|
||||||
|
server:
|
||||||
|
base_url: "https://..." # Public URL for QR codes & email links
|
||||||
|
admin:
|
||||||
|
password: "..." # Admin dashboard password
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, set these via environment variables:
|
||||||
|
- `AASD_BASE_URL` — public-facing URL
|
||||||
|
- `AASD_AI_API_KEY` — DeepSeek API key
|
||||||
|
- `AASD_ADMIN_PASSWORD` — admin dashboard password
|
||||||
|
- `SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`, `SMTP_FROM` — SMTP config
|
||||||
|
|
||||||
|
## Deployment (Production)
|
||||||
|
|
||||||
|
See `install.sh` for automated deployment. The script:
|
||||||
|
|
||||||
|
1. Creates an `app` system user if it doesn't exist
|
||||||
|
2. Downloads the pre-built release archive from GitHub
|
||||||
|
3. Extracts to `/opt/aasd`
|
||||||
|
4. Creates a systemd service (`aasd.service`) for auto-start on boot
|
||||||
|
5. Prompts for required configuration values
|
||||||
|
|
||||||
|
### Systemd Service Management
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl start aasd # Start the server
|
||||||
|
sudo systemctl stop aasd # Stop the server
|
||||||
|
sudo systemctl restart aasd # Restart
|
||||||
|
sudo systemctl status aasd # Check status
|
||||||
|
sudo journalctl -u aasd -f # Follow logs
|
||||||
|
```
|
||||||
|
|
||||||
|
## Version
|
||||||
|
|
||||||
|
**2026-04.1** — See [CHANGELOG.md](docs/CHANGELOG.md) for full history.
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
AttackSurface/
|
||||||
|
├── dist/ # Deployment directory (self-contained)
|
||||||
|
│ ├── aasd # Compiled Go binary
|
||||||
|
│ ├── config.yaml # Application configuration
|
||||||
|
│ ├── prompt.txt # DeepSeek AI system prompt
|
||||||
|
│ ├── gotestwaf # GoTestWAF binary
|
||||||
|
│ ├── domain-scan # Domain discovery tool
|
||||||
|
│ ├── testcases/ # GoTestWAF test cases
|
||||||
|
│ ├── static/ # Frontend HTML/JS
|
||||||
|
│ ├── templates/ # Go HTML templates
|
||||||
|
│ ├── reports/ # Generated scan reports
|
||||||
|
│ └── logs/ # Server logs
|
||||||
|
├── src/ # Go source code
|
||||||
|
│ ├── cmd/aasd/ # Main entry point
|
||||||
|
│ ├── internal/ # Core packages (scanner, ai, mailer, report)
|
||||||
|
│ ├── static/ # Frontend source files
|
||||||
|
│ ├── templates/ # Template source files
|
||||||
|
│ └── gotestwaf/ # Vendored GoTestWAF
|
||||||
|
├── docs/ # Documentation
|
||||||
|
│ ├── CHANGELOG.md
|
||||||
|
│ └── DEVELOPMENT_STATUS.md
|
||||||
|
├── install.sh # Automated deployment script
|
||||||
|
├── VERSION
|
||||||
|
└── README.md # This file
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Proprietary — For internal event use at GITEX 2026.
|
||||||
BIN
AttackSurface/dist/aasd
vendored
BIN
AttackSurface/dist/aasd
vendored
Binary file not shown.
9
AttackSurface/dist/config.yaml
vendored
9
AttackSurface/dist/config.yaml
vendored
|
|
@ -1,4 +1,11 @@
|
||||||
ai:
|
ai:
|
||||||
provider_url: "https://api.deepseek.com"
|
provider_url: "https://api.deepseek.com"
|
||||||
api_key: "sk-0553e582701e4d2a893f68826e941726"
|
api_key: "CHANGE_ME_DEEPSEEK_API_KEY" # <-- required: set your DeepSeek API key
|
||||||
model: "deepseek-chat"
|
model: "deepseek-chat"
|
||||||
|
|
||||||
|
server:
|
||||||
|
base_url: "CHANGE_ME_BASE_URL" # <-- required: e.g. https://aasd.sechpoint.app
|
||||||
|
|
||||||
|
admin:
|
||||||
|
username: "sechpoint"
|
||||||
|
password: "CHANGE_ME_ADMIN_PASSWORD" # <-- required: set a secure password
|
||||||
|
|
|
||||||
124
AttackSurface/dist/reports/4a48e516-2320-4db3-b717-75e5a72a28b6.html
vendored
Normal file
124
AttackSurface/dist/reports/4a48e516-2320-4db3-b717-75e5a72a28b6.html
vendored
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
|
<title>Security Report - lohmar.co.uk - API Attack Surface Discovery</title>
|
||||||
|
<script src="https://cdn.tailwindcss.com/"></script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-slate-900 text-slate-100 min-h-screen">
|
||||||
|
<div class="container mx-auto px-4 py-6 max-w-lg">
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="text-center mb-6">
|
||||||
|
<h1 class="text-2xl font-bold bg-gradient-to-r from-blue-400 to-purple-400 bg-clip-text text-transparent">AASD</h1>
|
||||||
|
<p class="text-sm text-slate-400">API Attack Surface Discovery</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Report Content -->
|
||||||
|
<div class="bg-gray-900 text-gray-100 p-8 rounded-lg shadow-lg max-w-4xl mx-auto font-sans">
|
||||||
|
<!-- Scan Overview -->
|
||||||
|
<div class="mb-8 border-b border-gray-700 pb-6">
|
||||||
|
<h2 class="text-2xl font-bold text-emerald-400 mb-4">🔍 Scan Overview</h2>
|
||||||
|
<p class="text-lg leading-relaxed">
|
||||||
|
Your application at <span class="text-cyan-300 font-mono">git.sechpoint.app</span> underwent a comprehensive security assessment on <strong>24 April 2026</strong>.
|
||||||
|
The test sent <strong>816 requests</strong> covering OWASP API and Application Security categories. While the current configuration shows room for improvement,
|
||||||
|
recognizing these gaps is the <span class="text-emerald-300 font-semibold">first step toward resilience</span>.
|
||||||
|
The scan reveals exactly where your defenses need attention — empowering you to take targeted, effective action.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Key Findings -->
|
||||||
|
<div class="mb-8 border-b border-gray-700 pb-6">
|
||||||
|
<h2 class="text-2xl font-bold text-amber-400 mb-4">⚠️ Key Findings</h2>
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<div class="bg-gray-800 rounded-lg p-4 border-l-4 border-red-500">
|
||||||
|
<p class="font-semibold text-red-300">API Security Grade: <span class="text-2xl">F</span></p>
|
||||||
|
<p class="text-sm text-gray-400">0% of true-positive attacks were blocked</p>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-800 rounded-lg p-4 border-l-4 border-red-500">
|
||||||
|
<p class="font-semibold text-red-300">Application Security Grade: <span class="text-2xl">F</span></p>
|
||||||
|
<p class="text-sm text-gray-400">0% of true-positive attacks were blocked</p>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-800 rounded-lg p-4 border-l-4 border-yellow-500">
|
||||||
|
<p class="font-semibold text-yellow-300">True-Negative Accuracy: <span class="text-xl">33.3%</span></p>
|
||||||
|
<p class="text-sm text-gray-400">94 legitimate requests were incorrectly blocked</p>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-800 rounded-lg p-4 border-l-4 border-purple-500">
|
||||||
|
<p class="font-semibold text-purple-300">Attack Surface Exposure</p>
|
||||||
|
<p class="text-sm text-gray-400">675 malicious requests bypassed your current security</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Resilience Score -->
|
||||||
|
<div class="mb-8 border-b border-gray-700 pb-6">
|
||||||
|
<h2 class="text-2xl font-bold text-cyan-400 mb-4">📊 Resilience Score: <span class="text-4xl font-black">0.0 / 100</span></h2>
|
||||||
|
<div class="bg-gray-800 rounded-lg p-5">
|
||||||
|
<div class="flex items-center gap-3 mb-3">
|
||||||
|
<div class="w-full bg-gray-700 rounded-full h-4">
|
||||||
|
<div class="bg-gradient-to-r from-red-500 via-amber-500 to-emerald-500 h-4 rounded-full" style="width: 0%;"></div>
|
||||||
|
</div>
|
||||||
|
<span class="text-sm font-bold text-red-400">Baseline</span>
|
||||||
|
</div>
|
||||||
|
<p class="text-gray-300">
|
||||||
|
Your current resilience score is at a starting point. The good news? Industry leaders like Wallarm achieve <strong>98.9%</strong> overall scores.
|
||||||
|
With continuous monitoring and the right tuning, you can rapidly climb the resilience ladder.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Remediation Recommendations -->
|
||||||
|
<div class="mb-6">
|
||||||
|
<h2 class="text-2xl font-bold text-emerald-400 mb-4">🛡️ Remediation Roadmap</h2>
|
||||||
|
<p class="text-gray-300 mb-4">
|
||||||
|
Based on this scan, your path to robust API security is clear. Here are the <span class="text-cyan-300">high-impact actions</span> to take:
|
||||||
|
</p>
|
||||||
|
<div class="space-y-3">
|
||||||
|
<div class="bg-gray-800 rounded-lg p-4 border-l-4 border-emerald-500">
|
||||||
|
<h3 class="font-bold text-emerald-300">1. Deploy Continuous API Attack Surface Monitoring</h3>
|
||||||
|
<p class="text-sm text-gray-400">Set up automated weekly scans to catch new vulnerabilities as your APIs evolve. Awareness is your first line of defense.</p>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-800 rounded-lg p-4 border-l-4 border-cyan-500">
|
||||||
|
<h3 class="font-bold text-cyan-300">2. Tune WAF Rules for True-Positive Detection</h3>
|
||||||
|
<p class="text-sm text-gray-400">Focus on SQL injection, XSS, and RCE payloads — these bypassed completely in your test. Use the detailed scan report as a rules checklist.</p>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-800 rounded-lg p-4 border-l-4 border-amber-500">
|
||||||
|
<h3 class="font-bold text-amber-300">3. Reduce False Positives</h3>
|
||||||
|
<p class="text-sm text-gray-400">94 legitimate requests were blocked. Whitelist trusted patterns while maintaining strong attack detection — balance is key.</p>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-800 rounded-lg p-4 border-l-4 border-purple-500">
|
||||||
|
<h3 class="font-bold text-purple-300">4. Benchmark Against Industry Leaders</h3>
|
||||||
|
<p class="text-sm text-gray-400">Top solutions detect over 97% of attacks. Your baseline of 0% means every improvement will deliver massive gains — celebrate each milestone!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-6 bg-gradient-to-r from-gray-800 to-gray-700 rounded-lg p-5 text-center">
|
||||||
|
<p class="text-2xl font-bold text-emerald-300">💪 Your API Resilience Journey Starts Now</p>
|
||||||
|
<p class="text-gray-400 mt-2">Continuous monitoring transforms today's gaps into tomorrow's strengths.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Token Reference -->
|
||||||
|
<div class="mt-6 p-4 bg-slate-800 rounded-xl text-center">
|
||||||
|
<p class="text-xs text-slate-500 mb-2">Report Token</p>
|
||||||
|
<p class="text-sm font-mono text-slate-300">4a48e516-2320-4db3-b717-75e5a72a28b6</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- QR Code -->
|
||||||
|
<div class="mt-4 text-center">
|
||||||
|
<img src="/qrcode?text=https://aasd.sechpoint.app/reports/report_4a48e516-2320-4db3-b717-75e5a72a28b6.html" alt="QR Code" class="inline-block w-40 h-40 rounded-xl border-2 border-slate-700 bg-white p-2" loading="lazy">
|
||||||
|
<p class="text-xs text-slate-500 mt-2">Ask a consultant to scan for your detailed report</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- CTA -->
|
||||||
|
<div class="mt-6 p-4 bg-slate-800 rounded-xl text-center border-2 border-blue-500/30">
|
||||||
|
<p class="text-sm text-slate-300">Show this code to <strong class="text-blue-400">Sechpoint Aftica Team</strong></p>
|
||||||
|
<p class="text-xs text-slate-500 mt-1">Your consultant will walk you through the findings</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-6 text-center text-xs text-slate-600">
|
||||||
|
GITEX 2026 — sechpoint.app
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
821
AttackSurface/dist/reports/report_4a48e516-2320-4db3-b717-75e5a72a28b6.csv
vendored
Normal file
821
AttackSurface/dist/reports/report_4a48e516-2320-4db3-b717-75e5a72a28b6.csv
vendored
Normal file
File diff suppressed because one or more lines are too long
1286
AttackSurface/dist/reports/report_4a48e516-2320-4db3-b717-75e5a72a28b6.html
vendored
Normal file
1286
AttackSurface/dist/reports/report_4a48e516-2320-4db3-b717-75e5a72a28b6.html
vendored
Normal file
File diff suppressed because it is too large
Load diff
2
AttackSurface/dist/templates/admin.html
vendored
2
AttackSurface/dist/templates/admin.html
vendored
|
|
@ -71,7 +71,7 @@
|
||||||
<td class="p-3 text-slate-400 hidden sm:table-cell">{{ len .Subdomains }}</td>
|
<td class="p-3 text-slate-400 hidden sm:table-cell">{{ len .Subdomains }}</td>
|
||||||
<td class="p-3">
|
<td class="p-3">
|
||||||
{{ if eq .Status "completed" }}
|
{{ if eq .Status "completed" }}
|
||||||
<a href="/reports/{{ .ReportToken }}.html" target="_blank" class="text-blue-400 hover:text-blue-300 text-xs font-medium underline underline-offset-2">View Report</a>
|
<a href="/reports/report_{{ .ReportToken }}.html" target="_blank" class="text-blue-400 hover:text-blue-300 text-xs font-medium underline underline-offset-2">Consultant Report</a>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
<span class="text-slate-600 text-xs">Pending</span>
|
<span class="text-slate-600 text-xs">Pending</span>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
|
||||||
250
AttackSurface/install.sh
Normal file
250
AttackSurface/install.sh
Normal file
|
|
@ -0,0 +1,250 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# install.sh — AASD (API Attack Surface Discovery) installer
|
||||||
|
#
|
||||||
|
# Supports: Debian 12+ | RHEL 9+ (AlmaLinux, Rocky Linux)
|
||||||
|
# Usage: sudo bash install.sh [--release-url URL]
|
||||||
|
#
|
||||||
|
# Environment variables (all optional):
|
||||||
|
# AASD_RELEASE_URL — URL to download the dist/ tarball
|
||||||
|
# AASD_AI_API_KEY — DeepSeek API key (prompted if empty)
|
||||||
|
# AASD_BASE_URL — Public base URL (prompted if empty)
|
||||||
|
# AASD_ADMIN_PASSWORD — Admin dashboard password (prompted if empty)
|
||||||
|
#
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
# Color helpers
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
|
||||||
|
info() { echo -e "${CYAN}[INFO]${NC} $*"; }
|
||||||
|
pass() { echo -e "${GREEN}[OK]${NC} $*"; }
|
||||||
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||||
|
fail() { echo -e "${RED}[FAIL]${NC} $*"; exit 1; }
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
# Root check
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
fail "This script must be run as root (sudo)."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
# OS detection
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
info "Detecting operating system..."
|
||||||
|
|
||||||
|
if [[ -f /etc/os-release ]]; then
|
||||||
|
. /etc/os-release
|
||||||
|
OS_ID="${ID,,}"
|
||||||
|
OS_VERSION_ID="${VERSION_ID:-0}"
|
||||||
|
elif [[ -f /etc/redhat-release ]]; then
|
||||||
|
OS_ID="rhel"
|
||||||
|
OS_VERSION_ID="$(rpm -q --qf '%{VERSION}' $(rpm -q --whatprovides redhat-release) 2>/dev/null || echo '0')"
|
||||||
|
else
|
||||||
|
fail "Unsupported OS. Only Debian 12+ and RHEL 9+ are supported."
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$OS_ID" in
|
||||||
|
debian|ubuntu)
|
||||||
|
PKG_MGR="apt-get"
|
||||||
|
PKG_UPDATE="$PKG_MGR update -qq"
|
||||||
|
PKG_INSTALL="$PKG_MGR install -y -qq"
|
||||||
|
info "Detected Debian/Ubuntu — using apt"
|
||||||
|
;;
|
||||||
|
rhel|centos|rocky|almalinux|fedora)
|
||||||
|
PKG_MGR="dnf"
|
||||||
|
PKG_UPDATE="$PKG_MGR check-update || true"
|
||||||
|
PKG_INSTALL="$PKG_MGR install -y -q"
|
||||||
|
info "Detected RHEL family — using dnf"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
fail "Unsupported OS: $OS_ID. Only Debian 12+ and RHEL 9+ are supported."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
# Prerequisites
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
info "Installing prerequisites..."
|
||||||
|
eval "$PKG_UPDATE"
|
||||||
|
eval "$PKG_INSTALL curl tar gzip"
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
# Create 'app' user
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
APP_USER="app"
|
||||||
|
APP_HOME="/opt/aasd"
|
||||||
|
|
||||||
|
if id "$APP_USER" &>/dev/null; then
|
||||||
|
pass "User '$APP_USER' already exists"
|
||||||
|
else
|
||||||
|
info "Creating user '$APP_USER' (system user, no login)..."
|
||||||
|
case "$OS_ID" in
|
||||||
|
debian|ubuntu)
|
||||||
|
useradd --system --no-create-home --shell /usr/sbin/nologin "$APP_USER"
|
||||||
|
;;
|
||||||
|
rhel|centos|rocky|almalinux|fedora)
|
||||||
|
useradd --system --no-create-home --shell /sbin/nologin "$APP_USER"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
pass "User '$APP_USER' created"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
# Determine source of dist/
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
RELEASE_URL="${AASD_RELEASE_URL:-}"
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
LOCAL_DIST="$SCRIPT_DIR/dist"
|
||||||
|
|
||||||
|
if [[ -n "$RELEASE_URL" ]]; then
|
||||||
|
# Download from URL
|
||||||
|
info "Downloading release archive from: $RELEASE_URL"
|
||||||
|
TMP_DIR=$(mktemp -d)
|
||||||
|
TARBALL="$TMP_DIR/aasd-release.tar.gz"
|
||||||
|
curl -fsSL "$RELEASE_URL" -o "$TARBALL"
|
||||||
|
[[ -s "$TARBALL" ]] || fail "Downloaded archive is empty — check RELEASE_URL"
|
||||||
|
|
||||||
|
info "Extracting to $APP_HOME ..."
|
||||||
|
mkdir -p "$APP_HOME"
|
||||||
|
tar -xzf "$TARBALL" -C "$APP_HOME" --strip-components=1
|
||||||
|
rm -rf "$TMP_DIR"
|
||||||
|
pass "Release downloaded and extracted"
|
||||||
|
elif [[ -d "$LOCAL_DIST" ]]; then
|
||||||
|
# Copy from local dist/
|
||||||
|
info "Copying local dist/ to $APP_HOME ..."
|
||||||
|
mkdir -p "$APP_HOME"
|
||||||
|
cp -r "$LOCAL_DIST"/* "$APP_HOME/"
|
||||||
|
pass "Local dist/ copied"
|
||||||
|
else
|
||||||
|
fail "No release URL set (AASD_RELEASE_URL) and no local dist/ found at $LOCAL_DIST"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
# Set ownership
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
chown -R "$APP_USER:$APP_USER" "$APP_HOME"
|
||||||
|
chmod 755 "$APP_HOME"
|
||||||
|
pass "Ownership set to $APP_USER"
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
# Create runtime directories
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
mkdir -p "$APP_HOME/reports" "$APP_HOME/logs"
|
||||||
|
chown "$APP_USER:$APP_USER" "$APP_HOME/reports" "$APP_HOME/logs"
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
# Configure secrets (prompt if not set via env)
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
AI_API_KEY="${AASD_AI_API_KEY:-}"
|
||||||
|
BASE_URL="${AASD_BASE_URL:-}"
|
||||||
|
ADMIN_PASS="${AASD_ADMIN_PASSWORD:-}"
|
||||||
|
|
||||||
|
if [[ -z "$AI_API_KEY" ]]; then
|
||||||
|
echo ""
|
||||||
|
read -rp "Enter DeepSeek API key (or press Enter to skip AI reports): " AI_API_KEY
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$BASE_URL" ]]; then
|
||||||
|
echo ""
|
||||||
|
read -rp "Enter public base URL (e.g. https://aasd.sechpoint.app): " BASE_URL
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$ADMIN_PASS" ]]; then
|
||||||
|
echo ""
|
||||||
|
read -rp "Enter admin dashboard password: " ADMIN_PASS
|
||||||
|
if [[ -z "$ADMIN_PASS" ]]; then
|
||||||
|
ADMIN_PASS="$(tr -dc A-Za-z0-9 </dev/urandom 2>/dev/null | head -c 16 || echo "aasd$(date +%s)")"
|
||||||
|
warn "Generated random password: $ADMIN_PASS"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Write config.yaml
|
||||||
|
CONFIG_FILE="$APP_HOME/config.yaml"
|
||||||
|
cat > "$CONFIG_FILE" <<CONFIGEOF
|
||||||
|
ai:
|
||||||
|
provider_url: "https://api.deepseek.com"
|
||||||
|
api_key: "${AI_API_KEY:-}"
|
||||||
|
model: "deepseek-chat"
|
||||||
|
|
||||||
|
server:
|
||||||
|
base_url: "${BASE_URL:-}"
|
||||||
|
|
||||||
|
admin:
|
||||||
|
username: "sechpoint"
|
||||||
|
password: "${ADMIN_PASS:-}"
|
||||||
|
CONFIGEOF
|
||||||
|
|
||||||
|
chown "$APP_USER:$APP_USER" "$CONFIG_FILE"
|
||||||
|
chmod 600 "$CONFIG_FILE"
|
||||||
|
pass "Configuration written to $CONFIG_FILE"
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
# Create systemd service
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
SYSTEMD_FILE="/etc/systemd/system/aasd.service"
|
||||||
|
|
||||||
|
cat > "$SYSTEMD_FILE" <<SERVICEEOF
|
||||||
|
[Unit]
|
||||||
|
Description=AASD — API Attack Surface Discovery
|
||||||
|
Documentation=https://github.com/valllabh/aasd
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=$APP_USER
|
||||||
|
Group=$APP_USER
|
||||||
|
WorkingDirectory=$APP_HOME
|
||||||
|
ExecStart=$APP_HOME/aasd
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
LimitNOFILE=4096
|
||||||
|
|
||||||
|
# Security hardening
|
||||||
|
NoNewPrivileges=true
|
||||||
|
ProtectSystem=full
|
||||||
|
ProtectHome=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
SERVICEEOF
|
||||||
|
|
||||||
|
chmod 644 "$SYSTEMD_FILE"
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable aasd.service
|
||||||
|
pass "Systemd service created and enabled"
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
# Start service
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
info "Starting aasd.service..."
|
||||||
|
systemctl start aasd.service
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
if systemctl is-active --quiet aasd.service; then
|
||||||
|
pass "aasd.service is running"
|
||||||
|
else
|
||||||
|
warn "Service did not start — check: sudo journalctl -u aasd -n 50 --no-pager"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
# Summary
|
||||||
|
# ──────────────────────────────────────────────
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}══════════════════════════════════════════════${NC}"
|
||||||
|
echo -e "${GREEN} AASD installation complete${NC}"
|
||||||
|
echo -e "${GREEN}══════════════════════════════════════════════${NC}"
|
||||||
|
echo ""
|
||||||
|
echo " URL: http://$(hostname -I 2>/dev/null | awk '{print $1}'):8080"
|
||||||
|
echo " Binary: $APP_HOME/aasd"
|
||||||
|
echo " Config: $CONFIG_FILE"
|
||||||
|
echo " Service: aasd.service"
|
||||||
|
echo ""
|
||||||
|
echo " Admin login: sechpoint / ${ADMIN_PASS:-<see config>}"
|
||||||
|
echo ""
|
||||||
|
echo " Manage:"
|
||||||
|
echo " sudo systemctl status aasd"
|
||||||
|
echo " sudo journalctl -u aasd -f"
|
||||||
|
echo ""
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/skip2/go-qrcode"
|
"github.com/skip2/go-qrcode"
|
||||||
|
|
||||||
"aasd/internal/ai"
|
"aasd/internal/ai"
|
||||||
|
|
@ -29,6 +30,23 @@ import (
|
||||||
"aasd/internal/scanner"
|
"aasd/internal/scanner"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// AppConfig holds application-level configuration from config.yaml.
|
||||||
|
type AppConfig struct {
|
||||||
|
Server ServerConfig `yaml:"server"`
|
||||||
|
Admin AdminConfig `yaml:"admin"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServerConfig holds server-level settings.
|
||||||
|
type ServerConfig struct {
|
||||||
|
BaseURL string `yaml:"base_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminConfig holds admin dashboard credentials.
|
||||||
|
type AdminConfig struct {
|
||||||
|
Username string `yaml:"username"`
|
||||||
|
Password string `yaml:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
emailRegex = regexp.MustCompile(`^[^@]+@[^@]+\.[^@]+$`)
|
emailRegex = regexp.MustCompile(`^[^@]+@[^@]+\.[^@]+$`)
|
||||||
projectDir string
|
projectDir string
|
||||||
|
|
@ -42,9 +60,20 @@ func main() {
|
||||||
projectDir = "."
|
projectDir = "."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read public base URL from environment (used for QR codes, email links)
|
// Read config.yaml for server and admin settings
|
||||||
// e.g. AASD_BASE_URL=https://coding.sechpoint.app
|
var appCfg AppConfig
|
||||||
|
if cfgData, err := os.ReadFile(filepath.Join(projectDir, "config.yaml")); err == nil {
|
||||||
|
if err := yaml.Unmarshal(cfgData, &appCfg); err != nil {
|
||||||
|
fmt.Printf("Warning: failed to parse config.yaml: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read public base URL: env var takes precedence, fallback to config.yaml
|
||||||
|
// Used for QR codes and email report links
|
||||||
baseURL := os.Getenv("AASD_BASE_URL")
|
baseURL := os.Getenv("AASD_BASE_URL")
|
||||||
|
if baseURL == "" {
|
||||||
|
baseURL = appCfg.Server.BaseURL
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize AI client (reads api_key from config.yaml in working directory)
|
// Initialize AI client (reads api_key from config.yaml in working directory)
|
||||||
deepSeekClient, err := ai.NewClient()
|
deepSeekClient, err := ai.NewClient()
|
||||||
|
|
@ -115,8 +144,8 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect to simulation page with token
|
// Redirect to analysing page with token
|
||||||
c.Redirect(http.StatusFound, "/simulation?token="+result.ReportToken)
|
c.Redirect(http.StatusFound, "/analysing?token="+result.ReportToken)
|
||||||
})
|
})
|
||||||
|
|
||||||
// ----- STATUS: Poll endpoint -----
|
// ----- STATUS: Poll endpoint -----
|
||||||
|
|
@ -152,8 +181,11 @@ func main() {
|
||||||
c.JSON(http.StatusNotFound, gin.H{"error": "Scan not found"})
|
c.JSON(http.StatusNotFound, gin.H{"error": "Scan not found"})
|
||||||
})
|
})
|
||||||
|
|
||||||
// ----- ADMIN: Dashboard -----
|
// ----- ADMIN: Dashboard (basic auth) -----
|
||||||
router.GET("/admin-dashboard", func(c *gin.Context) {
|
adminGroup := router.Group("/admin-dashboard", gin.BasicAuth(gin.Accounts{
|
||||||
|
appCfg.Admin.Username: appCfg.Admin.Password,
|
||||||
|
}))
|
||||||
|
adminGroup.GET("", func(c *gin.Context) {
|
||||||
results := orch.GetAllResults()
|
results := orch.GetAllResults()
|
||||||
total, completed, running := orch.CountStats()
|
total, completed, running := orch.CountStats()
|
||||||
|
|
||||||
|
|
@ -219,7 +251,9 @@ func main() {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// ----- SIMULATION: Serve new simulation page with token support -----
|
// ----- ANALYSING: Serve the analysis progress page with token support -----
|
||||||
|
router.StaticFile("/analysing", "./static/simulation.html")
|
||||||
|
// Keep old /simulation route for backward compatibility
|
||||||
router.StaticFile("/simulation", "./static/simulation.html")
|
router.StaticFile("/simulation", "./static/simulation.html")
|
||||||
|
|
||||||
// ----- DOWNLOAD: Serve the raw scan results for debugging -----
|
// ----- DOWNLOAD: Serve the raw scan results for debugging -----
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@
|
||||||
resetButton();
|
resetButton();
|
||||||
} else {
|
} else {
|
||||||
// Shouldn't get here, but handle gracefully
|
// Shouldn't get here, but handle gracefully
|
||||||
window.location.href = '/simulation?domain=' + encodeURIComponent(email.split('@')[1]);
|
window.location.href = '/analysing?domain=' + encodeURIComponent(email.split('@')[1]);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showError('Network error. Please check your connection.');
|
showError('Network error. Please check your connection.');
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@
|
||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<div class="text-center text-xs text-slate-600 mt-6">
|
<div class="text-center text-xs text-slate-600 mt-6">
|
||||||
GITEX 2026 — sechpoint.app | <a href="/admin-dashboard" class="text-blue-500 hover:underline">Consultant Dashboard</a>
|
GITEX 2026 — sechpoint.app
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@
|
||||||
<td class="p-3 text-slate-400 hidden sm:table-cell">{{ len .Subdomains }}</td>
|
<td class="p-3 text-slate-400 hidden sm:table-cell">{{ len .Subdomains }}</td>
|
||||||
<td class="p-3">
|
<td class="p-3">
|
||||||
{{ if eq .Status "completed" }}
|
{{ if eq .Status "completed" }}
|
||||||
<a href="/reports/{{ .ReportToken }}.html" target="_blank" class="text-blue-400 hover:text-blue-300 text-xs font-medium underline underline-offset-2">View Report</a>
|
<a href="/reports/report_{{ .ReportToken }}.html" target="_blank" class="text-blue-400 hover:text-blue-300 text-xs font-medium underline underline-offset-2">Consultant Report</a>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
<span class="text-slate-600 text-xs">Pending</span>
|
<span class="text-slate-600 text-xs">Pending</span>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
|
||||||
85
README.md
85
README.md
|
|
@ -1,84 +1,39 @@
|
||||||
# Resilience Challenge - Interactive Booth Experience
|
# GITEX 2026 — Sechpoint Booth Applications
|
||||||
|
|
||||||
An interactive booth experience that captures corporate emails, runs background security simulations using GoTestWAF, and provides a "Resilience Code" for lead conversion.
|
This repository contains the applications powering the **Sechpoint Aftica** booth at **GITEX 2026**. Each application demonstrates a unique aspect of the Sechpoint cybersecurity platform — from attack surface discovery and WAF testing to automated remediation and compliance reporting.
|
||||||
|
|
||||||
## Project Structure
|
## Repository Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
gitex2026/
|
gitex2026/
|
||||||
├── AttackSurface/ # Main application folder
|
├── AttackSurface/ # API Attack Surface Discovery — booth demo app
|
||||||
│ ├── dist/ # Deployment directory (self-contained)
|
└── README.md # This file
|
||||||
│ │ ├── aasd # Compiled application binary
|
|
||||||
│ │ ├── static/ # HTML/JS/CSS frontend files
|
|
||||||
│ │ ├── templates/ # Go HTML templates
|
|
||||||
│ │ ├── gotestwaf # GoTestWAF binary
|
|
||||||
│ │ ├── domain-scan # Domain discovery tool
|
|
||||||
│ │ ├── testcases/ # GoTestWAF test cases
|
|
||||||
│ │ ├── config.yaml # AI provider configuration
|
|
||||||
│ │ ├── prompt.txt # AI system prompt
|
|
||||||
│ │ ├── reports/ # Generated scan reports
|
|
||||||
│ │ ├── logs/ # Server logs
|
|
||||||
│ │ └── start.sh # Startup script
|
|
||||||
│ ├── src/ # Source code (Go server, frontend)
|
|
||||||
│ │ ├── cmd/ # Go command entry points
|
|
||||||
│ │ ├── static/ # HTML/JS/CSS frontend files
|
|
||||||
│ │ ├── templates/ # Go HTML templates
|
|
||||||
│ │ ├── gotestwaf/ # Vendored GoTestWAF source
|
|
||||||
│ │ ├── internal/ # Internal Go packages
|
|
||||||
│ │ └── pkg/ # Public Go packages
|
|
||||||
│ ├── docs/ # Documentation (CHANGELOG.md, DEVELOPMENT_STATUS.md)
|
|
||||||
│ ├── VERSION # Current version
|
|
||||||
│ └── .gitignore
|
|
||||||
└── README.md # This file
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Tech Stack
|
## Applications
|
||||||
|
|
||||||
- **Backend**: Go (Golang) with Gin web framework
|
| Application | Directory | Description |
|
||||||
- **Frontend**: HTML5, JavaScript, CSS
|
|-------------|-----------|-------------|
|
||||||
- **Security Testing**: GoTestWAF (external binary)
|
| **AASD** — API Attack Surface Discovery | `AttackSurface/` | Interactive booth experience: email capture → domain discovery → GoTestWAF scan → AI resilience report |
|
||||||
- **Data Storage**: In-memory map (volatile) for demo purposes
|
|
||||||
|
|
||||||
## Features
|
Each application directory contains its own `README.md` with detailed setup, deployment, and usage instructions.
|
||||||
|
|
||||||
1. **Email Capture & Validation**: POST `/start` endpoint with regex validation and security checks
|
## Deployment
|
||||||
2. **Background Security Scan**: Concurrent GoTestWAF execution with 120-second timeout
|
|
||||||
3. **Real-time Status Tracking**: Polling endpoint `/scan-status/:domain` for live updates
|
|
||||||
4. **Interactive Simulation**: Frontend step sequencer with animated progress visualization
|
|
||||||
5. **Resilience Code**: Static code `WX-2026` displayed after simulation completion
|
|
||||||
6. **Consultant Dashboard**: Protected `/admin-dashboard` to monitor all scan results
|
|
||||||
7. **Report Generation**: HTML reports served at `/reports/report_*.html`
|
|
||||||
8. **Graceful Shutdown**: OS signal handling (SIGINT, SIGTERM) with proper cleanup
|
|
||||||
|
|
||||||
## Quick Start
|
Applications are deployed as systemd services under `/opt/`. See each application's `install.sh` for automated deployment:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Option 1: Run from dist/ (recommended - no build needed)
|
# Deploy AttackSurface (example)
|
||||||
cd AttackSurface/dist
|
cd AttackSurface
|
||||||
./start.sh
|
sudo bash install.sh
|
||||||
|
|
||||||
# Option 2: Build and run from source
|
|
||||||
cd AttackSurface/src
|
|
||||||
go build -o ../dist/aasd ./cmd/aasd/
|
|
||||||
cd ../dist
|
|
||||||
./start.sh
|
|
||||||
|
|
||||||
# Access the application
|
|
||||||
# Frontend: http://localhost:8080 (or booth Wi-Fi IP)
|
|
||||||
# Admin dashboard: http://localhost:8080/admin-dashboard
|
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note**: Before running, set your DeepSeek API key in `dist/config.yaml` if AI-generated reports are desired. Without it, the app uses built-in fallback reports.
|
## Requirements
|
||||||
|
|
||||||
## Development
|
- **OS**: Debian 12+ or RHEL 9+ (AlmaLinux / Rocky Linux)
|
||||||
|
- **Runtime**: Go 1.25+ (for building from source)
|
||||||
### Current Status
|
- **Network**: Outbound HTTPS access for API calls and tool downloads
|
||||||
**Version 2026-04.1**
|
|
||||||
|
|
||||||
### Documentation
|
|
||||||
- [CHANGELOG.md](AttackSurface/docs/CHANGELOG.md) - Version history and detailed changes
|
|
||||||
- [DEVELOPMENT_STATUS.md](AttackSurface/docs/DEVELOPMENT_STATUS.md) - Current status and testing results
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Proprietary - For internal event use only.
|
Proprietary — For internal event use at GITEX 2026.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue