如何保护项目免受黑客攻击和攻击?

时间:2011-11-21 21:01:20

标签: php mysql security sql-injection

我不久前开始从事网络开发。我现在知道一些事情,但我真的很担心可能出现的安全问题。我知道像preg_replace这样简单的安全解决方案,但我对此并不自信。

所以我想问你任何一种可以在以下情况下应用的“通用”安全标准。正如我所提到的,我不是专业人士,所以如果你能从一些简单但有用的东西开始,那将会很棒。如果可能的话,你能提供一些例子吗?

我确实看过php手册,虽然我想知道人的其他信息。

以下是我在项目中使用的一些典型的MySQL / PHP内容。您能否提出任何改进措施以使其更安全?

$sql = mysql_query("SELECT * FROM stories WHERE showing = 1 ORDER BY cr_date DESC LIMIT 5") or die (mysql_error("There was an error in connection"));
        while($row = mysql_fetch_assoc($sql)){
            $story_id = $row["id"];
            // etc...
        }

$username = $_POST['username'];
$sql = mysql_query("INSERT INTO myMembers (username, //etc... ) 
VALUES('$username' //etc.. ")or die (mysql_error());

$username = $_GET['username']; 
//gets username from url like http://myweb.com/profile.php?username=blabla

4 个答案:

答案 0 :(得分:6)

首先,感谢您关心网络安全。许多PHP开发人员对此一无所知,也不在乎学习。他们是将我们的密码和银行账户暴露给黑客的人。成为解决方案的一部分! : - )

<强> 1。将mysql扩展视为已弃用。

使用PDOmysqli扩展名代替。普通的mysql扩展不支持预准备语句和一些其他功能,例如事务控制。如果他们有可用的PDO_mysql或mysqli,那么没有人应该使用mysql。

<强> 2。不要将外部数据插入SQL。

无论何时从$ _GET或$ _POST获取值,您都应该认为在任何SQL语句,shell_exec()或其他将字符串作为某种代码执行的实例中使用都是不安全的。

第3。使用准备好的查询参数而不是插值。

这很容易。实际上,使用查询参数比将变量插入SQL字符串更容易 。您不必担心转义或长期复杂的字符串连接。

请参阅此处的示例代码:http://us.php.net/manual/en/pdo.prepare.php

<强> 4。对于角落情况,请使用仔细过滤。

查询参数取代SQL表达式中一个文字值的位置。不是表名,不是列名,不是SQL关键字,不是值列表或完整表达式。对于那些,你需要使用字符串插值,但请参阅我的演示文稿SQL Injection Myths and Fallacies,了解如何将白名单&#34;白名单&#34;要插值的值。

另请查看PHP filter扩展,它提供了一种灵活的方式来验证输入或删除无效字符,以确保只使用输入的有效部分。


查看您的示例,SELECT查询没有从外部源(如$ _GET)插入的动态值。所以一个人是安全的。

INSERT查询从请求中获取一个值,该值可能包含更改查询运行方式的恶意内容。这个是使用查询参数的好选择。

还要考虑SQL注入是PHP最常见的两个安全问题之一。另一个是跨站点脚本(XSS)。这与SQL没有直接关系,但您也应该了解它。

这是了解有关网络编程安全性的更多资源:OWASP.org cheat sheets

答案 1 :(得分:2)

许多框架都有一套很好的安全措施,可以很好地防止像SQL注入这样的事情。 Yii,CakePhP,CodeIgnitre都可能有用。

答案 2 :(得分:1)

虽然几乎不可能击败比尔,但我觉得我必须澄清答案,说明“你必须不相信任何用户输入”。

事实上,完全相反 - 只有当完全不知道数据源时,SQL注入保护才会有用。并将所有数据视为潜在恶意。并据此处理。

因此,总结所有建议:

准备好的陈述是一种很好的方法但不是一个完整的方法 它有一个很棒的想法,即使用一些占位符,一个代理来表示查询中的实际值。因此,可以对该值进行适当的消毒 但正如比尔所说,这些占位符仅限于字符串和数字。因此,添加自己的另一个占位符(对于标识符)是个好主意。但您仍需要手动注意SQL语法关键字。

因此,而不是“不要将外部数据插入SQL”。声明一必须使用

“2.不要直接将值插入到查询中,只能由某个代理插入,执行必要的预防措施”

答案 3 :(得分:0)

最重要的是要记住永远不要相信来自外部来源的任何东西(例如用户输入,来自其他网络服务的响应等)。始终清理所有输入,并尽可能使用数据库提供程序中的代码来执行此操作。

在MySQL参数化的情况下,所有查询都是必不可少的,因此请使用预准备语句,例如

$statement = $db->prepare('SELECT * FROM stories WHERE title = :title');
$statement->execute(array(':title' => $title));
$rows = $statement->fetchAll();

您当前的插入语句容易受到SQL injection attack的攻击,将其修改为更接近:

$username = $_POST['username'];
$statement = $db.prepare("INSERT INTO myMembers (username) VALUES(':username');
$statement->execute(array(':username' => $username));

您还应该确保永远不会以纯文本格式存储任何密码,始终存储hashed版本的密码(以及盐)并检查哈希匹配而不是实际字符串。这意味着如果您的数据库受到损害,找出您的用户凭据将成为一件非常重要的任务。

这些只是让您的应用更安全的两种方法,我强烈建议您阅读OWASPs top 10 site vulnerabilities并单独研究这些内容,因为每个内容本身都是一个很大的主题!