2010-12-04 97 views
4

我想要一个没有任何撇号,逗号或&符号的网址,并将它与可能具有这些字符之一的数据库中的记录进行匹配。在mysql搜索中忽略撇号

例如:

mywebsite.com/bobs-big-boy 
mywebsite.com/tom--jerry 
mywebsite.com/one-two-three 

重写

index.php?name=bobs-big-boy 
index.php?name=tom--jerry 
index.php?name=bobs-big-boy 

然后在PHP我想用$ _GET [ '名']匹配记录

bob's big boy 
tom & jerry 
one, two, three 

现在我的查询看起来像这样:

"SELECT * from the_records WHERE name=$NAME"; 

我无法更改记录,因为它们是商业名称。有没有一种方法可以编写查询来忽略db中的&符号,逗号和撇号?

+0

将它们存储在数据库中,很傻。无需更改记录,只需添加另一列即可。 – 2010-12-04 07:45:47

+0

我不拥有数据库,并且无法写入它。 – 2010-12-06 19:10:26

+0

@pg:网址是否必须如此?约翰斯回答的作品,但它并不快。 – thejh 2010-12-06 19:50:13

回答

7

是的,你可以,但我很确定它会忽略列上的任何索引。这很恶心。

喜欢的东西

SELECT * FROM the_records 
WHERE replace(replace(replace(name, '''', ''), ',', ''), '&', '') = $NAME 

通过采取这样的一个GET变量,并将其注入到MySQL的查询可以是成熟的SQL注入,据我所知的方式。

pg,我知道你说你不能更改/更新你正在选择的数据库中的内容,但是是否有任何东西阻止你在另一个有写入权限的数据库中创建表格?您可以制作一个urlnames到商业名称的地图,第一次执行替换方法时只会很慢。

+0

看起来你是对的注射攻击:http://unixwiz.net/techtips/sql-injection.html – fncomp 2010-12-10 04:42:39

0

使用str_replace函数功能,我们将抓住$ name参数,更换

ampersands (&) with "" 
spaces (" ") with "-" 
commas (",") with "" 
apostrophes("'") with "" 

str_replace函数(混合$搜索,混合$更换,混合$主题[摘要& $计数])

$搜索= { “&”, “”, “”, “”“}
$替换= { ”“, ” - “, ”“, ”“}

$ComparableString = str_replace($Search, $Replace, $_GET['name']) 

之后,我们可以做的SQL查询:

$name = mysql_real_escape_string($name, $db_resource); 
SELECT * from the_records WHERE name='$name' 
+3

你完全错过了这个问题。 – 2010-12-04 07:49:40

0

这是一个有点janky,但你可能会爆炸的GET和建立多个条件WHERE。

喜欢的东西(未经测试):

$name_array = explode("-", $_GET['name']); 

$sql_str = "SELECT * FROM the_records WHERE "; 

$first_time = true; 
foreach($name_array as $name){ 
    if ($name != ""){ 
     if ($first_time){ 
      $sql_str .= "name LIKE \"%".$name."%\""; 
      $first_time = false; 
     } 
     else { 
      $sql_str .= " AND name LIKE \"%".$name."%\""; 
     } 
    } 
} 
4

问候,

这一次我花了几分钟就破解了!实际上你的要求中缺少一些细节,所以我试图通过不同的假设来解决问题,如下所述。

下面是从您的示例中提取的URL假设输入以及MySQL注入攻击(仅用于咯咯笑)以及商业名称的变体。键是预期的URL,值是要匹配的数据库值。

<?php 
$names = array(
    'bobs-big-boy'=>"bob's big boy", 
    'tom--jerry'=>'tom & jerry', 
    'tomjerry'=>'tom&jerry', 
    'one-two-three'=>'one, two, three', 
    'onetwothree'=>'one,two,three', 
    "anything' OR 'haxor'='haxor"=>'die-haxor-die', 
); 
?> 

一个聪明的方式做一个最终运行MySQL的缺乏正则表达式替换的是使用SOUNDEX,而这种做法似乎在这种情况下,大部分工作取决于精确的你所需要的水平,密度和客户名称等。例如相似性,这会产生这些值的SOUNDEX值以上:

$soundex_test = $names; 
$select = 'SELECT '; 
foreach ($soundex_test as $name=>$dbname) { 
    echo '<p>'.$name.': '.soundex($name).' :: '.$dbname.': '.soundex($dbname).'</p>'; 
    $select .= sprintf("SOUNDEX('%s'),", $name); 
} 
echo '<pre>MySQL queries with attack -- '.print_r($select,1).'</pre>'; 

因此,假设有没有客户名为“一,二,三”和独立的一个名为“onetwothree” ,这种方法应该很好地工作。

要使用这个方法,你的查询会是这个样子:

$soundex_unclean = $names; 
foreach ($soundex_unclean as $name=>$dbname) { 
    $soundex_unclean[$name] = sprintf("SELECT * from the_records WHERE name SOUNDS LIKE '%s';", $name).' /* matches name field = ['.$dbname.'] */'; 
} 
echo '<pre>MySQL queries with attack -- '.print_r(array_values($soundex_unclean),1).'</pre>'; 

然而,这里是一个,它对付注入攻击(注意新线)运行。我知道这是不是问题的重点,但ajreal提到的问题,所以我想对付它还有:

$soundex_clean = $names; 
foreach ($soundex_clean as $name=>$dbname) { 
    // strip out everything but alpha-numerics and dashes 
    $clean_name = preg_replace('/[^[:alnum:]-]/', '', $name); 
    $soundex_unclean[$name] = sprintf("SELECT * from the_records WHERE name SOUNDS LIKE '%s';", $clean_name).' /* matches name field = ['.$dbname.'] */'; 
} 
echo '<pre>MySQL queries with attack cleaned -- '.print_r($soundex_unclean,1).'</pre>'; 

如果这个方法不适合,你决定更换内嵌方法已经足够了,那么请记得在混音中添加逗号替换。作为这种方法的一个例子,我假设在这里,单引号,双引号,&符号和逗号(即',“,&和)是数据库中只包含四个特殊字符,但从URL,任何其他非字母数字字符,包含空格,转换为一个破折号(即 - )

首先,不与注入攻击应对运行:

$unclean = $names; 
foreach ($unclean as $name=>$dbname) { 
    $regex_name = preg_replace('/[-]+/', '[^[:alnum:]]+', $name); 
    $unclean[$name] = sprintf("SELECT * from the_records WHERE REPLACE(REPLACE(REPLACE(REPLACE(name, ',', ''), '&', ''), '\"', ''), \"'\", '') REGEXP '%s'", $regex_name); 
} 
echo '<pre>MySQL queries with attack -- '.print_r($unclean,1).'</pre>'; 

其次,一个能处理攻击的跑步:

$clean = $names; 
foreach ($clean as $name=>$dbname) { 
    $regex_name = preg_replace('/[^[:alnum:]-]/', '', $name); 
    $regex_name = preg_replace('/[-]+/', '[^[:alnum:]]+', $regex_name); 
    $clean[$name] = sprintf("SELECT * from the_records WHERE REPLACE(REPLACE(REPLACE(REPLACE(name, ',', ''), '&', ''), '\"', ''), \"'\", '') REGEXP '%s'", $regex_name); 
} 
echo '<pre>MySQL queries with attack cleaned -- '.print_r($clean,1).'</pre>'; 

Aaaand,这足够头脑风暴我一晚! = o)