联系博主


你的名字:
Email:
建议:

Web安全基础知识小结

编辑时间:2016-05-24      赞:3       踩:1

导言:

        这一片文章主要会对web安全的一些基础知识进行总结,其中包括一些常见的攻击类型及其防御,例如“大名鼎鼎”(臭名昭著)的SQL注入,XSS攻击及CSRF攻击等等。当然由于篇幅有限,这里并不可能把所有的攻击类型及其防护方法都列举出来,所以我也只能简单地介绍以下最常见的攻击手段及其防护,如有偏颇或需要校正的地方,请大牛们不吝赐教。虽然Web安全方面的内容涉及方方面面的知识,但是例子都是用PHP列举的,并且,这也是web后端开发人员的必备知识,所以就把它放在PHP栏目中了。

正文:

       在对Web安全方面的知识前先让我吐槽一下吧。当我用Laravel做完了商城的小项目后,在回来看自己的原生代码及文件管理,感觉真是糟糕透顶啊!漏洞百出的代码,混乱不堪的项目管理,“参差不齐”的接口,简直不能忍啊。可毕竟是“亲生”的,都怪自己当初太年轻,太冲动了。
       当我意识到这些问题的时候,我便在重写后台管理的代码时顺便把各个文件之间的关系给理了一理。然而由于问题太多,我也只能把各个项目文件的关系给理清,方面以后改代码时寻找某个功能模块的文件。然而关于漏洞和接口的问题还是没有解决。
       于是,趁着这次恶补web安全的知识机会,我便可以把代码的漏洞问题给解决掉。至于接口嘛!等下次有时间再来规范规范吧。这篇文件有点长,大家如果只想阅读其中一部分的内容,可以按Ctrl+F“召唤”中浏览器自带的搜索框来搜索相关内容。废话不(说了)多(这么)说(多),我们切入正题吧。
       一般来说,我们接触的网站能分为两大类,一类为静态网站,一类为动态网站。我们在日常生活中接触到的大部分网站都是动态网站,纯静态网站已经很少见到了。为什么这么说呢?这要从静态网站和动态网站的定义说起。动态网站并不是说网站有各种各样的动态效果(如Flash,JS的动态效果,或CSS3的动画效果)就是动态网站,而是说网站的前端与后端有数据交互,能根据访问者的动作而动态呈现相关内容,比如说某个网站用户,登陆前和登陆后所能看到的内容的区别。简单来说,动态网站的页面内容是从动态数据库中提取的,而静态网站的页面内容是一开始便已经写好的,无需从数据库中提取任何内容。
       由于静态网站无需和后台服务器进行动态数据交互,故其漏洞相对较少,不易受攻击。然而,它却并不容易维护。为了不断更新网页内容,你必须不断地重复制作HTML文档,随着网站内容和信息量的日益扩增,你就会感到工作量大得出乎想象。在我浅薄的认识中,静态网站一般都是钓鱼网站。动态网站的内容由于经常需要和服务器进行信息交互,所以它的漏洞相对来说就更多一点。但是安全措施做足了,其实也无须过多的关心。
       Web的安全防护涉及到网站开发中方方面面的知识,如前端三剑客(HTML,CSS,JavaScript)的相关知识,Linux操作系统的基础知识,数据库的查询,后台服务器语言的基础知识等等。如果你对上面这些知识有些陌生,那么你应该赶紧复习复习,不然你会无法理解某些攻击手段的实施原理。以下为常见攻击手段。
