Skip to content
This repository has been archived by the owner on Feb 8, 2018. It is now read-only.

Mitigate npm spam/phishing #4557

Closed
mattbk opened this issue Jul 31, 2017 · 30 comments
Closed

Mitigate npm spam/phishing #4557

mattbk opened this issue Jul 31, 2017 · 30 comments

Comments

@mattbk
Copy link
Contributor

mattbk commented Jul 31, 2017

Whether it's an accident or not, seeing this coming through Freshdesk.

Someone [...] is trying to use my email to claim the [...] package on gratipay.com and I'm getting a bunch of request spam. Please deal with this loophole. https://gratipay.freshdesk.com/helpdesk/tickets/9219

What is this asking me to do? I'm unsure who this [...] is.
https://gratipay.freshdesk.com/helpdesk/tickets/9220

@rohitpaulk
Copy link
Contributor

We do have rate limiting already, I think it is 3 emails per minute or similar.

@rohitpaulk
Copy link
Contributor

Well, that could end up in 1440 emails per day - so might be worth revising our algorithm.

@chadwhitacre
Copy link
Contributor

Alright, what's the right thing to do here?

@chadwhitacre
Copy link
Contributor

Since we're working with public emails that haven't been verified with us yet, there's no way we can close this off entirely without neutering the entire feature.

@chadwhitacre
Copy link
Contributor

I've marked the account doing the spamming as suspicious.

@mattbk
Copy link
Contributor Author

mattbk commented Jul 31, 2017

Considering that you need to be logged in to see the emails and click apply, I think limiting per account wouldn't be outside a realistic possibility.

Or do like Slack does and require that you can only have n unconfirmed emails. So if you click "apply" on three projects that aren't yours, you won't be able to on the fourth one.

@chadwhitacre
Copy link
Contributor

Or do like Slack does and require that you can only have n unconfirmed emails. So if you click "apply" on three projects that aren't yours, you won't be able to on the fourth one.

I like this idea.

@chadwhitacre
Copy link
Contributor

I'm trying to understand the damage here. How many mails did Spammer send?

@mattbk
Copy link
Contributor Author

mattbk commented Aug 1, 2017

@mattbk
Copy link
Contributor Author

mattbk commented Aug 1, 2017

Three to the person above, and he is not happy about it.

@chadwhitacre
Copy link
Contributor

I've replied:

