八股文不用背-常见的网络攻击方式XSS和CSRF

229 阅读4分钟

XSS(Cross Site Script)攻击以及预防

背景

如果html中存在<script></script>,那么浏览器就会将其当做js来解析然后执行;对于eval()传入的字符串,会被编译,然后执行。如果这两者里面的内容是有用户提交的话,就很不安全,接下来会讲解多个情况。

存储型XSS

用户A提交的东西(ASubmit)会先放入数据库,然后用户B访问该网站时,会获取ASubmit。如果ASubmit字符串中有<script></script>字段时,那么B访问的的html中就有<script></script>字段,那么浏览器就会将该内容编译执行。

比如:网站C有评论功能,用户A写了如下评论<script>调用一个api->关注up主用户A</script>并提交,当用户B访问该网站时,网站将A评论拼接在html里,然后返回给B,那么B在浏览时,就会执行调用一个api->关注up主用户A,这样用户A就能干坏事了。

代码如下

<body>
    <span class="comment">
        <!-- 以下是用户A提交的评论 -->
        <script>
            alert(1)
        </script>
    </span>
</body>

用户A这个糟老头子坏的很,那怎么预防这类攻击呢?

  1. 后端并非是将用户A评论的数据拼接在html,然后返回给用户B,而是先给个静态的html给用户b,然后通过ajax获取评论数据,然后将评论数据作为某标签的textContent,这样浏览器就不会将textContent当做脚本执行。代码如下:
<body>
    <span class="comment">
    </span>
    <script>
        // 通过ajax获取数据,然后设置textContent
        let a = document.getElementsByClassName('comment')[0]
        a.textContent =
        `<script>
            alert(1)
         <\/script>`
    </script>
</body>

这种方式有个问题,没法seo,想要seo就得拼接html,然后返回给搜索引擎,这搜索引擎才能知道这个页面是什么。那么拼接就会可能被xss攻击,怎么办?

  1. 在接受用户提交数据时,做转义,但不能再前端做,因为别人可以绕过前端发送请求,所以得后端在将用户提交的数据入库时做转义。

比如:
<script>alert(1)</script>嵌入html的话,会被解析成js;
&lt;script&gt;alert(1)&lt;/script&gt; 嵌入html里,不会被解析成js,会被转义成 <script>alert(1)</script>,然后当做一个正常的字符串使用。

然而html里不同的模块转义方式都不一样,比如:

  • 5 < 7 和 5 &lt; 7 两个嵌入html里面都会转义成5 < 7;
  • 5 &lt; 7当做字符串使用时,不会被转义成5 < 7;
  • 5 &lt; 7嵌入javascript和css中也不会被转义成5 < 7; 也就是说不同地方使用的转义方式都不一样,html、css、javascript、浏览器的url里使用的转义方式都不一样,这对后端来说可太多了,还好有转义库。
<body>
    <!-- 下面两个都转义成 5 < 7 -->
    5 &lt; 7
    5 < 7
    <span class="comment">
    </span>
    <script>
        let a = document.getElementsByClassName('comment')[0]
        // 不会被转义成 5 < 7
        a.textContent = `5 &lt; 7`
    </script>
</body>

反射型XSS

比如一个搜索引擎,当我们搜索一个关键字keyWord,该keyWord会拼接在url上,然后给搜索引擎发起请求,搜索引擎会返回一个html页面,该html中一般会带有该keyWord,哦吼,如果keyWord带有<script></script>的字样,那么访问该html时就会被解析成js,然后执行。

试想一下:某网站,有一个搜索接口,该接口的url组成是www.域名.com/?keyword=,然后返回的html页面里嵌入着keyword的内容。用户A,又是这和个恶名昭彰的用户A,在自己的网站上写了一个www.域名.com/?keyword=<script>触发一个api-关注up主用户A</script>的跳转链接,然后诱导用户B去点击这个连接,那么当用户B点击链接后,获得了嵌入了<script>触发一个api-关注up主用户A</script>内容的html,然后执行,就出事。

预防方法和存储型一模一样。

CSRF(Cross Site Request Forgery)攻击和预防

背景

网站发起http请求时,会默认带上cookie,且跨标签页存在。也就是说如果用户B,对,又是这个倒霉蛋用户B,在网站A登陆了,然后拿到了cookie,并存在本地浏览器,然后用户B又打开了一个标签页,然后访问了网站B,如果网站B的html中给网站A发起了一个请求(关注up主用户A),那么该请求就会自动带上浏览器上对应于网站A的cookie,这就相当于用户B在网站B中发起了网站A的请求,属于冒用。

解决方法

  • cookie一般是uid之类用户标识,然后它会在http请求自动带上,而且还能跨标签获取。那我们弄一个token,放入localstorage里面,然后就没办法http自动带上了。
  • 既然这攻击是在第三方的网站发起的,那么我们让一些重要的请求,必须得在当前网站时交互时才能请求成功,比如提交东西时弄个验证码,强制用户在当前页交互。

看到这里的看官,麻烦点个赞赞吧