I’ll be giving a talk next month on Securing Your Django Site. See you there!
This is going to be somewhat of a departure from your regularly scheduled programming here. I had some extra time over the past week or so and I decided to learn what I could about Bitcoin. This rant is going to contain some poor semblance of economic theory and really I should just stick to tech but I couldn’t resist.
Skip this if you already understand Bitcoin
Bitcoin is a peer-to-peer currency that has gotten some press lately. If I have a Bitcoin wallet (and I do), you can easily send me some “money”. I didn’t read through the code, but my understanding is that this is handled by adding my Bitcoin address to the digital data, signing it with your private key and then broadcasting it to the world. In that way, Bitcoin participants have the entire history of every transaction and only one person possesses any given Bitcoin at any given time. As you might guess, if everybody started using Bitcoin tomorrow, scalability might be a problem. However, it works for now.
What rocks about Bitcoin
A lot of different companies are trying to “solve” payments — be they mobile, physical, digital or anything else. One reason why folks think our current (credit card based) system needs solving is that it is pricey for merchants. The generally expected fees are somewhere just shy of 3% and can also include a fixed transaction fee as well. Fixed fees mean that credit card transactions don’t scale down very well when you are buying something cheap. Ever seen a sign saying $10 minimum for credit cards? That’s why. Bitcoin payments are virtually free which sounds awesome from a merchant’s perspective. They are not generally reversible unless the receiver chooses to reverse it and there’s no central authority to decide who is allowed to pay whom and for what. This is particularly useful if you’re Wikileaks and you’ve been cut off from payment processors or you operate a gambling website and you’re having problems with US banks stopping or reversing your transactions.
For regular users, Bitcoin comes with some advantages such as some level of privacy. No more embarrassing credit card statements. Jokes aside, anonymity of payment has quite a few legitimate purposes and is obviously useful for illegitimate purposes. In addition, Bitcoin requires very little upfront cost. There’s no need to setup a bank account or have a credit limit. It functions like cash but over the internet. You get yourself some Bitcoins and buy whatever you want with them. This has great potential where credit cards have limited penetration but you still want to have transactions over the internet. It’s also quite useful as a “universal” currency because you can avoid currency exchange fees when dealing internationally.
What sucks about Bitcoin
While there are few monetary barriers for a merchant to accept Bitcoin, it requires a lot of planning and constant vigilance. In the last year, Bitcoins have gone for as little as $0.20 and as much as $20. This causes havoc for a merchant who needs to buy things from his suppliers in dollars (or Euros, Yen, etc.) but gets paid in Bitcoin. The merchant needs to constantly be exchanging the Bitcoins he receives for his local currency or absorb some level of currency risk — and Bitcoin is a fairly volatile currency. Suddenly, a merchant needs to have a feel for the Bitcoin economy on top of understanding their business. In addition, exchanging Bitcoins for local currency involves fees (~0.5% usually) and a lack of fees was one of the main reasons a merchant would want to accept Bitcoin anyway. These problems can be mitigated somewhat by a merchant whose supply chain accepts Bitcoin.
For users, Bitcoin seems like a total pain. If I want to pay for something in Bitcoins, first I need to go to one of the exchanges and get myself some Bitcoins. This involves fees! People are not used to paying fees for buying things. In our credit card system, the merchant absorbs that fee and is often prohibited from passing that fee directly on to the consumer. The same problem of currency risk also arises. Holding Bitcoin in your wallet involves risk that the exchange rate could decline. Although the reverse is also true, rational people like to be compensated for taking risk. From a consumer’s perspective, Bitcoin is also not as safe as a credit card. If there is fraud on my credit card, I can reverse the charges. With Bitcoin, there’s no such luck. There’s no recourse short of a bad review for a merchant who sells you a defective product and won’t honor a return. This is the bad side of Bitcoin functioning like cash but on the internet.
The future of digital money?
For consumers, the proposition Bitcoin offers is generally awful. There’s no reason to pay with Bitcoin unless you are forced or incentivized to do so. For merchants, it makes considerably more sense but there are a few kinks to work out. I could see a future where merchants are provided with easy ways to manage or mitigate their currency risk and then they could offer incentives to customers who use Bitcoin because they can pass the fee savings from not using a credit card on to consumers. I could also see Bitcoin becoming/remaining fairly strong where anonymity or decentralization is very strongly desired or required (funding Wikileaks, gambling, illicit materials, private minded folks) or where banking infrastructure is not setup.
That said, I intend to procure and spend some Bitcoins but mostly for novelty reasons.
I released v0.1.10 of RPC4Django. I fixed an issue so that setup.py has no requirements on anything outside of the standard library and I set the project up such that python setup.py test runs the unit tests.
The bigger change is that I moved the project from Launchpad to Github. I’ve already been using Github quite a bit and I thought that I’d bite the bullet and do the move. While I liked Launchpad, I think it is better suited to larger projects that will use the features like Blueprints and Translations. For a small project like RPC4Django, Github’s code-centric approach works better.
I know Djangocon has been over for a week, but I didn’t get a chance to talk about day three and specifically Paul McMillan’s excellent security talk. I also think it’s interesting that Djangocon seems to correlate with security releases (2011, 2010).
Paul demonstrated a timing attack against password reset: a method that mails a user a one-time link to use to reset their password. This timing attack could guess that link with fewer requests than would be needed to guess that link via brute force — that is, fewer than having to guess all possible combinations. It did so by measuring the difference in the times requests took between requests with more vs. fewer correct characters in the URL. I spoke with Paul and he said that this attack works best locally and would be hard to execute remotely because variability in network latency would be significant enough to make measuring the differences in timing difficult. While this attack is not completely practical, a lot of people use shared or cloud hosting which allow attackers to somewhat mitigate this by setting up attack servers in the same network.
Paul also demonstrated a timing attack which leaked some information about whether a username was valid in the system.
Securing Django in production
Even if Django is completely secure (which nothing truly is), mistakes can be made in deployment. Paul recommended an app called django-secure which checks for common misconfigurations. In addition, he said that the login URL should always be throttled to prevent password guessing. The Django security docs which your humble blogger helped write also recommend that among a number of other things. They are worth a read.
I posted a primer about Django passwords last month. Paul had some more things to say about it. Firstly, database dumps/backups and initial data which contain hashed passwords should not be public (for example, on github). As I mentioned in the primer, eight character passwords using Django’s current hashing algorithm (sha1) can be brute forced in a matter of hours in the worst case. So if you accidentally leaked a backup — and a number of high profile sites have done things like this — then consider those passwords broken.
The fix for the password problem is to use a “slower” hashing algorithm designed for hashing passwords. I spoke with Paul after the talk and one of the road blocks to using something like bcrypt is its reliance on C extensions and the Django core team is reluctant to introduce them. However, they are really trying to get something better into the Django core for 1.4.
There were a number of other recommendations including:
- Be careful where you store pickled data (cache, /tmp, etc.). Pickled objects can contain executable code.
- Use the proper cryptographic functions available in Django and Python including: random.SystemRandom, django.utils.crypto.constant_time_compare, and django.utils.crypto.salted_hmac
- Be careful when deploying HTTPS to make sure it is done properly
It’s good to hear that security people are going over Django with a fine-toothed comb.
I enjoyed some brief time traveling when Jacob showed what Django looked like in 2005 or so. It has come a long way.
I attended two talks on APIs today: Isaac Kelly’s talk on Tastypie and Tareque Hossain’s talk on the Promises & Lies in REST. Tareque’s talk involved PBS’ use of Piston and the changes that they had to make (presumably because the core has not been updated). It seems like a number of new projects in the Django/REST space have cropped up (on top of Tastypie) such as Django REST framework and dj-webmachine. At last year’s Djangocon, Eric Holscher (I think) mentioned that it seemed like there was agreement on Piston for Django REST interfaces and now the REST community is fragmenting a little and using a variety of different tools and methodologies.
Tareque recommended a number of methodologies in his talk that I would say are not very RESTful such as including the status code in the data (as opposed to just using the HTTP status code), putting the API version in the URL (a good idea but maybe that should be in the header) or putting the desired output format in the URL (.xml, .json, etc) as opposed to in the HTTP header. Perhaps thinking about “not very RESTful” though is not the right way to think about it. In his talk, Isaac said that “Restish is enough” and maybe that is the answer. If you’re doing most of the RESTful things, you’re Doing Things Right. On the other hand, once you say “Restish is enough” you’re basically admitting that everybody does REST differently and that divergence in REST interfaces is going to continue for at least the foreseeable future.