diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/block.module | 2 | ||||
-rw-r--r-- | modules/block/block.module | 2 | ||||
-rw-r--r-- | modules/comment.module | 11 | ||||
-rw-r--r-- | modules/comment/comment.module | 11 | ||||
-rw-r--r-- | modules/filter.module | 27 | ||||
-rw-r--r-- | modules/filter/filter.module | 27 | ||||
-rw-r--r-- | modules/node.module | 17 | ||||
-rw-r--r-- | modules/node/node.module | 17 |
8 files changed, 90 insertions, 24 deletions
diff --git a/modules/block.module b/modules/block.module index 75a69b2f6..045cfe8f2 100644 --- a/modules/block.module +++ b/modules/block.module @@ -104,7 +104,7 @@ function block_block($op = 'list', $delta = 0, $edit = array()) { case 'view': $block = db_fetch_object(db_query('SELECT * FROM {boxes} WHERE bid = %d', $delta)); $data['subject'] = check_plain($block->title); - $data['content'] = check_output($block->body, $block->format); + $data['content'] = check_output($block->body, $block->format, FALSE); return $data; } } diff --git a/modules/block/block.module b/modules/block/block.module index 75a69b2f6..045cfe8f2 100644 --- a/modules/block/block.module +++ b/modules/block/block.module @@ -104,7 +104,7 @@ function block_block($op = 'list', $delta = 0, $edit = array()) { case 'view': $block = db_fetch_object(db_query('SELECT * FROM {boxes} WHERE bid = %d', $delta)); $data['subject'] = check_plain($block->title); - $data['content'] = check_output($block->body, $block->format); + $data['content'] = check_output($block->body, $block->format, FALSE); return $data; } } diff --git a/modules/comment.module b/modules/comment.module index 0bcb91448..539bc9f9a 100644 --- a/modules/comment.module +++ b/modules/comment.module @@ -280,7 +280,7 @@ function comment_nodeapi(&$node, $op, $arg = 0) { $text = ''; $comments = db_query('SELECT subject, comment, format FROM {comments} WHERE nid = %d AND status = %d', $node->nid, COMMENT_PUBLISHED); while ($comment = db_fetch_object($comments)) { - $text .= '<h2>'. check_plain($comment->subject) .'</h2>'. check_output($comment->comment, $comment->format); + $text .= '<h2>'. check_plain($comment->subject) .'</h2>'. check_output($comment->comment, $comment->format, FALSE); } return $text; @@ -440,6 +440,7 @@ function comment_validate_form($edit) { // 1) Filter it into HTML // 2) Strip out all HTML tags // 3) Convert entities back to plain-text. + // Note: format is checked by check_output(). $edit['subject'] = truncate_utf8(decode_entities(strip_tags(check_output($edit['comment'], $edit['format']))), 29, TRUE); } @@ -501,7 +502,9 @@ function comment_preview($edit) { $comment->name = check_plain($user->name ? $user->name : $comment->name); // Preview the comment. - $output .= theme('comment_preview', $comment, theme('links', module_invoke_all('link', 'comment', $comment, 1))); + if (!form_get_errors()) { + $output .= theme('comment_preview', $comment, theme('links', module_invoke_all('link', 'comment', $comment, 1))); + } $output .= theme('comment_form', $edit, t('Reply')); if ($edit['pid']) { @@ -982,7 +985,7 @@ function comment_delete($cid) { t('Any replies to this comment will be lost. This action cannot be undone.'), t('Delete')); // Show comment that is being deleted - $comment->comment = check_output($comment->comment, $comment->format); + $comment->comment = check_output($comment->comment, $comment->format, FALSE); $output .= theme('comment', $comment); } @@ -1447,7 +1450,7 @@ function theme_comment_view($comment, $links = '', $visible = 1) { // Switch to folded/unfolded view of the comment if ($visible) { - $comment->comment = check_output($comment->comment, $comment->format); + $comment->comment = check_output($comment->comment, $comment->format, FALSE); $output .= theme('comment', $comment, $links); } else { diff --git a/modules/comment/comment.module b/modules/comment/comment.module index 0bcb91448..539bc9f9a 100644 --- a/modules/comment/comment.module +++ b/modules/comment/comment.module @@ -280,7 +280,7 @@ function comment_nodeapi(&$node, $op, $arg = 0) { $text = ''; $comments = db_query('SELECT subject, comment, format FROM {comments} WHERE nid = %d AND status = %d', $node->nid, COMMENT_PUBLISHED); while ($comment = db_fetch_object($comments)) { - $text .= '<h2>'. check_plain($comment->subject) .'</h2>'. check_output($comment->comment, $comment->format); + $text .= '<h2>'. check_plain($comment->subject) .'</h2>'. check_output($comment->comment, $comment->format, FALSE); } return $text; @@ -440,6 +440,7 @@ function comment_validate_form($edit) { // 1) Filter it into HTML // 2) Strip out all HTML tags // 3) Convert entities back to plain-text. + // Note: format is checked by check_output(). $edit['subject'] = truncate_utf8(decode_entities(strip_tags(check_output($edit['comment'], $edit['format']))), 29, TRUE); } @@ -501,7 +502,9 @@ function comment_preview($edit) { $comment->name = check_plain($user->name ? $user->name : $comment->name); // Preview the comment. - $output .= theme('comment_preview', $comment, theme('links', module_invoke_all('link', 'comment', $comment, 1))); + if (!form_get_errors()) { + $output .= theme('comment_preview', $comment, theme('links', module_invoke_all('link', 'comment', $comment, 1))); + } $output .= theme('comment_form', $edit, t('Reply')); if ($edit['pid']) { @@ -982,7 +985,7 @@ function comment_delete($cid) { t('Any replies to this comment will be lost. This action cannot be undone.'), t('Delete')); // Show comment that is being deleted - $comment->comment = check_output($comment->comment, $comment->format); + $comment->comment = check_output($comment->comment, $comment->format, FALSE); $output .= theme('comment', $comment); } @@ -1447,7 +1450,7 @@ function theme_comment_view($comment, $links = '', $visible = 1) { // Switch to folded/unfolded view of the comment if ($visible) { - $comment->comment = check_output($comment->comment, $comment->format); + $comment->comment = check_output($comment->comment, $comment->format, FALSE); $output .= theme('comment', $comment, $links); } else { diff --git a/modules/filter.module b/modules/filter.module index 80b9edcef..410667dd1 100644 --- a/modules/filter.module +++ b/modules/filter.module @@ -646,13 +646,34 @@ function filter_list_format($format) { * @{ * Modules which need to have content filtered can use these functions to * interact with the filter system. + * + * For more info, see the hook_filter() documentation. + * + * Note: because filters can inject JavaScript or execute PHP code, security is + * vital here. When a user supplies a $format, you should validate it with + * filter_access($format) before accepting/using it. This is normally done in + * the validation stage of the node system. You should for example never make a + * preview of content in a disallowed format. */ /** * Run all the enabled filters on a piece of text. - */ -function check_output($text, $format = FILTER_FORMAT_DEFAULT) { - if (isset($text)) { + * + * @param $text + * The text to be filtered. + * @param $format + * The format of the text to be filtered. Specify FILTER_FORMAT_DEFAULT for + * the default format. + * @param $check + * Whether to check the $format with filter_access() first. Defaults to TRUE. + * Note that this will check the permissions of the current user, so you + * should specify $check = FALSE when viewing other people's content. When + * showing content that is not (yet) stored in the database (eg. upon preview), + * set to TRUE so the user's permissions are checked. + */ +function check_output($text, $format = FILTER_FORMAT_DEFAULT, $check = TRUE) { + // When $check = true, do an access check on $format. + if (isset($text) && (!$check || filter_access($format))) { if ($format == FILTER_FORMAT_DEFAULT) { $format = variable_get('filter_default_format', 1); } diff --git a/modules/filter/filter.module b/modules/filter/filter.module index 80b9edcef..410667dd1 100644 --- a/modules/filter/filter.module +++ b/modules/filter/filter.module @@ -646,13 +646,34 @@ function filter_list_format($format) { * @{ * Modules which need to have content filtered can use these functions to * interact with the filter system. + * + * For more info, see the hook_filter() documentation. + * + * Note: because filters can inject JavaScript or execute PHP code, security is + * vital here. When a user supplies a $format, you should validate it with + * filter_access($format) before accepting/using it. This is normally done in + * the validation stage of the node system. You should for example never make a + * preview of content in a disallowed format. */ /** * Run all the enabled filters on a piece of text. - */ -function check_output($text, $format = FILTER_FORMAT_DEFAULT) { - if (isset($text)) { + * + * @param $text + * The text to be filtered. + * @param $format + * The format of the text to be filtered. Specify FILTER_FORMAT_DEFAULT for + * the default format. + * @param $check + * Whether to check the $format with filter_access() first. Defaults to TRUE. + * Note that this will check the permissions of the current user, so you + * should specify $check = FALSE when viewing other people's content. When + * showing content that is not (yet) stored in the database (eg. upon preview), + * set to TRUE so the user's permissions are checked. + */ +function check_output($text, $format = FILTER_FORMAT_DEFAULT, $check = TRUE) { + // When $check = true, do an access check on $format. + if (isset($text) && (!$check || filter_access($format))) { if ($format == FILTER_FORMAT_DEFAULT) { $format = variable_get('filter_default_format', 1); } diff --git a/modules/node.module b/modules/node.module index e454de575..63e1ca02a 100644 --- a/modules/node.module +++ b/modules/node.module @@ -498,6 +498,13 @@ function node_view($node, $teaser = FALSE, $page = FALSE, $links = TRUE) { if ($links) { $node->links = module_invoke_all('link', 'node', $node, !$page); } + // unset unused $node part so that a bad theme can not open a security hole + if ($teaser) { + unset($node->body); + } + else { + unset($node->teaser); + } return theme('node', $node, $teaser, $page); } @@ -508,10 +515,10 @@ function node_view($node, $teaser = FALSE, $page = FALSE, $links = TRUE) { function node_prepare($node, $teaser = FALSE) { $node->readmore = (strlen($node->teaser) < strlen($node->body)); if ($teaser == FALSE) { - $node->body = check_output($node->body, $node->format); + $node->body = check_output($node->body, $node->format, FALSE); } else { - $node->teaser = check_output($node->teaser, $node->format); + $node->teaser = check_output($node->teaser, $node->format, FALSE); } return $node; } @@ -567,7 +574,7 @@ function node_search($op = 'search', $keys = null) { 'user' => format_name($node), 'date' => $node->changed, 'extra' => $extra, - 'snippet' => search_excerpt($keys, check_output($node->body, $node->format))); + 'snippet' => search_excerpt($keys, check_output($node->body, $node->format, FALSE))); } return $results; } @@ -1470,7 +1477,9 @@ function node_preview($node) { // Display a preview of the node: // Previewing alters $node so it needs to be cloned. - $output = theme('node_preview', drupal_clone($node)); + if (!form_get_errors()) { + $output = theme('node_preview', drupal_clone($node)); + } $output .= node_form($node); diff --git a/modules/node/node.module b/modules/node/node.module index e454de575..63e1ca02a 100644 --- a/modules/node/node.module +++ b/modules/node/node.module @@ -498,6 +498,13 @@ function node_view($node, $teaser = FALSE, $page = FALSE, $links = TRUE) { if ($links) { $node->links = module_invoke_all('link', 'node', $node, !$page); } + // unset unused $node part so that a bad theme can not open a security hole + if ($teaser) { + unset($node->body); + } + else { + unset($node->teaser); + } return theme('node', $node, $teaser, $page); } @@ -508,10 +515,10 @@ function node_view($node, $teaser = FALSE, $page = FALSE, $links = TRUE) { function node_prepare($node, $teaser = FALSE) { $node->readmore = (strlen($node->teaser) < strlen($node->body)); if ($teaser == FALSE) { - $node->body = check_output($node->body, $node->format); + $node->body = check_output($node->body, $node->format, FALSE); } else { - $node->teaser = check_output($node->teaser, $node->format); + $node->teaser = check_output($node->teaser, $node->format, FALSE); } return $node; } @@ -567,7 +574,7 @@ function node_search($op = 'search', $keys = null) { 'user' => format_name($node), 'date' => $node->changed, 'extra' => $extra, - 'snippet' => search_excerpt($keys, check_output($node->body, $node->format))); + 'snippet' => search_excerpt($keys, check_output($node->body, $node->format, FALSE))); } return $results; } @@ -1470,7 +1477,9 @@ function node_preview($node) { // Display a preview of the node: // Previewing alters $node so it needs to be cloned. - $output = theme('node_preview', drupal_clone($node)); + if (!form_get_errors()) { + $output = theme('node_preview', drupal_clone($node)); + } $output .= node_form($node); |