(一)SQL注入(SQL Injection)
       先从SQL注入讲起吧。SQL注入:利用现有应用程序,攻击者将精心构造的SQL语句注入到后台数据库,并使得数据库引擎成功执行,这是SQL注入的标准释义。那么攻击者是如何把SQL语句注入到后台服务器的呢?答案就是,需要用户输入的或者是用户可以输入的会被服务器构造成SQL语句的一部分的一切地方,如用户名的输入,或地址栏。此话怎讲?举个例子就容易明白了。(以PHP为例)
              $Sql=”select  id,name,password  from  user  where name=’ ”.$_GET[‘name’].” ‘ and password =’ “. $_GET[‘password].” ‘ “;
       这个说起来语句乍一看很正常,我刚开始学PHP的SQL扩展也是这样构造SQL语句的。然而,由于它没有对用户输入进行过滤,就给黑客可乘之机。黑客可以把上面的SQL语句构造成以下这样:
       令$_GET[‘name’]=’hello’, $_GET[‘password ’]=world’ or 1=’1(用户输入的两个单引号使sql语句中的单引号闭合,从而使其执行) ,把这两个变量的内容代入上面的SQL语句可得:
              $Sql=”select  id,name,password  from  user  where name=’hello‘ and password =’world‘ or 1=1 “;
       于是,黑客的目的便达到了。即使密码是错误的,PHP也能从数据库中提取关于hello用户的信息。如果程序员没有对数据库中的密码与用户输入的密码再次进行匹配,仅凭SQL语句查询结果的真假值来判断用户输入的密码,那么黑客便可冒充hello用户进行登录。
       这便是SQL注入的一个简单例子。当然,这只是最简单的SQL注入,但这已经足够说明SQL注入的原理了。至于黑客如何判断是否需要闭合单引号,那便是利用SQL注入攻击网站的问题了,这里揭过不提。那么SQL注入的危害仅限于冒充用户登录吗?显然不是,SQL注入的主要危害还包括:
       1、未经授权状况下操作数据库中的数据
       2、恶意篡改网页内容
       3、私自添加系统帐号或者是数据库使用者帐号
       4、网页挂木马
       那该如何防护SQL注入呢?常见的SQL注入防范手段有:
       1、对用户的输入进行过滤,把含有SQL关键字的语句过滤掉,如select,insert,update等等。当然,这个过滤的前提是不要把安全的内容也过滤,从而造成误操作,影响用户体验。
       2、利用后端语言自带的安全函数,以PHP程序为例,有以下安全函数:addslashes,mysql_real_escape_string等。
       3、利用成熟的商业软件,商业解决方案进行防护
       4、网站上线后,不要把SQL语句的报错信息显示在页面上
       5、尽量使用数据库的预处理语句进行数据库的查询。(如PHP中的PDO扩展)
(二)跨站脚本攻击(Cross-Site-Scripting,XSS)
       为什么不叫CSS攻击而叫XSS攻击呢?这主要是为了区别于cascading style sheets层叠样式表(CSS),因此缩写为XSS。
       XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中,比如这些代码包括HTML代码和客户端脚本(JavaScript脚本)-----摘自百度百科。
       常见的XSS攻击类型有以下两种,一种是反射型(DOM Based XSS漏洞),另一种是存储型(Stored XSS漏洞)。由于篇幅原因我只会粗略的介绍以下这两种攻击,并不会展开细讲,有兴趣可以看一下这篇文章→http://blog.csdn.net/ghsau/article/details/17027893
① 反射型漏洞
       反射型漏洞一般会被攻击者利用,将被攻击的网站URL构造为虚假的URL,并通过社工学的手段(社会工程学,黑客常用的手段,有兴趣可以上网浏览相关知识)诱使受害者点击。
光说太抽象了,还是举例说明吧。
       假设被攻击的网站的URL为“www.test.com?uid=1”,这是一个可信的连接,然而这个网站存在反射型漏洞,即uid的内容没经过滤便直接用JavaScript呈现在页面中。而且很不幸地被一些别有用心的人发现了。于是,这个别有用心的人就利用这个漏洞后构造了以下URL:“www.test.com?uid=1 ;alert(‘hello world!’) ;”,并将其用邮件的方式发给用户,诱使用户点击,当用户一点击,脚本便生效了(弹出警告框)。
       有人说这么明显有问题的代码用户怎么会点击呢?首先,大部分用户都是没有Web开发相关知识的,所以他们可能只根据域名来判断链接是否可信。其次,这个别有用心的人很聪明,为了防止被别人发现问题,他对uid的参数部分进行了转码,让人无法轻易察觉。
       以上代码仅仅弹出了一个警告框,如果攻击者的代码是把document.cookie(这个变量存放用户的cookie信息)的内容上传至某个服务器呢?那用户的cookie信息不就发生了泄漏?
