繁体   English   中英

PHP / SQL数据库查询良好实践和安全性

[英]PHP/SQL Database querying good practice and security

所以我是一个有点经验丰富的php开发人员,自2007年以来一直在做“该死的事”。 但是,在保护我的应用程序方面,我仍然相对较差。 我不知道我知道的所有事情,我可以而且应该这样做。

我已经选择了保护PHP Web应用程序,并正在阅读我的方式来测试一路上的东西。 我对与数据库查询有关的一般SO组有一些问题(主要是在mysql下):

创建将数据放入数据库的应用程序时,mysql_real_escape_string和输入数据的一般检查(is_numeric等)是否足够? 那些与sql注入不同的其他类型的攻击呢?

有人可以解释存储过程和准备好的语句,而不是 - 你制作它们并调用它们。 我想知道它们是如何工作的,幕后的验证是什么。

我在php4绑定环境中工作,php5暂时不是一个选项。 有没有其他人曾经在这个位置,你做了什么来保护你的应用程序,而所有酷孩子都在使用这个甜蜜的新mysqli界面?

人们发现有哪些一般的良好做法是有利的,强调创建一个能够承受升级和可能的迁移的基础设施(比如将php4移到php5)。

注意:有一个搜索周围找不到任何类似于这个打到php-mysql安全性的东西。

哈维尔的回答有一个owasp链接是一个好的开始。

还有一些事情你可以做更多:

  1. 关于SQL注入攻击,您可以编写一个函数来删除输入中的常见SQL语句,如“DROP”或“DELETE * WHERE”,如下所示:

    * $ sqlarray = array(“DROP”,“或1 = 1”,“union select”,“SELECT * FROM”,“select host”,“create table”,“FROM users”,“users WHERE”); *

    然后编写将检查此数组输入的函数。 确保$ sqlarray中的任何内容都不是来自用户的常见输入。 (别忘了在这上面使用strtolower,谢谢lou)。

  2. 我不确定memcache是​​否适用于PHP 4,但是你可以使用memcache实现一些垃圾邮件保护,只允许在Y时间段内对process.php页面X进行某些远程IP访问。

  3. 特权很重要。 如果您只需要插入权限(例如,订单处理),那么您应该使用只有插入且可能具有选择权限的用户登录订单处理页面上的数据库。 这意味着即使SQL注入完成,它们也只能执行INSERT / SELECT查询而不能删除或重构。

  4. 将重要的php处理文件放在/ include等目录中。 然后禁止所有IP访问该/ include目录。

  5. 在用户的会话中使用用户的代理+ remoteip + salt加盐腌MD5,并在每个页面加载时验证正确的MD5在其cookie中。

  6. 禁止某些标题( http://www.owasp.org/index.php/Testing_for_HTTP_Methods_and_XST )。 禁止PUT(如果您不需要文件上传)/ TRACE / CONNECT / DELETE标头。

我的建议:

  1. 沟通mysqli支持PDO (使用mysql驱动程序)
  2. 使用PDO paremeterized准备好的陈述

然后你可以这样做:

$pdo_obj = new PDO( 'mysql:server=localhost; dbname=mydatabase', 
                    $dbusername, $dbpassword );

$sql = 'SELECT column FROM table WHERE condition=:condition';
$params = array( ':condition' => 1 );

$statement = $pdo_obj->prepare( $sql, 
    array( PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY ) );
$statement->execute( $params );
$result = $statement->fetchAll( PDO::FETCH_ASSOC );

优点:

  1. 不再需要手动转移,因为PDO为您完成了所有工作!
  2. 突然切换数据库后端相对容易。

缺点:

  • 我什么都想不到。

我通常不使用PHP,因此我无法提供专门针对您的要求的建议,但我建议您查看OWASP页面,特别是前10个漏洞报告: http//www.owasp.org /index.php/Top_10_2007

在该页面中,对于每个漏洞,您将获得一些列表,您可以执行这些操作以避免在不同平台(.Net,Java,PHP等)中出现问题。

关于准备好的语句,它们的工作原理是让数据库引擎知道在特定查询期间有多少参数和类型,使用这些信息,引擎可以理解哪些字符是实际参数的一部分,而不是应该被解析为SQL就像'(撇号)作为数据的一部分而不是'作为字符串分隔符。 抱歉,我无法提供针对PHP的更多信息,但希望这会有所帮助。

AFAIK,PHP / mySQL通常没有参数化查询。

使用sprintf()mysql_real_escape_string()应该可以很好地工作。 如果为sprintf()使用适当的格式字符串(例如,对于整数使用“%d”),那么你应该非常安全。

我可能错了,但是在用户提供的数据上使用mysql_real_escape_string应该不够吗?

除非它们是数字,在这种情况下,您应该确保它们实际上是数字,而不是使用例如ctype_digitis_numericsprintf (使用%d%u强制输入数字)。

另外,为你的php脚本提供一个serarate mysql用户,只能SELECT,INSERT,UPDATE和DELETE,这可能是一个好主意......


来自php.net的示例

示例#3“最佳实践”查询

在每个变量周围使用mysql_real_escape_string()可以防止SQL注入。 此示例演示了查询数据库的“最佳实践”方法,与Magic Quotes设置无关。

查询现在将正确执行,SQL注入攻击将无法正常工作。

  <?php if (isset($_POST['product_name']) && isset($_POST['product_description']) && isset($_POST['user_id'])) { // Connect $link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password'); if(!is_resource($link)) { echo "Failed to connect to the server\\n"; // ... log the error properly } else { // Reverse magic_quotes_gpc/magic_quotes_sybase effects on those vars if ON. if(get_magic_quotes_gpc()) { $product_name = stripslashes($_POST['product_name']); $product_description = stripslashes($_POST['product_description']); } else { $product_name = $_POST['product_name']; $product_description = $_POST['product_description']; } // Make a safe query $query = sprintf("INSERT INTO products (`name`, `description`, `user_id`) VALUES ('%s', '%s', %d)", mysql_real_escape_string($product_name, $link), mysql_real_escape_string($product_description, $link), $_POST['user_id']); mysql_query($query, $link); if (mysql_affected_rows($link) > 0) { echo "Product inserted\\n"; } } } else { echo "Fill the form properly\\n"; } 

将存储过程用于涉及写入数据库的任何活动,并对所有选择使用绑定参数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM