I was at Defcon 27 recently and saw a talk titled “Secrets Worlds in Plain Web. The BlockChain DNS.” by Fernando Amatte. He spoke about blockchain based DNS infrastructure, specifically Namecoin and Emercoin, as a means of hiding secrets in plain view. I missed the beginning of the talk, but I don’t recall him presenting any specific examples of people using blockchain DNS services. This gave me a few questions:

  • Is anyone using these blockchain DNS services?
  • What are they using them for?
  • Are any interesting services “hiding in plain site?”

At first glance these questions should be easy to answer. If the DNS records are written to a blockchain I should be able to trivially download and search the blockchain(s), enumerate all the domains, and see what’s out there. So that’s what I set out to do.

Blockchain-DNS.info

My first stop was the website https://blockchain-dns.info/ to see what it takes for a layperson to access these sites. I downloaded the firefox plugin and visited their explore page just to see what was out there. As it turns out, a lot of resolution errors, parked domains, and porn. Off to a great start. Let’s get a bit more scientific with it.

Enumerating Namecoin

Clicking around the blockchain-DNS explore page was fun, but I wanted to more exhaustively see what was out there. Namecoin sounded familiar so I started with that.

First, download and install Namecoin from github. If you’re ever installed Bitcoin, it’s pretty much the exact same process. If you install the QT GUI version you will have to add the server option to your namecoin.conf. Here is what mine looks like:

datadir=/path/to/my/extra/ssd/namecoin/data
rpcallowip=127.0.0.1/32
rpcuser=[username]
rpcpassword=[password]
server=1

Once the Namecoin chain is running and synced I needed a way to dump all the records it contained. Thankfully Namecoin provides a utility just for this called ncdumpzone. Install instructions are on the ncdns github page.

During install I ran into the following error:

package golang_org/x/crypto/cryptobyte: unrecognized import path

I have no idea what caused this, but you can fix it by editing the following file in the x509-signature-splice dependency: ~/go/src/github.com/namecoin/x509-signature-splice/x509/x509_splice.go, changing golang_org to golang.org and re-installing.

Now I can run ncdumpzone from my ~/go/bin/ folder and get results in the following format:

zielmicha.bit.	600	IN	NS	87.98.234.72.zielmicha.bit.
zimperium.bit.	600	IN	A	127.0.0.1
zionsbank.bit.	600	IN	A	144.76.12.6
*.zionsbank.bit.	600	IN	A	144.76.12.6
zonealarm.bit.	600	IN	NS	ns1.cloud-name.ru.zonealarm.bit.
zonealarm.bit.	600	IN	NS	ns2.cloud-name.ru.zonealarm.bit.
i.bit.	600	IN	A	45.63.38.124
v.bit.	600	IN	A	45.63.38.124
x.bit.	600	IN	A	45.63.38.124

Awesome! I let the command run for a bit, dumping it to a text file, to see what happened. The command kept running for hours without end, and giving a lot of looping and duplicate results. I briefly checked the source code and it looks like it’s supposed to stop at some point? I didn’t spend a lot of time trying to figure out why it kept going so I came up with a lazy solution. I would take the records from ncdumpzone, hash them, ignore hashes I’d already seen, and store anything new.

Here is the quick and dirty python script I came up with:

#!/usr/bin/env python3

import sys
import sqlite3
import hashlib

conn = sqlite3.connect("domains.db")

c = conn.cursor()

c.execute("""CREATE TABLE IF NOT EXISTS records (
    id integer PRIMARY KEY,
    hash text NOT NULL,
    domain text NOT NULL,
    type text NOT NULL,
    record text NOT NULL);""")

try:  # try-except in case we want to quit early with ctrl+c
    for line in sys.stdin:
        p_line = line.strip()
        p_hash = hashlib.sha256(line.encode()).hexdigest()
        p_line = line.split("\t")
        
        # Check if the hash already exists
        c.execute("SELECT count(*) FROM records WHERE hash=?", (p_hash,))
        count = c.fetchone()[0]
        
        # If it's new, add it to the database
        if count == 0:
            print(f"Inserting: {p_line[0]}, {p_line[3]}, {p_line[4]}")
            c.execute("INSERT INTO records (hash, domain, type, record) VALUES (?, ?, ?, ?)",
                (p_hash, p_line[0], p_line[3], p_line[4]))
            conn.commit()
        else:
            print("Skipping.")
