What’s New And Secure About WordPress 1.5.3-beta?

Posted on Wed, 29th March 2006 at 19:02 under Software, Skills, WordPress, Education, Coding, Publicity

In the conjuring discussion, I offer an analysis of the security-related changes in the as-yet-unreleased WordPress 1.5.3.

This is my work and my report.


  1. Become A Subversive
  2. Download Latest WordPress
  3. Detect Changed Files
  4. Analyse File Changes
  5. Assess Security Implications
  6. Report

11 Responses



  1. Install Subversion (Source Management) Package

    The WordPress team use Subversion (SVN) for source code management. I use Concurrent Versions System (CVS). Like Ajay, I need to get a hold of a SVN client.

    I’m using Kubuntu Linux rather than Windows, so it is more difficult to locate and install applications. I used my graphical package manager but the full command needed is:

    sudo apt-get install subversion

    Done.

    Reply


  2. Download Latest WordPress 1.5 From The Repository

    I’ve never used SVN and I only have this command-line thing installed. Ajay’s Windows interface makes downloading from the repository look so easy. I’ll have a much harder time.

    So, I need to create a directory in which to download the WordPress files. OK.

    paul@kubuntu:~$ mkdir src/wordpress-1.5.3

    Now I need to check the files out from the WordPress SVN repository at http://svn.automattic.com/wordpress/branches/1.5/. Ajay just had to right-click the folder. I’ll have to type a command. Well, does the SVN client have a checkout option?

    paul@kubuntu:~$ svn checkout

    checkout (co): Check out a working copy from a repository.
    usage: checkout URL[@REV]... [PATH]
    
      If specified, REV determines in which revision the URL is first
      looked up.
    
      If PATH is omitted, the basename of the URL will be used as
      the destination. If multiple URLs are given each will be checked
      out into a sub-directory of PATH, with the name of the sub-directory
      being the basename of the URL.
    
    Valid options:
      -r [--revision] arg      : ARG (some commands also take ARG1:ARG2 range)
                                 A revision argument can be one of:
                                    NUMBER       revision number
                                    "{" DATE "}" revision at start of the date
                                    "HEAD"       latest in repository
                                    "BASE"       base rev of item's working copy
                                    "COMMITTED"  last commit at or before BASE
                                    "PREV"       revision just before COMMITTED
      -q [--quiet]             : print as little as possible
      -N [--non-recursive]     : operate on single directory only
      --username arg           : specify a username ARG
      --password arg           : specify a password ARG
      --no-auth-cache          : do not cache authentication tokens
      --non-interactive        : do no interactive prompting
      --config-dir arg         : read user configuration files from directory ARG
      --ignore-externals       : ignore externals definitions
    

    Yes! I know the URL of the repository and the path I want the files.

    paul@kubuntu:~$ svn checkout http://svn.automattic.com/wordpress/branches/1.5/ src/wordpress-1.5.3

    A    src/wordpress-1.5.3/wp-pass.php
    A    src/wordpress-1.5.3/wp-rss.php
    A    src/wordpress-1.5.3/wp-login.php
    ...
    A    src/wordpress-1.5.3/wp-admin/import-mt.php
    A    src/wordpress-1.5.3/wp.php
    A    src/wordpress-1.5.3/wp-feed.php
    Checked out revision 3664.
    

    Done.

    Reply


  3. What Files Have Changed?

    A source code management system should have extensive support for determining the differences between versions of files. Usually, I would compare the files I checked out against a set of WordPress 1.5.2 files I had previously downloaded. That’s exactly what I’ll do now.

    paul@kubuntu:~/src$ kompare libertus/ wordpress-1.5.3/

    Ajay didn’t need to do this because he was only interesting in updating an unliberated installation of WordPress. As my WordPress is liberated, I need to know exactly where the changes are and what they do before I can consider incorporating them into my code.

    Kompare is very nice. Scanning over the differences I reckon the following files have been changed from stock WordPress 1.5.2.

    wp-mail.php
    wp-register.php
    wp-settings.php
    wp-admin/admin.php
    wp-admin/page-new.php
    wp-admin/post.php
    wp-admin/profile.php
    wp-admin/user-edit.php
    wp-includes/class-snoopy.php
    wp-includes/comment-functions.php
    wp-includes/functions-formatting.php
    wp-includes/pluggable-functions.php
    wp-includes/template-functions-links.php
    wp-includes/version.php

    Reply


  4. Detailed File-by-file Change Analysis

    My blog runs Liberated WordPress 1.5.2, a home-grown affair. There are other changes in the offing which will result in the release of Liberated WordPress 1.5.1. The latest WordPress fixes form part of that, so an analysis of their scale and worth is necessary. If there are security changes in WordPress 1.5.3, I must apply them to my version.

    paul@kubuntu:~$ kompare src/wordpress-1.5.3/ src/libertus/ &

    wp-mail.php

    Description: A program to get mail from a POP3 server. I don’t use blog-by-email so the security fix for me is to delete the file.

    Change: ISO descrambling of the supplied subject is now unconditional (the previous necessity check presumably faulty), the supplied author is now unconditionally sanitised for the database and finally the entire supplied post is now unconditionally sanitised for the database.

    Analysis: Good riddance! If you blog by e-mail, don’t delete this file.

    wp-register.php

    Description: This is the program to register new users into WordPress. I don’t allow this on my blog at the moment, but I am hoping to open it up again soon, so security fixes here are important.

    Change: The supplied login and email address are now unconditionally sanitised for output.

    Analysis: Harmless. Apply.

    wp-settings.php

    Description: Now this is an important program. It sets up an environment for all the other programs and is the 4th program out of the many that WordPress runs every time a blog page is displayed. Changes here affect everything. I use the stock file, obviously.

    Change: If the incoming data has magic quotes, remove them. Then unconditionally reapply them.

    Analysis: Change incorrect. Do not apply.

    wp-admin/admin.php

    Description: The main program of the WordPress administrative interface. Every other administrative interface program begins with this one. It is vital.

    Change: Plugin name now sanitised for output.

    Analysis: Harmless. Apply.

    wp-admin/page-new.php

    Description: Write New Page interface. Quite important.

    Change: Add call to get_currentuserinfo() at line 17.

    Analysis: get_currentuserinfo() is already called on line 6. Do not apply.

    wp-admin/post.php

    Description: Write Post interface. All post action happens here. It is vital.

    Change: Subprograms post, editpost, confirmdeletecomment, mailapprovecomment, approvecomment and editedcomment all now call function check_admin_referer() before doing anything else.

    Analysis: This could be a security fix. On the face of it, without applying these changes my blog is currently vulnerable to attack because these subprograms could be called by pages that are not part of my administrative interface and would therefore be able to present data in any form desired, which could be bad. Further analysis is required.

    How would calling check_admin_referer() protect my blog from attack? What does the function do?

    File wp-admin/admin-functions.php. It checks that the blog’s admin URL (in my case http://www.libertini.net/libertus/wp-admin is contained in the referer header of the current HTTP request. If it is, the check_admin_referer action is triggered. If it is not, the following message is displayed:

    Sorry, you need to enable sending referrers for this feature to work.

    Phew! This isn’t a security fix. It is a user experience enhancement.

    Harmless. Apply.

    wp-admin/profile.php

    Description: Users manage thieir own profile with this program.

    Change: New password is escaped for the database and is stored as such in the password cookie.

    Analysis: The escaping looks necessary. This will bite if someone types an apostrophe into their password, which could allow a SQL injection attack. I’ll apply that.

    Storing the new password escaped into the cookie looks odd. Presumably this is to save having to escape it again when the cookie value is presented to the database for checking. Inelegant, but apply.

    wp-admin/user-edit.php

    Description: Administrators manage users globally with this program.

    Change: The update subprogram calls check_admin_referer().

    Analysis: Harmless user experience enhancement as for post.php. Apply.

    Notice my commenting-out fix for the annoying problem of hanging http:// in the comment URL. Consider submitting patch.

    $new_url = wp_specialchars($_POST[’new_url’]);
    /* No, you just get what you type in, rather than nonsense when you type nothing
    * $new_url = preg_match(’/^(https?|ftps?|mailto|news|gopher):/is’, $new_url) ? $new_url : ‘http://’ . $new_url;
    */
    $new_idmode = wp_specialchars($_POST[’new_idmode’]);

    wp-includes/class-snoopy.php

    Description: I don’t know what this does. I hope the class is named after the character from Peanuts. I’m only really concerned with the changes, but anything in wp-include can be called from anywhere by anything in the blog program sequence, so I like to know what happens in here.

    Change: Upgrade a third-party module from version 1.0 to 1.01.

    Analysis: Apply.

    wp-includes/comment-functions.php

    Description: Library of functions used by WordPress and third-party extensions to work with comments and their data.

    Change: Can’t tell. None.

    Analysis: Conflict with my customisations. Compare with stock WordPress 1.5.2.

    wp-includes/functions-formatting.php

    Description: Library of functions relating to the formatting of things.

    Change: Add function stripslashes_deep().

    Analysis: Needed by the unapplied change to wp-settings.php. Irrelevant. Do not apply.

    wp-includes/pluggable-functions.php

    Description: A cornucopia of miscellaneous functions that plug-in authors can have fun replacing with their own custom parts. Like user security.

    Change: function get_currentuserinfo() now verifies that the user is logged in by actually logging them in rather than just testing for the presence of the login cookie. Tidying of the user display name.

    Analysis: JESUS! Apply first one like a shot. Not sure if it was spoofable. The comment above still reads // *** retrieving user’s data from cookies and db - no spoofing.

    Apply harmless second one and additionally remove now-unused $idmode assignment.

    wp-includes/template-functions-links.php

    Description: A library for functions for generating links.

    Change: Sanitise HTTP request URI before building page link with it.

    Analysis: Apply.

    wp-includes/version.php

    Description: Sets which version of WordPress is installed.

    Change: From 1.5.2 to 1.5.3-beta1.

    Analysis: Set mine to 1.5.1-liberated.

    Reply
  5. Further Analysis

    There remains the removal of wp-mail.php and a stock comparison of comment-functions.php.

    Removing wp-mail.php

    Before removing a source file in its entirety, it is prudent to check that everything will still work fine without it. How exactly does WordPress decide when to check and download mail from a POP3 e-mail inbox?

    The top of the file says a lot. This program is designed to be called from outside WordPress because it reads the WordPress configuration file.

    require(dirname(__FILE__) . ‘/wp-config.php’);

    require_once(ABSPATH.WPINC.’/class-pop3.php’);

    I’m going to guess that it is also the only user of the POP3 class, leading to my being able to delete a second file!

    To be sure it is called externally, check if it is referenced in WordPress. Search the source for wp-mail.php. Nothing. Odd. Search for wp-mail. One hit.

    // used by wp-mail to handle charsets in email subjects
    function wp_iso_descrambler($string) {
    /* this may only work with iso-8859-1, I’m afraid */
    if (!preg_match(’#\=\?(.+)\?Q\?(.+)\?\=#i’, $string, $matches)) {
    return $string;

    That looks familiar. The check for ISO descrambling wasn’t faulty, it was redundant. Much like this whole function now, according to the comment.

    Nothing in WordPress references wp-mail.php. Rather than dig further, I’m just removing it. Is the POP3 class used anywhere else? Search the code for pop3, case-insensitive. Hits class-pop3.php and one mention in the options text. Remove class-pop3.php.

    Analysis of Changes To comment-functions.php

    I’ve customised this function right around where I suspect a 1.5.3 change was made, so for safety I’m comparing against stock 1.5.2. Especially now that the get_currentuserinfo() function has a totally new purpose (it now verifies rather than just acknowledges login) and adding a call to it looked like the change.

    paul@kubuntu:~/src$ diff -s wordpress-1.5.3/wp-includes/comment-functions.php wordpress-1.5.2/wp-includes/
    Files wordpress-1.5.3/wp-includes/comment-functions.php and wordpress-1.5.2/wp-includes/comment-functions.php are identical

    Phew! No change.

    Reply
  6. Do A Little Snooping

    I’m so pleased at deleting two files that I’m going after another. What does the snoopy class do?

    From the top of the file:

    Snoopy - the PHP net client

    A class that enables PHP programs to talk to the net? Sounds interesting, but what does that have to do with blogging? Could this be something to do with pings and trackbacks? Is this code of any value to me?

    A quick look over the code confirms my suspicions. This code allows PHP programs to simulate web users by submitting forms. I never, ever want my blog program to submit forms to someone else’s website. Well, not without their permission at least, and I have sought no such permission. I don’t think I need this class. Where is it used?

    Hello, 007. I’ve Been Expecting You.

    if ( !in_array(’Snoopy’, get_declared_classes() ) ) :
    class Snoopy
    {

    Search the code for Snoopy. Two hits; the class file and another old friend: rss-functions.php. This whole Snoopy file exists to serve the RSS functions, which serve only the Dashboard, which snoops on WordPress blogs.

    It’s Official. The Designed Purpose of Dashboard Is To Phone Home.

    Yes. The name Snoopy is apt. And gone. Along with all the RSS phone-home-spyware bloat. Dashboard won’t fail anyway, it just won’t get any feeds, which are all completely unnecessary. Nothing at all to do with blogging. Besides, I use Zeitgeist. Dashboard sucks.

    As a consequence of not processing RSS, the XML libraries may not need to be loaded.

    Reply
  7. Liberating WordPress From RSS

    Ohhh!!! I’ve been itching to ditch file wp-includes/rss-functions.php for weeks now, but that is no excuse for being cavalier about it. A careful analysis is necessary. What, if anything, will break?

    Search the code for rss-functions. One hit, as expected, in wp-admin/index.php, and it’s a showstopper!

    require_once (ABSPATH . WPINC . ‘/rss-functions.php’);

    BASTARDS! That’s a lie. The Dashboard program does not require the presence of the RSS functions library, because each call to the fetch_rss() function that it provides has errors squelched. For example, when Technorati is pinged by your blog.

    $rss = @fetch_rss(’http://feeds.technorati.com/cosmos/rss/?url=’. trailingslashit(get_option(’home’)) .’&partner=wordpress‘);

    My guess is that if the rss-functions.php file were not included at all, the Dashboard program would not fall over, despite the missing rss_feed() function. I’ll have to put this to the test.

    Testing The Changes So Far

    CVS is littered with changes to libertus so I’d better check nothing is badly broken. Browsing to front-stage is fine, for one post anyway. The Dashboard is broken, but I expected that because of the Snoopy removal. It’s time to remove RSS as well. The Dashboard now gives:

    Fatal error: main() [function.require]: Failed opening required ‘/home/paul/src/libertus/wp-includes/rss-functions.php’ (include_path=’.:/usr/share/php:/usr/share/pear’) in /home/paul/src/libertus/wp-admin/index.php on line 5

    Yes. A required file is missing. Now, what if instead of being a required file, it was just a desired file. Change line 5 of wp-admin/index.php from require_once to include_once.

    Dashboard Latest Activity Is Liberated!

    Now there are a couple of warnings about a missing file but the rest of the Dashboard program works a treat. No RSS, no feeds, no bother.

    To make it perfect, alter wp-admin/index.php to read:

    5: // disable triple-redundant blog-existence heartbeat to WordPress and partner
    6: // uncomment next line if you want to see WordPress feeds on your Dashboard
    7: //require_once (ABSPATH . WPINC . ‘/rss-functions.php’);

    In other words, disable the RSS functions and your blog becomes silent to WordPress. As a bonus, WordPress becomes silent to you.

    April Fool, Matt!

    Reply


  8. Report

    Yes, there appear to be security fixes in WordPress 1.5.3. Whether current 1.5.2 blog owners should upgrade is not a matter for me to decide. I have applied the changes I thought necessary to my blog. You do the same to yours.

    Reply
  9. Hey,

    Awesome job buddy. Fixed a few bugs for me that I was going crazy about trying to fix, and that is what led me to your post. :)

    But what about these two?

    I checked and I needed to do them both myself. I was running the official wordpress 1.5.2 release.

    http://trac.wordpress.org/changeset/3643

    http://trac.wordpress.org/changeset/3648

    Thanks,

    Will

    Reply
  10. Hey Will,

    Glad you found my post and I hope it helped.

    Those two both look like straightforward fixes to me. 3648 doesn’t affect me because I replaced the multi-field date input control with a single text input. 3643 deals only with the initial creation of wp-config.php by FORM. I’m not inclined to adopt either.

    Reply
  11. oh ok Yeah I just did them since I was having the header already sent problem on a few blogs I setup.

    But yeah glad to hear 1.5 lives on. Can\’t wait for 1.5.3. ;)

    Reply

Leave a Reply

You may also log in to post a comment.

XHTML:

If you want to <q>tag</q>, please balance these; a, i, em, b, strong, u, blockquote, q, ul, li, ol, abbr, code, pre, sub and sup.