Phreebird First Impressions

by Javantea
Nov 12, 2010

If you haven't heard yet, Dan Kaminsky released Phreebird-1.0 yesterday at Blackhat Abu Dhabi. It is beta software that is designed to allow a DNS admin to setup DNSSEC in less than an hour. In my experience, setting up Phreebird on my system has taken less than an hour but has shown how awful the software is. It is not ready for prime time and it definitely has a lot of little work ahead of it. One might even question whether we should trust a security researcher to write good code. As a security researcher who puts great care into the software I write, I will most certainly say that security researchers are the perfect people to write code. We understand what needs to be done and "real" programmers can always make it better once we've got it working right. And when "real" programmers make mistakes, we can always crash their code.

The tarball is awful. Has no one ever taught Dan Kaminsky how to tar a package for worldwide distribution? Anyway, minor gripe.

mkdir phreebird-1.0
cd phreebird-1.0
tar xzf ../phreebird_suite_1.0.tar.gz
chmod a-x Makefile *.*

The only dependency that gentoo didn't have was libghthash-0.6.2.tar.gz, which DanK packages with his program. It is easy to install just like every other standard automake/autoconf library:

cd ..
tar xzf phreebird-1.0/deps/libghthash-0.6.2.tar.gz
cd libghthash-0.6.2/
./configure && make
sudo make install
cd ../phreebird-1.0

At this point you're ready to generate your key. But this is not obvious.

jvoss@ASLinWS01:~/src/phreebird-1.0$ bin/phreebird -g
Unable to bind to port: 4194304.

At this point you should expect it to not have generated a key, but why is it trying to bind to a port greater than 65535 anyway? Well, that's a bug in the error printing code. Bug number 1 is on line 319. He's printing bsize (which is constant) instead of the port. Replace bsize with port on that line to get a valid error. And so now the program is telling you that it's trying to bind to port 53. Right, I didn't run it as root, so of course it can't bind to port 53. Why is it trying to bind to a port when I asked it to generate a key? Well, I call that bug number 2. On line 174 before the break;, add return 0;. If you'd like, feel free to add a printf that tells the user that dns.key has been created with improper permissions (oh no). Which is bug 3. File permissions of a key file should be set to 400 or 600. I won't fix that bug at the moment due to time constraints.

Now we can actually run phreebird and expect it to run. So long as you don't already run an http server on this machine. You see, part of phreebird's design is that instead of using udp, it uses http for some of its optimizations. It's faster than UDP says Dan in his talk, but I'm skeptical. On a lossy network, it may be possible but the overhead of http is not zero. Out of the box, it isn't possible to run phreebird when you have a webserver on port 80. This is bug 4, which can be easily fixed with a 4 line patch.

On my version, first add the following to line 193:

                       case 'p':
                               opts->http_port = atoi(optarg);

Then on line 1342 of my version, add this line:

fprintf(stdout, "  -p : Use the given port for http instead of port 80\n");

At this point we are ready to run phreebird, cool. But not for long, the first request I send (dig @ causes phreebird to exit with the error "couldn't insert into GHT hash". This is bug 5 if you are counting. On my version it's on line 615 and on the original, it is on line 610. I went as far as looking up the function and checking its possible return values. I ran it with gdb and found that ght_insert() returned -1. The code is not documented well enough for me to fix this. I would be happy to just remove that exit, but I won't. At this point it makes sense to add a bug to the count for lack of proper documentation (bug 6). These functions are not self-documenting even if Dan thinks they are. Here's the lines of code involved:

		status = ght_insert(reqlist, store_cache, sizeof(opts->pcount), &opts->pcount);
		if(status<0) { pb_abort("couldn't insert into GHT hash\n"); }

We aren't done even though my first command killed phreebird. That's right, we have more bugs. In fact, we have the mother of all bugs, memory corruption. That's right, I'm giving you a stacktrace to a segfault crash in phreebird 1 day after it was released. The reason is because it's difficult to exploit (even though it is user triggerable and is running as root) and trivially easy to test on a piece of beta software. The second request I sent was directly from Dan's talk, (dig +short @ ds). The first one returns correctly, hooray!

jvoss@dmitry:~/src$ dig +short @ ds
38282 7 1 6F888C3922AD3F0D0FB3897ABA13272B4A39EE08
DS 7 2 3600 20101211050953 20101113050953 38282 cMxwNyFms2Glg0IBfhdCNy53WLJdYiKxa8xEYLi4tdZeswVRjFdyyYZM ahKYYiq258beZECoiGdSEc4Qp1z06AJ46Z9cBA1qMstmWhtpasg5HQAn dFjrmS+Lkj9WMpZqQxbq603K1i8OIjK9ETE11IK6SYiU9q/H3hLsF4+h 5Ew=

The second call however, crashes phreebird (bug 7). Here is the stacktrace:

#0  0x00007fc8ec9e281d in ?? () from /lib/
(gdb) info threads
* 1 process 16467  0x00007fc8ec9e281d in ?? () from /lib/
(gdb) bt
#0  0x00007fc8ec9e281d in ?? () from /lib/
#1  0x00007fc8ec9e4fbe in malloc () from /lib/
#2  0x00007fc8ed285bbc in ldns_native2rdf_int16 () from /usr/lib/
#3  0x00007fc8ed29d1ed in ldns_key2rr () from /usr/lib/
#4  0x00007fc8ed6dd7b2 in stub_handle_request (opts=0x7fc8ed8e3010, buf=0x7fffa09f7020 ".w\001", len=28, 
    store_cache=0x7fc8ed8e41b0) at phreebird.c:537
