There's been some talk, lately, about the "friendly" AJAX worm coded by Benjamin Flesch as a proof of concept both leveraging and patching 3 XSS vulnerabilities he found in WordPress 2.2.x.
Allowing a foreign program to run on your system without a chance to scrutinize its source code is not a great idea (I know, many Microsoft customers could not agree).
I'm very new to WordPress (I started playing with it 3 days ago), and I've heard many nightmarish stories about its security, so I'd really love to patch everything I can before I start my own auditing.
On the other hand, I fully subscribe to .mario's concerns -- w/o code review no usage -- and looks like Symantec agrees about this beastie being not harmless, despite its good intentions.
Hence I decided to grab the snail by its tail and forced it to spit its 3 "little secrets".
Here you'll find the patches in a concise and readable form, and you can decide if manually applying them or not.
--- options._unpatched 2007-08-02 08:01:50.000000000 +0200 +++ options.php 2007-08-02 08:05:21.000000000 +0200 @@ -86,8 +86,9 @@ case 'update': $any_changed = 0; check_admin_referer('update-options'); + if (preg_match("/['\"<>]/", $_POST['page_options'])) wp_die(__('Cheatin, uh?')); if ( !$_POST['page_options'] ) { foreach ( (array) $_POST as $key => $value) { if ( !in_array($key, array('_wpnonce', '_wp_http_referer')) )
I'm not 100% sure about the full effectiveness of this one, since it's blacklist based (blocking just quotes and acute brackets), and therefore potentially open to some filtering evasion techniques. But as I said, I'm still far from knowing the intricacies of WordPress code, so maybe it does suffice. Anyway, better than nothing -- you can refine it later.
The remaining two are pretty straight-forward:
--- upload._unpatched 2007-08-02 07:53:45.000000000 +0200 +++ upload.php 2007-08-02 08:15:13.000000000 +0200 @@ -11,8 +11,10 @@ // IDs should be integers $ID = (int) $ID; $post_id = (int) $post_id; +$style = preg_replace('/\W/', '', $style); + // Require an ID for the edit screen if ( $action == 'edit' && !$ID ) wp_die(__("You are not allowed to be here")); --- link-import._unpatched 2007-08-02 08:02:20.000000000 +0200 +++ link-import.php 2007-08-02 08:13:24.000000000 +0200 @@ -72,9 +72,9 @@ <div class="wrap"> <h2><?php _e('Importing...') ?></h2> <?php - $cat_id = $_POST['cat_id']; + $cat_id = preg_replace('/\D/', '',$_POST['cat_id']); if ( $cat_id == '' || $cat_id == 0 ) $cat_id = 1; $opml_url = $_POST['opml_url'];
OK, another lesson I learned today is that publishing patches (and code, in general) with WordPress can be a true pain... Now I understand why bloggers deliver them as worms.
For the curious, here's the source code of the original worm and how to grab it the safe way.
Thanks to Benjamin for all the fis... patches, and happy hacking to everybody.
August 2nd, 2007 at 12:42 pm
Hi!
Thanks for the code. I planed to check that out this weekend and that just saved lots of time.
Btw - the source code link seems broken...
Greetings,
.mario
August 2nd, 2007 at 1:53 pm
.mario, thank you very much for reporting the broken link!
I'm such a WordPress n00b, and I didn't know that attachments inherit publishing status of their parent post (that's fine), but also that's quite easy to create orphaned attachment by error, like in this case.
Being logged in as the author the link worked perfectly, while it was missing for everyone else.
To repair it, I manually set the
field of the attachment record.
Maybe there's an UI way to bind an orphaned attachment to a certain already published post, and I'm grateful for any enlightenment in my perilous blogging journey.
August 2nd, 2007 at 4:01 pm
cool, thanks!
August 13th, 2007 at 7:21 am
preg_replace is rather proces costly just do a typecast to INTeger
$cat_id = (INT) $_POST['cat_id'];
(same as the post_id is parsed)
August 13th, 2007 at 7:29 am
@Jammer:
I agree with you, but these patches are extracted more or less verbatim from the worm.
At any rate, they're superseded by the official fixes released with WP 2.2.2 which, incidentally, did prefer your typecast technique :)