Why you shouldn't place your trust in someone else's code

About two years ago I used to regularly play World of Warcraft;
something which I’m not particularly proud of. While doing so I managed
and maintained a small community site for our guild. Our guild was
comprised of several members of the somethingawful forums and, as such,
our humour tended to be a little more odd than most. If you’ve laughed
at something morally bankrupt on the internet, chances are it originated
on the forums there. After a few months, we formed a chilled out
raidgroup and started regularly raiding dungeons. This meant we’d need
some system for distributing loot amongst ourselves lest we find
ourselves in a position where people’s
poopsockery go unrewarded.
We settled on a system called DKP, or Dragon Kill Points. Basically when
you attend raids you bid on loot, and your bid is divided amongst all
those present such that people who attend more get more loot. To
implement this, we settled with a popular PHP script called
EQDKP to manage our points.

Anyway, I installed EQDKP and because I was busy at the time and because
I’m pretty lazy, I never really got a chance to read around the
applications code. Pretty much everyone else is using this so I’m sure
it’s reasonably secure, right?

I quit playing World of Warcraft last August after realising that game
was a complete sack of shit and spending so much time playing it was
completely retarded. I continued to maintain the guild’s website in the
meantime before eventually passing it on to a fellow web developer
guild-member a week ago. While rsync’ing, out of boredom, I decided to
peruse EQDKP’s source. I started to become very nervous. This code had
been running for almost a year on my box?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
// First things first - a small amount of security
// This script is *so* hackable as to not be funny
// The possible benefit (IMO) outweighs the possible security
// issue with referrer hacking tho
// Check that the visitor's referrer was a page within your own site.
// Copyright 2001 Tim Green
// http://www.dwfaq.com/snippets/snippet_details.asp?SnipID=51

$tg__ServerName=explode(".",getenv("SERVER_NAME"));
$tg__server=$tg__ServerName[count($tg__ServerName)-2].".".$tg__ServerName[count($tg__ServerName)-1];
$tg__Referred = getenv("HTTP_REFERER");

// Get host name from URL
preg_match("/^(http://)?([^/]+)/i", $tg__Referred, $tg__RefHost);
$tg__Host = $tg__RefHost[2];
preg_match("/[^./]+.[^./]+$/", $tg__Host, $tg__RefHost);
if ($tg__RefHost[0] != $tg__server) {
// Change the location to your desired page
header("Location: ./../../viewnews.php");
}

// Now start the "stuff"
?>

This script is so hackable as to not be funny. The possible
benefit (IMO) outweighs the possible security issue with referrer
hacking tho.

Oh dear.

So, to access EQDKP’s database backup functionality within it’s admin
panel all we have to do is point a browser to:

http://myguild.com/eqdkp/admin/backup

And spoof HTTP request referral to read:

http://myguild.com/eqdkp/admin/

That’s it, you’ve now got full access to EQDKP’s database, we’re even
presented with a nice interface to dump the database’s contents.

As if this isn’t retarded enough, EQDKP doesn’t salt its user’s
passwords prior to hashing them. With this in mind we can fire up
whichever web version of RainbowCrack is currently not serving up 404’s
and we have the user’s plaintext password. We could also dump the
database and change the administrators password to one of our choosing
by simply replacing the hash (since it’s not salted). People being
people, we tend to use the same password for pretty much everything. Our
email, PayPal, banking details etc., all compromised by one shitty
script. Pretty scary, eh?

Runt - SVG & Rails

While developing Runt over the past few months it became obvious mid-way
through development that the integration of graphing was somewhat of an
afterthought. That’s okay though because we’re agile, right?

Graphing SNMP data in Rails applications (or any other application for
that matter) is difficult for a number of reasons:

  • What the hell do I graph?

    • SNMP data is so varied in scope that we need to narrow our scope
      in order to graph something useful. We don’t want to graph
      sysName against sysDescr because that’s retarded and
      completely useless.
    • Graphs obviously need need be composed of numerical data, so any
      SNMP data composed of strings is likely going to be useless.
  • Right, so what kind of data types should we be looking at (assuming
    we’re working with protocol version 2c)?

    • Integer32/Integer
      (Enumerated)/Unsigned32/Gauge32/Counter32/TimeTicks/Opaque/Bits

With these data types in mind, our scope is still way too vague for us
to be able to graph any meaningful data. With a deadline looming, I made
the decision to limit the scope of graphing in Runt to just bandwidth,
something which most SNMP graphing applications out there focus on
(MRTG for example). Having made my
decision I was then faced with some interesting decisions regarding
graphing. Initially I wanted graphing to be as sexy as that found in the
Tomato firmware installed on my
WRT54GL router.

