倉庫指標
- Star
- (4,680 star)
- PR 合併指標
- (平均合併 7天 4小時) (30 天內合併 20 個 PR)
描述
We recently got some garbage-tier spam (keyword-building for a captcha-breaking service). Oddly, the account mohanpierce99 was four years old with some light, realistic (if self-promo-y) usage.
When I looked at the logs, the same IP had first logged into srijancse, poked around, and logged out a couple minutes before. That account was also inactive, but there's a plausible github account with the same username. It had invited 3 accounts - 2 were unused with throwaway emails, 1 was already banned for trying to redeem an invite it sent (voting ring/sockpuppet setup, person goofed by opening the invite link in the logged-in browser they sent it from). Based on the prior abuse, inactivity, and shared login I banned it as an alt.
Also in the logs, the same IP had logged out and into a third account, also unused. I left that one alone so I could watch the logs to gather more info if the spammer returned.
I've been reviewing logs and chatting with the other mods about it because this all didn't quite match a familiar pattern, especially the fact that the accounts are years old. (Usually garbage-tier spammers are not patient.) Irene recognized it was probably account takeover and... yep! I searched the emails of the used accounts on Have I Been Pwned and all of them list a breach named Stealer Logs, Jan 2025 (and many others, it's ugly out there).
I no longer think the accounts I banned were alts of a spammer setting up a voting ring, I think they were all compromised in a breach and a spammer with a credential-stuffing script hit us. It's even possible the entire process was automated.
To prevent future abuse, we should use the HIBP Pwned Passwords list (announcement) to prevent this:
-
create a background job to download the hibp password database (what's the cadence for hibp: weekly, monthly updates?) -
decide on a threshold of how many times a password has been seen to be refused -
User: add validation that new password is not in list -
LoginController#loginblock breached passwords, explain situation, render pre-filled reset password form
(Yes, prod has much more than enough available disk for the full download.)
I would especially appreciate kibitzing from any Lobsters users who have implemented similar security controls professionally, it seems very likely we have experts in the community.
EDIT: This plan has received exactly the kind of experienced advice I hoped for, so I plan to follow that lead:
- Method to check a local password hash list like the roycewilliams list of the 20k most common password from HIBP, just import the file into our repo (Is there a more recent version than Nov 2021? By their nature commonly chosen passwords don't change too often, but it'd be nice.)
- If that check passes, check the HIBP API with a 1500 ms timeout (to match pwnd-passwords-django, though this is 3x higher than I guessed)
- Check on login - force failures into reset flow
- Check on setting a new password in the reset flow
- Check on setting a new password in
/settings