由上述信息可知,这种漏洞的受害者往往是少数人,特别是随着网络安全防范知识的普及,越来越多的人已经不会点击不确定的网络链接了。
② 存储型漏洞
       顾名思义,存储型漏洞是一种把攻击代码上传至服务器的漏洞。这种漏洞的危害性往往比反射型漏洞大得多。那攻击者是如何把代码上传至服务器的呢?一般来说,用户的评论区域,用户发表文章的区域,用户提交建议的区域都属于“重灾区”。
       例如,某个粗心的程序员忘记对用户提交的评论进行过滤和转码便提交给数据库了。这个漏洞被某个图谋不轨的攻击者发现了。于是,他提交了这样的评论“<script>alert(“hello world”)<script>”。于是,每个展现该评论的页面都会弹出警告框。如果这一段为恶意代码,那么其危害可想而知。
       由于攻击代码是存储在数据库上的,所以相对于反射型漏洞其危害范围更广,持久性更强。XSS攻击中常见的两种类型都说过了,下面就对其做个总结吧。
       XSS的常见危害有:
       1. 钓鱼攻击
       2. 窃取用户隐私
       3. 获取管理员权限,对数据进行非法操作(存储型漏洞)
等等。
       既然XSS的危害如此大,那该如何防范呢?归根结底,只有一点。不要相信用户输入,坚决对用户输入进行过滤,转码等处理(如用PHP中的htmlspecialchars,addslash,htmlentities,strip_tags等函数对输入进行处理)。虽然只有一点,但要做好这一点却很难。这种操作往往用中间件处理会方便很多。
(三)跨站请求伪造(Cross-site Request Forgery,CSRF)
     用过Laravel或其他框架的人对其应该并不陌生,因为每个表单都要有token才能提交成功,而token便是防范CSRF攻击的最常用的手段。那么什么是跨站请求伪造呢?跨站请求伪造即恶意网站盗用用户身份信息,进行一系列未经用户授权的操作的一种攻击方式。XSS和CSRF都属于前端攻击,那么这两者有什么区别呢?XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。这么说有点拗口,这次就不举例说明了,来个看图说话吧。
 
              图①,图片源自:http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html,原作者为hyddd(这是一篇关于CSRF的很好的文章,想详细了解CSRF的人可以去看看)
       为了(偷)把(懒)好文章分享给大家,我在借用一下别人的例子吧。
       银行网站A,它以GET请求来完成银行转账的操作,如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000
       危险网站B,它里面有一段HTML的代码如下:
              <img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
       首先,你登录了银行网站A,然后访问危险网站B,噢,这时你会发现你的银行账户少了1000块......
       为什么会这样呢?原因是银行网站A违反了HTTP规范,使用GET请求更新资源。在访问危险网站B的之前,你已经登录了银行网站A,而B中的<img>以GET的方式请求第三方资源(这里的第三方就是指银行网站了,原本这是一个合法的请求,但这里被不法分子利用了),所以你的浏览器会带上你的银行网站A的Cookie发出Get请求,去获取资源“http://www.mybank.com/Transfer.php?toBankId=11&money=1000”,结果银行网站服务器收到请求后,认为这是一个更新资源操作(转账操作),所以就立刻进行转账操作......(以上例子及其解析均与图①源于同一个网站)
       通过图文结合的方式,相信大家对CSRF攻击有了初步的了解。从上面例子相信大家也能看出CSRF巨大的危害了。至于CSRF的防范手段呢?各位看官且听我慢慢道来。
       常用的CSRF攻击防范收端有以下三种:
       1.验证 HTTP Referer 字段
       2.在请求信息中添加 token 并验证(重要)
       3.在 HTTP 头中自定义属性并验证
       其中用token验证的方法是一个安全性较高且被广泛应用的防御方法。所以这里就只谈用token验证的方法来防御CSRF的攻击。不过我还是稍微提一下其他两种防御手段吧。验证 HTTP Referer 字段,是通过浏览器发送的头信息中的Referer字段(用于记录该 HTTP 请求的来源地址)来验证来源站是否为可信任的站点。但是这个字段能被修改(特别是兼容旧版本浏览器的网站),并且用户有可能禁用该字段,所以这个方法虽然简单快捷,但通用性不高。
       至于在 HTTP 头中自定义属性并验证这个方法,其具体实现是通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中来进行验证的。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。而已这种方法的缺点也很明显,对于以前遗留下来的没有进行csrf代码来说,把所有的请求改为XMLHttpRequest,这无异于重写整个网站。
       下面终于要提到重点了。什么是token呢?token的在中文中是令牌的意思,在请求信息中添加token的意思便是在每个合法请求中添加可以通过后台验证的令牌。这个令牌往往是由后台生成并存放在session中的随机字符串。当用户发送请求的时候,服务器首先验证是否存在token这个值。不存在,直接返回;存在,便从session中取出相应的值并对其进行验证。每次验证完后要销毁这个token,并生成新的token。不然攻击者只需想办法获取一次token值,便可用此token进行多次请求。极大地降低了token的安全性。具体的实现程序我就不提了,大家可以上网搜索,也可以参照我推荐的关于csrf的文章。