Hi, []. Chad here, we met at Sustain. Sorry for the spam. :-(

The reason this happened is because your email address at npm is public in the npm API, and we use that information to verify ownership of npm packages in order to make it easy for npm package owners to apply to receive funding via Gratipay. I had lunch with the npm folks the day after Sustain, and they confirmed that until they implement OAuth this is the best method to use.

What this means is that a user who is signed in to Gratipay can see your email address on this page:

https://gratipay.com/on/npm/[]/

And they are able to click a button to (attempt to) claim the package using your email address. Ideally that user is you, but of course that's not the case here.

Our plan to address this spam/phishing loophole is to limit the number of email verifications that a user can initiate, probably to one at a time. That way the most spam messages an individual Gratipay user could send would be one.

Does that sound like an acceptable solution to you?

P.S. We've blocked the particular user who was doing the spamming in this case.

@chadwhitacre
Copy link
Contributor

Thanks for the details behind this. I see you're caught between a rock and a hard place with npm (it's too bad they haven't implemented OAuth yet). Just thinking outloud, is there a way to tie the npm email to a Github OAuth in the interim? If not, I suppose limiting to 1 email is fine; but I'd also like to see a report user link in said emails - something like "Didn't initiate this? Report ". Whenever I see an auth email like the 3 I saw earlier this week, I freak out that something has been compromised (email, account, etc) so I think better messaging in the email would help.

@chadwhitacre
Copy link
Contributor

My reply:

Good ideas, []. And I see what you mean about something like this making it look like something has been compromised. I've copied your (anonymized) comments over to our ticket about this. I've been traveling for six weeks (family road trip!) and return home today(!), so I get back to work full-time next week. Hopefully we'll start to have some better protections in place within a few weeks.

Sorry again for the unpleasant surprise. Thanks for helping us think this through!

@chadwhitacre chadwhitacre changed the title Rate limit or otherwise request npm-linking spam Mitigate npm spam/phishing Aug 10, 2017
@chadwhitacre
Copy link
Contributor

+1 from @/avoidwork on Twitter, cf. gratipay/project-review#549. @/apanoo marked suspicious.

@chadwhitacre
Copy link
Contributor

chadwhitacre commented Aug 23, 2017

Just thinking outloud, is there a way to tie the npm email to a Github OAuth in the interim?

Wonder what this means?

@chadwhitacre
Copy link
Contributor

If not, I suppose limiting to 1 email is fine; but I'd also like to see a report user link in said emails - something like "Didn't initiate this? Report ".

We have this copy in the email:

Something not right? Reply to this email for help.

... which is presumably how they got to us in the first place. I think that's actually sufficient?

@chadwhitacre
Copy link
Contributor

Zooming back out here from #4579 (comment) ff. ...

As all services do, we'll just add a note saying 'If this wasn't you, no action is required' at the bottom.

Do we need that {in addition to,instead of} our current "Something not right? Reply to this email for help."?

Generic sign-up email spam is understandable, and won't startle users like an email saying 'May we receive money on your behalf'.

👍

Add 'link/verify' buttons to the emails on the 'claim' page, without requiring the user to go to the emails page and come back.

Isn't this basically what we have now? I guess we have the further streamlining that we verify the email and claim the packages in one email-link-step—a bridge too far, I think you're saying?

Part of what we're up against is that at the top end, packages have about 100 maintainers on file. That's why we put them in a select instead of listing all maintainers, but that takes away from the idea of attaching a button to each maintainer in a listing (otherwise we could use the same layout evolving above on #4579, where we have guaranteed ourselves < 10 email addresses per participant).

What if we varied the action on the package claim page based on the state of the selected address? So it would only read "Apply to accept payments" if the selected address is verified, and it would read "Verify email address" if unverified:

"Ready to apply" mockup

screen shot 2017-08-23 at 5 31 19 pm

"Ready to verify" mockup

screen shot 2017-08-23 at 5 12 59 pm

When an email is verified, automatically fish out unclaimed packages related to that address, and take them to the claim page? (or a bulk claim page?)

Then we could surface claimable packages on /verify.html (#4431) to close the loop.

@chadwhitacre
Copy link
Contributor

I still think we should only allow one pending verification at a time, to mitigate phishing. I would be comfortable allowing self-service removal of pending verifications if we also tighten the verification window to five minutes. That plus low-level throttling (one user-initiated email per 30 seconds or so) should be pretty good.

@chadwhitacre
Copy link
Contributor

chadwhitacre commented Aug 23, 2017

I still think we should only allow one pending verification at a time, to mitigate phishing. I would be comfortable allowing self-service removal of pending verifications […]

Actually, it's the combination of these two that especially mitigates phishing. Once you remove a pending verification, it renders the verification link ineffective. The remove-and-readd workaround would only aid phishing if the verification link in the first phishing attempt survived the remove-and-readd. Limiting pending verifications to one at a time forces phishers to serialize their phishing—they can't mass-phish all of npm via Gratipay. They can at best engage in targeted phishing.

The five-minute limit on verification links would further mitigate since people not expecting a verification email are fairly likely to take at least that long to notice the message and process what's going on even if they were to end up clicking.

An additional mitigation would be a confirmation step once back on-site (cf. #4577 vis-a-vis oauth).

a report user link in said emails - something like "Didn't initiate this? Report ".

For the case where recipient addresses are not associated with Gratipay participant accounts, a generic unsubscribe (#4548 (comment)) could at least partially address the desire to take action on unexpected claim messages.

@chadwhitacre
Copy link
Contributor

The user above at #4557 (comment) claimed all their packages as a defense against phishing/spam. Part of bringing back pledging is to bring back locking (hard-opt-out of) all pledges, which would be an alternate and preferable active protection against individual targeted spam/phishing.

@chadwhitacre
Copy link
Contributor

chadwhitacre commented Aug 24, 2017

(or a bulk claim page?)

I forgot! We already have a bulk claim page! 😆

https://gratipay.com/on/npm/?flow=receive

screen shot 2017-08-24 at 1 03 05 am

@chadwhitacre
Copy link
Contributor

@rohitpaulk I think I'm starting to see what you're saying at #4579 (comment):

I still think that we should decouple email verification and linking packages. What I propose is:

  • Only allow users that have verified an email corresponding to a npm package to 'claim' it.
  • Once we do have a verified email that corresponds to an npm package, allow user to claim the package directly, and send a notice (not verification, just a notice) out to all maintainers. The email body should clearly mention that the Gratipay user is a verified owner of that specific email address.

Now that the email only says 'link [email protected] to the abcd account on Gratipay' - it is (perceived as?) less dangerous. As all services do, we'll just add a note saying 'If this wasn't you, no action is required' at the bottom. Generic sign-up email spam is understandable, and won't startle users like an email saying 'May we receive money on your behalf'.

In other words, phishing depends on email and the messages an attacker can get through to a victim via our service. Both the quantity and the quality of messages matter. We can limit the quantity in various additional ways. We can limit the quality by only ever sending verification messages to unknown addresses. I like that as a policy.

Okay! So ... #4520?

@chadwhitacre
Copy link
Contributor

We can limit the quality by only ever sending verification messages to unknown addresses. I like that as a policy.

Though of course sending "claim your free money!" messages to unknown addresses is exactly what we propose to do on #4569. 😬

@chadwhitacre
Copy link
Contributor

I guess the difference is that one type of message suggests that the user took an action. If they didn't take it, then they feel unsettled, "Why is this telling me I did something that I don't think I did? Did I really and I forgot? Or am I being hacked?" Whereas the second type of message does not assign agency to the user: "We have money waiting for you if you want it."

@chadwhitacre
Copy link
Contributor

Kicking out a PR for the "Ready to verify" idea above at #4557 (comment) ... #4584.

@chadwhitacre
Copy link
Contributor

Consolidating from @rohitpaulk at #4579 (comment):

Okay, so can we hash out the user flow on https://gratipay.com/on/npm/express, then? Do we display all maintainer emails and only allow the user to initiate a message to addresses they've already verified? Do we only display email addresses they've already verified? Do we offer to send an email verification right from the package page? Do we make them click over to the Emails page to add the address there?

Basics, just to get things working:

  • If user is a maintainer, show 'Claim' button directly. Make it clear that the user is allowed to claim this package because they own that specific address, and also show the list of maintainers that we'll send emails to if they claim the package.
  • If the user is not a maintainer, show all emails, say that you have to add one of these (link to emails page) as a verified email address on Gratipay. Once verified, come back to this page and you'll be able to claim a package.

Streamlining (building upon the above):

  • When an email is verified, automatically fish out unclaimed packages related to that address, and take them to the claim page? (or a bulk claim page?)
  • Add 'link/verify' buttons to the emails on the 'claim' page, without requiring the user to go to the emails page and come back.

@chadwhitacre
Copy link
Contributor

  • If user is a maintainer, show 'Claim' button directly.
  • If the user is not a maintainer, show all emails
  • Add 'link/verify' buttons to the emails on the 'claim' page, without requiring the user to go to the emails page and come back.

Done in #4584.

@chadwhitacre
Copy link
Contributor

I think with #4579 and #4584 we are back ahead of the spam/phishing risk given our present scale. Leaving open for further mitigations as we continue to scale #4427:

  • enforce constraints at the API level, not just in the UI
  • drop the verification window to five minutes
  • real-time throttling (once we have real-time sending: Send email messages immediately #4545)

@kaguillera
Copy link
Contributor

kaguillera commented Aug 30, 2017

  • If the user is not a maintainer, show all emails
  • Add 'link/verify' buttons to the emails on the 'claim' page, without requiring the user to go to the emails page and come back.

I am kind of concerned that this would encourage phishing. If I am "not the most honest person" and I see a situation where I can phish to get free money I may take it. I personally think that the packages claimers should verify their emails separately first (it should the one used in the maintainer list for that package(s) that you intend on claiming) and then go through the claiming of the package(s). This may be a longer process but (to me at least ) it reduces the possibility of phishing.

@mattbk
Copy link
Contributor Author

mattbk commented Oct 4, 2017

At least some are still getting through. I need to look deeper to see why. Temporarily marked requesting user suspicious, but not sure how this is happening.

Never mind, this was the email verification step, not the package claiming step.

Stop sending me this scam.
Remove my email address from your system.

https://gratipay.freshdesk.com/public/tickets/f8330d6771ec6fb2663812e1e25b17bf31ccce573457b89c1150ec9cbb36383a

Do we have any method for hard opt-out? We shouldn't store email addresses people don't want us to, even if pulled from a package manager API...although we'd need to store these to not use them. 🤔

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants