[Pkg-drupal-commits] r2156 - in /branches/lenny-security/debian: changelog patches/00list patches/20_SA-CORE-2010-002.dpatch
luigi at users.alioth.debian.org
luigi at users.alioth.debian.org
Thu Sep 9 06:43:32 UTC 2010
Author: luigi
Date: Thu Sep 9 06:43:26 2010
New Revision: 2156
URL: http://svn.debian.org/wsvn/pkg-drupal/?sc=1&rev=2156
Log:
Fixes multiple XSS vulnerabilities (Closes: #572439) (Ref: SA-CORE-2010-001, CVE-TBA)
Added:
branches/lenny-security/debian/patches/20_SA-CORE-2010-002.dpatch (with props)
Modified:
branches/lenny-security/debian/changelog
branches/lenny-security/debian/patches/00list
Modified: branches/lenny-security/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-drupal/branches/lenny-security/debian/changelog?rev=2156&op=diff
==============================================================================
--- branches/lenny-security/debian/changelog (original)
+++ branches/lenny-security/debian/changelog Thu Sep 9 06:43:26 2010
@@ -1,3 +1,12 @@
+drupal6 (6.6-3lenny6) stable-security; urgency=low
+
+ [ Luigi Gangitano ]
+ * debian/patches/20_SA-CORE-2010-002
+ - Fixes multiple XSS vulnerabilities (Closes: #592716)
+ (Ref: SA-CORE-2010-002, CVE-TBA)
+
+ -- Luigi Gangitano <luigi at debian.org> Thu, 09 Sep 2010 08:40:21 +0200
+
drupal6 (6.6-3lenny5) stable-security; urgency=high
[ Luigi Gangitano ]
Modified: branches/lenny-security/debian/patches/00list
URL: http://svn.debian.org/wsvn/pkg-drupal/branches/lenny-security/debian/patches/00list?rev=2156&op=diff
==============================================================================
--- branches/lenny-security/debian/patches/00list (original)
+++ branches/lenny-security/debian/patches/00list Thu Sep 9 06:43:26 2010
@@ -7,3 +7,4 @@
17_SA-CORE-2009-008
18_SA-CORE-2009-009
19_SA-CORE-2010-001
+20_SA-CORE-2010-002
Added: branches/lenny-security/debian/patches/20_SA-CORE-2010-002.dpatch
URL: http://svn.debian.org/wsvn/pkg-drupal/branches/lenny-security/debian/patches/20_SA-CORE-2010-002.dpatch?rev=2156&op=file
==============================================================================
--- branches/lenny-security/debian/patches/20_SA-CORE-2010-002.dpatch (added)
+++ branches/lenny-security/debian/patches/20_SA-CORE-2010-002.dpatch Thu Sep 9 06:43:26 2010
@@ -1,0 +1,460 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 20_SA-CORE-2010-002.dpatch by Luigi Gangitano <luigi at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Fixes multiple vulnerabilities
+
+ at DPATCH@
+diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' lenny~/includes/actions.inc lenny/includes/actions.inc
+--- lenny~/includes/actions.inc 2009-08-05 02:50:58.000000000 +0200
++++ lenny/includes/actions.inc 2010-09-09 08:35:16.000000000 +0200
+@@ -272,7 +272,7 @@
+ else {
+ // This is a new singleton that we don't have an aid for; assign one.
+ db_query("INSERT INTO {actions} (aid, type, callback, parameters, description) VALUES ('%s', '%s', '%s', '%s', '%s')", $callback, $array['type'], $callback, '', $array['description']);
+- watchdog('actions', "Action '%action' added.", array('%action' => filter_xss_admin($array['description'])));
++ watchdog('actions', "Action '%action' added.", array('%action' => $array['description']));
+ }
+ }
+ }
+@@ -294,7 +294,7 @@
+ $results = db_query("SELECT a.aid, a.description FROM {actions} a WHERE callback IN ($placeholders)", $orphaned);
+ while ($action = db_fetch_object($results)) {
+ actions_delete($action->aid);
+- watchdog('actions', "Removed orphaned action '%action' from database.", array('%action' => filter_xss_admin($action->description)));
++ watchdog('actions', "Removed orphaned action '%action' from database.", array('%action' => $action->description));
+ }
+ }
+ else {
+diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' lenny~/modules/comment/comment.module lenny/modules/comment/comment.module
+--- lenny~/modules/comment/comment.module 2010-09-09 08:35:13.000000000 +0200
++++ lenny/modules/comment/comment.module 2010-09-09 08:35:16.000000000 +0200
+@@ -663,7 +663,7 @@
+ global $user;
+
+ if ($op == 'edit') {
+- return ($user->uid && $user->uid == $comment->uid && comment_num_replies($comment->cid) == 0) || user_access('administer comments');
++ return ($user->uid && $user->uid == $comment->uid && comment_num_replies($comment->cid) == 0 && $comment->status == COMMENT_PUBLISHED) || user_access('administer comments');
+ }
+ }
+
+diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' lenny~/modules/openid/openid.install lenny/modules/openid/openid.install
+--- lenny~/modules/openid/openid.install 2009-08-05 02:51:31.000000000 +0200
++++ lenny/modules/openid/openid.install 2010-09-09 08:35:16.000000000 +0200
+@@ -66,5 +66,80 @@
+ 'primary key' => array('assoc_handle'),
+ );
+
++ $schema['openid_nonce'] = array(
++ 'description' => 'Stores received openid.response_nonce per OpenID endpoint URL to prevent replay attacks.',
++ 'fields' => array(
++ 'idp_endpoint_uri' => array(
++ 'type' => 'varchar',
++ 'length' => 255,
++ 'description' => 'URI of the OpenID Provider endpoint.',
++ ),
++ 'nonce' => array(
++ 'type' => 'varchar',
++ 'length' => 255,
++ 'description' => 'The value of openid.response_nonce'
++ ),
++ 'expires' => array(
++ 'type' => 'int',
++ 'not null' => TRUE,
++ 'default' => 0,
++ 'description' => 'A Unix timestamp indicating when the entry should expire.',
++ ),
++ ),
++ 'indexes' => array(
++ 'nonce' => array('nonce'),
++ 'expires' => array('expires'),
++ ),
++ );
++
+ return $schema;
+ }
++
++/**
++ * @defgroup updates-6.x-extra Extra openid updates for 6.x
++ * @{
++ */
++
++/**
++ * Add the openid_nonce table.
++ *
++ * Implementation of hook_update_N().
++ */
++function openid_update_6000() {
++ $ret = array();
++
++ $schema['openid_nonce'] = array(
++ 'description' => 'Stores received openid.response_nonce per OpenID endpoint URL to prevent replay attacks.',
++ 'fields' => array(
++ 'idp_endpoint_uri' => array(
++ 'type' => 'varchar',
++ 'length' => 255,
++ 'description' => 'URI of the OpenID Provider endpoint.',
++ ),
++ 'nonce' => array(
++ 'type' => 'varchar',
++ 'length' => 255,
++ 'description' => 'The value of openid.response_nonce'
++ ),
++ 'expires' => array(
++ 'type' => 'int',
++ 'not null' => TRUE,
++ 'default' => 0,
++ 'description' => 'A Unix timestamp indicating when the entry should expire.',
++ ),
++ ),
++ 'indexes' => array(
++ 'nonce' => array('nonce'),
++ 'expires' => array('expires'),
++ ),
++ );
++
++ db_create_table($ret, 'openid_nonce', $schema['openid_nonce']);
++
++ return $ret;
++}
++
++/**
++ * @} End of "defgroup updates-6.x-extra"
++ * The next series of updates should start at 7000.
++ */
+diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' lenny~/modules/openid/openid.module lenny/modules/openid/openid.module
+--- lenny~/modules/openid/openid.module 2010-09-09 08:35:13.000000000 +0200
++++ lenny/modules/openid/openid.module 2010-09-09 08:35:16.000000000 +0200
+@@ -96,7 +96,7 @@
+ 'data' => l(t('Cancel OpenID login'), '#'),
+ 'class' => 'user-link',
+ );
+-
++
+ $form['openid_links'] = array(
+ '#value' => theme('item_list', $items),
+ '#weight' => 1,
+@@ -215,12 +215,13 @@
+ * $response['status'] set to one of 'success', 'failed' or 'cancel'.
+ */
+ function openid_complete($response = array()) {
++ global $base_url;
+ module_load_include('inc', 'openid');
+
+ if (count($response) == 0) {
+ $response = _openid_response();
+ }
+-
++
+ // Default to failed response
+ $response['status'] = 'failed';
+ if (isset($_SESSION['openid']['service']['uri']) && isset($_SESSION['openid']['claimed_id'])) {
+@@ -233,7 +234,7 @@
+ $response['status'] = 'cancel';
+ }
+ else {
+- if (openid_verify_assertion($service['uri'], $response)) {
++ if (openid_verify_assertion($service, $response)) {
+ // If the returned claimed_id is different from the session claimed_id,
+ // then we need to do discovery and make sure the op_endpoint matches.
+ if ($service['version'] == 2 && $response['openid.claimed_id'] != $claimed_id) {
+@@ -245,6 +246,31 @@
+ else {
+ $response['openid.claimed_id'] = $claimed_id;
+ }
++ // Verify that openid.return_to matches the current URL (see OpenID
++ // Authentication 2.0, section 11.1).
++ // While OpenID Authentication 1.1, section 4.3 does not mandate
++ // return_to verification, the received return_to should still
++ // match these constraints.
++ $return_to_parts = parse_url($response['openid.return_to']);
++
++ $base_url_parts = parse_url($base_url);
++ $current_parts = parse_url($base_url_parts['scheme'] .'://'. $base_url_parts['host'] . request_uri());
++
++ if ($return_to_parts['scheme'] != $current_parts['scheme'] ||
++ $return_to_parts['host'] != $current_parts['host'] ||
++ $return_to_parts['path'] != $current_parts['path']) {
++
++ return $response;
++ }
++ // Verify that all query parameters in the openid.return_to URL have
++ // the same value in the current URL. In addition, the current URL
++ // contains a number of other parameters added by the OpenID Provider.
++ parse_str(isset($return_to_parts['query']) ? $return_to_parts['query'] : '', $return_to_query_parameters);
++ foreach ($return_to_query_parameters as $name => $value) {
++ if (!array_key_exists($name, $_GET) || $_GET[$name] != $value) {
++ return $response;
++ }
++ }
+ $response['status'] = 'success';
+ }
+ }
+@@ -487,33 +513,39 @@
+ /**
+ * Attempt to verify the response received from the OpenID Provider.
+ *
+- * @param $op_endpoint The OpenID Provider URL.
+- * @param $response Array of repsonse values from the provider.
++ * @param $service
++ * Array describing the OpenID provider.
++ * @param $response
++ * Array of response values from the provider.
+ *
+ * @return boolean
+ */
+-function openid_verify_assertion($op_endpoint, $response) {
++function openid_verify_assertion($service, $response) {
+ module_load_include('inc', 'openid');
+
+- $valid = FALSE;
++ // http://openid.net/specs/openid-authentication-2_0.html#rfc.section.11.3
++ // Check the Nonce to protect against replay attacks.
++ if (!openid_verify_assertion_nonce($service, $response)) {
++ return FALSE;
++ }
+
++ // http://openid.net/specs/openid-authentication-2_0.html#rfc.section.11.4
++ // Verify the signatures.
++ $valid = FALSE;
+ $association = db_fetch_object(db_query("SELECT * FROM {openid_association} WHERE assoc_handle = '%s'", $response['openid.assoc_handle']));
+ if ($association && isset($association->session_type)) {
+- $keys_to_sign = explode(',', $response['openid.signed']);
+- $self_sig = _openid_signature($association, $response, $keys_to_sign);
+- if ($self_sig == $response['openid.sig']) {
+- $valid = TRUE;
+- }
+- else {
+- $valid = FALSE;
+- }
++ // http://openid.net/specs/openid-authentication-2_0.html#rfc.section.11.4.2
++ // Verification using an association.
++ $valid = openid_verify_assertion_signature($service, $association, $response);
+ }
+ else {
++ // http://openid.net/specs/openid-authentication-2_0.html#rfc.section.11.4.3
++ // Direct verification.
+ $request = $response;
+ $request['openid.mode'] = 'check_authentication';
+ $message = _openid_create_message($request);
+ $headers = array('Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8');
+- $result = drupal_http_request($op_endpoint, $headers, 'POST', _openid_encode_message($message));
++ $result = drupal_http_request($service['uri'], $headers, 'POST', _openid_encode_message($message));
+ if (!isset($result->error)) {
+ $response = _openid_parse_message($result->data);
+ if (strtolower(trim($response['is_valid'])) == 'true') {
+@@ -529,3 +561,101 @@
+ }
+ return $valid;
+ }
++
++/**
++ * Verify the signature of the response received from the OpenID provider.
++ *
++ * @param $service
++ * Array describing the OpenID provider.
++ * @param $association
++ * Information on the association with the OpenID provider.
++ * @param $response
++ * Array of response values from the provider.
++ *
++ * @return
++ * TRUE if the signature is valid and covers all fields required to be signed.
++ * @see http://openid.net/specs/openid-authentication-2_0.html#rfc.section.11.4
++ */
++function openid_verify_assertion_signature($service, $association, $response) {
++ if ($service['version'] == 2) {
++ // OpenID Authentication 2.0, section 10.1:
++ // These keys must always be signed.
++ $mandatory_keys = array('op_endpoint', 'return_to', 'response_nonce', 'assoc_handle');
++ if (isset($response['openid.claimed_id'])) {
++ // If present, these two keys must also be signed. According to the spec,
++ // they are either both present or both absent.
++ $mandatory_keys[] = 'claimed_id';
++ $mandatory_keys[] = 'identity';
++ }
++ }
++ else {
++ // OpenID Authentication 1.1. section 4.3.3.
++ $mandatory_keys = array('identity', 'return_to');
++ }
++
++ $keys_to_sign = explode(',', $response['openid.signed']);
++
++ if (count(array_diff($mandatory_keys, $keys_to_sign)) > 0) {
++ return FALSE;
++ }
++
++ return _openid_signature($association, $response, $keys_to_sign) == $response['openid.sig'];
++}
++
++/**
++ * Verify that the nonce has not been used in earlier assertions from the same OpenID provider.
++ *
++ * @param $service
++ * Array describing the OpenID provider.
++ * @param $response
++ * Array of response values from the provider.
++ *
++ * @return
++ * TRUE if the nonce has not expired and has not been used earlier.
++ */
++function openid_verify_assertion_nonce($service, $response) {
++ if ($service['version'] != 2) {
++ return TRUE;
++ }
++
++ if (preg_match('/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z/', $response['openid.response_nonce'], $matches)) {
++ list(, $year, $month, $day, $hour, $minutes, $seconds) = $matches;
++ $nonce_timestamp = gmmktime($hour, $minutes, $seconds, $month, $day, $year);
++ }
++ else {
++ watchdog('openid', 'Nonce from @endpoint rejected because it is not correctly formatted, nonce: @nonce.', array('@endpoint' => $service['uri'], '@nonce' => $response['openid.response_nonce']), WATCHDOG_WARNING);
++ return FALSE;
++ }
++
++ // A nonce with a timestamp to far in the past or future will already have
++ // been removed and cannot be checked for single use anymore.
++ $time = time();
++ $expiry = 900;
++ if ($nonce_timestamp <= $time - $expiry || $nonce_timestamp >= $time + $expiry) {
++ watchdog('openid', 'Nonce received from @endpoint is out of range (time difference: @intervals). Check possible clock skew.', array('@endpoint' => $service['uri'], '@interval' => $time - $nonce_timestamp), WATCHDOG_WARNING);
++ return FALSE;
++ }
++
++ // Record that this nonce was used.
++ db_query("INSERT INTO {openid_nonce} (idp_endpoint_uri, nonce, expires) VALUES ('%s', '%s', %d)", $service['uri'], $response['openid.response_nonce'], $nonce_timestamp + $expiry);
++
++ // Count the number of times this nonce was used.
++ $count_used = db_result(db_query("SELECT COUNT(*) FROM {openid_nonce} WHERE nonce = '%s' AND idp_endpoint_uri = '%s'", $response['openid.response_nonce'], $service['uri']));
++
++ if ($count_used == 1) {
++ return TRUE;
++ }
++ else {
++ watchdog('openid', 'Nonce replay attempt blocked from @ip, nonce: @nonce.', array('@ip' => ip_address(), '@nonce' => $response['openid.response_nonce']), WATCHDOG_CRITICAL);
++ return FALSE;
++ }
++}
++
++/**
++ * Remove expired nonces from the database.
++ *
++ * Implementation of hook_cron().
++ */
++function openid_cron() {
++ db_query("DELETE FROM {openid_nonce} WHERE expires < %d", time());
++}
+diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' lenny~/modules/system/system.module lenny/modules/system/system.module
+--- lenny~/modules/system/system.module 2009-08-05 02:51:12.000000000 +0200
++++ lenny/modules/system/system.module 2010-09-09 08:35:16.000000000 +0200
+@@ -1338,7 +1338,7 @@
+ while ($action = db_fetch_object($result)) {
+ $row[] = array(
+ array('data' => $action->type),
+- array('data' => $action->description),
++ array('data' => filter_xss_admin($action->description)),
+ array('data' => $action->parameters ? l(t('configure'), "admin/settings/actions/configure/$action->aid") : ''),
+ array('data' => $action->parameters ? l(t('delete'), "admin/settings/actions/delete/$action->aid") : '')
+ );
+@@ -1544,9 +1544,8 @@
+ $aid = $form_state['values']['aid'];
+ $action = actions_load($aid);
+ actions_delete($aid);
+- $description = check_plain($action->description);
+- watchdog('user', 'Deleted action %aid (%action)', array('%aid' => $aid, '%action' => $description));
+- drupal_set_message(t('Action %action was deleted', array('%action' => $description)));
++ watchdog('user', 'Deleted action %aid (%action)', array('%aid' => $aid, '%action' => $action->description));
++ drupal_set_message(t('Action %action was deleted', array('%action' => $action->description)));
+ $form_state['redirect'] = 'admin/settings/actions/manage';
+ }
+
+@@ -1746,7 +1745,7 @@
+ );
+ }
+ $subject = strtr($context['subject'], $variables);
+- $body = strtr($context['message'], $variables);
++ $body = strtr(filter_xss_admin($context['message']), $variables);
+ $message['subject'] .= str_replace(array("\r", "\n"), '', $subject);
+ $message['body'][] = drupal_html_to_text($body);
+ }
+@@ -1795,11 +1794,11 @@
+ case 'taxonomy':
+ $vocabulary = taxonomy_vocabulary_load($object->vid);
+ $variables = array_merge($variables, array(
+- '%term_name' => $object->name,
+- '%term_description' => $object->description,
++ '%term_name' => check_plain($object->name),
++ '%term_description' => filter_xss_admin($object->description),
+ '%term_id' => $object->tid,
+- '%vocabulary_name' => $vocabulary->name,
+- '%vocabulary_description' => $vocabulary->description,
++ '%vocabulary_name' => check_plain($vocabulary->name),
++ '%vocabulary_description' => filter_xss_admin($vocabulary->description),
+ '%vocabulary_id' => $vocabulary->vid,
+ )
+ );
+@@ -1814,13 +1813,13 @@
+ '%uid' => $node->uid,
+ '%node_url' => url('node/'. $node->nid, array('absolute' => TRUE)),
+ '%node_type' => check_plain(node_get_types('name', $node)),
+- '%title' => filter_xss($node->title),
+- '%teaser' => filter_xss($node->teaser),
+- '%body' => filter_xss($node->body),
++ '%title' => check_plain($node->title),
++ '%teaser' => check_markup($node->teaser, $node->format, FALSE),
++ '%body' => check_markup($node->body, $node->format, FALSE),
+ )
+ );
+ }
+- $context['message'] = strtr($context['message'], $variables);
++ $context['message'] = strtr(filter_xss_admin($context['message']), $variables);
+ drupal_set_message($context['message']);
+ }
+
+diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' lenny~/modules/trigger/trigger.admin.inc lenny/modules/trigger/trigger.admin.inc
+--- lenny~/modules/trigger/trigger.admin.inc 2009-08-05 02:52:02.000000000 +0200
++++ lenny/modules/trigger/trigger.admin.inc 2010-09-09 08:35:16.000000000 +0200
+@@ -1,5 +1,5 @@
+ <?php
+-// $Id: trigger.admin.inc,v 1.5 2008/01/08 10:35:43 goba Exp $
++// $Id: trigger.admin.inc,v 1.5.4.1 2010/08/11 20:22:27 goba Exp $
+
+ /**
+ * @file
+@@ -84,7 +84,7 @@
+ $aid = actions_function_lookup($form_values['aid']);
+ db_query("DELETE FROM {trigger_assignments} WHERE hook = '%s' AND op = '%s' AND aid = '%s'", $form_values['hook'], $form_values['operation'], $aid);
+ $actions = actions_get_all_actions();
+- watchdog('actions', 'Action %action has been unassigned.', array('%action' => check_plain($actions[$aid]['description'])));
++ watchdog('actions', 'Action %action has been unassigned.', array('%action' => $actions[$aid]['description']));
+ drupal_set_message(t('Action %action has been unassigned.', array('%action' => $actions[$aid]['description'])));
+ $hook = $form_values['hook'] == 'nodeapi' ? 'node' : $form_values['hook'];
+ $form_state['redirect'] = 'admin/build/trigger/'. $hook;
+@@ -239,7 +239,7 @@
+ $rows = array();
+ foreach ($element['assigned']['#value'] as $aid => $info) {
+ $rows[] = array(
+- $info['description'],
++ filter_xss_admin($info['description']),
+ $info['link']
+ );
+ }
+diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' lenny~/modules/upload/upload.module lenny/modules/upload/upload.module
+--- lenny~/modules/upload/upload.module 2009-08-05 02:51:14.000000000 +0200
++++ lenny/modules/upload/upload.module 2010-09-09 08:35:16.000000000 +0200
+@@ -147,7 +147,13 @@
+ function upload_file_download($filepath) {
+ $filepath = file_create_path($filepath);
+ $result = db_query("SELECT f.*, u.nid FROM {files} f INNER JOIN {upload} u ON f.fid = u.fid WHERE filepath = '%s'", $filepath);
+- if ($file = db_fetch_object($result)) {
++ while ($file = db_fetch_object($result)) {
++ if ($filepath !== $file->filepath) {
++ // Since some database servers sometimes use a case-insensitive
++ // comparison by default, double check that the filename is an exact
++ // match.
++ continue;
++ }
+ if (user_access('view uploaded files') && ($node = node_load($file->nid)) && node_access('view', $node)) {
+ return array(
+ 'Content-Type: ' . $file->filemime,
Propchange: branches/lenny-security/debian/patches/20_SA-CORE-2010-002.dpatch
------------------------------------------------------------------------------
svn:executable = *
More information about the Pkg-drupal-commits
mailing list