summaryrefslogtreecommitdiff
path: root/modules/search
diff options
context:
space:
mode:
authorDries <dries@buytaert.net>2011-12-21 09:31:28 -0500
committerDries <dries@buytaert.net>2011-12-21 09:31:28 -0500
commit30d6b830cfc7b0acca3917208ca0662452678893 (patch)
treed8cfdfea1e8334b6ed45a06eabc8a99d932b19af /modules/search
parentfdf48f2b9962e04529e6b1a4bb3252ed9c01fc15 (diff)
downloadbrdo-30d6b830cfc7b0acca3917208ca0662452678893.tar.gz
brdo-30d6b830cfc7b0acca3917208ca0662452678893.tar.bz2
- Patch #1265946 by klausi, tstoeckler, dereine, aspilicious: DoS against core using a large number of OR search query terms.
Diffstat (limited to 'modules/search')
-rw-r--r--modules/search/search.extender.inc25
-rw-r--r--modules/search/search.test14
2 files changed, 39 insertions, 0 deletions
diff --git a/modules/search/search.extender.inc b/modules/search/search.extender.inc
index b7af4d06a..ad4b86e89 100644
--- a/modules/search/search.extender.inc
+++ b/modules/search/search.extender.inc
@@ -123,6 +123,16 @@ class SearchQuery extends SelectQueryExtender {
protected $multiply = array();
/**
+ * Whether or not search expressions were ignored.
+ *
+ * The maximum number of AND/OR combinations exceeded can be configured to
+ * avoid Denial-of-Service attacks. Expressions beyond the limit are ignored.
+ *
+ * @var boolean
+ */
+ protected $expressionsIgnored = FALSE;
+
+ /**
* Sets up the search query expression.
*
* @param $query
@@ -183,7 +193,17 @@ class SearchQuery extends SelectQueryExtender {
// Classify tokens.
$or = FALSE;
$warning = '';
+ $limit_combinations = variable_get('search_and_or_limit', 7);
+ // The first search expression does not count as AND.
+ $and_count = -1;
+ $or_count = 0;
foreach ($keywords as $match) {
+ if ($or_count && $and_count + $or_count >= $limit_combinations) {
+ // Ignore all further search expressions to prevent Denial-of-Service
+ // attacks using a high number of AND/OR combinations.
+ $this->expressionsIgnored = TRUE;
+ break;
+ }
$phrase = FALSE;
// Strip off phrase quotes.
if ($match[2]{0} == '"') {
@@ -212,6 +232,7 @@ class SearchQuery extends SelectQueryExtender {
}
$this->keys['positive'][] = $last;
$or = TRUE;
+ $or_count++;
continue;
}
// AND operator: implied, so just ignore it.
@@ -231,6 +252,7 @@ class SearchQuery extends SelectQueryExtender {
}
else {
$this->keys['positive'] = array_merge($this->keys['positive'], $words);
+ $and_count++;
}
}
$or = FALSE;
@@ -323,6 +345,9 @@ class SearchQuery extends SelectQueryExtender {
form_set_error('keys', format_plural(variable_get('minimum_word_size', 3), 'You must include at least one positive keyword with 1 character or more.', 'You must include at least one positive keyword with @count characters or more.'));
return FALSE;
}
+ if ($this->expressionsIgnored) {
+ drupal_set_message(t('Your search used too many AND/OR expressions. Only the first @count terms were included in this search.', array('@count' => variable_get('search_and_or_limit', 7))), 'warning');
+ }
$this->executedFirstPass = TRUE;
if (!empty($this->words)) {
diff --git a/modules/search/search.test b/modules/search/search.test
index b1edad62b..38bb0a74c 100644
--- a/modules/search/search.test
+++ b/modules/search/search.test
@@ -290,6 +290,20 @@ class SearchPageText extends DrupalWebTestCase {
$this->drupalGet('search/node/' . $arg);
$input = $this->xpath("//input[@id='edit-keys' and @value='{$arg}']");
$this->assertFalse(empty($input), 'Search keys with a / are correctly set as the default value in the search box.');
+
+ // Test a search input exceeding the limit of AND/OR combinations to test
+ // the Denial-of-Service protection.
+ $limit = variable_get('search_and_or_limit', 7);
+ $keys = array();
+ for ($i = 0; $i < $limit + 1; $i++) {
+ $keys[] = $this->randomName(3);
+ if ($i % 2 == 0) {
+ $keys[] = 'OR';
+ }
+ }
+ $edit['keys'] = implode(' ', $keys);
+ $this->drupalPost('search/node', $edit, t('Search'));
+ $this->assertRaw(t('Your search used too many AND/OR expressions. Only the first @count terms were included in this search.', array('@count' => $limit)));
}
}