- Patch #1265946 by klausi, tstoeckler, dereine, aspilicious: DoS against core using a large number of OR search query terms.
parent
fdf48f2b99
commit
30d6b830cf
|
@ -122,6 +122,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.
|
||||
*
|
||||
|
@ -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)) {
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue