mirror of
https://github.com/pgsty/minio.git
synced 2026-07-15 16:30:29 +03:00
fix: harden LDAP STS rate-limit source bucketing
Remove the per-username LDAP STS throttle bucket and keep the limiter keyed only by source IP. A username bucket is shared across all clients and lets one source keep a known account's bucket drained with bad-password attempts, locking the legitimate user out before LDAP bind. For trusted proxies, stop trusting the left-most forwarded address. Resolve X-Forwarded-For right-to-left, skip trusted proxy hops, reject catch-all trusted-proxy CIDRs, and intentionally ignore RFC 7239 Forwarded for this security-sensitive bucket. Document that X-Real-IP is trusted verbatim and must be overwritten by the trusted proxy, not passed through from clients. Update focused limiter, source-IP, trusted-proxy, and LDAP config tests to cover source-only buckets, spoofed appended XFF, multi-hop trusted proxies, Forwarded fallback, catch-all rejection, and the X-Real-IP deployment contract. Co-authored-by: Codex <codex@openai.com> Co-authored-by: Claude Code <claude-code@anthropic.com>
This commit is contained in:
@@ -184,7 +184,13 @@ func parseSTSTrustedProxies(value string) ([]netip.Prefix, error) {
|
||||
prefixes := make([]netip.Prefix, 0, len(fields))
|
||||
for _, field := range fields {
|
||||
if prefix, err := netip.ParsePrefix(field); err == nil {
|
||||
prefixes = append(prefixes, prefix.Masked())
|
||||
masked := prefix.Masked()
|
||||
// Reject catch-all ranges (0.0.0.0/0, ::/0): they would trust
|
||||
// forwarded headers from every peer and defeat the allowlist.
|
||||
if masked.Bits() == 0 {
|
||||
return nil, config.Errorf("LDAP STS trusted proxy %q is too broad", field)
|
||||
}
|
||||
prefixes = append(prefixes, masked)
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -74,3 +74,12 @@ func TestSetSTSTrustedProxiesRejectsInvalidEntries(t *testing.T) {
|
||||
t.Fatal("expected invalid trusted proxy list to fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetSTSTrustedProxiesRejectsCatchAll(t *testing.T) {
|
||||
for _, value := range []string{"0.0.0.0/0", "::/0", "192.0.2.0/24,0.0.0.0/0"} {
|
||||
var cfg Config
|
||||
if err := cfg.SetSTSTrustedProxies(value); err == nil {
|
||||
t.Fatalf("expected catch-all trusted proxy %q to be rejected", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user