web常见的安全问题

XSS(Cross Site Scripting),跨站脚本攻击,是一种允许攻击者在另外一个用户的浏览器中执行恶意代码脚本的脚本注入式攻击。本来缩小应该是CSS,但为了和层叠样式(Cascading Style Sheet,CSS)有所区分,故称XSS。

img

1、攻击者通过评论表单提交将<script>alert(‘aaa’)</script>提交到网站

2、网站后端对提交的评论数据不做任何操作,直接存储到数据库中

3、其他用户访问正常访问网站,并且需要请求网站的评论数据

4、网站后端会从数据库中取出数据,直接返回给用户

5、用户得到页面后,直接运行攻击者提交的代码<script>alert(‘aaa’)</script>,所有用户都会在网页中弹出aaa的弹窗

这种攻击方式恶意代码会被存储在数据库中,其他用户在正常访问的情况下,也有会被攻击,影响的范围比较大

2、反射型XSS攻击:恶意脚本来源于受害者的请求

在一个反射型XSS攻击中,恶意文本属于受害者发送给网站的请求中的一部分。随后网站又把恶意文本包含进用于响应用户的返回页面中,发还给用户。

我们来看下面这个场景

img

1、用户误点开了带攻击的url :http://xxx?keyword=<script>alert('aaa')</script>

2、网站给受害者的返回中包含了来自URL的的恶意文本

3、用户的浏览器收到文本后执行页面,会在网页中弹窗aaa

反射型的攻击需要用户主动的去访问带攻击的链接,攻击者可以通过邮件或者短信的形式,诱导受害者点开链接。如果攻击者配合短链接URL,攻击成功的概率会更高

3、基于DOM的XSS攻击

基于DOM的XSS攻击是反射型攻击的变种。服务器返回的页面是正常的,只是我们在页面执行js的过程中,会把攻击代码植入到页面中

下面展示的是这种攻击的场景

img

1、用户误点开了带攻击的url :http://xxx?name=<script>alert('aaa')</script>

2、网站给受害者的返回中正常的网页

3、用户的浏览器收到文本后执行页面合法脚本,这时候页面恶意脚本会被执行,会在网页中弹窗aaa

这种攻击方式发生在我们合法的js执行中,服务器无法检测我们的请求是否有攻击的危险

攻击的危害

攻击者把代码注入进了访问的页面,所以恶意脚本都在网站的上下文环境中执行,这就意味着恶意代码被当做网站提供的正常脚本一样对待:他有权访问页面与网站的关键数据(比如cookie),浏览器会认为他是网站的合法部分,允许他做任何事情。比如拿到用户的cookie信息,然后传送到攻击者自己的服务器,从cookie中提取敏感信息,拿到用户的登录信息,或者攻击者可以通过修改DOM在页面上插入一个假的登陆框,也可以把表单的action属性指向他自己的服务器地址,然后欺骗用户提交自己的敏感信息。

如何防止攻击

XSS攻击其实就是代码的注入。用户的输入被编译成恶意的程序代码。所以,为了防范这一类代码的注入,需要确保用户输入的安全性。对于攻击验证,我们可以采用以下两种措施:

1、编码,就是转义用户的输入,把用户的输入解读为数据而不是代码

2、校验,对用户的输入及请求都进行过滤检查,如对特殊字符进行过滤,设置输入域的匹配规则等

对于验证输入,我们既可以在服务端验证,也可以在客户端验证

对于持久性和反射型攻击,服务端的验证是必须的,服务端支付的任何语言都能够做到

而对于基于DOM的XSS攻击,验证输入在客户端必须执行,因为从服务端来说,所有发出的页面内容是正常的,只是在客户端js代码执行的过程中才发生可攻击

但是对于各种攻击,我们最好做到客户端和服务端都进行处理。这里,我们主要讨论的是客户端的验证,至于服务端如何过滤验证,可以查看其它资料

编码

在客户端使用javascript对用户输入进行编码时,有一些内置的方法和属性能够自动感知对上下文的情况下自动对所有的数据进行编码

下表就是一些自动编码的方式:

img 这些内置的方法会对用户的输入自动编码

但是对于用户的自动输入进行编码也会有弊端,恶意文本也有可能插入进上下文中。看下面的例子:

document.querySelector(‘a’).href = “javascript:alert(‘aaa’)”

虽然给href属性的时候会被自动编码,但是这已不能组织攻击者嵌入执行脚本。

另外,如果需求是可以让用户自定义页面的代码,对输入进行编码也不是一个很好的解决方案。编码会把用户的输入当成纯文本输出,这样就跟需求不符了。

针对这样的情况,我们只能对文本进行校验了。

校验

校验是一种过滤用户输入以至于让代码中恶意部分被移除的行为。校验都是通过一定的经验和规则,对用户的输入进行匹配,过滤,去除掉存在攻击风险的部分。我们可以通过黑名单的方式和白名单的方式来设置我们的规则

比如: 我们在检测a 标签的时候,只要输入带入javascript字段的时候,我们就认为非法,javascript字段就成为我们黑名单的匹配规则

同时,我们可以采用另外一种检测方式,只要a标签有href属性的时候,我们只允许http协议的链接,如果是我们通过,不是就认为非法,这里就需要我们建立一张白名单的匹配规则

