写的不怎么好。但可以给新毕业的学生一点启发。 看看别人是怎么做的。 当然安全肯定不止是文章中说的这点,而且老实说写的也很一般。为什么发。因为不知道什么是安全的太多了。怎么做的太少了。呵呵
武大的信息安全专业,到今年已经毕业三届了,不过好像没听说有几个毕业生真正在做安全相关的技术工作的,我那届有两三个在金山做杀毒的。在腾讯的安全部门,就我一个是武大的;还有一个信安的师弟在QQ医生那个项目组,也算是安全相关吧,不过这个组并不归属于我们部门。
在腾讯,安全工作主要是在三个层次上进行的:(1)传统的主机与网络层安全,主要包括网络入侵检测、主机完整性审计、防 DDOS攻击、网络及主机防火墙等等;(2)稍往上的是软件与应用安全,包括客户端软件漏洞挖掘、Web应用漏洞挖掘、通用Fuzzy平台等等;最上面一层的是业务安全,也就是跟“人”(而不是底层技术)相关的了,比如说盗号行为分析、密码保护系统等等。 应用安全大体可以分两端:(1) QQ客户端以及附属组件等客户端软件的安全,其中最大的一个安全胁便是溢出攻击了。06年底到今年,对于控件溢出漏洞的关注是最突出的,不独腾讯,包括微软、雅虎、阿里巴巴、迅雷等等,都爆出过漏洞的报告。(2)以WEB应用为主体的服务器端的安全,目前主要是寻找CGI程序中存在的漏洞,报告并要求业务部门去修改。国外的Web安全研究早在98年就很热了,专业做web安全的,有不少业绩能达数千万美元的公司。国内就不一样了,因为真正研究这个技术的人少,虽然问题一直存在,却因为黑客的关注并不是很多(而且几乎都是在很浅的层次上的),威胁也就变得不那么紧急了。
说实话,我们读书时教的那点信息安全知识,对于日新日异的互联网来说,显得有点学究和过时,用上的机会不多。特别是应用安全方面,业界还没有形成系统的知识和理论体系,可以参考的,是一篇又一篇散落在互联网中的文档。我们是边学习边研究,然后又快速地为眼下的问题找到一个合适的解决方案。这时候,一个老练的程序员是我们最期盼的了,因为一定方案定下来就得着手开发相应的系统,没有一定的编程功底,是没法胜任的。奇怪很,社会上那么多程序员,我们招了一年多,却没有招到几个合适的后台开发。所以我们小组几个开发不得不一直都很忙,有时一个人同时承担两三个项目的开发工作。
在12月26日凌晨,有人利用了百度空间的模板漏洞,专门制作了一个能够自我复制和传播的空间蠕虫,在短短的时间内,就有数千用户的空间受到了感染。百度官方的公告(可以在这里看到:http://hi.baidu.com/%B0%D9%B6%C8%BF%D5%BC% E4/blog/item/0e3433fa69eeb61aa8d3110f.html)说,这个蠕虫含有恶意代码,并传播垃圾消息,百度已经紧急对此漏洞进行了处理,云云。
对于一个互联网公司来说,这个是典型的安全事件。百度的安民公告写得很专业;不过在温情脉脉的公告背后,我想一定是公关部门、安全部门、开发部门等多个部门的联动,紧张对应对这个可能给他们带来×××烦的事件。在腾讯,我们有时候也会面对这样的安全事件。
百度空间所谓的模板漏洞,用专业的术语来说,叫做“跨站脚本注入漏洞”。简单地说,就是用户输入的内容里面包含了网页脚本代码(这对于任何应用来说都不应该允许的,因为它会使得这个网页的行为失去控制,所以必须要执行过滤才能保存到服务器上),而百度的过滤算法出现了漏洞,被别人绕过去了
其实网络上很多基于Web的应用都存在这种漏洞----他们的开发也不是不知道----实在是太普遍了,出现蠕虫只是迟早的事情。也许很多人会奇怪,既然他们知道有问题,为什么不一下子都改掉呢?这里面也许有很多原因;但是我想很重要的一个是:因为它们从来没有出过大事情遭受到×××烦,所以他们就拖着不动它。以我的经验为例:我们在工作中发现不少可能导致服务器被黑掉的WEB漏洞,报告给负责开发的人之后,他们也许会马上修改,也许会跟你扯一下皮(怎么也不相信自己的程序有问题),也许会有这样那样的理由推诿--总的来说,修改程序会增加额外的工作量,但既然这个程序在上面跑了数月甚至数年也没有发生什么事,可见改不改迟点改与早点改并没有太大的关系,我们眼下还有更多重要的事情要忙呢。往往是,安全人员的殷勤并没有受到多大的重视。但是一旦外界爆出了一点什么事情,那就不同了。比如说,有一个CGI程序没有过滤一些敏感的关键词,你输入什么就显示什么,就技术的角度来说是没有任何的安全威胁的。但经过媒体一曝光,就变成了一个紧急而且重要的事情,开发得赶紧修改程序,即使停掉业务也在所不惜,公关部得随时准备应对,上头也会很关注,闹不好一干人士还可能被罚钱。从这里也可以看出,对于所谓的用户价值,一个公司所真正关注的,和他们所声称的,实际上有着微妙的差别的。有时候我们在做推动工作的时候,就不得不借助一两次这样的事件,趁着“上头非常关注”的东风,把安全策略和政策推到其它部门去。
在腾讯在安全有一个非常大的优势,那就是它拥有一个巨大而复杂的网络(数万台的服务器,上百G的流量带宽),各种各样的安全威胁它都遭遇过,这对于每一个做技术的员工来说,都是一个难得的研究与学习的条件。不过仅有技术并不能解决问题,要把企业的安全做好,还得有政策以及领导的支持。对于每年为公司带来数亿实实在在的收入的业务部门来说,安全部门的“贡献”实在不值一提。也无怪乎我们一直都是支持与服务的角色,做什么事情都好像在求着他们。
公司的班车还得等到9点15才有,索性多写一篇吧----写了一天的代码,实在有点闷了。 在我刚加入腾讯的安全部门时,这个部门的力量还是挺少的,而事情则是非常的多,所以很多人都忙得不可开交。虽然一个混乱的环境对员工的长期发展来说是不利的,但是因为事事都是刚开端,我们也就有机会成为某种技术的开创者或者某种制度的制定者,这对我们的成长却又是难得的机会。
在一开始,我被安排做web漏洞的查找,头说我至少要手工测试过1万个页面之后,才有可能对漏洞查找有深刻的了解。但实际上不需要这么多的实践,我就掌握了基本的门路(嗯,实际上这些技巧并不复杂,甚至在彭国军老师的网络安全实验课上就有,只是我那时也没有太留心 ),发现了不少问题。在接二连三地发了N个漏洞报告之后,头说,看来我们问题还是挺严重的,你组织一次培训吧,给开发讲讲这个web安全编程。
我那时是不太情愿的,因为我是个非常害怕在公众前面讲话的人,只要站在讲台上就会紧张、脸红、说不出话来。但是既然是工作要求,我也就不得不硬着头皮来了。我花了两个多星期来准备PPT(第一次发现会熟练地用PowerPoint实在也是一个非常必要的技能),把网上找到的材料,加上自己总结的案例,将近有70页。我把什么都放到PPT上了,因为我怕自己紧张全都忘记了。
培训的报名工作是team leader组织的。到了培训的那天(我记得是去年的10月30日,那入职刚四个月),他告诉我报名的人有90多。等到去了培训教室,我才发现整个教室都坐满了人,还有人站着的。想着里面有同时进来的同事,也有很多可能是做了很多年的开发,我,一个编写的代码加起来没超过3千行的乳臭未干的小孩,却来给他们讲怎样编写安全的程序,实在是可笑。一开始我非常紧张,说话结结巴巴,身体都是抖的,只是照着投影念。但不久到了熟悉的内容之后,我慢慢地忘记了紧张,稍为自在点了。那次没想到一下子讲了2个半小时,出来后快虚脱了。后来听到一个同事说,讲得还不错,收获很大;那场面太壮观了,她来公司后还没有见过那么大规模人数的培训。我想自己的技术实在是比较肤浅的,但对于不同部门的人来说,我这点肤浅的知识就是我异于他们的优势了(在分工越来越细的今天,专业的差别可能就会形成这种“隔行如隔山”的效果)。这时候的培训,并不是展现个人的高超技术,而更重要的是,普及某种知识和技能而已。
后来这种安全培训成为了一种每月例行的工作。虽然每个月都讲相同的内容想起来就觉得是一件很乏味的事情,但每次的听众都不同,而你也可以在讲的过程中不断地进步,比如说,深化内容,讲得更有趣更生动。照组内另一位同事所说,要达到这样的一种境界:一份只有寥寥数字的提纲的PPT,能讲到可长即长,可短即短,随手拈来,那才是水平。
在第一篇文章里,芒果说到应用安全的两大块内容:客户端的安全和Web服务的安全。就技术方面,从本质上来说,我们当下所做的事情,其实是一种特殊形式的软件测试而已。也许大家还记得软件工程书上说的什么白盒啊黑盒啊,什么测试用例啊,这些概念也能在安全测试中用到。相对于一般的功能测试与性能测试,安全测试有一个专门的称谓:渗透测试,听起来就像我们正在一个看不见的战场上向敌方阵地渗透进去一样,无形中就增添了一份神秘感。
不过说到底,渗透测试还是某种形式的测试而已。一般的测试是看软件或系统是否实现了既定的功能,它运行起来是否与预期的一致,它跑得够不够快。在具体做的时候,一般都有专业的软件来做这些事情:输入一些数据,看输出来是否是正常行为所预期的数据。渗透测试呢,却是看你的软件或系统在完成正常的功能之外,还能不能做一些理应不被允许的事情。具体做的时候,也是输入一些数据,但看输出来是否是异常行为所预期的数据。
举个例子来说,QQ的自定义表情包功能,普通的测试会准备一堆这些表情包,打开自定义表情的菜单,调出一个对话框,然后选择一个表情包,按下导入按钮,再在聊天窗口中使用刚才导入的表情包中的一个表情。在这个过程中,测试员只需验证表情包是否导入成功、导入进去的表情包内容与源包是否一致,最后能否在聊天中正常使用。而渗透测试呢,基本上也是这样的过程,但是关注点有些差异。在这个例子里,我们关心这个操作的发起权是否完全掌握在正常用户手里(例如:是否可以通过网页调用的方式发起这个操作,就像弹出一个“与我交谈”的临时对话框一样);在与操作系统交互时,是否能够逾越既定的限制(比如说,释放这个表情包的时候,它能不能够跳出用户所指定的保存目录);在解析非正常的数据文件时,程序会不会崩溃;诸如此类。测试的时候呢,也是有一定的方法依循的,比如说路径操作,一般就是在路径名中加入..\(或者是../);文件解析呢,就是拿一些非正常的文件让它去读取----在这里,非正常的意思是很直观的,就是除了正常格式以外的所有文件,比如说新建一个txt,在里面胡乱输入一段文字,保存后把后缀名改为.eip,就形成了一个“非正常的”表情包文件。
一般来说,软件或者应用的正常行为都是一个很小的集合,我们通过有限的用例就能够遍历所有的可能性从而验证它是否实现了预期的功能。这样很容易就能想到,软件的非正常行为则可能是一个巨大的充满了未知数的集合,要进行测试则是非常困难的:首先,我们要测试和验证什么,这是不甚明确的;其次,即使是验证一个可能的问题,需要的测试用例可能是数量巨大的。想一下表情包的例子:一个测试员要证明它能正常解析,他只需准备数百个不同大小不同内容的正常表情包,全部跑一遍,如果每一个都正确导入了,他就可以声明这个功能是正常的,它通过了测试。相反,一个安全测试员如果要想验证,在非正常的文件格式下,这个程序会崩溃,那么他就得准备几乎是天文数字的表情包,用一台专门的机器连续跑上几天几夜(是的,我们客户端测试小组就是这样做的),看它会不会死掉。想想看,即使只用4个字节,就能构造出43亿个不同内容的文件,要想找出那些会使程序死掉的文件格式,无异于海里寻针。一般在实际操作的时候,也只是选取一些特定的排列格式(比如说全0或者全是0xff或者0与0xff相间)。
这样的测试我们有时候也叫做Fuzz。文件格式的Fuzz只是一个方面,网络协议的Fuzz是另一个方面,简单地说就是动态改变一个数据包的内容,看接收方的程序会不会死掉或者崩溃。可以想象,这并不比文件格式Fuzz好做多少。在业界,关于Fuzz已经有不少参考资料,也有各种各样的Fuzz工具,我们的工作,也就是参考这些已有的资料,以及各样的工具平台,然后自己摸索来发现问题的,负责这一块的,也都是06、07年毕业的学生。由此可见,做安全研究,其实也没有太大的门槛的。只不过在学校里太闭塞,又没有好的指引,所以觉得渺茫而已。大家有兴趣的,可以下载这些工具来试着玩玩- ---找个流行的IM工具(不独是QQ,MSN啊,Yahoo通啊),没事的时候就让Fuzz工具来跑跑,兴许能发现一两个0day(所谓的0day就是外界没有公开的漏洞),然后用来做一些有趣的事情,比如说,给一个看着不爽的家伙发一个消息,他的IM就立马崩溃……
嗯,趁着兴头再写一篇吧,反正明天是放假,一年里有两三个晚上睡得晚一点也不算太过份~~
上一篇讲到在客户端安全方面,我们可以做些什么事情,又是怎么做的。这一篇就讲一下另一块,在web安全这方面,我们在做的,又是什么样的事情,使用的是什么样的技术。 让我先把时间回退到大学时代:那时候听到很多故事,什么中美黑客大战啦,大陆与台湾的黑客大战啦,白宫的官方网站被黑啦,谁家的小孩因为入侵什么重要的系统被抓啦,诸如此类的非常多,那时觉得很神奇,也对信息安全这个专业充满幻想,以为学到最后,我们也能如传说中的黑客那样,在网络上自由自在地游弋。不过幻想始终是幻想,直到毕业了我也不知道在实际中我怎样才能“黑”掉一台服务器。虽然幻想没有实现,不过我也知道不要把传说太当真。不过在大三的时候,发生了一件让我难以接受的事情:同班同学告诉我,我们学院网站的数据库被别的学校的一个学生用什么方法下载了!这个消息让我非常沮丧:一是我们计算机学院的网站(很多人都会有一种看法,即某个机构的网站在一定程度上代表这个机构的计算水平)竟然这样不堪一击;二是我们一直引以为傲的信息安全,所教导的学生,却无法做到一件一个不太入流的大学里的一个普通学生所能做到的事情,这很让我对自己所受的教育产生怀疑。
直到参加工作一段时间之后,当初的怀疑与沮丧才消除:从根本上来说,怎样攻占站点其实只是一种实际的技术而已,这种技术和学习某一门编程语言一样,是可以通过自学与实践很快就掌握的,会与不会只是一个谁先学谁后学的问题。但更重要的,却是解决问题的思维方式与方法论,而这则会决定一个人以后能在多大的天地做出贡献。
有点罗嗦了,呵呵。把主题集中回web安全这里:web安全往具体里说也包括很多,渗透测试是其中很重要的一个方面。我在腾讯一年半的时间里,做的都是这个事情。从本质上来说,web渗透测试就是一种黑盒测试,但比起客户端软件来说,做起来就容易很多。这是由web应用的特点所决定的:传统上,每一个web程序都是一个功能单一、体积小巧的独立程序,输入有限,输出有限,能访问的资源也有限。这样无论是普通的功能与性能测试,还是安全渗透测试,都比较容易进行。
总的来说,web渗透测试就是给目标程序提交各种“变态”的参数,看这个程序能不能访问到正常情况下不允许访问的数据、文件,是否输出了一些不×××全的内容到返回页面上。所需的全部家当呢,就是一个浏览器了,可能还得加上一个可以查看HTTP请求的工具。
比如说,我们查看山水的一篇帖子,是在浏览器地址栏里面输入这样形式的地址来进行的:
在这里,bbsrecon.php就是一个web程序,id就是这个程序的输入参数,2525就是一个具体的输入数据实例。我们可以猜测,这个web程序以这个id为索引,去后台数据库里查找一条匹配的记录,然后把内容复制到一个网页框架里,再返回来给我们的浏览器;也有可能,论坛的帖子是以文件形式存放的,这个web程序用这个id形成一个具体的文件名,然后
首先,这个程序是一个黑盒子,我是不知道它里面的具体实现的。但是我可以通过一些固定的模式来测试去得到足够的信息来猜测它是怎么做的。这样的模式是通用而且非常简单的:我在看到“?id=2525”这样形式的链接地址时,就会习惯地在参数后面多加一个引号(或者是双引号),再按下回车让浏览器发送这样的一个请求:
[url]http://bbs.whu.edu.cn/bbsrecon.php?id=2525'[/url] 为什么是单双引号呢?因为这个符号可以构成一个很奇妙的测试用例:(1)原本是一串数字的2525,现在因为末尾的引号而变成了一个不合法的数字,程序怎样处理一个原本期望是数字串但实际却含有非数字字符的输入呢?(2)对于使用数据来做存储的应用来说,它极有可能利用输入参数来构造一个SQL语句传给后台数据库,才能最终完成的请求,我们可以猜想这个语句具有这样的形式: select * from article where aid=2525 。而我们额外添加的引号有可能原封不动地添加到这个SQL语句的末尾----而这如果传到DB中去的话,势必会引起一个语法错误,这时的web程序,又是怎么应对呢?(3)如果使用文件来做存储,它可能会把id=2525映射成一个实际的路径:/data/bbs/article_2525.html,类似这样的形式,那么多余的一个引号如果也原样传进来,最后构成的一个路径十有八九是不存在的文件路径,读取文件失败,程序又会怎样响应呢?
在考虑不周的程序中,非正常的输入会导致程序运行失败(通常返回一个“内部服务器错误”的页面),有些程序员会把错误信息打印出来,比如说类型不对啊,SQL语句非法啊,读取什么文件失败啊----在这一步,程序已经开口告诉我们很多信息了。在网上有非常多的站点都存在这样的问题的,不信你可以试试(只需简单地在地址栏的参数后面加一个引号)。
也有可能程序对错误进行了处理,在操作失败的时候输出一个提示信息(比如说,对不起,系统繁忙之类的),从而掩盖了底层的出错信息。但是如果程序没有对输入进行过滤的话,我们还是有办法知道的:因为一个失败的操作所得到的结果和一个成功的操作所得到的结果是不一样的,这种不一样必然又会反映到最终返回的页面上。我们要做的,就是用其它的的例子继续测试,直到我们能够确认它有问题或者没有问题为止,而这些用例的数量是很有限的,可以在数分钟内就能测试完毕。
比如说,对于文件类型的存储,要确认是否有问题的话,就在参数后面有序地添加../序列(我们知道这会返回到上一层的目录),并指向一个可能的文件(比如windows的c:/boot.ini,linux的/etc/passwd),一直到5~6层(再高也不太可能了),如果有漏洞的话,它就会在某一层成功,打开你所指定的文件,并把这个文件的内容读取出来返回到你的浏览器上。这就是文件型漏洞的测试方法。而对于SQL型呢,你就在脑海中想着一个正常的SQL语句,后面跟着你输入的参数,你怎样在这个SQL语句中“插入”其它的语句来控制它呢?用“ and 1=1 ”和“ and 1=2 ”来对比一下如何?熟悉SQL的同学会明白,and 1=1是一个为真的条件,附加在原SQL语句后对查询结果无影响,但and 1=2是一个为假的条件,附在原SQL语句后却会使得整个查询返回一个空集。DB有没有数据给web程序,是可以在浏览器上一目了然地看到的,所以我们就能知道我们能否通过URL参数来控制后台DB。这种漏洞就是SQL注入漏洞,网上很多入侵的案例,都是通过这种漏洞来进行的。大家想验证一下的,也可以在 google中找些来试下(比如说:在google中查找 inurl:id inurl:php就可以找到不少xxx.php?id=yyy形式的链接)。这种漏洞还是非常普遍的。
至于另外一种比较典型的漏洞跨站脚本漏洞,就是在参数后面加入一段HTML的代码,比如说这样的形式id=2525< script>alert('xss')</script>,看最后返回来的页面中有没有包含你输入的这段HTML代码,如果有的话,就是有跨站漏洞了。对于论坛、发帖等形式的也一样,在输入中包含HTML代码,保存,如果最后这段代码能够原封不动地显示出来,那就是有这个问题了(也就意味着,你也可以制造一只类似于百度蠕虫一样的跨站蠕虫了)。
嗯,基本上,web测试的原理就这样,不过要做到纯熟,还是需要很多的练习,并且要多看一些有深度的文档,这样才有进步。