Tomato generates its graphs in between AJAX requests and renders them to
the user using
SVG.
Unfortunately, browser SVG support is patchy for Intel Mac users with
Safari 2.0.4 (even though SVG support landed in WebKit landed
over two years ago). Adobe
have offered a plugin for SVG support in Safari (which is going to be
unsupported next year), but only for users running Safari on PowerPC
Macs. As an Intel user you could of course run Safari under Rosetta to
enable the plugin to function but jesus don’t. Thankfully SVG support
will finally find its way into Safari 3.0 in Leopard, but that’s several
months away. IE6/7 users enjoy SVG support through the same Adobe
plugin, while Gecko based browser users see SVG built-in.

With this in mind, and due to the fact I’m a selfish jerk who uses
Safari, I decided against using SVG in Runt, at least for the time
being. My options for graphing in Rails boiled down to three contenders:

  • Gruff - pretty graphs that are
    rendered as PNGs. Rails plugin.
  • Scruffy - - pretty graphs,
    internally rendered using SVG and it can spit out your graphs in
    pretty much any format imaginable. Unfortunately it hasn’t been
    updated in over 9 months.
  • ZiYa - pretty Flash graphs. Flash,
    ugh.

I eventually rolled with Gruff since I found it the easiest to get to
grips with and because it somehow felt more Rails like than the
others. I was seriously considering ZiYA for several weeks but
considering how much I’ve come to hate almost all implementations of
Flash “hay guys lets totally offload the rendering of this website to
some proprietary plugin! This is a great idea, right guys! Guys?!” I
decided it was best to roll with something I could stomach myself using.
Unfortunately, this meant that interactivity with the graph was going to
be seriously limited as Gruff was just going to throw rendered PNGs at a
user with a rather horrible rendering delay between AJAX requests. This
is something that has bothered me ever since I chose to use Gruff, but
what’s done is done.

The next iteration of Runt will see me revisit the idea of using SVG
rendering because it’s sexy as hell and because, for the time being at
least, I’ve begun using Firefox 2.0 regularly once more.

Out with the old

In the midst of some downtime, I finally got around to doing something
I’d planned to do for 2 or 3 years; give
autosystems.ie a complete
rewrite/redesign. At the moment the homepage is a mess of static content
and things don’t get much better when we look at the shopping cart
system. The shopping cart as it stands right now is a pretty hacked up
version of OSCommerce which has been
slowly disintegrating over the past year. No less than 4 times in the
past year I’ve had a call from my brother where it had broken
unexpectedly, seemingly without any user interaction whatsoever.

So I decided to set about developing a really simple shopping cart
system which would be a snap to maintain and which my brother would find
easy to use. I also needed to implement a really lightweight CMS so that
he could change some page elements on the homepage informing people of
new offers and the like. 4 hours later and I’ve got a pretty nifty Ajax
shopping cart system working. There’s still quite a bit to do (payment
functionality with PayPal/Authorize.net for one) but on the whole I’m
amazed at how quickly it came together. Well, maybe not that amazed, I
have been using it to develop Runt over the past few months.

Bloggin' the Blogosphere (Web two point oh)

I never thought I’d actually have any use for a blog (and to be honest
I’d always found myself struggling to see why other people needed them
too), but I guess what with working on new projects and having finally
completed college I could do with some place to organise my ramblings,
so here we are.

I’d been meaning to put together an online portfolio with quite some
time now, so I guess now is as good a time as any.

Runt - almost ready for release

For the past few months at college I’ve been
developing a web-based Rails application called Runt; Ruby Network Tool.
It’s a small application which displays nicely formatted, up to the
second SNMP data from pretty much any device attached to your network.
If you’re after specific data from specific devices, you simply load a
custom MIB for that device and Runt can get data from it. It features a
sort of tacked on ability to graph interface traffic for a given device
also, but it really doesn’t feel all that at home in the application
itself at the moment for a variety of reasons. I’d like to expand upon
this a lot with later releases, but I find myself hindered with current
browser SVG support (at the moment RUNT uses Gruff to generate static
PNG graphs each pass).

The response from the demonstrations I’ve done over the past few months
has been encouraging but the codebase remains a bit too clumsy for my
liking to release it to the general public, at least not yet anyway. It
had been my first foray into the world of both Ruby and Rails so there’s
a lot of cruft which needs reworking.

The version which I’ll release will be v0.1, and I have a lot of other
functionality planned for v0.2. One of the biggest problems I
encountered while developing the application was finding myself
constantly hindered by the very nature of web-based applications - they
sort of need interaction before they’ll do things. As a result, v0.2
will see a lot of functionality handled by a Ruby daemon (using
BackgrounDRb) such as graphing and
some cool alerting functionality through SMS should certain user
specified conditions arise like a device fails to respond to SNMP
requests.

One thing I will say about this learning experience is that I’m quickly
understanding why so many developers are using both Rails and Ruby for
development, regardless of of their rather sluggish performance in
comparison to say Django and Python. There’s just something about blocks
like

1
2
3
foo = [10, 20, 30, 40, 50]
foo.collect { |bar| bar/5*8 }
# => [16, 32, 48, 64, 80]

which make me consider how amazingly eloquent Ruby really is. I’m having
a blast with this stuff.