Most active commenters
  • junon(6)
  • lelanthran(6)
  • rollcat(4)
  • hunter2_(3)
  • notmyjob(3)
  • (3)

←back to thread

1369 points universesquid | 62 comments | | HN request time: 1.379s | source | bottom
Show context
junon ◴[] No.45169794[source]
Hi, yep I got pwned. Sorry everyone, very embarrassing.

More info:

- https://github.com/chalk/chalk/issues/656

- https://github.com/debug-js/debug/issues/1005#issuecomment-3...

Affected packages (at least the ones I know of):

- ansi-styles@6.2.2

- debug@4.4.2 (appears to have been yanked as of 8 Sep 18:09 CEST)

- chalk@5.6.1

- supports-color@10.2.1

- strip-ansi@7.1.1

- ansi-regex@6.2.1

- wrap-ansi@9.0.1

- color-convert@3.1.1

- color-name@2.0.1

- is-arrayish@0.3.3

- slice-ansi@7.1.1

- color@5.0.1

- color-string@2.1.1

- simple-swizzle@0.2.3

- supports-hyperlinks@4.1.1

- has-ansi@6.0.1

- chalk-template@1.1.1

- backslash@0.2.1

It looks and feels a bit like a targeted attack.

Will try to keep this comment updated as long as I can before the edit expires.

---

Chalk has been published over. The others remain compromised (8 Sep 17:50 CEST).

NPM has yet to get back to me. My NPM account is entirely unreachable; forgot password system does not work. I have no recourse right now but to wait.

Email came from support at npmjs dot help.

Looked legitimate at first glance. Not making excuses, just had a long week and a panicky morning and was just trying to knock something off my list of to-dos. Made the mistake of clicking the link instead of going directly to the site like I normally would (since I was mobile).

Just NPM is affected. Updates to be posted to the `/debug-js` link above.

Again, I'm so sorry.

replies(39): >>45169833 #>>45169877 #>>45169899 #>>45169922 #>>45170115 #>>45170202 #>>45170608 #>>45170631 #>>45170738 #>>45170943 #>>45171084 #>>45171127 #>>45171420 #>>45171444 #>>45171619 #>>45171648 #>>45171666 #>>45171859 #>>45172334 #>>45172346 #>>45172355 #>>45172660 #>>45172846 #>>45174599 #>>45174607 #>>45175160 #>>45175246 #>>45176250 #>>45176355 #>>45176505 #>>45177184 #>>45177316 #>>45178543 #>>45178719 #>>45182153 #>>45183937 #>>45194407 #>>45194912 #>>45229781 #
nodesocket ◴[] No.45169899[source]
What did the phishing email say that made you click and login?
replies(1): >>45170070 #
1. junon ◴[] No.45170070[source]
That it had been more than 12 months since last updating them. Npm has done outreach before about doing security changes/enhancements in the past so this didn't really catch me.

Screenshot here: https://imgur.com/a/q8s235k

replies(7): >>45170187 #>>45170240 #>>45170308 #>>45170321 #>>45170333 #>>45170335 #>>45171291 #
2. SSLy ◴[] No.45170187[source]
Can you post full message headers somewhere? It'd be interesting which MTA was involved in delivery from the sender's side.
replies(1): >>45170454 #
3. nodesocket ◴[] No.45170240[source]
Yikes, looks legit. Curious what are the destination addresses? Would like to monitor them to see how much coin they are stealing.
replies(3): >>45170331 #>>45170449 #>>45170952 #
4. bflesch ◴[] No.45170308[source]
Thanks for sharing, I've created an OTX entry for this: https://otx.alienvault.com/pulse/68bf031ee0452072533deee6
replies(1): >>45175807 #
5. twoodfin ◴[] No.45170321[source]
Perfect example of why habituating users to renewing credentials (typically password expiration) is a terrible practice.
replies(2): >>45170802 #>>45172284 #
6. hunter2_ ◴[] No.45170331[source]
In terms of presentation, yes. In terms of substance, short deadlines are often what separate phishing from legitimate requests.
replies(1): >>45172370 #
7. lifeinthevoid ◴[] No.45170333[source]
That green checkmark ... what application is this?
replies(2): >>45170475 #>>45170542 #
8. rollcat ◴[] No.45170335[source]
@everyone in the industry, everywhere:

Urgency is poison.

Please, please put a foot in the door whenever you see anyone trying to push this kind of sh*t on your users. Make one month's advance notice the golden standard.

I see this pattern in scam mail (including physical) all the time: stamp an unreasonably short notice and expect the mark to panic. This scam works - and this is why legit companies that try this "in good faith" should be shamed for doing it.

Actual alerts: just notify. Take immediate, preventive, but non-destructive action, and help the user figure out how to right it - on their own terms.

replies(1): >>45171125 #
9. FergusArgyll ◴[] No.45170449[source]
0x66a9893cC07D91D95644AEDD05D03f95e1dBA8Af

0x10ed43c718714eb63d5aa57b78b54704e256024e

0x13f4ea83d0bd40e75c8222255bc855a974568dd4

0x1111111254eeb25477b68fb85ed929f73a960582

0xd9e1ce17f2641f24ae83637ab66a2cca9c378b9f

Source: https://github.com/chalk/chalk/issues/656#issuecomment-32670...

replies(1): >>45172699 #
10. junon ◴[] No.45170454[source]
Yep - https://gist.github.com/Qix-/c1f0d4f0d359dffaeec48dbfa1d40ee...
replies(3): >>45170638 #>>45171252 #>>45173824 #
11. junon ◴[] No.45170475[source]
Migadu. The tooltip hovering over it shows:

    dkim=pass header.d=smtp.mailtrap.live header.s=rwmt1 header.b=Wrv0sR0r
12. markasoftware ◴[] No.45170542[source]
check marks in email clients usually mean DKIM / other domain verification passed. The attack author truly owns npmjs.help, so a checkmark is appropriate.
13. SSLy ◴[] No.45170638{3}[source]
let's see the header of interest:

     Received: from npmjs.help by smtp.mailtrap.live
replies(1): >>45172000 #
14. anonymars ◴[] No.45170802[source]
Frustrating that you're being downvoted

https://pages.nist.gov/800-63-FAQ/#q-b05

15. mcintyre1994 ◴[] No.45170952[source]
There's a lot, looks like they start at line 103 in the gist here: https://gist.github.com/sindresorhus/2b7466b1ec36376b8742dc7...
16. notmyjob ◴[] No.45171125[source]
Agree, but this example wasn’t even that aggressive in its urgency and op said they were merely ticking things off the todo, not feeling alarmed by the urgency. The problem is email as it’s used currently. The solution is to not use email.
replies(3): >>45171417 #>>45172700 #>>45173543 #
17. alexellisuk ◴[] No.45171252{3}[source]
How did simply opening this email in something like Gmail or a desktop client result in it being able to compromise NPM packages under your control?

I'm just curious - and as a word of warning to others so we can learn. I may be missing some details, I've read most of the comments on the page.

