|
All checks were successful
CI Trade-In / changes (pull_request) Successful in 7s
CI / changes (pull_request) Successful in 6s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 2m50s
Лимит на логине ключевался парой (username, IP), поэтому распределённый перебор одного имени с тысячи адресов получал по 5 попыток с каждого источника и не упирался ни во что. После снятия Caddy basic_auth с /trade-in (#2558) POST /auth/login — единственная ручка, доступная из интернета без кредов, так что дыра открыта прямо сейчас. Поверх существующего per-IP лимита добавлен глобальный счётчик неудач на ИМЯ, без IP в ключе. Превышение порога не блокирует учётку, а растит задержку ответа (удвоение от 1с до потолка): блокировка по имени была бы вектором отказа в обслуживании против конкретного человека — не зная пароля, злоумышленник гарантированно выключал бы чужой вход. Задержка применяется по ПРИСЛАННОМУ имени, без проверки его в реестре, и из одного места — общего хвоста всех отказов по кредам. Иначе «быстрый 401» для несуществующего имени стал бы оракулом существования учётки, то есть ровно той user-enumeration, от которой уже защищают одинаковый generic-ответ и безусловный bcrypt. |
||
|---|---|---|
| .. | ||
| __init__.py | ||
| auth.py | ||
| auth_db.py | ||
| config.py | ||
| db.py | ||
| fdw.py | ||
| password.py | ||
| ratelimit.py | ||
| rbac.py | ||
| request_audit.py | ||
| shutdown.py | ||