My first CVE
Back when I was a kid, there was a lot of talk about website defacement.
Y'know, when someone would break into some high-profile site and replace it with some message about how "xXwhateverXx Waz Hear".
Now, this was in the golden age of Wordpress1, so the only thing really keeping anyone out was...2

Now, there are ways to harden this.3
- Rate-limiting.
- Better password hashes.
- Longer, more complex passwords.
- Something about correctly reminiscing about horses and battery staples.
- Password managers.
- Two-factor authentication.4
- Passkeys.
- Making it someone else's problem.
But... does our public webpage need all this stuff at all? Can't we just... remove the admin interface completely?
No online page editor (we can run that as a separate local application anyway..), no "upload this plugin to install"5, no account system at all.
Genius! Why hadn't anyone thought of that before?6
So I ran off to SourceForge7 to register the project. I remember the pure excitement I felt, seeing the email a few days later that it had been approved.8
Well then. No excuses left, time to write some PHP!9 Showing one page is easy enough..10
<?php
$cursor = mysql_query("SELECT content FROM pages");
$row = mysql_fetch_assoc($cursor);
echo $row['content'];
Well, that was simple!11
But what about subpages? Fancy custom URLs like /my/cool/subpage
are a
bit
trickier
in PHP, but /?page=1234
is just a
$_GET
away!
<?php
$page = isset($_GET['page']) ? $_GET['page'] : 1;
$cursor = mysql_query("SELECT content FROM pages WHERE id=$page");
$row = mysql_fetch_assoc($cursor);
echo $row['content'];
Close enough, and simple enough to be invulnerable!12 We're done here, time for mellis.
...okay, you might see where this is going. A while later, I saw something concerning.
A CVE13? For my toy project?!
It's kind of funny, there's this.. intense sense of dread about the
situation ("Oh $DEITY, what did I fuck up?!"). But to child me there
was also a surprise that there was someone out there. That someone was
paying attention to the thing that I had built. That.. it mattered, in
some faint way.14
But back to the issue at hand.. What was the actual problem? A visit from Li'l Bobby Tables.
The code assumes that ?page=1
is a number, but.. It's just text. It
could be anything. And the database would have no idea what part was the
query, and what was the (untrusted) data. It could be
/?page=1 OR 1=1
. Which would get spliced into the database query,
returning some arbitrary page at random. Or it could modify the database
somehow, or return something more sensitive.
I think the big takeaway here is that.. I had decided that it shouldn't do the dangerous thing.15 But hubris led me to think that that was it. That I had the one brilliant idea that had Solved™ the security of the whole application.
I hadn't thought properly about how to constrain it, how to prevent it from how to end up accidentally doing the bad thing anyway.
I should have used a prepared statement. Or escaped it. Or made sure that it actually was a number, and nothing else. I should have made sure to run it as an unprivileged database user, with no permission to modify things anyway.16
But I didn't know that. Didn't know that I should look for that. Because I was Secure™.
At least, when I hear people today talking about how Secure™ they are.. I can't help but think back to 12-year-old me. And how Secure™ she "was".
Because security isn't one magic trick. It's a process. And it's learning how to learn, and what to learn. And we could all use some humble pie on a regular basis.
-
Not that we're really out of it, I suppose. But it definitely feels a lot less dominant these days. ↩
-
Well, this is from modern WordPress, because that's what the playground has on offer... But it's basically the same. ↩
-
Not that all of the details were around at the time. ↩
-
Maybe this sounds like a Static Site Generator to you? ..yeah, but I didn't know that word at the time. Hell, there were packaged products for exactly this! ↩
-
This was back when SF was still "good". ↩
-
Yeah.. that was also a thing, back then. Strange times. ↩
-
As was the custom of the time. ↩
-
All of the actual code samples are going to be vaguely reproduced from my memory; the CVEs are still around, but the code has long since been lost to the sands of time. ↩
-
But isn't this completely vulnerable to XSS? Not really under its security model, since the editors are assumed to be trusted anyway. ↩
-
Totally not foreshadowing. ↩
-
Common Vulnerability Enumeration, basically a way to index known security flaws in products. ↩
-
Not that anyone should have, or did (to my knowledge, anyway), use it. ↩
-
That is, modifying pages. ↩
-
Or view any sensitive tables. ↩
-
Remote Code Execution as a Service ↩