Web安全问题梳理
一、XSS(Cross-Site Scripting)
跨站脚本攻击,与CSS缩写一样,故叫XSS。它是指通过存在安全漏洞的web网站,在注册/登录用户的浏览器内运行非法的HTML标签或javascript脚本的一种攻击。
原理
恶意攻击者在web页面里插入可执行的网页脚本代码,当用户浏览该页之时,嵌入其中的脚本代码就会被执行,从而可以达到攻击者盗取用户信息或其他隐私的目的。
目的
在正常界面中运行非站点的脚本
可能的影响:
- 利用虚假输入表单骗取用户个人信息(通过注入js脚本,弹出虚假表单,将个人隐私信息窃取)
- ...TODO
类别
xss攻击方式大致可以分为以下几类
-
非持久型XSS(反射型XSS)
一般是给别人发送带有恶意脚本代码参数的URL,诱导正常用户点击,该地址被打开时,恶意的代码就被html解析、执行了。
非持久型 XSS 漏洞攻击有以下几点特征:
- 即时性,不经过服务器存储,直接通过 HTTP 的 GET 和 POST 请求就能完成一次攻击,拿到用户隐私数据。
- 攻击者需要诱骗点击,必须要通过用户点击链接才能发起
- 反馈率低,所以较难发现和响应修复
- 盗取用户敏感保密信息
攻击方式汇总:
- TODO
- TODO
-
持久型XSS(存储型XSS)
一般存在于form表单提交等交互功能,如文章留言,提交文本信息等,并经由服务器等中间媒介最终存储到数据库持久保存,当前端页面从数据库中读出的注入代码时,将其渲染并执行。
持久型 XSS 有以下几个特点:
- 持久性,植入在数据库中
- 盗取用户敏感私密信息
- 危害面广
攻击成功需要同时满足以下条件:
- POST 请求提交表单后端没做转义直接入库
- 后端从数据库中取出数据没做转义直接输出给前端
- 前端拿到后端数据没做转义直接渲染成 DOM
攻击方式汇总:
- TODO
为了防止出现该类型XSS漏洞,需要确保:
- TODO
如何防御?
-
CSP
本质上就是建立白名单,开发者需要明确告诉浏览器哪些外部资源可以加载和执行。我们只需要配置规则,如何拦截是由浏览器自己实现的,该方式可以尽量减少XSS攻击。开启方式:
- 设置 HTTP Header 中的 Content-Security-Policy
- 设置 meta 标签的方式
这里以设置 HTTP Header 来举例:
- 只允许加载本站资源:Content-Security-Policy: default-src 'self'
- 只允许加载 HTTPS 协议图片:Content-Security-Policy: img-src https://*
- 允许加载任何来源框架:Content-Security-Policy: child-src 'none'
如需了解更多属性,请查看Content-Security-Policy文档
对于这种方式来说,只要开发者配置了正确的规则,那么即使网站存在漏洞,攻击者也不能执行它的攻击代码,并且 CSP 的兼容性也不错。
- 转义字符
用户的输入永远是不可信的,最普遍的做法就是转义输入输出的内容,对于引号、尖括号、斜杠进行转义,转义时,可以通过设置白名单,保留安全、正常的渲染。 - HttpOnly Cookie
预防XSS攻击窃取用户cookie的最有效的手段。web应用程序在设置cookie时,将其属性设置为HttpOnly,就可以避免该网页的cookie被客户端恶意javaScript脚本窃取,保护用户cookie信息。
二、CSRF(Cross Site Request Forgery)
跨站请求伪造,一种常见的web攻击,利用用户已登录的身份,在用户毫不知情的情况下,以用户的名义完成非法操作。
原理
完成CSRF攻击的三个前提条件:
- 正常用户已经登录了站点A,并且在本地记录了cookie(而且该cookie也能被B使用)
- 用户在登录时效内,访问了恶意攻击者提供的“引诱”(因为一般情况下是通过各种诱惑用户)危险站点B,且B站点要求访问站点A
- 站点A没有做任何CSRF防御
目的
模仿正常用户发起一些修改操作(修改金额、密码)、获取敏感信息操作(获取地址、电话等)
如何防御?
根据上述的三个前提条件进行破坏就行了,防范CSRF攻击可以遵循以下几种规则:
- Get请求不对数据进行修改(仅一定程度上,Post的攻击仍无法避免)
- 不让第三方用户访问到用户cookie(domain或SameSite【目前不是所有浏览器都兼容】)
- 阻止第三方网站请求接口(referer判定)
- 请求时附带验证信息,比如验证码或者Token
防御方式
1.设置cookie可用性
对Cookie设置SameSite属性。该属性表示Cookie不随着跨域请求发送,可以很大程度减少CSRF攻击,但是并非所有浏览器都兼容。
2.检查Referer请求头
Referer是http请求的一部分,一般的请求会带上信息告诉接收方是从哪个界面过来的,服务器借此可以获得一些信息用于处理。正常请求的referer具有一定规律,比如是哪些域名的界面发起,所以通过检查该值是不是这些界面发起的。
|
3.加入Anti-CSRF-Token参数
目前比较完善的解决方案是加入Anti-CSRF-Token,即由服务器向用户浏览器提供一段信息(token),浏览器发送请求时将token返回,并在服务器建立一个拦截器来验证该token。
3.1 验证过程:
(1)、登录或任意请求后均在session中设置随机code
(2)、发起请求时读取cookie中token值,作为参数传递(或者直接隐藏在表单中)
(3)、服务端拦截器验证cookie中token和参数token是否一致且为服务端发放(读取session),若是,认为是合法请求,否则不是合法请求
该方式比referer检查安全,由于token的存在,攻击者无法再构造出一个完整的URl实施CSRF攻击【表示存疑,如果读取到cookie并动态拼接不也是一样吗,当然Xss先行,然后cookie可见性需要设置好】
3.2 如何生成和校验token
3.2.1 生成令牌时需要遵循以下原则:
(1)、使用具有足够熵的、不可预测的、完善的随机数生成器
(2)、令牌在短时间内过期,以使它们无法重复使用
(3)、使用安全的方法来验证接收到的令牌是否与设置的令牌相同,例如,比较哈希。【为何这是安全的???????】
(4)、不要在HTTP GET请求中发送令牌,保证它们在URL中不会被直接可用,并且不会在Referer头中泄漏。
3.2.2 特殊的表单token
更进一步的安全加护时,针对特定表单生成特定的token,加入该表单的名字作为生成和校验即可。
3.3.3 每个请求使用不用的token
如果有较高的安全级别,想为每个请求使用不同的token,即:验证后即将该令牌设置为无效。但是具有几个缺点:喜欢在多个tab中工作的用户无法使用(一个请求一个,未失效前即使开多个也是一个token);后退按钮也会有问题,可能会使用已失效的token导致体验下降。
3.3.4 非持久化token方式
如果站点非常繁忙,且存储空间有限,那就需要避免持久保存令牌。如果如此,可以改用加密方法,使用这种方法,无需在服务器会话中存储令牌:
(1)使用仅服务器知道且不会共享出去的对称加密key;
(2)结合时间戳、用户信息、表单名(非必须)形成加密内容;
(3)接收到浏览器的请求后,使用**进行解密;
(4)比较解密出来的时间戳和当前时间戳【应该是判断是否在有效期内】,解密用户和当前用户,解密表单和当前表单即可。
该方法能够避免存储消耗,但是加/解密相比单纯对比更消耗资源。
另一种非持久token方式是double-submit,TODO
4.验证码
application和user进行交互时,特别是账户交易等高安全要求步骤,强制用户输入验证码,才能完成最终请求。虽然降低了用户体验,但是很好的遏制了CSRF攻击。所以目前一般是关键业务点使用此方式。
三、sql注入
该方式没什么好说的,预参数化就行了
参考文档: