This document contains information for an outdated version (2.4) and may not be maintained any more. If some of your projects still use this version, consider upgrading as soon as possible.

2.4.3 (2010-11-11)

Overview

Fixed a security issue where destructive controller actions are not correctly secured against Cross-Site Request Forgery (CSRF). This affects various CMS interfaces, as well as classes based on TableListField or ComplexTableField.

Enhance the protection of the assets/ directory in both IIS and Apache by including a file type whitelist.

Compatibility with PHPUnit 3.5

Allow direct test execution through the "phpunit" binary, in addition to the existing "sake" executable and TestRunner class.

Misc. fixes to validation in date-based form fields, as well as better formatting of dates in non-default locales.

Upgrading Notes

Important: If you are running PHP as FastCGI with Apache

Your development environment, or production web host may be running PHP as FastCGI with Apache. If this is the case,
there is a regression in 2.4.3 which will break your site. There are two ways to resolve this problem:

This does NOT affect IIS, or other web servers that don't understand .htaccess files.

If you're not sure whether PHP is running as FastCGI in your server environment, please check the output of phpinfo().
The easiest way to do this is to open mysite/_config.php and add phpinfo() to the bottom of the file, then browse to
your site to see the environment information.

Cross Site Request Forgery (CSRF) allows an attacker to initiate unauthorized actions against a victim with a valid
login to a target site in the same browser session, e.g. a login to SilverStripe CMS (read more about
CSRF).

While SilverStripe protects form submissions from CSRF automatically, destructive GET and POST actions in subclasses of
Controller are vulnerable without manual checks.

You will need to review any custom subclasses of RequestHandler and Controller (including subclasses of
FormField), and add manual checks. Best practice is to return a "400 Bad Request" HTTP error when the CSRF check
fails.

Also review the method signatures of any form actions - these are only protected automatically with the correct count of
parameters (//$data, $form// instead of $request).

Note: It is regarded as good practice in HTTP to only have destructive actions in POST submissions rather than GET
links.

If you have overwritten any CMS templates (based on LeftAndMain), you will need to update them to include "SecurityID"
parameter in all manually created forms.

Affected classes and methods:

AssetAdmin->addfolder()

AssetAdmin->deletefolder()

AssetAdmin->deleteunusedthumbnails()

AssetAdmin->removefile()

AssetTableField

CMSMain->addpage()

CMSMain->buildbrokenlinks()

CMSMain->createtranslation()

CMSMain->duplicate()

CMSMain->duplicatewithchildren()

CMSMain->publishall()

CMSMain->restore()

CMSMain->rollback()

CMSMain->unpublish()

CommentTableField

ComplexTableField

LeftAndMain->ajaxupdateparent()

LeftAndMain->ajaxupdatesort()

LeftAndMain->deleteitems()

MemberTableField

MemberTableField->addtogroup()

MemberTableField->delete()

MemberTableField_ItemRequest->delete()

PageComment

PageComment_Controller

SecurityAdmin->addgroup()

SecurityAdmin->addmember()

SecurityAdmin->MemberForm()

SecurityAdmin->removememberfromgroup()

SecurityAdmin->savemember()

TableListField

Usage of Controller::join_links() to concatenate links now mandatory

The Controller::join_links()&version=2.4&module=framework) method
to create links within SilverStripe controllers is now mandatory. This method ensures that links with existing GET
parameters don't break through string concatenation.

Using this method is particularly important for any custom
TableListField or
ComplexTableField subclasses and any
LeftAndMain subclass for the CMS UI. These classes in
particular were refactored to secure destructive links against Cross Site Request Forgery (CSRF). This is achieved via a
mandatory "SecurityID" GET parameter appended to the base link.

Auto-disabled "SecurityID" field in FunctionalTest

"SecurityID" tokens are now disabled by default in unit tests, to make form submissions easier.
You can manually enable security tokens, either globally or for a specific form.

[rev:112272] MySQLDatabase::renameField() no longer checks that the field exists in fieldList(). alterField() does no such check, so it should be consistent. Removing this should provide a small performance improvement as well

