All checks were successful
check / check (push) Successful in 5s
Security hardening implementing three issues: CSRF Protection (#35): - Session-based CSRF tokens with cryptographically random generation - Constant-time token comparison to prevent timing attacks - CSRF middleware applied to /pages, /sources, /source, and /user routes - Hidden csrf_token field added to all 12+ POST forms in templates - Excluded from /webhook (inbound) and /api (stateless) routes SSRF Prevention (#36): - ValidateTargetURL blocks private/reserved IP ranges at target creation - Blocked ranges: 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16, ::1, fc00::/7, fe80::/10, plus multicast, reserved, test-net, and CGN ranges - SSRF-safe HTTP transport with custom DialContext for defense-in-depth at delivery time (prevents DNS rebinding attacks) - Only http/https schemes allowed Login Rate Limiting (#37): - Per-IP rate limiter using golang.org/x/time/rate - 5 attempts per minute per IP on POST /pages/login - GET requests (form rendering) pass through unaffected - Automatic cleanup of stale per-IP limiter entries - X-Forwarded-For and X-Real-IP header support for reverse proxies Closes #35, closes #36, closes #37
60 lines
2.3 KiB
HTML
60 lines
2.3 KiB
HTML
{{template "base" .}}
|
|
|
|
{{define "title"}}Login - Webhooker{{end}}
|
|
|
|
{{define "content"}}
|
|
<div class="min-h-screen flex items-center justify-center py-12 px-4">
|
|
<div class="max-w-md w-full">
|
|
<div class="text-center mb-8">
|
|
<h1 class="text-3xl font-medium text-gray-900">Webhooker</h1>
|
|
<p class="mt-2 text-gray-600">Sign in to your account</p>
|
|
</div>
|
|
|
|
<div class="card p-8">
|
|
{{if .Error}}
|
|
<div class="alert-error">
|
|
<div class="flex items-center">
|
|
<svg class="w-5 h-5 mr-2 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
|
|
</svg>
|
|
<span>{{.Error}}</span>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
|
|
<form method="POST" action="/pages/login" class="space-y-6">
|
|
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
|
|
<div class="form-group">
|
|
<label for="username" class="label">Username</label>
|
|
<input
|
|
type="text"
|
|
id="username"
|
|
name="username"
|
|
required
|
|
autofocus
|
|
autocomplete="username"
|
|
placeholder="Enter your username"
|
|
class="input"
|
|
>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="password" class="label">Password</label>
|
|
<input
|
|
type="password"
|
|
id="password"
|
|
name="password"
|
|
required
|
|
autocomplete="current-password"
|
|
placeholder="Enter your password"
|
|
class="input"
|
|
>
|
|
</div>
|
|
|
|
<button type="submit" class="btn-primary w-full py-3">Sign In</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{end}}
|