四)文件上传漏洞
       一般来说,文件上传漏洞是指文件用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。这种攻击方式是最为直接和有效的,有时候几乎没有什么技术门槛。从以上描述可知,文件上传漏洞能被攻击者利用是有条件的。首先,攻击者需要知道文件上传的所在路径,及其文件名。其次,存放该文件的文件夹能被外部访问。最后,要确保服务器会正确解析上传的文件,例如攻击者上传的是PHP文件,但却被解析为图片文件,那么该攻击脚本也无法发挥作用。正是因为有这些条件,我们才能设置多重屏障来防范攻击者的攻击。
         在实际编程中,安全防范意识不足的程序员因为对于文件的上传只设置一两道简简单单屏障便可“保平安”了。恕不知,其实那些屏障在某些“有心人”里形同虚设。在这里,我便说两个攻击者常用的绕过文件上传合法性检查屏障的手段。
① 00截断
       有的程序员为了贪图一时方便,便只是在用户上传的文件名末尾加上合法的后缀名(如.jpg,.png等等)来构造新的文件名,然后存放起来。然而,这却给了攻击者可乘之机。接下来还是举例说明吧。以PHP为例,
              $newFileName= $_POST[‘picturename'] . ’.jpg’;
              move_uploaded_file($_FILES["pictures"]["tmp_name"] , ’/images/’. $newFileName);
       上述两行代码的意思是用上传者上传的文件的文件名加一个jpg的后缀名构成新的文件名,然后便把该文件移动到指定目录。这段代码看上去没啥问题,因为所有文件都是以jpg为后缀名的,故该目录的所有文件也只能以图片格式去解析。然而,若是攻击者在文件名后加‘\0x00’这个后缀,那么jpg这个后缀就会被截断。虽然,在windows下面文件不能出现先‘\’这样的特殊字符,但是,攻击者可以通过代理抓包工具来修改文件名,从而达到添加“\0x00”的目的。
如果不想安装抓包工具,但又想亲自动手体验一下00截断,看其是否真的能把后缀给截断。
<html>
       <form action="http://localhost/test.php" method='post' enctype="multipart/form-data">
              <input type="hidden" name="MAX_FILE_SIZE" value=100000000>
              <input type="file" name='picture' value="picture" >
              <INPUT  TYPE='SUBMIT'  NAME='dosubmit'>
       </form>
</html>
<?php
       $tmpfile = $_FILES['picture']['tmp_name'];
       $filename=$_FILES['picture']['name'] . "x00" . '.jpg';
       if( move_uploaded_file($tmpfile,"./".$filename)){
              return $filename;
       }else{
              return false;
       }
       这样你上传的文件的文件名就能保持原样(哪怕是php脚本),而忽略JPG这个后缀了。我是在WampServer  2.5版本的集成PHP开发环境下测试的,其中Apache版本为2.4.9,PHP的版本为5.5.12,MySQL的版本为5.6.17。注意\0x00要用双引号,若是单引号那么它会照原样输出这个字符串,并不会对其进行转义。想详细了解PHP中00截断漏洞的知识,可以看一下下面这篇文章→http://bobao.360.cn/news/detail/1383.html
② 服务器解析漏洞
       Apache解释漏洞:若按照文件后缀名无法用相应的方式去解析(如test.aaaa),那么它会解析为php,这是一个上传文件的漏洞,黑客可以把PHP文件的后缀名改为一个无法解析的后缀名,绕过文件上传检查,从而让服务器将其按PHP的方式执行。
       当然其他服务器也有解析漏洞,这里就不细讲了。接下来,我们就讲一下如何对文件上传漏洞进行防护吧。
       1.上传文件的文件名必须全部由服务器自动生成,前缀最好用复杂一点的随机字符串组成,而后缀可根据实际情况制定。这也是我们从网上下载的图片的图片名往往都是一串很长的随机字符串的原因。
       2. 要把存放上传文件的目录的执行权限给关掉,防止黑客通过层层防御而执行他自己上传的恶意脚本
       3.文件的后缀名也所需要检查过滤,虽然它能被绕过,但它确实能将一部分的攻击过滤,并且能防止一些用户的误操作。
       呼~~~~~讲到这里,总算可以告一段落了。不知道有没有人真的有耐心从头看到尾呢?如果有,那就点个赞呗!当然,如果发现我有某些地方讲错了,那么可以直接告诉我,让我可以少误导一些人。下面我就对各种攻击手段的防范措施做个小结吧,毕竟这才我写这篇文章的真正目的。
       1.永远不要相信用户的输入,一定要对用户的输入或者是可以由用户输入的内容(如地址栏的内容,上传文件的文件名等等)进行检查过滤。这可谓是Web安全领域里面的共识。以前我总是在查阅Web开发资料的时候看到这句话,当时由于安全意识不强,所以对这句话并没有多大的感触。随着我对web安全方面的接触越来越多,我对这句话的感触可谓越来越深。相信能从头看到尾的同学对此也会有一定的体会。
       2.要对Apache的权限做好控制,不应允许它读取一些敏感文件。对此,网上有许多限制Apache权限的方法,我就不展开细讲了。
       3.如果可以,最好禁用后端语言的一些敏感函数。以PHP为例,有system,exec,exec_shell等等(可以在PHP的配置文件中对其进行限制)。
       4.做好MySQL的权限管理,不应把高权限的用户直接赋给普通的页面链接。例如,有的页面只需要对数据库进行select操作,那么就不应该把拥有insert,update和create等权限的用户直接交由这些页面进行连接。有的页面也往往只需要对一个库进行操作,那么就不必把其他库的操作权限赋给这个页面的数据库连接(这样做可以防止攻击者跨库操作)
       5.对一些敏感请求进行token认证。
       Web安全防护是一门非常高深的学问,我讲的这些知识不过是Web安全防护中的基础知识,有志于此的人可以继续深入学习。最后,请大家高抬贵手,放过我这个不堪一击的小网站吧。如果发现漏洞了,可以直接联系我,对此我会不胜感激。最后的最后,我还是把一些我觉得关于Web安全防护的好文章放上来给大家阅读吧,相信大家能从这些文章中学习到更多更详细的内容。

关于CSRF:
http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html
http://www.ibm.com/developerworks/cn/web/1102_niugang_csrf/index.html#icomments

关于XSS:
http://www.cnblogs.com/bangerlee/archive/2013/04/06/3002142.html

PHP文件上传漏洞:
http://bobao.360.cn/news/detail/1383.html

转载请注明:
    本文转载自:www.kantblog.com/blog/WebDevelop/5

Kant©2016 All rights reserved 粤ICP备16014517号