nawasara / secscan
Security threat detection for the Nawasara superapp — scans monitored MySQL databases (WordPress focus) for judol/gambling SEO spam, defacement, phishing, and malware indicators. Read-only: detect + alert, never remediate.
Requires
- php: ^8.1
- ext-pdo: *
- illuminate/support: ^10.0|^12.0
- livewire/livewire: ^3.0
- nawasara/alerting: *
- nawasara/auth-primitives: *
- nawasara/cloudflare: *
- nawasara/database-monitor: *
- nawasara/notification: *
- nawasara/registry: *
- nawasara/sync: *
- nawasara/ui: *
- nawasara/vault: *
- spatie/laravel-permission: ^6.0
This package is auto-updated.
Last update: 2026-08-04 07:51:37 UTC
README
Security threat detection & response for the Nawasara superapp. Two independent sources of signal feed one dashboard:
- Database scanner — reads the MySQL databases already monitored by
nawasara/database-monitor(read-only) for indicators of compromise on hosted sites (WordPress in particular). - Host agents (
nawasara-agent) — a Go binary installed on each server that tails logs, watches SSH, and scans the filesystem for webshells / backdoors, reporting incidents + findings back to the dashboard.
Everything is detect + alert — the database scanner never writes to OPD
databases. Findings get a confidence score (0-100) and severity, a triage
workflow (open / acknowledged / false-positive / resolved), a dashboard, and
alerts via nawasara/alerting.
Dashboard pages
| Page | Route | Isi |
|---|---|---|
| Dashboard | /nawasara-secscan/dashboard |
Ringkasan: agent online, incident kritis, temuan mendesak |
| Temuan Website | /nawasara-secscan/findings |
Temuan dari database scanner (judol/malware/defacement) + triage |
| Incidents | /nawasara-secscan/incidents |
Insiden dari agent (SSH brute-force, exploit chain, scanner bot) |
| Agents | /nawasara-secscan/agents |
Daftar agent terpasang + detail (scan findings, command queue) |
| IP Timeline | /nawasara-secscan/ip/{ip} |
Semua insiden dari satu IP sumber |
Permissions: secscan.view, secscan.finding.triage, secscan.agent.view,
secscan.agent.scan, secscan.agent.command.
Setup (database scanner)
nawasara/database-monitorharus dikonfigurasi (Vault groupdatabase-monitor) — secscan pakai ulang koneksi read-only-nya.- Seed permission:
php artisan db:seed --class="Nawasara\Secscan\Database\Seeders\PermissionSeeder" - Scan berjalan otomatis (scheduler). Trigger manual dari tombol "Pindai sekarang"
di dashboard, atau:
\Nawasara\Secscan\Jobs\ScanWordpressJob::dispatch(triggerSource: 'manual');
API
Butuh nawasara/api. Kalau paket itu tidak terpasang, route tidak di-mount dan tidak ada yang berubah.
Autentikasi: Authorization: Bearer nws_… atau X-API-Key: nws_…. Semua path berawalan /api/v1/secscan.
Jangan tertukar dengan /api/agent/* — itu jalur agent melapor ke server, autentikasinya X-Agent-Key, dan tidak ada hubungannya dengan token maupun scope di bawah.
Scope
| Scope | Akses |
|---|---|
secscan.incident.read |
Insiden dari agent |
secscan.finding.read |
Temuan situs |
secscan.agent.read |
Status agent |
secscan.stats.read |
Statistik agregat |
secscan.ipblock.read |
Daftar IP terblokir |
secscan.ipblock.write |
Block IP baru |
secscan.ipblock.delete |
Buka blokir |
Dipisah per domain supaya token bisa diberi akses sempit — konsumen yang hanya butuh statistik tidak perlu ikut bisa membaca tiap insiden beserta IP penyerangnya. Atur di Pengaturan → API Token.
Endpoint
| Method | Path | Query params |
|---|---|---|
| GET | /incidents |
severity, type, ip, blocked, since, per_page |
| GET | /incidents/{incidentId} |
|
| GET | /findings |
status (default aktif; all untuk semua), threat, severity, q, per_page |
| GET | /findings/{id} |
|
| GET | /agents |
status, per_page |
| GET | /agents/{agentId} |
|
| GET | /stats |
days (1–90, default 1) atau from+to (ISO8601) |
| GET/POST/DELETE | /ip-blocks |
lihat bagian IP block |
Parameter multi-nilai menerima koma: ?severity=high,critical.
curl -H "Authorization: Bearer nws_xxx" \ "https://nawasara.ponorogo.go.id/api/v1/secscan/stats?days=7"
{
"data": {
"total": 1,
"by_severity": { "critical": 1 },
"by_type": { "sqli_attempt": 1 },
"top_ips": [{ "ip": "203.0.113.99", "count": 1, "score": 95 }],
"top_hosts": [{ "host": "dinaskesehatan.ponorogo.go.id", "count": 1 }],
"blocked": 0, "blocked_active": 0,
"agents_online": 1, "agents_total": 1
},
"meta": { "from": "…", "to": "…" }
}
Angka di sini berasal dari IncidentStatsCollector yang sama dengan email digest harian, jadi keduanya tidak bisa berbeda diam-diam.
Yang tidak pernah dikembalikan
Tiap Resource adalah allow-list, bukan dump yang disaring. Sengaja ditahan:
evidenceinsiden — baris log mentah. Satu request line utuh bisa memuat query string dengan token atau session id, username SSH yang dicoba, dan payload serangan apa adanya. Hanya fieldhost-nya yang diambil, muncul sebagaitargets.metadatainsiden — blob bebas dari agent, hanya divalidasinullable|array. Isinya tidak terkendali.evidencetemuan — memuataccounts.recent_admin_listdannon_gov_email_admins: daftar akun admin WordPress beserta email. PII, sekaligus daftar sasaran phishing yang rapi.db_name— nama schema database di server bersama.- Detail agent:
api_key_hash(kredensial),ip_local(IP privat),hostname,agent_version,os,web_server,plugins_active. Satu per satu terlihat sepele; digabung menjadi "server X menjalankan nginx di Ubuntu 20.04", yaitu daftar belanja bagi penyerang yang mencari versi rentan. AgentCommandseluruhnya — itu bidang kendali. Mengeksposnya, bahkan untuk dibaca, memberi tahu perintah jarak jauh apa yang bisa dijalankan di server OPD.cf_rule_iddannotesIP block — handle Cloudflare dan jejak audit.
Memperlebar daftar ini adalah keputusan sadar, bukan kemudahan: ubah Resource-nya, dan tulis alasannya di commit yang sama.
Batasi token berdasarkan IP
top_hosts adalah daftar situs milik kita sendiri yang paling sering diserang. Berguna untuk memprioritaskan pertahanan — tapi kalau tokennya bocor, itu daftar sasaran siap pakai. Hal yang sama berlaku untuk source_ip pada insiden.
Pasang IP allow-list pada setiap token yang membawa scope secscan, lewat halaman API Token.
Panduan Install nawasara-agent
Agen keamanan yang dipasang di tiap server target. Memantau log (nginx, SSH, Laravel), mendeteksi serangan (brute-force, exploit, scanner bot), dan memindai file berbahaya (webshell/backdoor), lalu melaporkan ke dashboard.
Butuh: akses root/sudo · Linux (amd64/arm64) · ± 3 menit
Cara cepat — satu baris (direkomendasikan)
Jalankan di server target sebagai root:
curl -sSL https://nawasara.ponorogo.go.id/agent/install.sh | bash
Skrip ini otomatis:
- Unduh binary sesuai arsitektur (amd64/arm64)
- Daftar ke dashboard → dapat
agent_id+api_keyotomatis - Tulis config (
/etc/nawasara-agent/config.yaml,chmod 600) - Pasang service systemd (
nawasara-agent run --config …) - Jalankan service
Tidak perlu langkah manual. Output sukses:
==> Registering agent with dashboard...
Registered — agent_id: RmKhmpjHXaAoPXYOL4vx…
==> Installation complete! Agent registered + running.
config : /etc/nawasara-agent/config.yaml
logs : tail -f /var/log/nawasara-agent/agent.log
Sudah pernah pasang? Jika
/etc/nawasara-agent/config.yamlsudah ada, skrip melewati pendaftaran (kredensial lama dipertahankan). Untuk daftar ulang dari awal, hapus config dulu:rm -f /etc/nawasara-agent/config.yaml curl -sSL https://nawasara.ponorogo.go.id/agent/install.sh | bash
Verifikasi
# 1. Status service — harus "active (running)" systemctl status nawasara-agent # 2. Pantau log — cari heartbeat, jangan ada "HTTP 403" berulang tail -f /var/log/nawasara-agent/agent.log
Lalu buka Dashboard → Security Scan → Agents. Server muncul online dalam ± 30 detik (interval heartbeat).
Konfigurasi
Config ditulis otomatis ke /etc/nawasara-agent/config.yaml. Sentuh hanya untuk
menyesuaikan path log atau menyalakan pemindai file.
| Field | Arti |
|---|---|
dashboard_url |
Alamat dashboard Nawasara (terisi otomatis) |
agent_id |
ID unik agen (dapat otomatis saat pendaftaran) |
api_key |
Kunci auth (nwa_…, dapat otomatis, disimpan chmod 600) |
heartbeat_interval |
Interval heartbeat (default 30s) |
plugins.enabled |
Kolektor aktif: nginx, ssh, laravel |
plugins.laravel.log_paths |
Daftar path log Laravel yang dipantau |
scanner.enabled |
Pemindai file webshell/backdoor (default false) |
scanner.scan_interval |
Interval scan (default 6h) |
scanner.web_dirs |
Direktori web yang dipindai saat scanner aktif |
scanner.watch_paths |
Path yang dipantau perubahan integritas (mis. .env, /etc/nginx) |
Struktur config (contoh):
dashboard_url: https://nawasara.ponorogo.go.id agent_id: <auto> api_key: <auto> heartbeat_interval: 30s plugins: enabled: - nginx - ssh - laravel laravel: log_paths: - /var/www/html/storage/logs/*.log - /home/*/public_html/storage/logs/*.log scanner: enabled: false # set true untuk aktifkan pemindai file (Fase 3) scan_interval: 6h web_dirs: - /var/www/html - /home/*/public_html watch_paths: - /etc/nginx - /var/www/html/.env hash_db: /var/lib/nawasara-agent/hashes.db
Menyalakan pemindai file (Fase 3): edit config → scanner.enabled: true →
sesuaikan web_dirs & watch_paths → restart:
nano /etc/nawasara-agent/config.yaml systemctl restart nawasara-agent
Cara manual (kalau curl | bash dilarang kebijakan server)
1. Unduh binary (ganti amd64 → arm64 untuk server ARM):
curl -sSL -o /usr/local/bin/nawasara-agent \ https://nawasara.ponorogo.go.id/agent/download/latest/linux/amd64/nawasara-agent chmod +x /usr/local/bin/nawasara-agent
2. Daftarkan agen (catat agent_id + api_key — api_key hanya muncul sekali):
curl -s -X POST https://nawasara.ponorogo.go.id/api/agent/register \ -H 'Content-Type: application/json' \ -d "{\"name\":\"$(hostname)\",\"hostname\":\"$(hostname)\",\"os\":\"linux\",\"arch\":\"$(uname -m)\"}"
3. Tulis config /etc/nawasara-agent/config.yaml — tempel agent_id/api_key
dari langkah 2, ikuti struktur di atas.
4. Buat service systemd /etc/systemd/system/nawasara-agent.service.
⚠️ ExecStart wajib pakai subcommand run:
[Unit] Description=Nawasara Security Agent After=network.target [Service] Type=simple ExecStart=/usr/local/bin/nawasara-agent run --config /etc/nawasara-agent/config.yaml Restart=always RestartSec=10 User=root StandardOutput=append:/var/log/nawasara-agent/agent.log StandardError=append:/var/log/nawasara-agent/agent.log [Install] WantedBy=multi-user.target
5. Aktifkan & jalankan:
systemctl daemon-reload
systemctl enable --now nawasara-agent
Pemecahan masalah
🔴 Skrip berhenti "Registration failed" — endpoint pendaftaran tak terjangkau (firewall / tantangan bot Cloudflare memblokir curl dari VM). Uji manual:
curl -s -o /dev/null -w "%{http_code}\n" -X POST \ https://nawasara.ponorogo.go.id/api/agent/register \ -H 'Content-Type: application/json' \ -d '{"name":"t","hostname":"t","os":"linux","arch":"x86_64"}'
Harus 201. Kalau 403/timeout → minta admin membuka jalur /agent/* dari IP
server ini di WAF Cloudflare.
🔴 Log terus "HTTP 403, buffering" — laporan ditolak; buffer lama menyimpan payload gagal. Bersihkan buffer lalu restart:
rm -f /var/lib/nawasara-agent/buffer.db systemctl restart nawasara-agent
Kalau masih 403, sumbernya bukan di agen — hubungi admin dashboard untuk cek
gating /api/agent/*.
🟠 status=203/EXEC saat start — ExecStart tanpa subcommand run. Pastikan
barisnya … nawasara-agent run --config …, lalu:
systemctl daemon-reload && systemctl restart nawasara-agent
🟠 Binary hanya beberapa byte / "Not Found" — unduhan mengembalikan halaman error. Cek ukuran (harus belasan MB):
ls -lh /usr/local/bin/nawasara-agent
Kalau kecil → repo release belum publik atau tag rilis salah. Unduh ulang setelah admin mengonfirmasi release tersedia.
Checklist akhir
- Binary di
/usr/local/bin/nawasara-agent(belasan MB) -
agent_id&api_keytidak kosong di/etc/nawasara-agent/config.yaml -
systemctl status nawasara-agent→active (running) - Log ada heartbeat, tidak ada
403berulang - Server tampil online di Security Scan → Agents
Agent binary release
Binary di-build via GitHub Actions (release.yml) saat push tag ke repo
nawasara/agent (linux/amd64 + linux/arm64). Dashboard menyajikan:
GET /agent/install.sh— installer one-liner (text/plain)GET /agent/download/latest/linux/{arch}/nawasara-agent— redirect ke GitHub release asset terbaru
Repo release harus public agar download asset tak 404.
Roadmap
- F1: SQL signal detector + findings + triage UI + alerts. ✅
- F2: Host agent — log collectors (nginx/ssh/laravel) + incident reporting. ✅
- F3: Agent file scanner — webshell/backdoor signatures + file integrity. ✅
- F4: Live HTTP probe (cloaking, redirect-on-fetch) via sidecar.
- F5: Auto-response — block malicious source IP via
nawasara/opnsensefirewall blocklist (FirewallBlocklistService::block($ip)).