白名单和黑名单都可以对数据进行过滤,但是黑名单会随着攻击方式的变化而改变,对于规则的使用,白名单更具长效性。所以对于匹配规则最好采用白名单的机制

下面有一个类库是针对防XSS攻击的,可以引入到我们日常项目中使用:

https://github.com/leizongmin/js-xss

Content Security Policy(CSP)

只使用验证输入来防止XSS攻击的劣势在于即使存在一丝的漏洞也会使得你的网站遭到攻击。最近的一个被称为Content Security Policy(CSP)的标准能够减少这个风险。白名单

CSP对你用于浏览页面的浏览器做出了限制,以确保它只能从可信赖来源下载的资源。资源可以是脚本,样式,图片,或者其他被页面引用的文件。这意味着即使攻击者成功的在你的网站中注入了恶意内容,CSP也能免于它被执行。

CSRF定义

CSRF,即(Cross-site request forgery), 中文名为跨站请求伪造。是一种挟持用户在当前已登录的Web应用程序上执行非本意的操作的一种攻击方式。CSRF攻击的本质在于利用用户的身份,执行非本意的操作。根据CSRF的全名,可以得出的结论是:CSRF的请求是跨域且伪造的。

跨域指的是请求来源于其他网站。比如说,目标网站上的删除文章功能接收到来自其他网站的删除文章的请求,那么这个请求就是跨域的。

伪造指的是如果这个请求不是用户自身的意愿,那么这个请求就是伪造的。

简单的说,跨站请求伪造的攻击是攻击者通过一些技术手段欺骗用户的浏览器去访问用户曾经认证过的网站并执行一些操作(如发送邮件、发消息、甚至财产操作如转账和购买商品等)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去执行。这利用了web登录身份认证的一个漏洞:简单的身份认证只能保证请求来自用户的浏览器,但不能识别请求是用户自愿发出的。

CSRF防范

  1. 检测请求头中的Referer字段

从GET CSRF例子中可以看到,目标网站A和恶意网站B发出的请求中,请求头唯一的不同就是Referer字段。通常来说,Referer字段通常与Host字段的域名是一样的。

以上面删除文章功能为例,在目标网站A中的Referer字段为http://www.a.com/blog/,而恶意网站B中的Referer字段为http://www.b.com/csrf.html。所以根据Referer字段与Host字段在同一域名下的规则,可以检测Referer字段值,如果发现其与Host值不在同一域名下,这时候服务器就能够识别出恶意的访问了。

  1. 添加检验token

由于CSRF的本质在于攻击者欺骗用户去访问自己设置的地址,所以如果要求在访问敏感数据请求时,要求用户浏览器提供不保存在cookie中,并且攻击者无法伪造的数据作为校验,那么攻击者就无法再执行CSRF攻击。这种数据通常是表单中的一个数据项。服务器将其生成并附加在表单中,其内容是一个随机数。即<input type="hidden" name="_csrf_token" value="xxxx">)的形式。

当客户端通过表单提交请求时,这个随机数也一并提交上去以供校验。正常的访问时,客户端浏览器能够正确得到并传回这个随机数,而通过CSRF传来的欺骗性攻击中,攻击者无从事先得知这个随机数的值,服务器端就会因为校验token的值为空或者错误,拒绝这个可疑请求。

为了防范CSRF,在需要增删改数据时,使用POST请求,而不要使用GET请求。

具体的方案如下:

1. 服务端在收到客户端请求时,生成一个随机数,在渲染页面时将随机数埋入页面(一般埋入form表单中),<input type="hidden" name="_csrf_token" value="xxxx">)`的形式。每次刷新页面后这个随机数都会改变,并在服务器中存储。
2. 服务端设置Set-Cookie, 把该随机数作为cookie种入用户浏览器。
3. 当用户发送GET或POST请求时带上_csrf_token参数(对于form表单直接提交即可)
4. 后台在接受到请求后解析请求头中的cookie字段,获取_csrf_token的值,然后和用户请求提交的_csrf_token值做比较。如果相等则表示请求来源是合法的。

警惕iframe带来的风险

有些时候我们的前端页面需要用到第三方提供的页面组件,通常会以iframe的方式引入。典型的例子是使用iframe在页面上添加第三方提供的广告、天气预报、社交分享插件等等。

iframe在给我们的页面带来更多丰富的内容和能力的同时,也带来了不少的安全隐患。因为iframe中的内容是由第三方来提供的,默认情况下他们不受我们的控制,他们可以在iframe中运行JavaScirpt脚本、Flash插件、弹出对话框等等,这可能会破坏前端用户体验。

img

如果说iframe只是有可能会给用户体验带来影响,看似风险不大,那么如果iframe中的域名因为过期而被恶意攻击者抢注,或者第三方被黑客攻破,iframe中的内容被替换掉了,从而利用用户浏览器中的安全漏洞下载安装木马、恶意勒索软件等等,这问题可就大了。

最后说几句

如果有任何问题或建议,可以给我发邮件:156343782@qq.com.

欢迎交换友链,给我 发邮件:156343782@qq.com, 基本上可以做到秒加.

赞助

如果您觉得这篇文章对您有用,可以请作者喝一杯咖啡~~

微信:举个桃子的微信 支付宝:举个桃子的支付宝