except KeyboardInterrupt:
    print("Exiting...")
    conn.commit()
    conn.close()
    sys.exit(1)


conn.commit()
conn.close()

Then I ran ./ncdumpzone | ./dump_namecoin.py and let it sit for a while. After a short while I started seeing only “Skipping.” lines with no new entries, so I ran watch ls -latr domains.db and left the terminal for a few days so I could quickly see if the database had been updated. After a few days with no updates I killed the script and called it “good enough for now.” I had a database with (probably) most of the DNS records in Namecoin.

Enumerating Emercoin

Emercoin took a bit more thought than Namecoin. Emercoin stores DNS records in its Name-Value Storage (NVS) service. By default it supports a number of service abbreviations that you can prepend to names to indicate what the name and value should be used for. So, sort of a tag:name->value storage system. The abbreviation for DNS is “dns:” so a DNS record Name would look like dns:emercoin.com. The Value is just DNS records delimited by the pipe character, like A=192.168.0.123|TXT=example website.

To enumerate all DNS records then, we can enumerate the NVS service, get all the names that start with dns:, and look at their values. Thankfully, the emercoin-cli has a method called name_scan that does exactly that.

The Emercoin node installed without any issues. Again, it was just like installing Bitcoin (it’s Bitcoin forks all the way down).

TL;DR, here is my emercoin.conf:

rpcallowip=127.0.0.1/32
rpcuser=[username]
rpcpassword=[password]
server=1
emcdns=1

And here is the script I used to dump the NVS service to a sqlite database:

#!/usr/bin/env python3

import sqlite3
import json
import sys
from subprocess import check_output

# Create the database
conn = sqlite3.connect("emercoin_nvs.db")
c = conn.cursor()
c.execute("""CREATE TABLE IF NOT EXISTS nvs_records (
    id integer PRIMARY KEY,
    name text NOT NULL,
    value text NOT NULL,
    expires_in integer NOT NULL,
    expired integer NOT NULL);""")

# Get the first 500  NVS pairs
out = check_output(["/path/to/emercoin-cli",
    "-rpcuser=[username]",
    "-rpcpassword=[password]",
    "name_scan"])

# decode with replace to preserve all that binary
out = json.loads(out.decode("utf-8", "replace"))

try:  # try-except in case we want to quit early with ctrl+c
    while len(out) > 0:
        for nvp in out:
            if "expired" not in nvp.keys() and nvp["expires_in"] > 0:
                # If the record hasn't expired, set expired to 0 (False)
                nvp["expired"] = 0
            else:
                # Otherwise set expired to 1 (True)
                nvp["expired"] = 1
            print(f"Inserting {nvp['name']}")
            c.execute("""INSERT INTO nvs_records (name, value, expires_in, expired)
                VALUES (?, ?, ?, ?)""",
                (nvp["name"], nvp["value"], nvp["expires_in"], nvp["expired"]))
            conn.commit()
        
        # Get the next 500 records
        out = check_output(["/path/to/emercoin-cli",
            "-rpcuser=[username]",
            "-rpcpassword=[password]",
            "name_scan",
            out[-1]["name"], "501"])
        out = json.loads(out.decode("utf-8", "replace"))
        # First record will be the one we searched for, which is the last
        # Name-Value pair saved from the previous batch, so get rid of it
        out.pop(0)
except KeyboardInterrupt:
    print("Exiting...")
    conn.commit()
    conn.close()
    sys.exit(1)
    
conn.commit()
conn.close()

This on actually terminates properly. After a few minutes I had the entire Name-Value Storage enumerated in emercoin_nvs.db.

Is anybody there?

So I have these records, now what? I need some way of checking all these sites to see what’s on them. There are lots of tools for scraping websites and taking screenshots. I considered sketchy but it seemed like overkill for what I wanted to do. I settled on EyeWitness because it attempts to classify the sites it scrapes, which is exactly what I wanted to do.

