inqaba-security/gatekeeper 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

inqaba-security/gatekeeper

Composer 安装命令:

composer require inqaba-security/gatekeeper

包简介

Bridge Laravel applications to your SOC: normalized security event logging (ECS) to Microsoft Sentinel, Wazuh and syslog, with honeypots, endpoint-abuse detection and auth monitoring out of the box.

README 文档

README

Bridge your Laravel application to your SOC. Gatekeeper (inqaba-security/gatekeeper) turns application-level security signals — logins, registrations, honeypot hits, scanner probes, endpoint abuse — into normalized Elastic Common Schema (ECS) events and ships them to Microsoft Sentinel, Wazuh, or any syslog/CEF pipeline, without slowing your requests down.

Laravel app ──> SecurityEvent (ECS + MITRE ATT&CK) ──> queue ──> Sentinel / Wazuh / syslog / log
     ▲
     ├── auth events (login, register, lockout, ...)
     ├── honeypot routes (incl. parameterized decoys) & form honeypots
     ├── endpoint abuse detection (brute force, scanning, 429 hammering)
     ├── resource enumeration / IDOR probing detection (photos/1, 2, 3 ...)
     ├── request threat scanner (SQLi / XSS / traversal / JNDI probes)
     └── Siem::log(...) custom events
                          + GeoIP enrichment ──> Slack / Teams alerting

