0%

常见Web攻击与应对方式

总结和概括一下常见的Web安全注意点

XSS攻击

XSS(Cross Site Script)攻击,是攻击者想Web页面提交恶意脚本,当用户浏览页面的时候就会触发脚本。

攻击思路

  1. 盗取Cookie,模拟用户登录。用document.cookie获取cookie然后发送给某个后台服务器
  2. 弹出”Flash插件已过期”的提示,欺骗用户去钓鱼页下载被种下木马的插件

检测方式

一般的检测方式是检测弹窗,看能否执行alert(1)

  • 对提交后展示的文本,输入<script>alert(1)</script>
  • 提交插入图片的连接,输入javascript:alert(1),图片元素会被渲染成<img src="javascript:alert(1)">

预防方式

  • 后端对<>使用&lt;&gt对输入内容转义,或者node用encodeURI对文本转义
  • 使用React可以避免XSS攻击,只有明确需要嵌入html代码的时候,使用<span dangerouslySetInnerHTML={{"__html":data}}></span>

SQL注入

SQL注入是通过构造输入,改变服务端的SQL执行逻辑。例一条登录判断的SQL:select * from user where username = '" + username + "' and password = '" + password + "'"。对于任何用户名,构造以下输入作为密码:

  • ' or '1'='1
  • ' or '1'='1' --
  • ' or '1'='1' /*

实际上最终执行的SQL是select * from user where username = 'xxx' and password = '' or '1'='1',这条一定可以查找到用户实现登录。

攻击思路

  • 构造多条语句:' or '1'='1'; DROP TABLE user; --,删库。也可用来修改用户密码,创建新用户
  • UDF反弹Shell,对服务器提权

检测方式

单引号检测,一般老式php,asp项目存在SQL注入点的时候遇到单引号输入会报错

预防方式

使用SQL的预编译功能

JDBC的PreparedStatment继承自Statement,Statement执行SQL语句(包含参数)会直接发给DBMS,编译后直接执行;PreparedStatement执行SQL先将用?作为占位符的SQL语句模板发给DBMS先编译,之后直接运行编译后的SQL语句,参数在执行阶段传入。

<select id="selectPerson" parameterType="int" resultType="hashmap">
SELECT * FROM PERSON WHERE ID = #{id}
</select>

<select id="selectPerson" parameterType="int" resultType="hashmap">
SELECT * FROM PERSON WHERE ID = ${id}
</select>

Mybatis中有两种参数传递的方式:#{}是先传递参数,然后再执行编译,再执行语句。为了避免被SQL注入,应采用#传参。

CSRF攻击

CSRF(cross-site request forgery),跨站请求伪造。攻击者可以通过冒用你的身份执行某些请求。

完成一次CSRF攻击,被攻击人必须:

  1. 登录受信任网站A,并在本地生成Cookie
  2. 在不登出A(Cookie没有过期)的情况下,访问危险网站B。

攻击案例

  1. 站点A的某个接口以GET请求完成银行转账操作:GET https://somebank.com/transfer?bankid=114514&money=1919810。被害人登录A后继续访问了B,B页面中有这样一串代码:

    <img src="https://somebank.com/transfer?bankid=114514&money=1919810">

    浏览器会带上用”somebank.com”的Cookie执行这一请求,使得用户给卡号为114514的卡汇入了1919810元。

  2. 上个案例中A使用GET方法设计请求,违反了HTTP规范,于是他们改用POST。对于一些老的PHP实现的后台站点,如果获取参数采用的$_REQUEST["bankdid"]这种方式,不区分GET和POST,照样能获得参数,所以POST还是没有起到作用。

假设后台实现区分了POST,危险站点B依然可以构造一个POST请求:

<html>
  <head>
    <script type="text/javascript">
      function steal() {
iframe = document.frames["steal"];
iframe.document.submit("transfer");
      }
    </script>
  </head>

  <body onload="steal()" src="https://somebank.com">
    <iframe name="steal" display="none">
      <form method="POST" name="transfer" action="https://somebank.com/transfer">
        <input type="hidden" name="bankid" value="114514">
        <input type="hidden" name="money" value="1919810">
      </form>
    </iframe>
  </body>
</html>

即使A站点不允许跨域,该处也可以用iframe构造一个同域的请求。

预防方式

  • 尽可能使用POST执行需要高安全性保障的接口
  • 将页面HTTP返回Header加上X-Frame-Options: DENY

X-Frame-Options头部选项中,DENY是拒绝非同源页面引用该页面;SAMEORIGIN是允许被同源页面引用,ALLOW-FROM uri是允许被特定页面引用。

  • 设置页面HTTP返回头Content-Security-Policy: script-src。将设置外链js只能从本域名引用。
  • 对于支付等特别敏感的接口,强制使用验证码
  • 由于CSRF攻击中假设A站点是可信的,不存在A站点还有XSS漏洞,攻击者无法拿到A站点的Cookie。所以基于这一判断,可以对Cookie Hashing,让表单中包含一个hash(cookie)token字段。服务器端接受表单请求的时候需要判断hash(cookie) == token才能继续执行,由于攻击者无法直接拿到Cookie,而且就算使用中间人攻击拿到了token也无法反推出cookie,这个方案可以彻底解决CSRF攻击。如果A页面也含有XSS漏洞,可以让攻击者拿到Cookie,可以让A页面的Cookie或者SESSION每次都变动,每次请求生成一个随机字段,并将改字段的hash渲染在form上,这样每次请求页面都会获取一个新的token,让攻击者几乎没有可能有时间伪造请求。

参考资料:

Disqus评论区没有正常加载,请使用科学上网