好的,我和一个朋友正在做一个关于PHP安全的小型演示文稿(虽然我没有真正进入PHP),并且他让我找到一些易受攻击的PHP代码的例子(一个容易出现SQL注入和所有其他类型的攻击)。我想知道是否有任何网站既有好的也有坏的代码,显示你应该怎样编码?易受攻击的PHP代码示例?
基本上我会把它们放到我们的网站上,他会尝试破解它,然后我们将显示“正确”的网站,他会尝试再次破解它。
好的,我和一个朋友正在做一个关于PHP安全的小型演示文稿(虽然我没有真正进入PHP),并且他让我找到一些易受攻击的PHP代码的例子(一个容易出现SQL注入和所有其他类型的攻击)。我想知道是否有任何网站既有好的也有坏的代码,显示你应该怎样编码?易受攻击的PHP代码示例?
基本上我会把它们放到我们的网站上,他会尝试破解它,然后我们将显示“正确”的网站,他会尝试再次破解它。
SQL injection很简单:
$var = mysql_real_escape_string($_POST['var']);
其他常见的一种是XSS (cross site scripting):
$var = $_POST['var'];
echo "<div>$var</div>\n";
允许你注入正在运行JavaScript
$var = $_POST['var'];
mysql_query("SELECT * FROM sometable WHERE id = $var");
这是很容易解决的从您的网站。没有与此处理,例如几个方面:
$var = strip_tags($_POST['var']);
和
$var = filter_var($_POST['var'], FILTER_SANITIZE_STRING);
是的,基本上你永远不会相信用户输入,把它当作恶意输入,并用'addslashes()','strip_tags()'或'htmlspecialchars()'将其转义。 – Rob 2009-11-23 13:38:15
'strip_tags'不足以阻止HTML注入(认为属性值注入)。用FILTER_SANITIZE_STRING调用请求数组是一个绝对不应该使用的可怕黑客攻击。相反,通过调用HTML内容中每个字符串的'htmlspecialchars'来避免HTML注入。 – bobince 2009-11-23 13:40:05
你可以用正则表达式解析它... – nickf 2009-11-23 13:42:00
一个SQL注入脆弱的登录脚本的另一个例子。不幸的是,这在新程序员中很常见。
$username = $_POST["username"];
$password = $_POST["password"];
$query = "SELECT username, password
FROM users
WHERE (username = '{$username}')
AND (password = '{$password}')";
更不用说以明文存储密码了。 – 2009-11-23 14:25:24
@ Vilx-除非$ _POST [“password”]被散列在客户端;)这是不可靠的,因为客户端生成的散列不能在不向客户端透露salt的情况下被腌制。 – 2015-06-28 07:31:21
@ dwarf015 - 嗯,我认为如果哈希函数本身足够慢,揭示盐不会是一个大问题。但我不是专家,所以不要听我的话。 :) – 2015-06-28 07:50:36
一个真正常见的初学者的错误是忘记在重定向后终止脚本执行。
<?php
if ($_SESSION['user_logged_in'] !== true) {
header('Location: /login.php');
}
omg_important_private_functionality_here();
解决办法:
if ($_SESSION['user_logged_in'] !== true) {
header('Location: /login.php');
exit();
}
这可以在一个正常的浏览器进行测试时,因为浏览器通常遵循Location
头勿使任何脚本的输出被错过。
查看Open Web Application Security Project。他们有很多不同种类的攻击的解释和例子。 http://www.owasp.org/index.php/Category:Attack
我见过这样的代码写在了过去:
foreach ($_REQUEST as $var => $val) {
$$var = $val;
}
这是模拟中伤register_globals
选项的方式。这意味着你可以访问你这样的变量:
$myPostedVar
,而不是非常复杂:
$_POST['myPostedVar']
安全风险的情况下,会弹出这样的:
$hasAdminAccess = get_user_access();
foreach ($_REQUEST as $var => $val) {
$$var = $val;
}
if ($hasAdminAccess) { ... }
由于所有你需要做的是将?hasAdminAccess=1
添加到网址,然后你就进入了。
这个模拟的功能是'register_globals' – 2009-11-23 13:49:22
啊谢谢!这是我在脑海中阻止的事情之一。恐怖......恐怖...... – nickf 2009-11-23 13:50:21
鲍比表
Bobby Tables是专门描述一个脚本可以通过SQL injection脆弱的各种方式的页面。这不是PHP独有的,但是,SQL注入是许多网页漏洞的原因。
这可能是你想要包含在你的演示文稿中的东西。
XSS漏洞很容易显示。刚创建提出的GET变量“Q”值某个页面上的页面,然后点击下面的网址:
http://mysite.com/vulnerable_page.php?q%3D%3Cscript%20type%3D%22javascript%22%3Ealert(document.cookie)%3B%3C%2Fscript%3E
这将导致一个警告框将显示在用户的cookie。
允许上传并且不检查扩展名。观察:
网站A允许图像上载并显示它们。
饼干人上传一个文件,并诱使你相信它的图像文件(通过HTTP mimetypes)。此文件具有PHP扩展名并包含恶意代码。然后他试图看到他的图像文件,因为每个PHP extesioned文件都是由PHP执行的,代码就会运行。他可以做任何apache用户可以做的事情。
哦,男孩,你不会缺乏实例。只是谷歌PHP tutorial和他们每个人都有足够的洞来填补阿尔伯特音乐厅。
结果1,w3schools。他们的第一个例子包括用户输入?
Welcome <?php echo $_POST["fname"]; ?>!<br />
Bzzt。 HTML注入,在每个示例代码中重复使用。他们的第一个数据库查询是什么
$sql="INSERT INTO Persons (FirstName, LastName, Age) VALUES ('$_POST[firstname]','$_POST[lastname]','$_POST[age]')";
Bzzt。 SQL注入,你输了。下一个。
结果2,官方PHP教程。输出变量的第一个例子是什么?
echo $_SERVER['HTTP_USER_AGENT'];
Bzzt。 HTML注入。这不是一个容易被利用的问题,但仍然是在php.net的学习资料中重复出现的错误练习。
结果3,tizag.com。呼应用户输入的第一个例子是什么?
echo "You ordered ". $quantity . " " . $item . ".<br />";
Bzzt。
结果4,freewebmasterhelp.com。太基本包括很多,但仍然管理:
print "Hello $name"; // Welcome to the user
Bzzt。
结果5,learnphp-tutorial.com。
<title><?= $greeting ?> World!</title>
的Bz ...
我可以继续下去。
难怪PHP代码在野外的一般质量是如此灾难性的,当这种可怕的垃圾是编程人员正在学习的东西?
“填补阿尔伯特音乐厅的孔”?好的。 +1 – Franz 2009-11-25 20:57:56
你说得对。看到示例代码非常有趣,它向您展示了如何测试代码以及引入/丢失/遗漏其他漏洞示例...... – Franz 2009-11-25 20:59:06
我最喜欢的是Apress的书“Pro PHP Security”。作者简要介绍了常见的漏洞,并为每个漏洞提供了解决方案(通常是一种非常不合适的解决方案,例如通过SQL转义映射POST)。然后在其他解决其他漏洞的例子中,他又错了,给代码带来了上一章刚才警告我们的漏洞。 XSS章节的例子中甚至存在XSS漏洞,以避免XSS漏洞略有不同。以及使用'eval'和'system'的相当恐怖的部分。 “临”安全的确如此。 – bobince 2009-11-25 21:32:34
CSRF为胜利。
<?php
$newEmail = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
$pdoStatement = $pdoDb->prepare('UPDATE user SET email=:email WHERE ID=:id');
$pdoStatement->execute(array(':email'=>$newEmail, ':id'=>$_SESSION['userId']));
您感觉这类代码安全。一切都很好,您的用户可以在不注入SQL的情况下更改他们的电子邮件,因为您的代码。 但是,想象一下,在您的网站http://siteA/上有此功能,您的一位用户已连接。 在相同的浏览器,他那张http://siteB/,其中一些AJAX这段代码相当于:
<form method="post" action="http://site/updateMyAccount.php">
<p>
<input name="email" value="[email protected]"/>
<input type="submit"/>
</p>
</form>
您的用户刚拿到他的电子邮件改变了没有他知道它。如果你不认为这种攻击是很危险的,ask google about it
为了帮助防止这种攻击,您可以:
另一个是会话劫持。其中一种方法是搭载。 如果您的服务器接受非cookie会话,则可以使用像http://siteA/?PHPSESSID=blabla这样的URL,这意味着您的会话ID是blabla。
攻击者可以开始会话并记下他的会话ID,然后将链接http://siteA/?PHPSESSID=attackerSessionId给予您网站的其他用户。当这些用户关注此链接时,他们将与攻击者共享相同的会话:未记录的会话。所以他们登录。 如果网站没有做任何事情,攻击者和您的用户仍然共享具有相同权限的同一个会话。糟糕的是,如果用户是管理员。
要缓解这种情况,当用户凭据更改(登录和注销,进入管理部分等)时,必须使用session_regenerate_id。
if(strstr($username, '**')) {
$admin = 1;
$username = str_replace('**', '', $username);
$_SESSION['admin'] = 1;
} else {
$admin = 0;
}
HTTP响应拆分攻击
如果Web应用程序存储在cookie的HTTP请求输入假设
<?php setcookie("author",$_GET["authorName"]); ?>
这是很容易如果输入未正确验证“\ r \ n”字符,则会导致HTTP响应分裂攻击。
如果攻击者提交恶意字符串,例如“AuthorName \ r \ nHTTP/1.1 200 OK \ r \ n ..””,那么HTTP响应就会被分割成以下形式的两个响应:
HTTP/1.1 200 OK
...
的Set-Cookie:作者= AUTHORNAME
HTTP/1.1 200 OK ...
明显地,第二响应完全由攻击者控制的,并且可以与任何报头和主体内容,而不是
嗯,我认为这是PHP版本相关。 PHP 5似乎将所有特殊字符编码为百分比编码。 – Tower 2009-11-24 13:09:19
HTTP响应分裂已经解决了相当长的一段时间。 http://php.net/releases/5_1_2.php – 2009-11-24 17:53:10
Email headerinjection attacks是一个更大的痛苦中来构造那么你可能会怀疑这个脖子(除非你必须处理它们)。
这是非常糟糕:
$to = '[email protected]';
$subject = $_POST["subject"];
$message = $_POST["message"];
$headers = "From: ".$_POST["from"];
mail($to,$subject,$message,$headers);
(代码从第二参考上面复制)
基本(常常安全敏感)操作无法正常运行,而不需要程序员使用第二“真正”版本获得非破坏功能。
的最严重的人会在那里实际操作会受到影响:在“==”操作不工作,正如人们所期望的那样,而是需要在“===”操作符来获得真正的平等的比较。
一个大3的PHP论坛程序包是受一个漏洞,它的代码“保持登录”。该cookie将包含用户的ID和他们的密码哈希。 PHP脚本会读取和清理ID,用它来查询用户在数据库中的正确哈希值,然后将其与cookie中的哈希值进行比较,以查看它们是否应该自动登录。
但是,比较结果是与==,所以通过修改cookie,攻击者使用布尔:真的散列“值”,使得散列比较语句无用。因此攻击者可以用任何用户ID来替换而不用密码登录。
允许人们上传的文件,该API是否应该由用户或不能使用。例如,如果程序将某些文件上传到服务器,并且该程序将永远不会上传坏文件,那没问题。
但黑客可以跟踪发送的是什么,在哪里。他可以发现它允许文件上传。
从那里,他可以轻松上传的PHP文件。一旦完成,游戏就结束了。他现在可以访问您的所有数据,并可以销毁或更改他想要的任何内容。
另一个常见的错误是允许泛滥。你应该对你的数据进行一些合理的限制。不要让用户输入无意义的数据。为什么用户名是2MB?这样的事情会让有人泛滥数据库或文件系统变得如此容易,并且由于空间不足而导致系统崩溃。
+1因为它听起来很有趣:) – Johan 2009-11-23 15:43:51