duanduji2986 2011-03-24 04:23
浏览 135
已采纳

mysql_real_escape_string()和mysql_escape_string()是否足以满足应用安全性?

Will mysql_real_rescape_string() be enough to protect me from hackers and SQL attacks? Asking because I heard that these don't help against all attack vectors? Looking for the advice of experts.

EDIT: Also, what about LIKE SQL attacks?

  • 写回答

5条回答 默认 最新

  • douzhi1972 2011-03-25 14:07
    关注

    @Charles is extremely correct!

    You put yourself at risk for multiple types of known SQL attacks, including, as you mentioned

    • SQL injection: Yes! Mysql_Escape_String probably STILL keeps you susceptible to SQL injections, depending on where you use PHP variables in your queries.

    Consider this:

    $sql = "SELECT number FROM PhoneNumbers " .
           "WHERE " . mysql_real_escape_string($field) . " = " . mysql_real_escape_string($value);  
    

    Can that be securely and accurately escaped that way? NO! Why? because a hacker could very well still do this:

    Repeat after me:

    mysql_real_escape_string() is only meant to escape variable data, NOT table names, column names, and especially not LIMIT fields.

    • LIKE exploits: LIKE "$data%" where $data could be "%" which would return ALL records ... which can very well be a security exploit... just imagine a Lookup by last four digits of a credit card... OOPs! Now the hackers can potentially receive every credit card number in your system! (BTW: Storing full credit cards is hardly ever recommended!)

    • Charset Exploits: No matter what the haters say, Internet Explorer is still, in 2011, vulnerable to Character Set Exploits, and that's if you have designed your HTML page correctly, with the equivalent of <meta name="charset" value="UTF-8"/>! These attacks are VERY nasty as they give the hacker as much control as straight SQL injections: e.g. full.

    Here's some example code to demonstrate all of this:

    // Contains class DBConfig; database information.
    require_once('../.dbcreds');                       
    
    $dblink = mysql_connect(DBConfig::$host, DBConfig::$user, DBConfig::$pass);
    mysql_select_db(DBConfig::$db);
    //print_r($argv);
    
    $sql = sprintf("SELECT url FROM GrabbedURLs WHERE %s LIKE '%s%%' LIMIT %s",
                   mysql_real_escape_string($argv[1]),
                   mysql_real_escape_string($argv[2]),
                   mysql_real_escape_string($argv[3]));
    echo "SQL: $sql
    ";
    $qq = mysql_query($sql);
    while (($data = mysql_fetch_array($qq)))
    {
            print_r($data);
    }
    

    Here's the results of this code when various inputs are passed:

    $ php sql_exploits.php url http://www.reddit.com id
    SQL generated: SELECT url FROM GrabbedURLs 
                   WHERE url LIKE 'http://www.reddit.com%'
                   ORDER BY id;
    Returns: Just URLs beginning w/ "http://www.reddit.com"
    
    $ php sql_exploits.php url % id
    SQL generated: SELECT url FROM GrabbedURLs 
                   WHERE url LIKE '%%' 
                   ORDER BY id;
    Results: Returns every result Not what you programmed, ergo an exploit --
    

    $ php sql_exploits.php 1=1 'http://www.reddit.com' id Results: Returns every column and every result.

    Then there are the REALLLY nasty LIMIT exploits:

    $ php sql_exploits.php url 
    > 'http://www.reddit.com'
    > "UNION SELECT name FROM CachedDomains"
    Generated SQL: SELECT url FROM GrabbedURLs 
                   WHERE url LIKE 'http://reddit.com%' 
                   LIMIT 1 
                   UNION
                   SELECT name FROM CachedDomains;
    Returns:  An entirely unexpected, potentially (probably) unauthorized query
              from another, completely different table. 
    

    Whether you understand the SQL in the attacks or not is irrevelant. What this has demonstrated is that mysql_real_escape_string() is easily circumvented by even the most immature of hackers. That is because it is a REACTIVE defense mechism. It only fixes very limited and KNOWN exploits in the Database.

    All escaping will NEVER be sufficient to secure databases. In fact, you can explicitly REACT to every KNOWN exploit and in the future, your code will most likely become vulnerable to attacks discovered in the future.

    The proper, and only (really) , defense is a PROACTIVE one: Use Prepared Statements. Prepared statements are designed with special care so that ONLY valid and PROGRAMMED SQL is executed. This means that, when done correctly, the odds of unexpected SQL being able to be executed are drammatically reduced.

    Theoretically, prepared statements that are implemented perfectly would be impervious to ALL attacks, known and unknown, as they are a SERVER SIDE technique, handled by the DATABASE SERVERS THEMSELVES and the libraries that interface with the programming language. Therefore, you're ALWAYS guaranteed to be protected against EVERY KNOWN HACK, at the bare minimum.

    And it's less code:

    $pdo = new PDO($dsn);
    
    $column = 'url';
    $value = 'http://www.stackoverflow.com/';
    $limit = 1;
    
    $validColumns = array('url', 'last_fetched');
    
    // Make sure to validate whether $column is a valid search parameter.
    // Default to 'id' if it's an invalid column.
    if (!in_array($column, $validColumns) { $column = 'id'; }
    
    
    $statement = $pdo->prepare('SELECT url FROM GrabbedURLs ' .
                               'WHERE ' . $column . '=? ' .
                               'LIMIT ' . intval($limit));
    $statement->execute(array($value));
    while (($data = $statement->fetch())) { }
    

    Now that wasn't so hard was it? And it's forty-seven percent less code (195 chars (PDO) vs 375 chars (mysql_). That's what I call, "full of win".

    EDIT: To address all the controversy this answer stirred up, allow me to reiterate what I have already said:

    Using prepared statements allows one to harness the protective measures of the SQL server itself, and therefore you are protected from things that the SQL server people know about. Because of this extra level of protection, you are far safer than by just using escaping, no matter how thorough.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

悬赏问题

  • ¥15 用友U8:向一个无法连接的网络尝试了一个套接字操作,如何解决?
  • ¥30 我的代码按理说完成了模型的搭建、训练、验证测试等工作(标签-网络|关键词-变化检测)
  • ¥50 mac mini外接显示器 画质字体模糊
  • ¥15 TLS1.2协议通信解密
  • ¥40 图书信息管理系统程序编写
  • ¥20 Qcustomplot缩小曲线形状问题
  • ¥15 企业资源规划ERP沙盘模拟
  • ¥15 树莓派控制机械臂传输命令报错,显示摄像头不存在
  • ¥15 前端echarts坐标轴问题
  • ¥15 ad5933的I2C