laravel-security-monitor maintained by robyajo
Laravel Security Monitor (Bulwark)
Laravel Security Monitor (Bulwark) adalah paket keamanan komprehensif (Self-Hosted WAF & Threat Engine) berbasis Headless REST API untuk ekosistem Laravel. Paket ini murni PHP Composer library (Zero-NPM / standar Spatie) yang dirancang khusus untuk memproteksi aplikasi web internal dari serangan siber tingkat lanjut, injeksi payload pentest, eksploitasi webshell, dan brute force tanpa mengikat aplikasi ke template frontend tertentu.
📚 Portal Dokumentasi Resmi Lengkap: Tersedia 25 bab dokumentasi mendalam di direktori
documents/serta portal interaktif offlinedocuments/index.html.
🌟 Fitur Utama
-
Self-Hosted WAF & Zero-Tolerance Threat Detection:
- Deteksi instan tanpa batas ambang (zero-tolerance) untuk null-byte upload (
.php%00.jpg), ekstensi ganda (.php.jpg), path traversal (../../../public/), probe file sensitif (.htaccess,.env,.git), dan SSTI canary ({{7*7}}). - Deteksi komprehensif untuk SQL Injection, Cross-Site Scripting (XSS), Local File Inclusion (LFI), Command Injection, dan Scanner User-Agents.
- Pola regex yang diperketat dan kebal terhadap serangan ReDoS (Regular Expression Denial of Service).
- Deteksi instan tanpa batas ambang (zero-tolerance) untuk null-byte upload (
-
Isolasi Perangkat Granular (Device-Level Quarantine):
- Dukungan isolasi di tingkat perangkat menggunakan
device_id(WebRTC/fingerprint) danlocal_ip. - Memastikan perangkat penyerang terblokir tanpa mengganggu pengguna sah lain yang berbagi alamat IP publik yang sama (seperti kantor atau router Wi-Fi publik).
- Dukungan isolasi di tingkat perangkat menggunakan
-
Tiket Banding & Permohonan Buka Blokir (Appeal Tickets):
- Endpoint publik REST API bagi pengguna yang terblokir untuk mengajukan tiket permohonan buka blokir beserta status pelacakannya.
- Antarmuka persetujuan admin yang secara otomatis mencabut karantina IP/perangkat dan memasukkannya ke whitelist.
-
Multi-Tier Stepped Login Lockout:
- Sistem pencegahan credential stuffing & brute force berjenjang (1 menit, 5 menit, 15 menit, 1 jam, hingga 24 jam).
- Pencatatan otomatis riwayat kegagalan otentikasi ke log audit keamanan.
-
Pure SVG CAPTCHA (Zero Dependency):
- Generator CAPTCHA berbasis matriks vektor SVG murni tanpa memerlukan ekstensi PHP GD atau Imagick.
- Token tantangan sekali pakai (stateless one-time challenge) yang aman secara kriptografis.
-
Server Integrity & Webshell Scanner:
- Pembuatan dan verifikasi baseline hash SHA-256 untuk berkas-berkas aplikasi inti.
- Pemindaian berkas mencurigakan / webshell (ekstensi ganda, skrip di direktori publik/upload, polyglot media).
- Fitur penghapusan berkas berbahaya yang aman dengan proteksi path traversal dan berkas sistem vital.
- Audit konfigurasi keamanan server (
APP_DEBUG, secure session cookie, Fortify 2FA).
-
Streaming Access Log Scanner:
- Pemindai berkas log mentah Apache / Nginx secara streaming berdaya hemat memori untuk menangkap penyerang yang ditolak oleh web server sebelum request mencapai proses PHP Laravel.
-
Headless & Arsitektur Terkopel Longgar:
- 100% REST API JSON murni.
- Model
Userdan nama tabel database sepenuhnya dapat dikonfigurasi melaluiconfig/security.php. - Trait
HasSecurityRelationsuntuk kemudahan integrasi relasi Eloquent.
📋 Persyaratan Sistem
- PHP:
^8.2,^8.3,^8.4, atau^8.5 - Laravel:
^10.0,^11.0,^12.0, atau^13.0
🚀 Instalasi
1. Pasang Paket via Composer
composer require robyajo/laravel-security-monitor
2. Publikasikan Aset Otomatis (security:install)
Gunakan perintah satu langkah untuk mempublikasikan dan menerapkan seluruh aset keamanan secara otomatis:
php artisan security:install
Aset yang Didapat Pengguna Setelah Menjalankan Perintah Ini:
- 📄
config/security.php: Konfigurasi lengkap WAF, ambang batas blokir, IP whitelist, stepped login lockout, SVG Captcha, dan log scanner. - 🗄️
database/migrations/(6 tabel): Menyiapkan tabelblocked_ips,security_logs,login_attempts,ip_unblock_requests,user_logins, dantrusted_ips. - 🌐
nginx.conf: Konfigurasi produksi Nginx Hardened WAF (Dual-zone rate limit, single-PHP execution/index.php, storage sandboxing). - 🛡️
public/.htaccess: Hardening web server Apache & LiteSpeed (Blokir dotfiles, double extension.php.jpg, file backup dump.sql, dan matikan directory listing).Catatan Keamanan: Jika
public/.htaccesslama sudah ada, installer otomatis membuat cadanganpublic/.htaccess.backup-YYYYMMDD_HHMMSSdan menyisipkan aturan keamanan di bawah tanpa merusak rewrite rules aplikasi Anda. - 🚫
resources/views/errors/blocked.blade.php: Halaman 403 default yang menampilkan alasan blokir, kode referensi, dan formulir banding yang terhubung langsung ke endpoint publik tiket banding. Dapat disesuaikan sesuai branding aplikasi Anda. - ⚙️ Penyematan Variabel ke
.env&.env.example: Installer secara otomatis menambahkan blok konfigurasi lengkap disertai penjelasan fungsi berbahasa Indonesia untuk setiap variabel (SECURITY_*danCAPTCHA_*) langsung ke berkas.envdan.env.exampleaplikasi Anda.
Opsi Perintah security:install:
| Opsi | Keterangan |
|---|---|
--force |
Menimpa seluruh berkas konfigurasi, migrasi, nginx.conf, public/.htaccess, dan halaman blokir. |
--without-nginx |
Melewatkan pembuatan berkas nginx.conf. |
--without-htaccess |
Melewatkan pembaruan berkas public/.htaccess. |
--without-views |
Melewatkan publikasi halaman blokir errors/blocked.blade.php. |
--with-htaccess |
Memaksa pembaruan berkas public/.htaccess. |
--without-env |
Melewatkan penyematan variabel konfigurasi ke berkas .env dan .env.example. |
Publikasi Aset Secara Parsial (Manual):
# 1. Konfigurasi saja
php artisan vendor:publish --tag=security-config
# 2. Migrasi database saja
php artisan vendor:publish --tag=security-migrations
# 3. Konfigurasi server Nginx saja
php artisan vendor:publish --tag=security-nginx
# 4. Aturan hardening Apache .htaccess saja
php artisan vendor:publish --tag=security-htaccess --force
# 5. Halaman blokir default saja
php artisan vendor:publish --tag=security-views --force
# 6. Seluruh aset sekaligus
php artisan vendor:publish --tag=security-all --force
Jalankan migrasi database:
php artisan migrate
⚙️ Konfigurasi & Integrasi
1. Tambahkan Trait ke Model User
Buka model App\Models\User.php dan tambahkan trait HasSecurityRelations:
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Internal\SecurityMonitor\Concerns\HasSecurityRelations;
class User extends Authenticatable
{
use HasSecurityRelations;
// ...
}
Trait ini menyediakan relasi Eloquent bawaan:
$user->logins(): Riwayat login pengguna (UserLogin).$user->trustedIps(): Daftar IP terpercaya pengguna (TrustedIp).$user->securityLogs(): Riwayat event keamanan pengguna (SecurityLog).$user->blockedIps(): Riwayat pemblokiran yang dilakukan oleh pengguna (BlockedIp).$user->resolvedTickets(): Tiket permohonan buka blokir yang diselesaikan admin (IpUnblockRequest).
2. Daftarkan Middleware
Pada Laravel 11 / 12 / 13 (bootstrap/app.php)
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
// Daftarkan penegakan WAF dan blokir IP secara global
$middleware->append(\Internal\SecurityMonitor\Http\Middleware\BlockIpAddress::class);
$middleware->append(\Internal\SecurityMonitor\Http\Middleware\DetectSecurityThreats::class);
// Lacak aktivitas sesi pengguna di grup web
$middleware->web(append: [
\Internal\SecurityMonitor\Http\Middleware\TrackUserActivity::class,
]);
// Alias middleware keamanan
$middleware->alias([
'security.block' => \Internal\SecurityMonitor\Http\Middleware\BlockIpAddress::class,
'security.detect' => \Internal\SecurityMonitor\Http\Middleware\DetectSecurityThreats::class,
'security.admin' => \Internal\SecurityMonitor\Http\Middleware\EnsureSecurityAdmin::class,
'security.activity' => \Internal\SecurityMonitor\Http\Middleware\TrackUserActivity::class,
]);
})
->create();
Pada Laravel 10 (app/Http/Kernel.php)
protected $middleware = [
// ...
\Internal\SecurityMonitor\Http\Middleware\BlockIpAddress::class,
\Internal\SecurityMonitor\Http\Middleware\DetectSecurityThreats::class,
];
protected $middlewareGroups = [
'web' => [
// ...
\Internal\SecurityMonitor\Http\Middleware\TrackUserActivity::class,
],
];
protected $middlewareAliases = [
'security.block' => \Internal\SecurityMonitor\Http\Middleware\BlockIpAddress::class,
'security.detect' => \Internal\SecurityMonitor\Http\Middleware\DetectSecurityThreats::class,
'security.admin' => \Internal\SecurityMonitor\Http\Middleware\EnsureSecurityAdmin::class,
'security.activity' => \Internal\SecurityMonitor\Http\Middleware\TrackUserActivity::class,
];
📡 Headless REST API Reference
Semua rute REST API didaftarkan secara default dengan prefix /api/security (dapat diubah melalui config('security.routes.prefix')).
1. Endpoint Publik
| Metode | URI | Deskripsi |
|---|---|---|
GET |
/api/security/captcha |
Menghasilkan SVG CAPTCHA dan mengembalikan gambar vector langsung beserta X-Captcha-Token |
POST |
/api/security/captcha/verify |
Memvalidasi jawaban CAPTCHA (phrase & token) |
POST |
/api/security/unblock-tickets/submit |
Mengirim permohonan banding pembukaan blokir IP/perangkat |
GET |
/api/security/unblock-tickets/check/{ticketNumber} |
Memeriksa status tiket permohonan banding |
Contoh Payload Pengajuan Tiket:
POST /api/security/unblock-tickets/submit
{
"name": "Budi Santoso",
"email": "budi@example.com",
"phone": "081234567890",
"reason": "Alamat IP kantor saya terblokir saat mengakses dashboard.",
"device_id": "client-uuid-1234",
"local_ip": "192.168.1.50"
}
2. Endpoint Pengguna Terautentikasi (auth)
| Metode | URI | Deskripsi |
|---|---|---|
POST |
/api/security/trusted-ips/save-my-ip |
Menyimpan alamat IP saat ini sebagai IP terpercaya pengguna |
3. Endpoint Manajemen Admin (auth + security.admin)
Log Keamanan & Analitik Serangan
| Metode | URI | Deskripsi |
|---|---|---|
GET |
/api/security/logs |
Mendapatkan log ancaman (paginasi, filter event/level/tanggal, statistik, tren 24 jam/7 hari) |
DELETE |
/api/security/logs/clear |
Mengosongkan seluruh log audit keamanan |
DELETE |
/api/security/logs/{id} |
Menghapus satu entri log keamanan tertentu |
Daftar Blokir IP & Perangkat
| Metode | URI | Deskripsi |
|---|---|---|
GET |
/api/security/blocked-ips |
Mendapatkan daftar IP yang diblokir (aktif & kedaluwarsa) |
POST |
/api/security/blocked-ips |
Memblokir IP atau perangkat secara manual |
GET |
/api/security/blocked-ips/{id} |
Melihat detail data pemblokiran |
PATCH |
/api/security/blocked-ips/{id}/toggle |
Mengaktifkan / menonaktifkan status blokir |
DELETE |
/api/security/blocked-ips/{id} |
Mencabut blokir dan menghapus entri |
Audit Server & Integritas Berkas
| Metode | URI | Deskripsi |
|---|---|---|
GET |
/api/security/server |
Laporan komprehensif audit keamanan server & integritas berkas |
POST |
/api/security/server/baseline |
Membuat baseline hash SHA-256 berkas aplikasi baru |
DELETE |
/api/security/server/baseline |
Menghapus baseline integritas |
DELETE |
/api/security/server/suspicious-files |
Menghapus berkas mencurigakan/webshell yang terdeteksi |
DELETE |
/api/security/lockouts/{id} |
Membuka kunci akun yang terkena lockout login berjenjang |
Sesi Pengguna & IP Terpercaya
| Metode | URI | Deskripsi |
|---|---|---|
GET |
/api/security/user-sessions |
Riwayat sesi login seluruh pengguna |
GET |
/api/security/user-sessions/realtime |
Daftar pengguna yang aktif secara real-time |
DELETE |
/api/security/user-sessions/{id} |
Menghapus log sesi pengguna |
DELETE |
/api/security/user-sessions/session/{sessionId} |
Memutus sesi pengguna tertentu (force logout) |
DELETE |
/api/security/trusted-ips/{id} |
Menghapus IP dari daftar terpercaya |
Pengelolaan Tiket Banding
| Metode | URI | Deskripsi |
|---|---|---|
GET |
/api/security/unblock-tickets |
Daftar seluruh tiket permohonan banding |
POST |
/api/security/unblock-tickets/{id}/respond |
Menyetujui atau menolak tiket (buka blokir & whitelist) |
DELETE |
/api/security/unblock-tickets/{id} |
Menghapus arsip tiket |
🛡️ Validation Rules Bawaan
Paket menyediakan aturan validasi siap pakai untuk request form aplikasi Anda:
1. SafeImageFile
Memvalidasi unggahan gambar dan mencegah serangan polyglot image (gambar JPEG/PNG sah yang diinjeksi kode <?php), ekstensi ganda berbahaya, dan SVG bereksekusi JavaScript/XSS:
use Internal\SecurityMonitor\Rules\SafeImageFile;
$request->validate([
'avatar' => ['required', 'file', new SafeImageFile(maxKilobytes: 2048)],
]);
2. SafeAssetPath
Memvalidasi string path aset gambar/ikon agar terbebas dari path traversal, probe direktori sensitif, dan file .htaccess:
use Internal\SecurityMonitor\Rules\SafeAssetPath;
$request->validate([
'icon_path' => ['required', 'string', new SafeAssetPath],
]);
3. ValidCaptcha
Memvalidasi verifikasi CAPTCHA SVG tanpa dependensi:
use Internal\SecurityMonitor\Rules\ValidCaptcha;
$request->validate([
'captcha' => ['required', new ValidCaptcha],
]);
💻 Perintah Artisan CLI
Paket ini menyertakan perintah Artisan lengkap untuk otomasi di server produksi:
1. Pemindaian Log Akses Web Server (security:scan-logs)
Memindai berkas log Apache atau Nginx, mendeteksi pola serangan, dan memblokir IP penyerang secara otomatis:
# Pratinjau temuan tanpa memodifikasi database (dry-run)
php artisan security:scan-logs --file=/var/log/nginx/access.log --dry-run
# Pindai, impor ke log keamanan, dan blokir IP penyerang zero-tolerance
php artisan security:scan-logs --file=/var/log/nginx/access.log --import --block
2. Manajemen Baseline Integritas Berkas (security:baseline)
# Menampilkan status verifikasi integritas berkas
php artisan security:baseline
# Membuat baseline baru
php artisan security:baseline --create
# Menghapus baseline
php artisan security:baseline --destroy
3. Membuka Blokir IP (security:unblock-ip)
php artisan security:unblock-ip 198.51.100.50
4. Pembersihan Log Kedaluwarsa (security:prune-logs)
# Menghapus log lebih tua dari durasi retensi terkonfigurasi (default: 90 hari)
php artisan security:prune-logs
# Menghapus log lebih tua dari 30 hari
php artisan security:prune-logs --days=30
5. Pembersihan Data Residu Pentest (security:purge-injected-data)
Mendeteksi dan menghapus payload injeksi sisa pengujian keamanan (seperti {{7*7}}, .htaccess, path traversal) dari tabel aplikasi:
# Mode simulasi (hanya mendeteksi data tercemar)
php artisan security:purge-injected-data
# Hapus data yang terindikasi
php artisan security:purge-injected-data --force
🌐 Konfigurasi Web Server Hardened
Paket ini menyertakan template konfigurasi hardened siap pakai untuk web server Nginx maupun Apache / LiteSpeed / cPanel.
1. Nginx Hardened WAF (nginx.conf)
Diterbitkan via php artisan vendor:publish --tag=security-nginx:
- Dua Zona Rate Limiting Terpisah:
auth_limit: 5 request/menit (burst 5) untuk endpoint sensitif (/login,/register,/forgot-password,/reset-password, dll.).general_limit: 30 request/detik (burst 50) untuk rute umum aplikasi.
- Proteksi Aset Statis Vite / Frontend:
- Direktori
/build/dibebaskan dari rate-limiting agar chunk parallel JS tidak memicu HTTP 429 atauNS_ERROR_CORRUPTED_CONTENT.
- Direktori
- Strict Single-PHP Execution:
- Hanya
/index.phpyang boleh dieksekusi oleh PHP-FPM. Berkas skrip lain yang berada di direktori publik langsung ditolak dengan HTTP 403.
- Hanya
- Pencegahan Double Extension & Ekstensi Berbahaya:
- Menolak ekstensi ganda (
.php.jpg,.phtml.zip, dll.).
- Menolak ekstensi ganda (
- Sandboxing Direktori Storage / Upload:
- Folder
/storage/dimatikan dari eksekusi PHP dengan headerX-Content-Type-Options: nosniffdan CSP sandbox.
- Folder
- Blokir Dotfiles & Berkas Backup:
- Menolak akses berkas
.env,.git,.htaccess,.sql,.bak, dan.log.
- Menolak akses berkas
2. Apache & LiteSpeed Hardened (public/.htaccess)
Diterapkan otomatis via php artisan security:install atau php artisan vendor:publish --tag=security-htaccess:
- Front Controller & Authorization Header: Routing Laravel standar, pemeliharaan header
AuthorizationdanX-XSRF-Token. - Blokir Akses ke Dotfile (
<FilesMatch "^\.">):- Menutup akses ke
.htaccess,.env,.git,.htpasswd(kompatibel Apache 2.4+Require all denieddan Apache 2.2Deny from all).
- Menutup akses ke
- Blokir Serangan Ekstensi Ganda (Double Extension Webshell):
- Menolak berkas berbahaya seperti
shell.php.jpgatau trik null-bytewne.php%00.jpg:
<FilesMatch "\.(php[0-9]?|phtml|pht|phar|phps|asp|aspx|ashx|asmx|jsp|jspx|cgi|pl|py|rb|sh|bash|exe|dll|bat|cmd|scr)\.[a-z0-9]+$"> Require all denied </FilesMatch> - Menolak berkas berbahaya seperti
- Blokir Berkas Backup, Dump Database, dan Log Sensitif:
- Menutup berkas
.sql,.bak,.old,.orig,.save,.swp,.log,.ini,.conf,.yml,.yaml.
- Menutup berkas
- Matikan Directory Listing:
Options -Indexesmencegah browser menampilkan daftar berkas di dalam folder publik/storage.
🧪 Menjalankan Pengujian (Testing)
Paket ini dilengkapi dengan pengujian menyeluruh menggunakan Pest PHP dan Orchestra Testbench:
./vendor/bin/pest
Hasil uji: 82 passed (333 assertions) 100% Passed mencakup:
DetectorTuningTest: Verifikasi akurasi pola deteksi dan ketahanan ReDoS.InstantBlockTest: Verifikasi zero-tolerance instant blocking pada percobaan pertama.PolyglotImageTest: Uji penolakan polyglot image ber-tag PHP dan SVG XSS.SecurityAdminApiTest: Pengujian lengkap otorisasi, mutasi data, dan respons JSON REST API.DeviceLevelBlockingTest: Uji isolasi perangkat pada IP publik bersama.ServerSecurityTest: Audit keamanan lingkungan, baseline SHA-256, dan webshell sanitizer.AccessLogScanTest: Uji parser streaming log akses web server.SecurityMonitorTest: Uji ambang batas auto-blocking dan rotasi log.NginxPublishTest: Verifikasi publikasi konfigurasi hardened virtual host Nginx.HtaccessPublishTest: Verifikasi publikasi, penambahan aturan otomatis, dan pencadangan.htaccessApache.
❤️ Dukungan (Support)
Jika paket ini bermanfaat untuk proyek Anda, Anda dapat mendukung pengembangan berkelanjutannya melalui:
- 🇮🇩 Saweria: https://saweria.co/robykartis
Dukungan Anda sangat membantu agar paket ini tetap terawat, aman, dan terus diperbarui. Terima kasih! 🙏
📄 Lisensi
Paket ini dilisensikan di bawah lisensi terbuka MIT.