replies(1): >>45171314 #
18. IshKebab ◴[] No.45171291[source]
And then what happens when you click the link? Wouldn't your password manager fail to auto fill your details?
replies(1): >>45171308 #
19. junon ◴[] No.45171308[source]
This was mobile, I don't use browser extensions for the password manager there.
20. junon ◴[] No.45171314{4}[source]
I clicked the link like a genius :)
replies(2): >>45171400 #>>45171927 #
21. alexellisuk ◴[] No.45171400{5}[source]
:-( How did the link hijack your password/2fa? Or did you also enter some stuff on the form?
22. niwtsol ◴[] No.45171417{3}[source]
The email says accounts will start locking Sept 10th and it was sent Sept 8th - so a 48 hour urgency window or an account would be locked is urgency IMO
replies(2): >>45171501 #>>45171862 #
23. notmyjob ◴[] No.45171501{4}[source]
Fair enough, was just thinking about many low effort scams that have “EMERGENCY!!! ACT NOW!!!” in red boldface. This, by being slightly? less aggressive is actually less likely to trip my “this is phishing” detector. Obviously ymmv.
24. ◴[] No.45171862{4}[source]
25. osa1 ◴[] No.45171927{5}[source]
I don't understand. The link could've come from anywhere (for example from a HN comment). How does just clicking on it give your package credentials to someone else? Is NPM also at fault here? I'd naively think that this shouldn't be possible.

For example, GitHub asks for 2FA when I change certain repo settings (or when deleting a repo etc.) even when I'm logged in. Maybe NPM needs to do the same?

replies(3): >>45171987 #>>45172119 #>>45172628 #
26. koil ◴[] No.45171987{6}[source]
As OC mentioned elsewhere, it was a targeted TOTP proxy attack.
replies(1): >>45172637 #
27. XxgodReixX88 ◴[] No.45172000{4}[source]
what about it?
28. dboreham ◴[] No.45172119{6}[source]
OP entered their credentials and TOTP code, which the attacker proxied to the real npmjs.com

FWIW npmjs does support FIDO2 including hard tokens like Yubikey.

They do not force re-auth when issuing an access token with publish rights, which is probably how the attackers compromised the packages. iirc GitHub does force re-auth when you request an access token.

replies(1): >>45173739 #
29. NooneAtAll3 ◴[] No.45172284[source]
is there an actual habituation?

that message feels like it could work as a first-time as well

replies(2): >>45172830 #>>45173084 #
30. mrguyorama ◴[] No.45172370{3}[source]
There is NO reliable indicators, because every single one of these "Legit requests don't ..." recommendations has been done by a local bank trying to get their customers to do something.

My local credit union sent me a "please change your password" email from a completely unassociated email address with a link to the change password portal. I emailed them saying "Hey it looks like someone is phishing" and they said, "nope, we really, intentionally, did this"

Companies intentionally withhold warning emails as late as possible to cause more people to incur late fees. So everyone is used to "shit, gotta do this now or get screwed"

You can't hope to have good security when everyone's money is controlled by organizations that actively train people to have bad OPSEC or risk missing rent.

replies(2): >>45172585 #>>45175013 #
31. hunter2_ ◴[] No.45172585{4}[source]
I agree: any of the potential indicators of phishing (whether it's poor presentation, incorrect grammar, tight deadlines, unusual "from" addresses, unusual domains in links, etc.) can easily have false positives which unfortunately dull people's senses. That doesn't mean they can't continue to be promulgated as indicators of possible (not definite) phishing, though.

I used the word "often" rather than "always" for this reason.

32. ◴[] No.45172628{6}[source]
33. hughw ◴[] No.45172637{7}[source]
So, he clicked the link and then entered his correct TOTP? how would manually typing the url instead of clicking the link have mitigated this?
replies(1): >>45172796 #
34. naikrovek ◴[] No.45172700{3}[source]
> The solution is to not use email.

and use what? instant message? few things lack legitimacy more than an instant message asking you to do something.

Links in email are much more of a problem than email itself. So tempting to click. It's right there, you don't have to dig through bookmarks, you don't have to remember anything, just click. A link is seductive.

the actual solution is to avoid dependencies whenever possible, so that you can review them when they change. You depend on them. You ARE reviewing them, right? Fewer things to depend on is better than more, and NPM is very much an ecosystem where one is encouraged to depend on others as much as possible.

replies(2): >>45180184 #>>45185874 #
35. dbdr ◴[] No.45172699{3}[source]
Next comment:

> Those are swap contract addresses, not attacker addresses. E.g. 0x66a9893cC07D91D95644AEDD05D03f95e1dBA8Af the Uniswap v4 universal router addr.

> Every indication so far is that the attacker stole $0 from all of this. Which is a best-case outcome.

replies(1): >>45172741 #
36. FergusArgyll ◴[] No.45172741{4}[source]
Oh, that makes much more sense - thanks!
37. Mogzol ◴[] No.45172796{8}[source]
They wouldn't have manually typed the exact URL from the email, they would have just typed in npmjs.com which would ensure they ended up on the real NPM site. Or even if they did type out the exact URL from the email, it would have made them much more likely to notice that it was not the real NPM URL.
38. twoodfin ◴[] No.45172830{3}[source]
We should be immediately suspicious when we get any solicitation to "renew" something "expired" in a security domain. Swapping un-compromised secrets is essentially always more risky than leaving them be.

Regardless of whether the real NPM had done this in the past, decades of dumb password expiration policies have trained us that requests like this are to be expected rather than suspected.

39. nicoburns ◴[] No.45173084{3}[source]
If legitimate companies didn't do this, then the email would be suspicious.
replies(1): >>45175545 #
40. lelanthran ◴[] No.45173543{3}[source]
> The problem is email as it’s used currently. The solution is to not use email.

No. The problem is unsigned package repositories.

The solution is to tie a package to an identity using a certificate. Quickest way I can think off would be requiring packages to be linked to a domain so that the repository can always check incoming changes to packages using the incoming signature against the domain certificate.

replies(4): >>45174057 #>>45175941 #>>45180210 #>>45181866 #
41. osa1 ◴[] No.45173739{7}[source]
> They do not force re-auth when issuing an access token with publish rights, which is probably how the attackers compromised the packages

I'm surprised by this. Yeah, GitHub definitely forces you to re-auth when accessing certain settings.

42. nsdfg ◴[] No.45173824{3}[source]
https://mailtrap.io/contact-details/
43. cluckindan ◴[] No.45174057{4}[source]
And one pwned domain later, we are back in square one.
replies(1): >>45177524 #
44. cataflam ◴[] No.45175013{4}[source]
> There is NO reliable indicators

Completely agree. The only reliable way is to never use an email/SMS link to login, ever.

replies(1): >>45185442 #
45. ◴[] No.45175545{4}[source]
46. dgl ◴[] No.45175807[source]
Just looking for "const _0x112" as an IOC seems a bit false positive prone: https://github.com/search?q=%2Fconst+_0x112%2F+lang%3Ajs&typ... (most of that code is pretty dodgy obviously, but it's not unique enough to identify this).
47. dabockster ◴[] No.45175941{4}[source]
That wouldn't work against a really sophisticated attacker. Especially for something that's clearly being maintained for free by one overworked person in their spare time (yet again).

You'd need some kind of offline verification method as well for these widely used infrastructure libraries.

replies(1): >>45179137 #
48. lelanthran ◴[] No.45177524{5}[source]
> And one pwned domain later, we are back in square one.

1. It's an extra step: before you pwn the package, you need to pwn a domain.

2. When a domain is pwned, the packages it signs can be revoked with a single command.

49. lelanthran ◴[] No.45179137{5}[source]
> That wouldn't work against a really sophisticated attacker.

Nothing "really works" against a sophisticated hacker :-/ Doesn't mean that "defense in depth" does not apply.

> You'd need some kind of offline verification method as well for these widely used infrastructure libraries.

I don't understand why this is an issue, or even what it means: uploading a new package to the repository requires the contributor to be online anyway. The new/updated/replacement package will have to be signed. The signature must be verified by the upload script/handler. The verification can be done using the X509 certificate issued for the domain of the contributor.

1. If the contributor cannot afford the few dollars a year for a domain, they are extremely vulnerable to the supply chain attack anyway (by selling the maintenance of the package to a bad actor), and you shouldn't trust them anyway.

2. If the contributor's domain gets compromised you only have to revoke that specific certificate, and all packages signed with that certificate, in the past or in the future, would not be installable.

As I have repeatedly said in the past, NPM (and the JS tools development community in general) had no adults in the room during the design phase. Everything about JS stacks feels like it was designed by children who had never programmed in anything else before.

It's a total clown show.

replies(2): >>45181071 #>>45182425 #
50. rollcat ◴[] No.45180184{4}[source]
> the actual solution is to avoid dependencies whenever possible, so that you can review them when they change.

If you're publishing your software: you can't "not" depend on some essential service like source hosting or library index.

> You ARE reviewing them, right?

Werkzeug is 20kloc and is considered "bare bones" of Python's server-side HTTP. If you're going to write a complex Python web app using raw WSGI, you're just going to repeat their every mistake.

While at it: review Python itself, GCC, glibc, maybe Linux, your CPU? Society depends on trust.

51. rollcat ◴[] No.45180210{4}[source]
> The solution is to tie a package to an identity using a certificate.

Identity on the Internet is a lie. Nobody knows you're a dog.

The solution is to make security easy and accessible, so that the user can't be confused into doing the insecure thing.

replies(1): >>45181591 #
52. idiotsecant ◴[] No.45181071{6}[source]
If only they would have had the benefit of you being around to do all that work with your glorious hindsight.
replies(1): >>45181107 #
53. lelanthran ◴[] No.45181107{7}[source]
> If only they would have had the benefit of you being around to do all that work with your glorious hindsight.

They didn't need me; plenty of repositories doing signed packages existed well before npm was created.

Which is why I likened them to a bunch of kids - they didn't look around at how the existing repos were designed, they just did the first thing that popped into their head.

replies(1): >>45191920 #
54. lelanthran ◴[] No.45181591{5}[source]
> Identity on the Internet is a lie.

What do you think HTTPS is?

replies(2): >>45183094 #>>45196677 #
55. benchloftbrunch ◴[] No.45181866{4}[source]
As long as you're OK with self signed certificates or PGP keys, I'd be on board with this.

I really, really dislike the idea of using TLS certificates as we know them for this purpose, because the certificate authority system is too centralized, hierarchical, and bureaucratic, tightly coupled to the DNS.

That system is great for the centralized, hierarchical, bureaucratic enterprises who designed it in the 90s, but would be a pain in the ass for a solo developer, especially with the upcoming change to 45 day lifetimes.

replies(1): >>45182842 #
56. benchloftbrunch ◴[] No.45182425{6}[source]
> X509 certificate

It should be a PGP or SSH key, absolutely not an X509 certificate (unless you allow self signed).

Personal identity keys should be fully autonomous and not contingent on the formal recognition of any external authority.

57. lelanthran ◴[] No.45182842{5}[source]
> As long as you're OK with self signed certificates or PGP keys, I'd be on board with this.

I am with PGP but more wary of self-signed certs, though even self-signed certs allow mass revocation of packages when an author's cert is compromised.

58. mdaniel ◴[] No.45183094{6}[source]
Transport Layer Security, and has nothing to do with Identity. Take for example the perfectly valid certificate that was issued for npmjs[.]help which unquestionably does not belong to Microsoft/GitHub. Hell, even the certificate for npmjs.com is 'O=Google Trust Services' which doesn't sound like any of the business entities one would expect to own that cert
59. hunter2_ ◴[] No.45185442{5}[source]
Or go ahead and use them, but abort if your password manager doesn't auto fill. Such abort scenarios include not only a password field without auto fill, but also a total lack of password field (e.g., sites that offer OTP-only authentication), since either way you don't have your password manager vetting the domain.
60. notmyjob ◴[] No.45185874{4}[source]
Depends what you use it for. I don’t think email is a single thing in that regard. For example I’ve used it as a backup method for important files and also as 2 factor. Those are wholly different things that warrant different solutions. The majority of email volume is not person to person communication but part of some corporation/spammers/scammers business model who at best, like my bank, is using it to shift liability away from themselves onto consumers and at worst is attempting to defraud me of all I own. It’s still useful in business, maybe, but pretty sure teams/slack/… will win eventually.
61. idiotsecant ◴[] No.45191920{8}[source]
On the other hand, they did the actual work when nobody else did. It's so easy to take potshots, when you've never done anything consequential enough for the results to matter as much as they do for npm.
62. rollcat ◴[] No.45196677{6}[source]
"Whoever was on the cacert list that ships with your browser" has signed "I claim to be Acme Widgets Inc. and I own microsoft.com".