软件安全速成课 你的系统有多脆弱?

日期: 2008-08-24 作者:Bob Breznak翻译:潘春燕 来源:TechTarget中国 英文

  软件安全仍然是一个热门话题。无论是普通百姓,还是《财富》500强公司,谁都听说过由互联网上的病毒和攻击者引起的身份窃取、数据丢失以及一般性的混乱。单单2008年第一季度,就有1474个不同的软件脆弱点报告上来,只有64个发布了相应的解决方案。也就是说解决率大约只有4%。由于软件和系统安全方面议论纷纷,计算机业界似乎完全处于一片混乱之中,这让许多人问道:“我的系统有多脆弱?”


  本文介绍了伍斯特理工学院近期开展的一个安全项目取得的部分成果,还介绍了其他研究。目的在于,通过阐明常见的安全术语,并且提供典型安全漏洞的一些实际例子,表明什么是软件安全。


  本文并不想提供全面的计算机安全教育,而是旨在介绍信息安全这个广阔、并且在不断扩展的领域当中的一些关键话题。


  标准课程不会提到软件脆弱点


  早期在系统安全方面的兴趣实际上激发了我最初对计算机科学的兴趣;从此以后,计算机安全成了我关注的一个焦点。所以不用说,伍斯特理工学院没有开设大学本科生软件或者系统安全课程,这让我觉得多少有点失望。由于没有专门介绍安全的任何正式课程,我和另外两名计算机科学系的学生决定进行独立研究,了解关于软件安全的更多知识。今年年初,我们与伍斯特理工学院的计算机科学系教授 Kathryn Fisler谈论了进行软件安全方面的独立研究项目的事宜。我们打算开一门安全软件工程课程,会最先在08-09学年开课。现在大家也知道了,CS4400x 成为伍斯特理工学院开设的第一门大学本科生计算机科学安全课。


  我们在开设这门课程的过程中,发现了有关软件脆弱点和预防的几个事实,而标准的课程根本不会提到这些事实。我们发现,大部分脆弱点通常是由很小的逻辑错误或者软件开发人员没有发现或没有解决的某种情况引起的。有些脆弱点不是太复杂,因而很容易被黑客利用。只要使用一些简单的资源,比如Web浏览器和文本编辑器,就能找出这些脆弱点。在软件开发团队没有犯错的其他情况下,安全漏洞可能由最终用户对软件配置或者使用不当引起。


  我们得出了这个结论:最大的安全缺陷来自于开发人员错误地以为安全问题会在系统其他地方得到处理――比方说,他们想当然地以为输入数据值得信任。经验教训是,我们一定要认识到确保安全是每个人的职责,而不是别人的职责。


  什么是脆弱点?“可被人利用的漏洞”、“攻击”和“脆弱点”及其他术语通常用于描述合适的软件安全旨在纠正的对象:系统当中让黑客得以获取权限、从而访问信息或者破坏系统的缺陷。Mitre公司对脆弱点的定义是“系统或者网络中的一种状态,这种状态让黑客得以以另一个用户的身份执行命令、访问不该访问的数据、冒充别人,以及/或者发动拒绝服务攻击。”根据这个定义,脆弱性就意味着处于这种状态:攻击者(无论是人,还是像病毒或者间谍软件这些恶意程序)可以访问某个系统中超出其访问权限范围的部分。


  导致出现脆弱点的途径很广,有的很明显,比如使用脆弱的密码或者存储未加保护的私人数据;有的则比较隐密,比如未加检查的输入。




  • 溢出攻击


  这种攻击是最早实施的攻击之一,如今依然很普遍;它正是利用了这一点:开发人员想当然地以为最终用户输入的数据值得信任。大多数程序设计员没有料到用户名字段当中居然会有4万行的文本,或者把连键盘上都没有的模糊字符输入到密码字段当中,所以输入数据从来不会被验证正确无误。这种假设导致了溢出类攻击的出现。比方说,使用本文编辑器,加上对微软PowerPoint文件格式的一些了解,人们就可以手动编辑PowerPoint文件。对PowerPoint文件进行编辑,以便内部字段中拥有超出格式允许范围的更多数据,就会导致微软PowerPoint XP崩溃,然后执行攻击者想要执行的任何程序。在大家熟悉的有关这种脆弱点的一个例子中,内嵌的Windows计算器程序被执行;然而,被执行的程序同样很可能是比较恶意的程序。这只是表明无数这种漏洞的一个例子而已。


  实质上,溢出类攻击中出现的是,放入了太多的数据,结果原始程序设计员以为绰绰有余的空间装不下这么多数据。多出来的数据就溢出到了预期存储区附近的内存中,并且覆盖了与该存储区的原始用途没有关系的数据。程序的其余部分执行时,它就使用刚被覆盖的数据。如果攻击者能够用伪数据(dummy data)填充足够大的空间(即空操作),然后添加一段恶意代码或者一个值,程序就会执行恶意代码或者使用这个新值。这可能会导致许多不同的后果。攻击者也许能够越过登录这一道机制,获得程序的管理员权限。如果受攻击的程序由系统管理员来启动,那么恶意代码随后将作为原始程序的一部分来运行,为攻击者提供了这个系统的管理员权限。溢出漏洞尽管并非总是很明显,但在一些情况下,很容易得到补救:只要在开发应用程序时,使用“安全”库、使用堆栈保护(即StackGuard),或者对输入数据进行检查,确保数据大小和类型正确。这个漏洞系列的工作方式都很相似,不过受影响内存的类型和预期效果会有所不同。




  • 缓冲区溢出攻击


  在缓冲区溢出攻击的情况下,程序的内部值溢出,结果改变了程序的运行方式。在程序的正常运行过程中,函数被调用后,所调用函数的所有参数连同返回位置的指针都放到堆栈中。函数完成操作后,返回指针用来回到原始位置,程序继续运行。利用缓冲区溢出的攻击可以改变这个过程,让攻击者可以执行他们想要执行的任何函数。实现这种攻击的手段就是,只要输入足够多的数据,使用伪数据来覆盖函数参数,并且使用指向不同函数的新返回指针;现在执行的是新函数。




  • SQL注入攻击


  除了溢出漏洞外,SQL注入攻击是依赖开发人员忽视了对输入数据进行测试的另一种攻击。大多数人使用的密码采用字母数字;如果是关注安全的人,所用密码除了字母数字外,还会添加其他键盘符号。考虑到这一点,开发人员可能想允许任何字符都适合作为密码的一部分。这通常没什么问题,只要他们不忘清洁或者检查输入数据。遗憾的是,这种不该出现的情况却频频出现。使用SQL数据库的密码系统(这在许多网站上非常普遍)可能运行这样的查询:


    select * FROM users where ’username’ = ’$USER’ AND ’password’=’$PASS’;


    $USER 和 $PASS将由用户提供的用户名和密码来代替。所以,如果用户输入了‘bob’和‘1234’,随之得到的查询会是这样子:


    select * FROM users where ’username’ = ’bob’ AND ’password’ = ’1234’;


  而来自数据库的返回值将是任何一行行用户名为bob、密码为1234的数据。现在,如果攻击者输入admin和<<’hi’ 或 1=1>>–,那么查询是这样子: 


    select * FROM users where ’username’ = ’admin’ and `password` = ’hi’ OR 1=1–’
  
  请注意:用户输入的引号与原始查询中的第三个引号的匹配情况。现在,数据库会返回用户名为admin的任何行,并且会取消对密码的检查,因为AND ’password’ = ’hi’ OR 1=1命令数据库寻找密码为hi或者1=1的行;而由于1总是1,所以每行都有可能是返回的对象。–这个SQL注释符取消了查询中原先的多余引号,还会取消任何额外检查;所以,就算有额外证书(即密钥卡或者captcha),它也会被忽略。现在,攻击者可以以管理员身份进入系统,甚至不必提供合法密码。只要使用越来越复杂的查询,攻击者就能变更、添加或者查询数据。这让攻击者对于数据库拥有与应用程序同样的权限。


  事实证明,这种脆弱点是针对Web 应用程序最有效的攻击类型之一;随着人们日益依赖 Web 应用程序,这种漏洞的功效只会更加让人望而生畏。好消息是,与溢出类攻击一样,只要清洁输入数据,并且从不立即信任用户输入内容(至少对输入数据),就能在很大程度上预防这种脆弱点。


  即使有了经过最全面测试的、最安全的软件,一旦软件交到了最终用户手里,结果就很难说了。如何配置及部署软件对安全起到的作用如同其他任何安全步骤一样来得重要。




  • 靠不住的默认值


  用户在部署一款新软件时经常会犯错误,其中最严重的一个错误就是,满足于默认值。许多软件会为各种选项定义了默认值,那样用户就能尽快运行起来。虽然有时候这可能很有帮助,比如Web服务器默认设置为标准的Web服务器通信端口,这也会导致许多安全问题。比方说,许多路由器及其他网络设备都随带默认的登录用户名和密码。如果用户不把这些默认值改为独特的值,就会出现问题。搜索“默认的路由器密码”,结果会得到好多网站,它们列出了市面上大多数路由器的默认用户名和密码。如果攻击者企图闯入网络,那么原封不动的用户名、密码、IP 地址及其他默认值如同成了挂在门上的一串钥匙。




  • 不安全的系统


  要是最终用户不太清楚自己添加的软件与系统其他部分的兼容情况,也不太清楚需要另外采取哪些安全措施,就会出现另一个问题。同样以Web搜索为例。搜索“view/index.shtml axis”,会返回未加保护的网络摄像头的列表。在一些情况下,最终用户成功地设置了想让全世界都能看到的网络摄像头。在其他情况下,网络摄像头被添加到了某个网络上,根本没经过配置,以便不让外人看到。现在,凡是能连接互联网的人都能看到这个未加保护的摄像头,这个摄像头还很快就会侵犯隐私。有些书籍和网站专门提供搜索查询,可以返回主人可能根本没有考虑过采取安全保护的数据,如今这些数据成了公开数据。


  我们可以从这些新颖的搜索当中汲取几个教训。第一,默认值天下人都知道,因而如果让默认值原封不动,就要考虑清楚:如果让攻击者知道了默认值,后果会多严重。第二,你应该知道系统的各部分是如何可以访问的,并且考虑这种访问功能是不是合适。第三,记住通过隐藏获得安全(security through obscurity)行不通。不管公众可以获得的信息多么不重要或者多保密,只要通过自动搜索或者通过某种人力,致力于找到这种数据的人总会搞到手。


  总之,随着越来越多的脆弱点每天被发现,这些威胁只是沧海一粟。与这些例子一样,即便不是全部脆弱点,至少大部分脆弱点源于疏忽:无论是开发人员疏忽了采取安全做法,还是最终用户忽视了更改配置。诚然,我给出的例子可能很肤浅,似乎很容易就能避免;但随着一个项目越来越大,出现简单情况未加检查的可能性随之加大。攻击者只要抓住小小的机会,就能对系统构成严重威胁,并且带来永久性破坏。开发人员应当充分了解想当然的假设会带来什么影响,并且测试时要考虑到非正常使用。如果充分了解系统的工作方式,并且假定攻击者可能瞄上自己的产品,开发人员就会定期审查自己的工作,并且必要时发布补丁。


  个人可能说不出软件存在多大的缺陷;尽管世界上没有什么完全安全的系统,但人们可以采用多层安全机制,以便尽量减少脆弱点。强密码、让软件保持更新版本、合理打上补丁,并知道软件每个部分带来的影响,这些都是最终用户增强保护层的小办法。最后,与软件相关的每个人都有责任关注安全,并且设法减少脆弱点。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

电子邮件地址不会被公开。 必填项已用*标注

敬请读者发表评论,本站保留删除与本文无关和不雅评论的权力。

相关推荐