Features

  • Normalized events — every event is an ECS 8.x document (source.ip, user.id, event.action, event.outcome, ...) with MITRE ATT&CK tactic/technique tags, so analysts get consistent fields regardless of destination.
  • Microsoft Sentinel sink — Azure Monitor Logs Ingestion API (DCE/DCR, Entra ID auth) or the legacy HTTP Data Collector API.
  • Wazuh sink — JSON-lines file tailed by the Wazuh agent (Wazuh's recommended pattern for custom app logs).
  • Syslog sink — RFC 5424 over UDP/TCP with JSON or CEF payloads (works with Wazuh's syslog listener, rsyslog, or Sentinel's AMA/CEF connector).
  • Auth monitoring — automatic listeners for Laravel's Login, Failed, Logout, Registered, PasswordReset, Lockout, Verified events; each individually toggleable.
  • Slack & Teams alerting — webhook sinks (Slack Block Kit / Teams Adaptive Card via Workflows) with a per-sink severity floor, so only high/critical events page the channel while the full stream flows to the SIEM.
  • GeoIP enrichment — ECS source.geo.* (country, city, coordinates, AS org) added at delivery time; local MaxMind database or HTTP driver, cached per IP, always off the request path.
  • Route honeypots — decoy endpoints (/wp-login.php, /.env, ...) that log high-confidence attack traffic and can auto-block the source IP. Parameterized decoys (internal/photos/{id}) capture exactly which IDs were probed, with optional method and regex constraints.
  • Resource enumeration / IDOR detection — flags per-IP behaviour real users don't exhibit on parameterized routes: constant-stride ID scans (photos/1, 2, 3...), abnormal distinct-ID breadth, and high 404/403 miss ratios from ID guessing.
  • Form honeypot — invisible field + minimum-fill-time check via a Blade component; reject or silently accept bot submissions.
  • Endpoint abuse detection — per-IP thresholds for auth failures (brute force), 404 bursts (forced browsing / scanning), 429 hammering, and raw volume.
  • Request threat scanner — passive heuristics for SQLi, XSS, path traversal, command/template injection, JNDI (log4shell-style) and PHP wrapper probes. Telemetry-first; optional blocking.
  • IP blocklist — cache-backed, TTL'd, CIDR-aware exemptions, enforced by middleware, fed by honeypots/abuse detection or Siem::blockIp().
  • Queue shipping — events ship on a queue with retries + backoff; failures fall back to the local log so nothing is lost silently.
  • Privacy controls — key-based redaction (password, token, ...) and optional sha256 pseudonymization of usernames.

Installation

composer require inqaba-security/gatekeeper
php artisan vendor:publish --tag=siem-config

Choose your destinations in .env:

SIEM_SINKS=sentinel,wazuh   # any of: sentinel, wazuh, syslog, log, null
SIEM_QUEUE=true             # ship on the "siem" queue (recommended)

Verify connectivity end-to-end:

php artisan siem:test            # all active sinks
php artisan siem:test --sink=sentinel

Sinks

Microsoft Sentinel (recommended: Logs Ingestion API)

  1. Create a Data Collection Endpoint (DCE) and a custom table (e.g. Gatekeeper_CL) with a Data Collection Rule (DCR) in your Log Analytics workspace.
  2. Create an Entra ID app registration and grant it the Monitoring Metrics Publisher role on the DCR.
  3. Configure:
SIEM_SENTINEL_MODE=dcr
SIEM_SENTINEL_TENANT_ID=...
SIEM_SENTINEL_CLIENT_ID=...
SIEM_SENTINEL_CLIENT_SECRET=...
SIEM_SENTINEL_DCE=https://<dce-name>.<region>.ingest.monitor.azure.com
SIEM_SENTINEL_DCR_ID=dcr-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
SIEM_SENTINEL_STREAM=Custom-Gatekeeper_CL

Events include a TimeGenerated field ready for the DCR transform. Example hunting query:

Gatekeeper_CL
| where event_action == "honeypot_route_hit" or event_severity >= 7
| summarize hits = count() by source_ip = tostring(source_ip), event_action
| order by hits desc

For legacy workspaces, set SIEM_SENTINEL_MODE=legacy with SIEM_SENTINEL_WORKSPACE_ID and SIEM_SENTINEL_SHARED_KEY (HTTP Data Collector API — deprecated by Microsoft but still common).

Wazuh

Events are appended as JSON lines to a file the Wazuh agent tails:

SIEM_WAZUH_PATH=/var/log/gatekeeper/events.json

Agent ossec.conf:

<localfile>
  <log_format>json</log_format>
  <location>/var/log/gatekeeper/events.json</location>
</localfile>

Example manager rule (all ECS fields are available to the JSON decoder):

<group name="laravel,siem,">
  <rule id="100100" level="10">
    <decoded_as>json</decoded_as>
    <field name="event.module">gatekeeper</field>
    <field name="event.action">honeypot_route_hit</field>
    <description>Laravel honeypot hit from $(source.ip)</description>
    <mitre><id>T1595</id></mitre>
  </rule>
  <rule id="100101" level="12">
    <decoded_as>json</decoded_as>
    <field name="event.module">gatekeeper</field>
    <field name="event.action">brute_force_detected</field>
    <description>Brute force against Laravel app from $(source.ip)</description>
    <mitre><id>T1110</id></mitre>
  </rule>
</group>

Rotate the file with logrotate (copytruncate) so the agent keeps its file handle.

Syslog / CEF

SIEM_SINKS=syslog
SIEM_SYSLOG_HOST=siem.internal
SIEM_SYSLOG_PORT=514
SIEM_SYSLOG_PROTOCOL=udp     # or tcp (RFC 6587 octet framing)
SIEM_SYSLOG_FORMAT=json      # or cef

Use cef for ArcSight-style pipelines, including Sentinel's AMA/CEF connector and Wazuh's <remote> syslog listener.

Slack & Microsoft Teams (alerting)

SIEM_SINKS=sentinel,slack,teams
SIEM_SLACK_WEBHOOK=https://hooks.slack.com/services/T000/B000/xxx
SIEM_SLACK_MIN_SEVERITY=high          # only high/critical page the channel
SIEM_TEAMS_WEBHOOK=https://...logic.azure.com/workflows/...   # Teams Workflows webhook
SIEM_TEAMS_MIN_SEVERITY=high

Slack receives a Block Kit card (severity color bar, source IP + geo, user, request, MITRE technique, context). Teams receives an Adaptive Card via a Workflows/Power Automate "post to a channel when a webhook request is received" flow — the replacement for the retired O365 connectors. The minimum_severity floor is what makes these alerting channels rather than a firehose.

GeoIP enrichment

SIEM_GEOIP=true
SIEM_GEOIP_DRIVER=maxmind   # or: ipapi
SIEM_GEOIP_MMDB=/var/lib/geoip/GeoLite2-City.mmdb
  • maxmind — offline lookups against a local GeoLite2/GeoIP2 City database. Requires composer require geoip2/geoip2.
  • ipapi — HTTP lookups (ip-api.com format by default, URL configurable). Zero dependencies; check your provider's terms.

Enrichment happens at delivery time on the queue worker, results (including misses) are cached per IP for 24h, and any resolver failure degrades to an un-enriched event — GeoIP can never delay a request or lose an event. Fields land under ECS source.geo.* / source.as.* and show up in Slack/Teams alerts as 203.0.113.9 (Oslo, NO).

Custom resolver: bind your own Inqaba\Gatekeeper\Geo\GeoIpResolver implementation in the container.

Middleware

Register where appropriate (typically the global stack or the web/api groups):

Alias Purpose
siem.block Enforce the IP blocklist (put it first)
siem.abuse Per-IP brute force / scanning / rate-abuse detection
siem.scan Request payload threat scanner (detection-only by default)
siem.enum Resource enumeration / IDOR probing detection on parameterized routes
siem.honeypot Form honeypot validation on POST/PUT/PATCH/DELETE routes
// bootstrap/app.php (Laravel 11+)
->withMiddleware(function (Middleware $middleware) {
    $middleware->prepend(\Inqaba\Gatekeeper\Http\Middleware\BlockDeniedIps::class);
    $middleware->web(append: [
        \Inqaba\Gatekeeper\Http\Middleware\DetectEndpointAbuse::class,
        \Inqaba\Gatekeeper\Http\Middleware\ScanRequestThreats::class,
    ]);
})

Honeypots

Route honeypots are registered automatically from config('siem.honeypots.routes.paths') — decoy paths like wp-login.php, .env, phpmyadmin. Any hit emits a high-severity honeypot_route_hit event and (by default) blocks the source IP for 24h. Add paths that make sense for your stack; remove any that collide with real routes.

Decoys can take route parameters — useful for trapping ID-guessing scripts on endpoints that look like real resources:

'paths' => [
    'wp-login.php',
    'internal/photos/{id}',   // params are captured in the event context
    ['path' => 'legacy/export/{file}', 'methods' => ['GET'], 'where' => ['file' => '.*\.sql']],
],

The probed parameter values (route_params) and the matched pattern land in the event, so the SOC sees exactly what the attacker tried to pull. Make sure a decoy never shadows a real route.

Form honeypot — drop the component into any form and protect the route:

<form method="POST" action="/register">
    @csrf
    <x-siem::honeypot />
    ...
</form>
Route::post('/register', ...)->middleware('siem.honeypot');

Bots that fill the invisible field or submit faster than min_seconds are logged and rejected (respond => 'reject') or fed a fake success (respond => 'silent').

Resource enumeration / IDOR detection

Attach siem.enum to routes with parameters:

Route::get('/photos/{photo}', [PhotoController::class, 'show'])
    ->middleware('siem.enum');

Per IP and per route pattern (photos/{photo}), within a 5-minute window, it raises a high-severity resource_enumeration_detected event when it sees behaviour no human browsing session produces:

Pattern Trigger (defaults) What it catches
sequential_scan ≥ 5 numeric IDs advancing with a constant stride photos/1, 2, 3... and photos/10, 20, 30... scrapers
high_distinct_ids ≥ 15 distinct IDs touched breadth-first scraping, incl. non-numeric IDs/slugs
high_miss_ratio ≥ 50% 404/403/410 across ≥ 10 requests IDOR guessing — probing IDs that don't exist or aren't theirs

Events include the resource pattern, distinct-ID count, detected stride, miss counts and a sample of probed IDs. Each pattern fires once per IP per window, and SIEM_ENUM_AUTOBLOCK=true blocks the scanner outright. Tune thresholds in config('siem.enumeration').

Custom events

use Inqaba\Gatekeeper\Facades\Siem;
use Inqaba\Gatekeeper\Events\{EventType, Severity};

// One-liner
Siem::log('export_download', 'Customer data export downloaded', Severity::High, [
    'rows' => 12000,
], $request->user());

// Fluent builder with a catalog type
Siem::event(EventType::AccessDenied)
    ->user($request->user())
    ->fromRequest($request)
    ->with(['ability' => 'orders.export'])
    ->report();

Custom sink drivers:

Siem::extend('kafka', fn ($app) => new KafkaSink(...));
// config/siem.php: 'active' => ['kafka'],

Blocklist API

Siem::blockIp('203.0.113.7', minutes: 120, reason: 'analyst-decision');
Siem::unblockIp('203.0.113.7');
Siem::blocklist()->isBlocked('203.0.113.7');

IPs/CIDRs in siem.blocklist.never_block (health checks, offices, load balancer probes) can never be auto-blocked.

Event catalog

event.action Severity MITRE Emitted by
login_succeeded / login_failed / logout info / low / info T1078 / T1110 / — auth listener
user_registered, password_reset*, email_verified info–low auth listener
auth_lockout high T1110 auth listener
honeypot_route_hit high T1595.003 honeypot routes
honeypot_form_triggered medium siem.honeypot
brute_force_detected critical T1110 siem.abuse
scanning_detected high T1595.003 siem.abuse
rate_limit_abuse / endpoint_abuse medium / high T1595 siem.abuse
suspicious_input high T1190 siem.scan
resource_enumeration_detected high T1119 siem.enum
blocked_ip_attempt low siem.block
anything via Siem::log() your choice your code

Operational notes

  • Run a queue worker for the siem queue (php artisan queue:work --queue=siem). With SIEM_QUEUE=false events ship inline — fine for the file/log sinks, not for network sinks.
  • Failure handling: sink failures are retried (3 tries, backoff 5/30/120s) and then written to the local Laravel log with the full event, so security telemetry is never dropped silently.
  • Noise control: abuse detections fire once per IP per window; blocked-IP events once per IP per 5 minutes; SIEM_MIN_SEVERITY filters globally.
  • Privacy: context keys like password/token are always redacted; set SIEM_HASH_USERNAMES=true to pseudonymize identifiers before they leave the app.
  • The scanner and abuse detectors are telemetry, not a WAF — keep your WAF/CDN protections in front; this package gives your SOC the application-layer signal those layers can't see.

Testing

composer install
composer test

License

MIT

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-07-14

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固