For the longest time VOGONS was the place to get information about VDMsound the sound blaster emulator for NTVDM, allowing a far more rich gaming experience on NT, DOSBox, the ubiquitous PC/MS-DOS emulator that is simply everywhere, and of course where I was ‘discovered’ via ‘Quake1 with WATTCP built with DJGPP on DOSBox‘ some 10+ years ago!
What makes you nostalgic? I don’t know about you, but for me, it’s definitely early 2000s web forums. Names like vBulletin, UltimateBB, phpBB, YaBB, IkonBoard, … bring a smile to my face. Thus, I figured it would be time to revisit the oldest vBulletin I could get my hands on. As it turns out, vBulletin used to offer “vBulletin Lite†back in the year 2000, which is a version of vBulletin 1.x stripped down so much, it almost stops being vBulletin.
Because they hid it behind a form, the web archive didn’t quite catch it, but I managed to find a different copy online, which seems pristine enough at least: vbulletinlite101.zip
So that’s just a bunch of code. I could just get a period-appropriate Red Hat 9 installation going, but that’d be boring. How much work could it possibly be to get this to run? In hindsight: just about six hours. Please allow me to say that the code is of rather questionable quality. Do not expose this to the Internet. Without even trying, I found at least two SQL injections. Every SQL injection immediately leads to code execution under PHP as well since the templates are interpreted using eval(). And so I set out on my quest to port this to a modern OS.
Software
Original Requirement
My Version
Operating System
“different flavours of UNIX, as well as Windows NT/98”
Ubuntu 19.04
Interpreter
PHP 3.0.9
PHP 7.2.19
Database
MySQL 3.22
MariaDB 10.3.13
The details of this are rather boring, so allow me to point out some highlights and discoveries made while digging through the code:
50 reply limit: Threads were limited to 50 replies. There was no pagination. Any replies beyond that would just replace the most recent post. I’m not sure if this was an attempt at preventing server and client load from excessively large pages or an attempt to “encourage†people to actually buy vBulletin.
No accounts: Unlike vBulletin 1.x, there were no accounts. All posts would just have a username field and an optional field for an e-mail address; even if provided, the e-mail address does not get verified.
No thread/post management: There’s no way to conveniently delete threads or posts, leaving the forums completely defenseless against spam. I suspect this was by design, so that nobody would stick with vBulletin Lite.
Icon plagiarism: The icons for the “search†and “home†buttons are actually taken from Internet Explorer 4. For comparison, here are the buttons in Internet Explorer:
Questionable security: vBulletin Lite was not a pinnacle of secure and defensive coding. Though some efforts were made (e. g. using addslashes(), which is nowadays considered inappropriate, but was all that what was available at the time in PHP 3), they were not thorough and overlooked spots. When encountering a database error, the actual SQL query and error details would be shown in an HTML comment on the error page, greatly helping attackers build their SQL injection even without source code available. The admin control panel password is stored in plaintext: on the server as well as in the cookie that persists an admin session. I’m also not sold on using eval() for interpreting templates from the database.
Filenames ending in .php3: Back then, it was common for PHP scripts to have a filename ending in .php3, though I couldn’t find the exact reason why this used to be common practice (possibly to allow PHP/FI 2.0 and PHP 3.0 to co-exist, maybe?). Nowadays, everything’s normally just a .php file.
register_globals was very much a thing: The PHP (anti-)feature register_globals caused request parameters and cookies to be turned into global variables in the script, e. g. https://www.php.example/test.php?x=1 would set $x to 1. vBulletin Lite relied on register_globals existing and working. PHP removed it in version 5.4, so a lot of request handling needed to be changed for vBulletin Lite to work at all.
MySQL has implicit defaults: Apparently, if strict mode is not enabled, MySQL has implicit defaults for various data types. vBulletin Lite relied on this behavior, much to my surprise. I’m not sure who thought this was a good feature, but it sure surprised me.
Password caching until exactly 2020: When successfully logging into the admin control panel, a cookie “controlpassword†is set. It is hardcoded to expire at the beginning of 2020—next year. I’m glad I didn’t have to try and debug that subtle issue. My patch makes it so that the cookie expires at the start of the next year.
A typo in the admin control panel: In admin/forum.php, deletion of a forum should bring the list of forums again. However, due to a typo (“modfiy†instead of “modifyâ€), the page instead stays blank. I also took the liberty to fix this obvious bug.
Feature remnants: vBulletin Lite kind of looks like a rushjob; I’d love to find out if that’s true. There are leftovers of various features, which manifest themselves in stray variables being referenced but never set. For example, the e-mail field in the template for the newthread.php page actually references $password, which nothing else ever reads or sets. Similarly, forumdisplay.php references a $datecut variable, which I assume regular vBulletin 1.x would use to prune old threads by date (to save space on the database?).
Ampersands in HTML: vBulletin had literal ampersands (&) in the templates, namely in links. Firefox complains about this nowadays and expects & even in <a href>, but I didn’t want to touch that because I’m afraid I might break an old browser by changing this behavior.
As mentioned above, I made a patch for vBulletin Lite 1.0.1 to make it work with modern versions of PHP and MySQL: vbulletinlite101-2019.diff Applying it requires some preparation (renaming the files from .php3 to .php and adjusting the names of included files ahead of time); after that, it should apply cleanly:
$ for i in *.php3; do mv $i $(basename $i .php3).php; done
$ cd admin && for i in *.php3; do mv $i $(basename $i .php3).php; done
$ cd .. && find . -name "*.php" -exec sed -i 's/php3/php/g' {} \;
$ patch -p1 < PATH_TO_PATCH.diff
vBulletin Lite had a mechanism that would send e-mail a configurable address about SQL errors. I ended up disabling that in db_mysql.php, spilling the error onto the page and kept that behavior in the patch to make debugging easier (since this has no business running in production anymore anyway). See the areas marked with TODO if you want to undo that after all.
I used the new ?? syntax introduced in PHP 7, so this patch may not immediately work with PHP 5, though the worst grunt work has already been taken care of.
The website that used to host vBulletin Lite notes that “vBulletin Lite may be modified for your own use only. Under no circumstances may any modified vBulletin Lite code be distributedâ€.
I hope that separating this into a pristine archive and a patch—with no functional changes—is good enough. Should this still not be enough for the rightsholders (currently MH Sub I, LLC dba vBulletin), takedown requests will of course be honored.