#5  0x00007fc8ed6ddf11 in stub_handler_UDP (fd=<value optimized out>, event=<value optimized out>, 
    arg=0x7fc8ed8e3010) at phreebird.c:415
#6  0x00007fc8eccd0c57 in event_base_loop () from /usr/lib/
#7  0x00007fc8ed6dd294 in execute_event_listener (opts=0x7fc8ed8e3010) at phreebird.c:388
#8  0x00007fc8ed6de29f in main (argc=3, argv=0x7fffa09f7ba8) at phreebird.c:207
[New process 16467]
#0  0x00007fc8ec9e281d in ?? () from /lib/

Would you like my coredump? Make your own, friend. It's not exactly rocket science. I'm running gentoo amd64 (no ~amd64 in my tree, in before ricer, 64-bit only, blah blah blah) with ldns-1.6.4 (1 version below the one in Dan K's deps directory), libevent-1.4.14b (several versions below Dan K's 2.0.1-alpha in deps directory), and unbound-1.4.3 (same as in Dan K's deps directory). Do I need to update my dependencies? Really? Who uses alpha software running as root these days Dan? Running online keysigning is fine, using http as a prerequisite of dns as an optimization is fine, and running Dan Kaminsky's code on my production machine is fine, but running alpha software as root is not. This memory corruption bug actually easily illustrates why my friend scoffed when I told him that phreebird does not drop priviledges after opening sockets. This is a bug no doubt, making it bug number 8. Will phreebird be ready for prime time when we fix all of these bugs? No. Phreebird needs a line by line code audit. We never run stuff as root before it gets a code audit, right? Right? Also we must compare phreebird against DNSSEC implementations that don't require proxying, http, and alpha software.

Update: After rereading slide 40 (remember, I only read his slide while listening to him speak at Toorcon 12), it seems that ldns-1.6.5 that he's using is possibly the solution to my bug 7. I will test this out and update this blog post. If so, the real solution to bug 7 is to put a #pragma error when the code detects version 1.6.4 of ldns which not many people really have yet.

Update: I tried it with the supplied ldns-1.6.5 and it still crashed with a similar stacktrace. Shall I try using the alpha libevent?

Update: I tried it with the supplied libevent-2.0.1-alpha and it still crashed with a similar stacktrace. Perhaps it's something else.

But I've been quite critical of the source code. The reason I'm listing the bugs in this way is because I actually care about Phreebird. After watching Dan's talk at Toorcon, I understand what he's talking about. There's a certain point where difficult to understand software causes bugs and there's a certain pont where I'm not willing to deal with a technology that is too difficult to use. It's not too much to ask, I run Gentoo for crissakes. What I'm trying to say is that so long as it's the best way to get DNSSEC done, phreebird is a generally sound idea. Proxying is fine and I actually like Dan's from scratch implementation of these protocols. In fact, I plan on implementing it as soon as it works. The idea of using passwords for giving a person access to a server is outdated and relying on DNS responses for tons of stuff without crypto is pretty ridiculous. Dan is totally correct in wanting to topple the X.509 CA's M-to-any trust model and replace it with a slightly more obvious M-to-1 DNSSEC trust model. The actors that will attack this trust model are much easier to disrupt than X.509's CA's, which will make it a very interesting protocol to use in the next 6 months.

I for one look forward to Phreebird version 1.01.

Javantea out. I'm just a rock in the rain.
E-mail me for questions or clarifications.


Comments: 0

Leave a reply »

  • Leave a Reply
    Your gravatar
    Your Name