BitSquatting is not new but it’s relatively new. This type of attack relies on a random bit that switches from 0 to 1 or from 1 to 0 inside a RAM. Because of this even though you try to access domain like cnn.com, in fact your computer is requesting ann.com. It’s rare but it happens. It can be caused by a cosmic radiation or overheated memory modules. If You would like to learn more I can recommend Artem’s page.
To make it easier to find a domain that is in a single bit-shift distance (as in Hamming distance) I’ve created a script that is generating all the possibilities.
For example lets search for domains (bit-wise) close to cnn.com. The script output will be:
snn.com knn.com gnn.com ann.com bnn.com c.n.com cfn.com cjn.com cln.com con.com cnf.com cnj.com cnl.com cno.com cnn.som cnn.kom cnn.gom cnn.aom cnn.bom cnn.cgm cnn.ckm cnn.cmm cnn.cnm cnn.coe cnn.coi cnn.coo cnn.col
To make it easier to check if particular domain is already registered or not, I’ve made a wrapper script that will execute the python script and for each generated domain it will execute command:
> nslookup domain | grep "NXDOMAIN"
The wrapper script is executed with a single argument that is a domain name. Sample output for twitter.com:
Some of those reported as available are obviously false-positive since TLDs like kom don’t really exist. I did not removed them because new TLDs are added from time to time and you might as well have a custom domain setup within your LAN.
The wrapper code:
#!/bin/bash for i in $( ./digbit.py $1); do dotcheck=$( echo "$i" | grep "\." | wc -l) echo -n "$i "; check=$(nslookup $i| grep "NXDOMAIN" | wc -l); if [[ $check -ne 0 && dotcheck -ne 0 ]]; then echo " < available"; else echo " "; fi; done
The Digbit script code:
#!/usr/bin/env python3 import binascii import re import os import sys def new_text2bin(mtext): result = [ bin(ord(ch))[2:].zfill(8) for ch in mtext ] return ''.join(result) def switch_bit(bit, my_list ): result_list = my_list[:] if result_list[bit] == '1': result_list[bit] = '0' else: result_list[bit] = '1' return result_list def generate_similar( domain ): domains = [] domain_list = list(domain) for i in range(len(domain)): print(switch_bit(i, domain_list)) return domains def binstr_to_ascii( binstr ): binstr = -len(binstr) % 8 * '0' + binstr string_blocks = (binstr[i:i+8] for i in range(0, len(binstr), 8)) string = ''.join(chr(int(char, 2)) for char in string_blocks) return string if len(sys.argv) != 2: sys.exit("Not enough args") else: domain=str(sys.argv[1]) domain_list = list(new_text2bin(domain)) for i in range(len(domain_list)): new_d = (''.join(switch_bit(i, domain_list))) new_d_str = binstr_to_ascii(new_d) corect_domain = re.match("^(((([a-z0-9]+){1,63}\.)|(([a-z0-9]+(\-)+[a-z0-9]+){1,63}\.))+){1,255}$", new_d_str + "." ) if ( corect_domain is not None and len(corect_domain.string) > 1 and (corect_domain.string).index(".") < len(corect_domain.string)-1 ): print(new_d_str, end="\n") print(" ")