? filter-warnings-2.patch
? filter-warnings.patch
? sites/all/modules
? sites/default/files
? sites/default/settings.php
Index: modules/filter/filter.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.install,v
retrieving revision 1.9
diff -u -p -r1.9 filter.install
--- modules/filter/filter.install 14 Apr 2008 17:48:37 -0000 1.9
+++ modules/filter/filter.install 23 Oct 2008 17:20:53 -0000
@@ -99,6 +99,57 @@ function filter_schema() {
}
/**
+ * Implementation of hook_requirements().
+ *
+ * Display error messages for sites which allow anonymous users
+ * (or authenticated users with open registration enabled)
+ * to use a format without the HTML filter.
+ */
+function filter_requirements($phase) {
+ if ($phase == 'runtime') {
+ $requirements = array();
+ $formats = filter_formats();
+ $insecure = array();
+ $filters = array();
+ $result = db_query("SELECT fid, format FROM {filters} WHERE module = 'filter' AND delta = 0");
+ while ($filter = db_fetch_object($result)) {
+ $filters[$filter->format] = $filter->fid;
+ }
+ foreach ($formats as $id => $format) {
+ if (!isset($filters[$format->format])) {
+ if (variable_get('filter_default_format', 1) == $format->format) {
+ $insecure['default'] = 1;
+ }
+ if (strstr($format->roles, ",1,")) {
+ $insecure['anonymous'] = 1;
+ }
+ if (strstr($format->roles, ",2,") && variable_get('user_register', 1) > 0) {
+ $insecure['authenticated'] = 1;
+ }
+ }
+ }
+ if (count($insecure)) {
+ if (isset($insecure['default'])) {
+ $description = t('The default input format does not filter HTML tags.') . ' ';
+ }
+ if (isset($insecure['anonymous'])) {
+ $description .= t('Anonymous users have access to a format which does not filter HTML tags.') . ' ';
+ }
+ if (isset($insecure['authenticated'])) {
+ $description .= t('Authenticated users have access to a format which does not filter HTML tags and user registration is open.') . ' ';
+ }
+ $requirements['filter'] = array(
+ 'title' => t('HTML Filtration'),
+ 'value' => t('Insecure'),
+ 'description' => $description . t('This configuration creates a security vulnerability. You should modify your filters and set the default to Filtered HTML.', array('@input-filters' => url('admin/settings/filters'))),
+ 'severity' => REQUIREMENT_ERROR,
+ );
+ }
+ return $requirements;
+ }
+}
+
+/**
* Add a weight column to the filter formats table.
*/
function filter_update_7000() {
Index: modules/filter/filter.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.test,v
retrieving revision 1.8
diff -u -p -r1.8 filter.test
--- modules/filter/filter.test 12 Oct 2008 04:30:06 -0000 1.8
+++ modules/filter/filter.test 23 Oct 2008 17:20:53 -0000
@@ -236,3 +236,113 @@ class FilterTestCase extends DrupalWebTe
}
}
}
+
+class FilterWarningTestCase extends DrupalWebTestCase {
+ /**
+ * Implementation of getInfo().
+ */
+ function getInfo() {
+ return array(
+ 'name' => t('Filter Security Warning'),
+ 'description' => t('Test the warning messages for insecure HTML filter configurations.'),
+ 'group' => t('Filter'),
+ );
+ }
+
+ /**
+ * Implementation of setUp().
+ */
+ function setUp() {
+ parent::setUp();
+
+ $admin_user = $this->drupalCreateUser(array('administer filters', 'administer site configuration'));
+ $this->drupalLogin($admin_user);
+ }
+
+ /**
+ * Set the default format to contain / not contain the HTML filter and check for error messages.
+ */
+ function testSecureHTMLDefault() {
+ // Start fresh with all new formats for testing
+ db_query("DELETE FROM {filter_formats}");
+
+ // Create a format which filters HTML
+ $safe_format_auth = $this->createFormat(0, 2);
+
+ // Create a format which converts line breaks but does not filter HTML
+ $unsafe_format_auth = $this->createFormat(1, 2);
+
+ variable_set('filter_default_format', $safe_format_auth);
+ $this->drupalGet('admin/reports/status');
+ $this->assertNoText(t('The default input format does not filter HTML tags.'), t('No default HTML filter security error shown on status page when default format filters HTML.'));
+
+ variable_set('filter_default_format', $unsafe_format_auth);
+ $this->drupalGet('admin/reports/status');
+ $this->assertText(t('The default input format does not filter HTML tags.'), t('Default HTML filter security error shown on status page when default format does not filter HTML.'));
+ }
+
+ /**
+ * Give / remove anonymous users access to a format without the HTML filter
+ * and check for error messages.
+ */
+ function testSecureHTMLAnonymous() {
+ // Start fresh with all new formats for testing
+ db_query("DELETE FROM {filter_formats}");
+
+ // Create a format which filters HTML for anonymous users
+ $safe_format_anon = $this->createFormat(0, 1);
+ variable_set('filter_default_format', $safe_format_anon);
+ $this->drupalGet('admin/reports/status');
+ $this->assertNoText(t('Anonymous users have access to a format which does not filter HTML tags.'), t('No anonymous user HTML filter security error shown on status page when inapplicable.'));
+
+
+ // Add a format which does not filter HTML for anonymous users
+ $unsafe_format_anon = $this->createFormat(1, 1);
+ $this->drupalGet('admin/reports/status');
+ $this->assertText(t('Anonymous users have access to a format which does not filter HTML tags.'), t('Anonymous user HTML filter security error shown on status page when applicable.'));
+ }
+
+ /**
+ * Give / remove authenticated users access to a format without the HTML filter
+ * when user registration is open and check for error messages.
+ */
+ function testSecureHTMLOpenAuthenticated() {
+ // Start fresh with all new formats for testing
+ db_query("DELETE FROM {filter_formats}");
+ variable_set('user_register', 1);
+
+ // Create a format which filters HTML
+ $safe_format_auth = $this->createFormat(0, 2);
+ $this->drupalGet('admin/reports/status');
+ $this->assertNoText(t('Authenticated users have access to a format which does not filter HTML tags and user registration is open.'), t('Authenticated user HTML filter security error not shown on status page when inapplicable.'));
+
+ // Create a format which converts line breaks but does not filter HTML
+ $unsafe_format_auth = $this->createFormat(1, 2);
+ $this->drupalGet('admin/reports/status');
+ $this->assertText(t('Authenticated users have access to a format which does not filter HTML tags and user registration is open.'), t('Authenticated user HTML filter security error shown on status page when applicable.'));
+
+ variable_set('user_register', 0);
+ $this->drupalGet('admin/reports/status');
+ $this->assertNoText(t('Authenticated users have access to a format which does not filter HTML tags and user registration is open.'), t('Authenticated user HTML filter security error not shown on status page when inapplicable.'));
+
+ // When user registration is open but approval needed, error also shows
+ variable_set('user_register', 2);
+ $this->drupalGet('admin/reports/status');
+ $this->assertText(t('Authenticated users have access to a format which does not filter HTML tags and user registration is open.'), t('Authenticated user HTML filter security error shown on status page when applicable.'));
+ }
+
+ /**
+ * Given a filter number and a role id,
+ * create a new test format and return its format id.
+ */
+ function createFormat($filter, $role) {
+ $edit = array(
+ 'name' => $this->randomName(),
+ 'roles[' . $role .']' => TRUE,
+ 'filters[filter/' . $filter . ']' => TRUE,
+ );
+ $this->drupalPost('admin/settings/filters/add', $edit, t('Save configuration'));
+ return db_result(db_query("SELECT format FROM {filter_formats} WHERE name = '%s'", $edit['name']));
+ }
+}
+
Index: modules/php/php.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/php/php.install,v
retrieving revision 1.2
diff -u -p -r1.2 php.install
--- modules/php/php.install 14 Apr 2008 17:48:41 -0000 1.2
+++ modules/php/php.install 23 Oct 2008 17:20:53 -0000
@@ -27,3 +27,54 @@ function php_install() {
function php_disable() {
drupal_set_message(t('The PHP module has been disabled. Please note that any existing content that was using the PHP filter will now be visible in plain text. This might pose a security risk by exposing sensitive information, if any, used in the PHP code.'));
}
+
+/**
+ * Implementation of hook_requirements().
+ *
+ * Display error messages for sites which allow anonymous users
+ * (or authenticated users with open registration enabled)
+ * to use a format with the PHP filter.
+ */
+function php_requirements($phase) {
+ if ($phase == 'runtime') {
+ $requirements = array();
+ $formats = filter_formats();
+ $insecure = array();
+ $filters = array();
+ $result = db_query("SELECT fid, format FROM {filters} WHERE module = 'filter' AND delta = 0");
+ while ($filter = db_fetch_object($result)) {
+ $filters[$filter->format] = $filter->fid;
+ }
+ foreach ($formats as $id => $format) {
+ if (!isset($filters[$format->format])) {
+ if (variable_get('filter_default_format', 1) == $format->format) {
+ $insecure['default'] = 1;
+ }
+ if (strstr($format->roles, ",1,")) {
+ $insecure['anonymous'] = 1;
+ }
+ if (strstr($format->roles, ",2,") && variable_get('user_register', 1) > 0) {
+ $insecure['authenticated'] = 1;
+ }
+ }
+ }
+ if (count($insecure)) {
+ if (isset($insecure['default'])) {
+ $description = t('The default input format allows PHP evaluation.') . ' ';
+ }
+ if (isset($insecure['anonymous'])) {
+ $description .= t('Anonymous users have access to a format which allows PHP evaluation.') . ' ';
+ }
+ if (isset($insecure['authenticated'])) {
+ $description .= t('Authenticated users have access to a format which allows PHP evaluation and user registration is open.') . ' ';
+ }
+ $requirements['php_filter'] = array(
+ 'title' => t('PHP Evaluator Access'),
+ 'value' => t('Insecure'),
+ 'description' => $description . t('This configuration creates a security vulnerability. You should modify your filters to restrict access to the PHP filter.', array('@input-filters' => url('admin/settings/filters'))),
+ 'severity' => REQUIREMENT_ERROR,
+ );
+ }
+ return $requirements;
+ }
+}
Index: modules/php/php.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/php/php.test,v
retrieving revision 1.5
diff -u -p -r1.5 php.test
--- modules/php/php.test 20 Oct 2008 13:04:27 -0000 1.5
+++ modules/php/php.test 23 Oct 2008 17:20:53 -0000
@@ -115,4 +115,113 @@ class PHPAccessTestCase extends PHPTestC
$this->drupalGet('node/' . $node->nid . '/edit');
$this->assertNoFieldByName('body_format', '3', t('Format not available.'));
}
-}
\ No newline at end of file
+}
+
+
+class PHPWarningTestCase extends DrupalWebTestCase {
+
+ /**
+ * Implementation of getInfo().
+ */
+ function getInfo() {
+ return array(
+ 'name' => t('PHP Filter Security Warning'),
+ 'description' => t('Test the warning messages for insecure PHP filter configurations.'),
+ 'group' => t('PHP'),
+ );
+ }
+
+ /**
+ * Implementation of setUp().
+ */
+ function setUp() {
+ parent::setUp('php');
+ $admin_user = $this->drupalCreateUser(array('administer filters', 'administer site configuration'));
+ $this->drupalLogin($admin_user);
+ }
+
+ /**
+ * Set the default format to contain / not contain the PHP filter and check for error messages.
+ */
+ function testSecurePHPDefault() {
+ // Start fresh with all new formats for testing
+ db_query("DELETE FROM {filter_formats}");
+
+ // Create a format which does not evaluate PHP
+ $safe_format_auth = $this->createFormat(0, 2);
+
+ // Create a format which evaluates PHP
+ $unsafe_format_auth = $this->createFormat(3, 2);
+ variable_set('filter_default_format', $safe_format_auth);
+
+ $this->drupalGet('admin/reports/status');
+ $this->assertNoText(t('The default input format allows PHP evaluation.'), t('No default PHP filter security error shown on status page when default format evaluates PHP.'));
+ variable_set('filter_default_format', $unsafe_format_auth);
+ $this->drupalGet('admin/reports/status');
+ $this->assertText(t('The default input format allows PHP evaluation.'), t('Default PHP filter security error shown on status page when default format evaluates PHP.'));
+ }
+
+ /**
+ * Give / remove anonymous users access to a format with the PHP filter
+ * and check for error messages.
+ */
+ function testSecurePHPAnonymous() {
+ // Start fresh with all new formats for testing
+ db_query("DELETE FROM {filter_formats}");
+
+ // Create a format which does not evaluate PHP for anonymous users
+ $safe_format_anon = $this->createFormat(0, 1);
+ variable_set('filter_default_format', $safe_format_anon);
+ $this->drupalGet('admin/reports/status');
+ $this->assertNoText(t('Anonymous users have access to a format which allows PHP evaluation.'), t('No anonymous user PHP filter security error shown on status page when inapplicable.'));
+
+
+ // Add a format which evaluates PHP for anonymous users
+ $unsafe_format_anon = $this->createFormat(3, 1);
+ $this->drupalGet('admin/reports/status');
+ $this->assertText(t('Anonymous users have access to a format which allows PHP evaluation.'), t('Anonymous user PHP filter security error shown on status page when applicable.'));
+ }
+
+ /**
+ * Give / remove authenticated users access to a format with the PHP filter
+ * when user registration is open and check for error messages.
+ */
+ function testSecurePHPOpenAuthenticated() {
+ // Start fresh with all new formats for testing
+ db_query("DELETE FROM {filter_formats}");
+ variable_set('user_register', 1);
+
+ // Create a format which does not filter PHP
+ $safe_format_auth = $this->createFormat(0, 2);
+ $this->drupalGet('admin/reports/status');
+ $this->assertNoText(t('Authenticated users have access to a format which allows PHP evaluation and user registration is open.'), t('Authenticated user PHP filter security error not shown on status page when inapplicable.'));
+
+ // Create a format which evaluates PHP for authenticated users
+ $unsafe_format_auth = $this->createFormat(3, 2);
+ $this->drupalGet('admin/reports/status');
+ $this->assertText(t('Authenticated users have access to a format which allows PHP evaluation and user registration is open.'), t('Authenticated user PHP filter security error shown on status page when applicable.'));
+
+ variable_set('user_register', 0);
+ $this->drupalGet('admin/reports/status');
+ $this->assertNoText(t('Authenticated users have access to a format which allows PHP evaluation and user registration is open.'), t('Authenticated user PHP filter security error not shown on status page when inapplicable.'));
+
+ // When user registration is open but approval needed, error also shows
+ variable_set('user_register', 2);
+ $this->drupalGet('admin/reports/status');
+ $this->assertText(t('Authenticated users have access to a format which allows PHP evaluation and user registration is open.'), t('Authenticated user PHP filter security error shown on status page when applicable.'));
+ }
+
+ /**
+ * Given a filter number and a role id,
+ * create a new test format and return its format id.
+ */
+ function createFormat($filter, $role) {
+ $edit = array(
+ 'name' => $this->randomName(),
+ 'roles[' . $role .']' => TRUE,
+ 'filters[filter/' . $filter . ']' => TRUE,
+ );
+ $this->drupalPost('admin/settings/filters/add', $edit, t('Save configuration'));
+ return db_result(db_query("SELECT format FROM {filter_formats} WHERE name = '%s'", $edit['name']));
+ }
+}