2009-11-23 268 views
21

好的,我和一个朋友正在做一个关于PHP安全的小型演示文稿(虽然我没有真正进入PHP),并且他让我找到一些易受攻击的PHP代码的例子(一个容易出现SQL注入和所有其他类型的攻击)。我想知道是否有任何网站既有好的也有坏的代码,显示你应该怎样编码?易受攻击的PHP代码示例?

基本上我会把它们放到我们的网站上,他会尝试破解它,然后我们将显示“正确”的网站,他会尝试再次破解它。

+0

+1因为它听起来很有趣:) – Johan 2009-11-23 15:43:51

回答

18

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); 
+1

是的,基本上你永远不会相信用户输入,把它当作恶意输入,并用'addslashes()','strip_tags()'或'htmlspecialchars()'将其转义。 – Rob 2009-11-23 13:38:15

+16

'strip_tags'不足以阻止HTML注入(认为属性值注入)。用FILTER_SANITIZE_STRING调用请求数组是一个绝对不应该使用的可怕黑客攻击。相反,通过调用HTML内容中每个字符串的'htmlspecialchars'来避免HTML注入。 – bobince 2009-11-23 13:40:05

+4

你可以用正则表达式解析它... – nickf 2009-11-23 13:42:00

3

一个SQL注入脆弱的登录脚本的另一个例子。不幸的是,这在新程序员中很常见。

$username = $_POST["username"]; 
$password = $_POST["password"]; 
$query = "SELECT username, password 
      FROM users 
      WHERE (username = '{$username}') 
      AND (password = '{$password}')"; 
+7

更不用说以明文存储密码了。 – 2009-11-23 14:25:24

+0

@ Vilx-除非$ _POST [“password”]被散列在客户端;)这是不可靠的,因为客户端生成的散列不能在不向客户端透露salt的情况下被腌制。 – 2015-06-28 07:31:21

+0

@ dwarf015 - 嗯,我认为如果哈希函数本身足够慢,揭示盐不会是一个大问题。但我不是专家,所以不要听我的话。 :) – 2015-06-28 07:50:36

17

一个真正常见的初学者的错误是忘记在重定向后终止脚本执行。

<?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头勿使任何脚本的输出被错过。

+0

也许对我来说,早上还为时过早,但这里的漏洞是什么? – Jakub 2009-11-23 13:39:47

+3

头可以被忽略,并且PHP脚本仍在执行。即使用户未登录,私有函数仍会执行。 – Ikke 2009-11-23 13:41:57

+1

header()重定向可能不会立即生效,或者可能被故意忽略,从而显示下面的私有数据。 – 2009-11-23 13:42:10

4

我见过这样的代码写在了过去:

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添加到网址,然后你就进入了。

+2

这个模拟的功能是'register_globals' – 2009-11-23 13:49:22

+0

啊谢谢!这是我在脑海中阻止的事情之一。恐怖......恐怖...... – nickf 2009-11-23 13:50:21

10

鲍比表

alt text

Bobby Tables是专门描述一个脚本可以通过SQL injection脆弱的各种方式的页面。这不是PHP独有的,但是,SQL注入是许多网页漏洞的原因。

这可能是你想要包含在你的演示文稿中的东西。

0

错误的方式来做模板。

<?php 

    include("header.php"); 
    include($_GET["source"]); //http://www.mysite.com/page.php?source=index.php 
    include("footer.php"); 

?> 
+4

你还应该展示做模板的最佳方式。 – Ikke 2009-11-23 13:43:35

+0

问题出在易受攻击的例子,而不是恰当的例子。 – Sampson 2009-11-23 14:51:03

0

XSS漏洞很容易显示。刚创建提出的GET变量“Q”值某个页面上的页面,然后点击下面的网址:

http://mysite.com/vulnerable_page.php?q%3D%3Cscript%20type%3D%22javascript%22%3Ealert(document.cookie)%3B%3C%2Fscript%3E 

这将导致一个警告框将显示在用户的cookie。

0

允许上传并且不检查扩展名。观察:

网站A允许图像上载并显示它们。

饼干人上传一个文件,并诱使你相信它的图像文件(通过HTTP mimetypes)。此文件具有PHP扩展名并包含恶意代码。然后他试图看到他的图像文件,因为每个PHP extesioned文件都是由PHP执行的,代码就会运行。他可以做任何apache用户可以做的事情。

12

哦,男孩,你不会缺乏实例。只是谷歌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代码在野外的一般质量是如此灾难性的,当这种可怕的垃圾是编程人员正在学习的东西?

