我不久前开始从事网络开发。我现在知道一些事情,但我真的很担心可能出现的安全问题。我知道像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
答案 0 :(得分:6)
首先,感谢您关心网络安全。许多PHP开发人员对此一无所知,也不在乎学习。他们是将我们的密码和银行账户暴露给黑客的人。成为解决方案的一部分! : - )
<强> 1。将mysql扩展视为已弃用。
使用PDO或mysqli扩展名代替。普通的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”。声明一必须使用
答案 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并单独研究这些内容,因为每个内容本身都是一个很大的主题!