Instead of mucking about with DNS settings I spun up a fresh Kali VM, installed EyeWitness, and added all the valid A records I had to the /etc/hosts file. I don’t have a script here, I just opened up the databases in a DB browser, copy pasted them into vim, and ran some commands until they were formatted properly. Then I pasted them into /etc/hosts, made a new file called domains.txt, removed the IPs from domains.txt, fired off ./EyeWitness.py --web -f domains.txt, and waited. And waited. And… waited… As it turns out, a lot of these sites have nothing going on. About half timed out.

In total I had 4463 domains with A records. This matches the Blockchain-DNS explore page, which claims that of the 140,472 domains it serves 5,016 have IP addresses. I’ll assume the 553 I’m missing are from OpenNIC and not blockchain.

Results

Here are the categorization results from EyeWitness:

Category Count
Uncategorized 1624
Directory Listings 9
Content Management System (CMS) 1
Network Devices 1
401/403 Unauthorized 139
404 Not Found 60
Splash Pages 14
Internal Error 5
Bad Request 48
Errors 2560

Okay, so I misspoke earlier. More than half aren’t actually hosting anything.

I spent a lot of time looking through the results and most of them are really boring. A lot of empty CMS and “blog coming soon” type pages. The directory listings are all pretty much the same site, and only host a single image. I’ll include some of the screenshots so you don’t have to bother installing the plugins and visiting them yourself.

Namecoin

Someone registered a few domains on Namecoin to create an uncensored host for the Bible on biblical themed domains (such as bible4u.bit):

Blockchain-DNS.info had several alternative Namecoin domains registered. There are some blogs and personal sites of blockchain enthusiast types. A few blockchain projects had alternative domains. One router login page, one router traffic graph. A wedding invitation. Some wikileaks mirrors. Not a whole lot “hiding in plain site” as it were. One of the running themes is the repetition of domains. When there is an active site, it is rarely registered once. The bible site had at least 4 or 5 names. There were half a dozen sites dedicated to the 12 networking truths. It was pretty easy to tell when looking at the list which sites would be identical, they would have similar names, the same A record, and similar TXT records.

In the category of crime sites I did come across a few. Joker’s Stash for one, although it’s not clear if this is the real site or a phishing page:

There were a number of free movie and TV sites, mostly in some Cyrillic script. Some nextcloud login pages, and a lot of 404s.

Emercoin

Emercoin was about as interesting as Namecoin. There were no exposed router logins or anything like that, but there were a few more crime sites and one very dedicated Chaturbate white label.

The overwhelming majority of emercoin domains were parked. Again, there was a plethora of 404s, domains that go nowhere, and blockchain projects.

In the crime sites categories we have many more alternative domains for Joker’s Stash as well as a few carding sites. Here’s one called unicc:

And another called Antigreedy:

The following is by far my favorite discovery. Someone invested in creating a white label Chaturbate affiliate and really really wants blockchain enthusiasts as their customer base. There were 996 domains dedicated to this singular Chaturbate white label site:

When I came across this I was a bit perplexed. Why is there a cam site that seems exclusively available on blockchain based DNS? How does it have this many performers? Surely this must be some kind of e-whore or catfishing setup. Alas, no, as it turns out Chaturbate makes it very easy to create and market your own white label version of the site (NSFW), with the same community/backend, and a revenue share based on traffic you drive. So I guess registering as a white label and throwing up 996 domains on emercoin was cheap enough that the traffic gained from curious blockchain enthusiasts was profitable? I guess?

TL;DR

  • Is anyone using these blockchain DNS services?

Maybe a few dozen people.

  • What are they using them for?

Mostly domain parking, empty projects, and a smattering of crime.

  • Are any interesting services “hiding in plain site?”

Not really.

If you really wanted to create hidden services that were difficult for others to find or contained content that is illegal there are much better tools to do so. For the most part these blockchain domains look like the kind of thing you’d find on the regular internet, with a bias towards sites that would be made by the kind of people that use blockchain DNS.

TODO

  • Look at other Emercoin NVS attributes
  • Look at other record types besides A records
  • I’d love to see traffic stats on that white label from blockchain DNS