+0

“填补阿尔伯特音乐厅的孔”?好的。 +1 – Franz 2009-11-25 20:57:56

+0

你说得对。看到示例代码非常有趣,它向您展示了如何测试代码以及​​引入/丢失/遗漏其他漏洞示例...... – Franz 2009-11-25 20:59:06

+2

我最喜欢的是Apress的书“Pro PHP Security”。作者简要介绍了常见的漏洞,并为每个漏洞提供了解决方案(通常是一种非常不合适的解决方案,例如通过SQL转义映射POST)。然后在其他解决其他漏洞的例子中,他又错了,给代码带来了上一章刚才警告我们的漏洞。 XSS章节的例子中甚至存在XSS漏洞,以避免XSS漏洞略有不同。以及使用'eval'和'system'的相当恐怖的部分。 “临”安全的确如此。 – bobince 2009-11-25 21:32:34

2

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

为了帮助防止这种攻击,您可以:

  • 检查您的用户REFERER(远非完美)
  • 实现一些当你得到你的数据时,你必须使用令牌并检查他们的存在。

另一个是会话劫持。其中一种方法是搭载。 如果您的服务器接受非cookie会话,则可以使用像http://siteA/?PHPSESSID=blabla这样的URL,这意味着您的会话ID是blabla。

攻击者可以开始会话并记下他的会话ID,然后将链接http://siteA/?PHPSESSID=attackerSessionId给予您网站的其他用户。当这些用户关注此链接时,他们将与攻击者共享相同的会话:未记录的会话。所以他们登录。 如果网站没有做任何事情,攻击者和您的用户仍然共享具有相同权限的同一个会话。糟糕的是,如果用户是管理员。

要缓解这种情况,当用户凭据更改(登录和注销,进入管理部分等)时,必须使用session_regenerate_id

3

Today's DailyWTF

if(strstr($username, '**')) { 

    $admin = 1; 
    $username = str_replace('**', '', $username); 
    $_SESSION['admin'] = 1; 

} else { 

    $admin = 0; 

} 
+0

只需在thedailywtf上阅读即可。该代码伤害... – knittl 2009-11-23 14:42:59

+0

...和那个谁称自己是程序员?! – Strae 2009-12-01 11:00:35

3

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 ...

明显地,第二响应完全由攻击者控制的,并且可以与任何报头和主体内容,而不是

+0

嗯,我认为这是PHP版本相关。 PHP 5似乎将所有特殊字符编码为百分比编码。 – Tower 2009-11-24 13:09:19

+2

HTTP响应分裂已经解决了相当长的一段时间。 http://php.net/releases/5_1_2.php – 2009-11-24 17:53:10

2

Email headerinjection attacks是一个更大的痛苦中来构造那么你可能会怀疑这个脖子(除非你必须处理它们)。

这是非常糟糕:

$to = '[email protected]'; 
$subject = $_POST["subject"]; 
$message = $_POST["message"]; 
$headers = "From: ".$_POST["from"]; 
mail($to,$subject,$message,$headers); 

(代码从第二参考上面复制)

0

基本(常常安全敏感)操作无法正常运行,而不需要程序员使用第二“真正”版本获得非破坏功能。

的最严重的人会在那里实际操作会受到影响:在“==”操作不工作,正如人们所期望的那样,而是需要在“===”操作符来获得真正的平等的比较。

一个大3的PHP论坛程序包是受一个漏洞,它的代码“保持登录”。该cookie将包含用户的ID和他们的密码哈希。 PHP脚本会读取和清理ID,用它来查询用户在数据库中的正确哈希值,然后将其与cookie中的哈希值进行比较,以查看它们是否应该自动登录。

但是,比较结果是与==,所以通过修改cookie,攻击者使用布尔:真的散列“值”,使得散列比较语句无用。因此攻击者可以用任何用户ID来替换而不用密码登录。

0

允许人们上传的文件,该API是否应该由用户或不能使用。例如,如果程序将某些文件上传到服务器,并且该程序将永远不会上传坏文件,那没问题。

但黑客可以跟踪发送的是什么,在哪里。他可以发现它允许文件上传。

从那里,他可以轻松上传的PHP文件。一旦完成,游戏就结束了。他现在可以访问您的所有数据,并可以销毁或更改他想要的任何内容。

另一个常见的错误是允许泛滥。你应该对你的数据进行一些合理的限制。不要让用户输入无意义的数据。为什么用户名是2MB?这样的事情会让有人泛滥数据库或文件系统变得如此容易,并且由于空间不足而导致系统崩溃。