Bitcoin sites are the focus of intense hacking.

More than just a steady flood of hacking, bitcoin hacking has become more of a culture within a subculture. As such their methods are ever evolving and they are extremely coordinated. Once a critical flaw is found it is exploited rapidly throughout the entire ecosystem. Conventional security guides cannot keep up with such a culture nor do they understand the unique terrain that bitcoin startups must deal with. There is a lot of talk about securing bitcoin as a user but very little in the way of security guides for those running bitcoin services. It’s time began sharing what we have learned.

We at Paxful have had to deal with nearly every hacking the book. As a peer to peer market place that is home to many pro traders who have a great deal of bitcoin we must secure our users as well as our hot wallet. Our founders have built a previous bitcoin exchange, worked with the European SEPA banking network and released an open-source Bitcoin API server . Here are seven security tips that you must deploy right away. In the end it could save your startup.

  1. Clickjacking
  2. XSS Attacks
  3. Webserver Hardening
  4. Port and IP Cloaking
  5. SQL Injection
  6. No NoSQL For Financial transactions
  7. Race Conditions
  8. Vulnerability Scanner blocks

There is ALOT more to cover and we’ll be releasing more tips going forward as a series.

Click Jacking

Attackers have become skilled at getting users to perform their desired actions for them using their own clicks against them. They will insert an iframe of a website they usually use and are logged into within your website. This is clickjacking.

One of their favorite tricks is getting users to allow flash scripts to have total access. Then they inject a flash script to let them invade users machines.
One of their favorite tricks is getting users to allow flash scripts to have total access. Then they inject a flash script to let them invade users machines.
The basics of clickjacking are get them to give you their private information by typing it in themselves.
The basics of clickjacking are get them to give you their private information by typing it in themselves.

Adding “add_header X-Frame-Options SAMEORIGIN;” to your nginx configuration file can protect against this on the server level but it isn’t enough. You should also add some client side code to each page request to bust out of any frames not originating from your server.

