【问题标题】:MATCH AGAINST SQL Inject prevention and wpdb->prepareMATCH AGAINST SQL 注入预防和 wpdb->prepare
【发布时间】:2011-04-28 14:46:04
【问题描述】:

我正在尝试使用 $wpdb->prepare(); 从 sql 注入优化 SQL;

此查询不返回任何内容。谁能看到原因或有更优雅的选择。也有必要在 MATCH AGAINST 语句中转义搜索词。

$search_terms = "example search" // input post
// remove single quotes from search terms
$search_terms = str_replace("'","",$search_terms);

$sql = "SELECT
    post.ID,
    post.post_author,
    post.post_date,
    post.post_title,
    LEFT(post.post_content, 240) As post_content,
    post.post_name,
    post.post_type,
    post.comment_count,
    post.comment_status,
    MATCH (post_search.post_content,post_search.post_title) AGAINST (%s IN BOOLEAN MODE) AS score
FROM wp_posts post
LEFT JOIN wp_term_relationships term_rel
    ON post.ID = term_rel.object_id
LEFT JOIN wp_term_taxonomy term_tax
    ON term_rel.term_taxonomy_id = term_tax.term_taxonomy_id
LEFT JOIN wp_terms terms
    ON term_tax.term_id = terms.term_id
LEFT JOIN wp_posts_fulltext_search post_search 
    ON post.ID=post_search.post_id
WHERE MATCH(post_search.post_content,post_search.post_title) AGAINST (%s IN BOOLEAN MODE) && 
    post.post_status = 'publish' && 
    post.post_type = 'post' && 
    (term_tax.description != '' && 
    term_tax.description NOT LIKE '%sample%') 
GROUP BY post.ID
ORDER BY score DESC
LIMIT 0,20";

$results = $wpdb->get_results( $wpdb->prepare( $sql, $search_terms ) );

“作为分数”用于将更相关的结果返回到顶部。重申一下,我更关心 SQL 注入、MATCH AGAINST 和 wordpress 准备功能。

【问题讨论】:

  • $wpdb->print_error() 显示什么?
  • $wpdb->show_errors();什么都不显示。

标签: php mysql sql-injection wordpress


【解决方案1】:

不要永远使用此代码:

// remove single quotes from search terms 
$search_terms = str_replace("'","",$search_terms); 

它坏了,因为它没有考虑 MySQL 的编码。

如果你想逃跑,用这个代替:

$search_terms = mysql_real_escape_string($search_terms);

但要小心!,这只会转义值,而不是表名和字段名。
如果你想在查询中操作字段或表名,规则是:

  1. 别这样,你是在找 SQL 注入麻烦。
  2. 也不要使用 PDO,您仍然会遇到 SQL 注入问题。
  3. 阅读 Pekka 对我的问题的回答:How to prevent SQL injection with dynamic tablenames?

但是
不需要转义,因为您使用的是准备好的语句。

【讨论】:

  • 感谢您的建议。我已经改变了。当我尝试使用 MATCH AGAINST (%s IN BOOLEAN MODE) 和 $wpdb->prepare 时,它​​仍然没有返回结果。
  • 你是说,如果我使用 mysql_real_escape_string() 则不需要使用准备好的语句。
  • @madphp,反之,使用 PDO 时不需要 mysql_real_escape_string()。 PDO 比使用 mysql_real_escape_string() 更安全,但不是 100% 安全。
  • @madphp,有关 SQL 注入的更多信息,请参阅:stackoverflow.com/questions/332365/…
【解决方案2】:

http://codex.wordpress.org/Function_Reference/wpdb_Class复制粘贴

保护查询免受 SQL 注入攻击

有关 WordPress 中 SQL 转义的更完整概述,请参阅database Data ValidationData Validation 文章是所有 WordPress 代码贡献者和插件作者的必读文章。

不过,简而言之,SQL 查询中的所有数据必须在执行 SQL 查询之前进行 SQL 转义,以防止 SQL 注入攻击。这可以通过prepare 方法方便地完成,该方法支持sprintf()-like 和vsprintf()-like 语法。

<?php 
  $sql = $wpdb->prepare('query' [, value_parameter, value_parameter ... ] ); 
?>

查询
(字符串)您希望执行的 SQL 查询,带有 %s 和 %d 占位符。任何其他 % 字符都可能导致解析错误,除非它们被转义。 SQL 字符串文字中的所有 % 字符,包括 LIKE 通配符,都必须以 %% 的形式进行双 % 转义。 (

_value_parameter_
(int|string|array) 要替换为占位符的值。可以通过简单地以类似 sprintf() 的方式传递更多参数来传递许多值。或者,第二个参数可以是一个包含 PHP 的 vsprintf() 函数中的值的数组。必须注意不允许用户直接输入此参数,这将启用具有多个占位符的任何查询的数组操作。值不能已经被 SQL 转义。

示例

添加元键 => 值对 "Harriet's Adages" => "WordPress 的数据库界面就像 Sunday Morning: E​​asy。"到 10 号后。

$metakey = "Harriet's Adages";
$metavalue = "WordPress' database interface is like Sunday Morning: Easy.";

$wpdb->query( $wpdb->prepare( "
    INSERT INTO $wpdb->postmeta
    ( post_id, meta_key, meta_value )
    VALUES ( %d, %s, %s )", 
        10, $metakey, $metavalue ) );

由 add_meta() 在 WordPress 中执行。

使用类似 vsprintf() 语法的相同查询。

$metakey = "Harriet's Adages";
$metavalue = "WordPress' database interface is like Sunday Morning: Easy.";

$wpdb->query( $wpdb->prepare( "
    INSERT INTO $wpdb->postmeta
    ( post_id, meta_key, meta_value )
    VALUES ( %d, %s, %s )", 
        array(10, $metakey, $metavalue) ) );

(部分)您的问题

您没有在 like 语句中双重转义您的“%”。
变化:

term_tax.description NOT LIKE '%sample%')  

term_tax.description NOT LIKE '%%sample%%') 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 1970-01-01
    • 2017-12-17
    • 2012-12-21
    • 2012-05-22
    相关资源
    最近更新 更多