[rev:111891] #4903 !MemberLoginForm field for "You are logged in as %s" message customisation (thanks walec51!)

[rev:111887] #3775 Added getter to GD so you can retrieve the internal GD resource being used. Made setGD public so you can override the GD yourself as well

[rev:111873] Show "Database Configuration" section of installer requirements for reference (collapsed by default)

[rev:111868] MySQLDatabase::getVersion() now uses mysql_get_server_info() which has been supported since PHP 4. This gives us a better version than say "5.1", instead we now get something like "5.1.51"

[rev:111850] Make use of mysql_get_server_info() when calling MSSQLDatabase::getVersion(), if there's a problem getting info this way, falls back to using query for VERSION() details

[rev:111086] #6023 Shorten SSViewer cached template path for readability of the filenames, and also so Windows doesn't break on long paths

[rev:111050] Added custom test listener for PHPUnit in order to call setUpOnce() and tearDownOnce() on !SapphireTest

[rev:111048] Allowing to run single tests via phpunit through new test bootstrap XML file (e.g. "phpunit sapphire/tests/api/!RestfulServerTest.php" or "phpunit sapphire/tests/api")

[rev:111045] Added !FullTestSuite.php, so that you can test by running "phpunit sapphire/tests/!FullTestSuite".

[rev:111041] refactored runTests, using the new phpunit wrapper classes.

[rev:111039] Created a phpunit wrapper class to ensure that Sapphire's test framework is capable of running unit tests, coverage report and retrieve clover-statistics for PHPUnit 3.4 and PHPUnit 3.5

API Changes

[rev:113282] Fixed various controllers to enforce CSRF protection through Form_!SecurityToken on GET actions that are not routed through Form->httpSubmission(): !AssetAdmin, CMSBatchActionHandler, CMSMain, !CommentTableField, !LeftAndMain, !MemberTableField, !PageComment, !PageComment_Controller

[rev:113275] Added security token to !TableListField->Link() in order to include it in all URL actions automatically. This ensures that field actions bypassing Form->httpSubmission() still get CSRF protection

Bugfixes

[rev:113590] ErrorPage::requireDefaultRecords() case where no assets directory causes an fopen() error. Ensure assets directory is created before attempting to write error page files

[rev:113157] Add PHPUnit includes to !SapphireTest? class (can be loaded outside of !TestRunner? for static calls, in which case the PHPUnit autoloaders/includes aren't in place yet) (merged from r113156)

[rev:112961] Don't include web.config in the assets tracked in the File table.

[rev:112288] Renamed !MySQLQuery::destroy() renamed to destruct() so that it is called properly after the object is destroyed

[rev:112258] one more requirement switched to SSL

[rev:111949] Ensure that \r carriage return characters get stripped out before setting content in HTMLValue::setContent(). DOMDocument will transform these into &#13 entities, which is apparently XML spec, but not necessary for us as we're using HTML

[rev:111932] #6089 Avoid javascript error when "Allow drag & drop reordering" enabled, and attempt to drag a file from one folder to another is performed

[rev:111493] Moving folder after executing Folder::findOrMake will not set the Filenames properly. Invoking updateFilesystem() in File->onAfterWrite() instead of onBeforeWrite(), and avoid caching in FIle->getRelativePath() (fixes #5994 and #5937, thanks muzdowski)

[rev:111255] ContentController::!SiteConfig() should look to the !SiteTree record so an alternate !SiteConfig is considered, if this method doesn't exist on the data record then fall back to the default !SiteConfig

[rev:111202] Fixed quoting and GROUP BY statement in !ManyManyComplexTableField->getQuery() for Postgres compatibility

[rev:111852] Revert r111850 to !MySQLDatabase::getVersion as version comparisons need to happen, and this will strip out non-numeric characters e.g. "ubuntu1" or "lenny4" which are prefixed on some Linux distros

[rev:111851] dev/build now shows database name and version next to "Building database ..." text