<style id=”antiClickjack”>body{display:none !important;}</style>
<script type=”text/javascript”>
if (self === top) {
var antiClickjack = document.getElementById(“antiClickjack”);
} else {
top.location = self.location;

XSS Attacks

Anytime you allow the user to give you data that you will display to the browser you risk XSS attacks. Attackers can insert malicious client side javascript or redirects. They can easily steal traffic and even worse any and all user information. Usually considered not as serious as SQL injection many websites neglect protecting their users against css attacks and instead of having their entire site hacked they simply get all their active users hacked instead, which is just as bad.

XSS attacks allow attackers to make your website work for them by inserting malicious client side scripts into the user data you output to the browser. They can steal away your traffic and rob your active users of their data.
XSS attacks allow attackers to make your website work for them by inserting malicious client side scripts into the user data you output to the browser. They can steal away your traffic and rob your active users of their data.

There are some measures you can take on the server side configuration side but primarily it is up to you to escape any and all content you take from users before you spit it back out.

Ex.  Never Insert Untrusted Data Except in Allowed Locations

  • <script>…NEVER PUT UNTRUSTED DATA HERE…</script> directly in a script
  • <!–…NEVER PUT UNTRUSTED DATA HERE…–> inside an HTML comment
  • <div …NEVER PUT UNTRUSTED DATA HERE…=test /> in an attribute name
  • <NEVER PUT UNTRUSTED DATA HERE… href=”/test” /> in a tag name <style>…NEVER PUT UNTRUSTED DATA HERE…</style> directly in CSS
  • <div attr=…ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE…>content</div> inside UNquoted attribute
  • <div attr=’…ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE…’>content</div> inside single quoted attribute
  • <div attr=”…ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE…“>content</div> inside double quoted attribute.
  • etc….

Webserver Hardening

Chances are you’re either using Apache or Nginx to host your web app. N-ginx (pronounced engine X) is a popular choice for a non bloated fast web server. Locking it down involves editing the main nginx.conf file usually in /usr/local/nginx/conf/nginx.conf. Here is a list of settings to properly lock it down on the server level. This will offer protection against XSS, cross site forgery

# config to don’t allow the browser to render the page inside an frame or iframe
# and avoid clickjacking
# if you need to allow [i]frames, you can use SAMEORIGIN or even set an uri with ALLOW-FROM uri
add_header X-Frame-Options SAMEORIGIN;

# when serving user-supplied content, include a X-Content-Type-Options: nosniff header along with the Content-Type: header,
# to disable content-type sniffing on some browsers.
# currently suppoorted in IE > 8
# ‘soon’ on Firefox
add_header X-Content-Type-Options nosniff;

# This header enables the Cross-site scripting (XSS) filter built into most recent web browsers.
# It’s usually enabled by default anyway, so the role of this header is to re-enable the filter for
# this particular website if it was disabled by the user.
add_header X-XSS-Protection “1; mode=block”;

# with Content Security Policy (CSP) enabled(and a browser that supports it(,
# you can tell the browser that it can only download content from the domains you explicitly allow
# I need to change our application code so we can increase security by disabling ‘unsafe-inline’ ‘unsafe-eval’
# directives for css and js(if you have inline css or js, you will need to keep it too).
# more:
add_header Content-Security-Policy “default-src ‘self’; script-src ‘self’ ‘unsafe-inline’ ‘unsafe-eval’; img-src ‘self’; style-src ‘self’ ‘unsafe-inline’; font-src ‘self’; frame-src; object-src ‘none'”;

Any off-site script or resource you call in your pages must have it’s domain added to the above line. For example, google analytics, any con’s hosting js or css files etc..

You’ll also have to add a few lines to each site’s config file to protect against SSL Beast attacks by disabling ssl3 etc.. Take any and all precautions as the more and more bitcoin is worth the more desperate and extreme hackers will get. Remember the heart bleed zero day exploit? It bleed out quite a few bitcoins as well. SSL powers the entire secure web and it is an object of constant attention by hackers, stay on top of it.

SSH IP and Port Cloaking

SSH remains the primary way that admins access linux servers. While an essentially secure protocol the fact that most admins leave the port settings on the default and also access ssh via the same ip address as public users to their web app. We can do better than this and for financial applications we MUST do better. Purchase another ip address, preferably from a different subnet, from your web host and assign this new ip address to your network card. Then configure ssh to only be accessed from this ip address. Setup your firewall to allow ssh access via this ip address. Now hackers will have a much harder time even locating your ssh ip address. In addition to this there is also the option of changing the default ssh port for ssh on the cloaked ip address.

There is intense debate about weather or not moving ssh ports off the default of 22 to something random like 22042. Some argue that moving ssh off port 22 encourages the lazy practice of security obscurity and that webmasters should reply on keys and disable passwords etc. Others argue that changing the ssh port off the default is a good idea as it protects against zero day exploits. One webmaster logged over 4 scans on his non conventional ssh port and over twenty two thousand to his default ssh port, in a single day. We say , change your ssh port to anything other than the default. Hackers usually go for low hanging fruit and if it buys you even a single day from a zero day exploit it could make all the difference.

Many bitcoin startups have opted to use the full node of the original bitcoin core server, and still best in our humble opinion, bitcoin server. This software is currently in 0.10 and is maintained by the very best developers in the bitcoin world. We suggest everyone use this server as it is the most battle hardened. Securing a server with Bitcoin Core isa job in and of itself but one of the best things you can do is to close up the RPC ports and specify new hard to guess ones. Determined attackers will do port scans and find them anyway but you’d be surprised at how lazy most hackers are, they spend most of their time looking for low hanging fruit and if you pass that test they usually move on. Here are some examples

SQL Injection

It is sad that we even have to mention this exploit this day and age but an enormous amount of web applications are still vulnerable to sql injection. Many frame works protect against such attacks but many developers still do not use frameworks or use custom frameworks and forget to escape their user database destined input. The PHP community is notorious for this as it draws in many newbie coders who are happy just to get anything working at all that they utterly neglect security.

SQL injection is when hackers submit sql database code in form fields hoping that the web app doesn't escape the input. This way they can simply get a dump of the entire database with the right sql statement or give themselves admin access to the server.
SQL injection is when hackers submit sql database code in form fields hoping that the web app doesn’t escape the input. This way they can simply get a dump of the entire database with the right sql statement or give themselves admin access to the server.

We’re not hating on PHP as it is still the most popular language on the internet, powering wordpress, Facebook and Flickr etc. With the right framework and precautions is can be one of the most secure platforms because of it;s maturity, twenty plus years. The use of database ORM packages that ship with many frameworks such as Eloquent in Laravel will automatically escape user input.

Say No to NoSQL

Flexcion fell prey to a hack attack that drained their hot wallet because of their use of NoSql database mongoDB for financial transactions. While MongoDB has some support for atomic transactions it is nowhere near the level required for a financial application. Stick with a proven relational database with time test ACID support like PostgresSQL. NoSQL can be used for non financial data such as log tables and chat messages. Always use atomic transactions for all financial inserts, and updates.

Also a special note to MongoDB users take care to lockdown web access to your MongoDb instance. A recent security scan discovered over 40,000 MongoDB instances admin panels were freely available to browser via port 27017. It seems that some NoSQL users psychologically don’t see their databases as hacking targets and thus do not lockdown their instances. A vulnerability search engine like will as of now reveal an immense amount number of such databases vulnerable to hacking or outright access.

Race Conditions

Race conditions in software are when two concurrent threads of execution access a shared resource in a way that unintentionally produces different results depending on the time at which the code is executed. For example, a multi-threaded program may spawn 2 threads that have access to the same location in memory. Thread #1 might store the value 300 in this location and expect it to still be 300 a few instructions later. Since thread #2 is executing at the same time as thread #1, thread #2 may overwrite the memory location with another value while thread #1 still expects it to be 300. Sometimes it will happen, sometimes it will not. It depends if thread #2 is “lucky enough” to execute just after thread #1 wrote the value 300.

Race conditions can devastate financial apps
Race conditions can devastate financial apps

This deserves a whole article and it will get one but be on the lookout for race condition attacks which are essentially application level double spend attacks. These can be absolutely devastating and require a deep understanding of row locking. Simply relying on your relational SQL databases transaction systems are not enough.

Vulnerability Scanner Blocks

The first thing hackers and script kiddies alike do is to run a security vulnerability scanner like Acunetix on your side. It scans for common app paths and tries to hijack every form on your web app. It is a good idea to run this on your own application if if others try and run it on your app then it is best to block them.

There are three ways to do this. On the web server level with say Nginx, in your robots.txt and in your webapp itself.

Add these lines within your Nginx conf file.

sudo nano /usr/local/nginx/conf/nginx.conf

server {
#protect from vulnerability scanners
if ($http_user_agent ~* (Baiduspider|webalta|nikto|wkito|pikto|scan|acunetix|morfeus|webcollage|youdao) ) {
return 401;

if ($http_user_agent ~* (HTTrack|clshttp|archiver|loader|email|harvest|extract|grab|miner) ) {
return 401;

Add these lines to your web app. This example is for PHP. add it to the first files to execute

//protect against acunetix security scanner

Then add these lines to your robots.txt file

User-agent: Acunetix
Disallow: /

User-agent: UbiCrawler
Disallow: /

User-agent: DOC
Disallow: /

User-agent: Zao
Disallow: /

Disallow: /

User-agent: Zealbot
Disallow: /

User-agent: MSIECrawler
Disallow: /

User-agent: SiteSnagger
Disallow: /

User-agent: WebStripper
Disallow: /

User-agent: WebCopier
Disallow: /

User-agent: Fetch
Disallow: /

User-agent: Offline Explorer
Disallow: /

User-agent: Teleport
Disallow: /

User-agent: TeleportPro
Disallow: /

User-agent: WebZIP
Disallow: /

User-agent: linko
Disallow: /

User-agent: HTTrack
Disallow: /

User-agent: Microsoft.URL.Control
Disallow: /

User-agent: Xenu
Disallow: /

User-agent: larbin
Disallow: /

User-agent: libwww
Disallow: /

User-agent: ZyBORG
Disallow: /

User-agent: Download Ninja
Disallow: /

User-agent: wget
Disallow: /

User-agent: grub-client
Disallow: /

User-agent: k2spider
Disallow: /

User-agent: NPBot
Disallow: /

User-agent: WebReaper
Disallow: /

User-agent: *
Disallow: /100mb.bin
Allow: /


The biggest bitcoin heist of all, MT. Gox was blamed on a core bitcoin flaw called “transaction malleability” It was not included in the list because it is no longer a real issue and as more and more people suspect it was never a real issue, certainly not one big enough to account for the loss of over 800,000 bitcoins. Instead of worrying about unique and extreme exploits we should focus on the known basics and fundamentals of security. If the entire industry committed to this we’d have a far after and more secure crypto eco system and that is good for all of us.