Web安全开发
这是我参与「第四届青训营」笔记创作活动的的第7天!
一、XSS - Cross-Site Scripting
跨站脚本攻击
XSS => ①盲目信任用户提交内容; ②前端直接将内容转化成DOM
特点:
- 通常很难从UI上进行感知
- 窃取用户的信息(Cookie/token)
- 绘制UI(例如弹窗,广告),诱骗用户点击/填写表单
四种场景XSS类型:
(一) Store XSS
- 恶意脚本被存在数据库中
- 访问页面 -> 读数据 === 被攻击
- 危害大,对全部用户可见
🎄 Mark:实际上,就是服务端从存于数据库的恶意XSS脚本取出来之后,将其与正常代码一起返回给浏览器端,导致浏览器端拿到的响应内容包含了恶意代码,往往这种影响很广,所有访问到这个页面的用户都会受到影响
(二) Reflect XSS
- 不涉及数据库
- 从URL上攻击
🎄 Mark:服务器直接读去URL上的内容,如果攻击者将其构造成script脚本返回给浏览器端,那么就会形成XSS攻击,这种攻击一般来说就是访问一次,执行一次XSS脚本攻击
DEMO:
host/path/?param=<script>alert('123')</script>
(三) DOM XSS
- 不需要服务器的参与
- 恶意的攻击和执行,全部在浏览器来完成
🎄 Mark:在innerHTML中插入了恶意的脚本,这种类型的XSS攻击是前端渲染页面时没过滤恶意DOM操作行为导致的
(四) Mutation XSS
- 利用浏览器渲染DOM的特性(独特优化)
- 不同的浏览器,会有区别(按浏览器进行攻击)
DEMO:
<body>
<noscript><p title="</noscript><img src=x onerror=alert(1)>"></noscript>
</body>
<!-- 如果是chrome浏览器,将会被解析成如下情况 -->
<body>
<noscript><p title="</noscript>
<img src="x" onerror="alert(1)">
"">"
</body>
防御
- 永远不要相信用户提交的内容
- 不要直接将用户提交的内容直接转成DOM
- 建立CSP白名单,告诉浏览器哪些外部资源是可以加载执行的,从而防止恶意代码的注入执行,通常有两种方式来开启CSP,一种是设置HTTP首部的Content-Security-Policy,一种是设置meta标签
- 另外也可以对一些敏感信息进行保护,比如cookie使用http-only,也就是让脚本无法获取用户身份信息等,从而预防其进一步进行CSRF攻击
防御的工具:
- 前端 -> Ⅰ. 主流框架默认防御XSS Ⅱ. google-closure-library;
- 服务端(Node)-> DOMPurify
注意事项
- 尽量不要动态生成DOM,如果必须要的话,就要对String进行转化
- 如果要上传svg,那么也要对svg中的内容进行扫描,因为svg中可以插入script标签,会被执行
- 尽量不要做用户自定义跳转链接,因为有可能出现如
<a href="javascript:alert('xss')"></a>
这种情况 - 如果运行用户自定义样式,如在background-url中访问某个请求,当某些选项被checked的时候,就会被触发
二、CSRF - Cross-site Request Forgery
跨站请求伪造
CSRF指的是跨站请求伪造,本质上是通过利用cookie会在同源请求中携带发送给服务器的特点,以此来实现用户的冒充
攻击者诱导用户进入第三方网站,然后该网站向被攻击网站发送跨站请求,如果用户在被攻击网站中保留了登录状态,那么攻击者就可以利用这个状态,然后用户的认证,冒充用户来进行一些接口请求
攻击类型
常见CSRF攻击类型有三种
- GET类型,比如在浏览器中的img标签中onerror中构造一个请求,当用户打开网站的时候就会自动发起提交
- POST类型,比如构建一个表单,当用户进入页面时,自动提交表单
- 链接型的CSRF,在a标签中的href属性构建一个请求,诱导用户去点击
防御方式
- 进行同源检测,根据http请求中的origin和referer信息来判断是否为允许访问的站点,从而对其进行过滤,当origin和referer字段都不存在时,直接阻止此次请求。这种方式的缺点就是在有些情况下referer可以被伪造,同时还会把搜索引擎给屏蔽了。(如果运行搜索引擎过来,可能会被攻击者利用),另外referer字段指的是告诉服务器页面时从哪个页面链接过来的
- 使用token进行验证,服务器会在用户返回一个token,当用户后续发起请求时都需要携带此token。只有token验证通过了才能进行响应,但是要注意防止token被伪造,所以我们都会为token设置默认的有效时间
- 使用samesite,限制cookie不能被第三方使用,从而避免被一些攻击者利用。通过设置
SameSite=None
,来实现,另外如果一定要用到第三方的cookie的话,比如内嵌b站视频播放,就可以设置SameSite: none; secure;来告诉服务器这是安全的第三方
三、Injection
注入攻击有
- SQL注入 - 通过提交内容,构造出SQL语句,进行一些非法数据库的操作
- 命令注入 - 命令行注入,如在某个业务逻辑是,直接执行系统命令,那么用户提交的数据中,可以带上
&& rm -rf *
这样的字符串来实现恶意操作
预防的方式
- 不要信任用户的输入的信息,对内容进行过滤
- SQL注入,则可以通过预操作的方式,只需要进行传参来避免构造sql
- 命令行注入,则一定要防止在root高权限用户下进行操作,另外还可以建立命令白名单
其他的攻击如:
- 获取/修改服务器内的文件,如更改nginx的配置,将请求反向代理到第三方,使第三方浏览器激增,进行引发崩溃
- 基于正则表达式回溯的攻击,编写一些会引发回溯行为的字符串,进行匹配;避免方式:①不允许用户自定义正则表达式 ②避免写一些贪婪匹配的正则表达式
- DDOS攻击,主要的目的就是使得目标服务器的带宽耗尽
- 泛洪攻击,利用tcp三次握手,攻击方发生SYN包,服务器回应SYN和ACK包后,攻击方却不做回应。通过大量的发送SYN包,消耗服务器的连接数,从而无力接受建立其他的请求连接
四、MITM - Man-in-the-middle attack
中间人攻击
攻击简易过程如下:
- 客户端发送请求到浏览器端
- 浏览器发送自己的公钥
- 中间人截获公钥,生成一个伪造的公钥发给客户端
- 客户端收到伪造的公钥,生成加密hash值发送给服务器
- 中间人截获加密的hash值,用自己的私钥解密获得真密钥,同时生成假的加密的hash值发给服务器
- 服务器用私钥解密获得假密钥,然后加密数据传输给客户端
可以通过可信的CA认证来预防,服务端将自己的元信息和公钥拿到CA机构进行私钥签名认证,然后发送给客户端,客户端通过使用CA的公钥进行解密,从而拿到服务器公钥信息
五、防御说明
最好是使用中间件MiddleWare进行统一防御,而不是case by case
- 流量治理
- 负载均衡
- API网关
- CDN
- 快速自动扩容
- 非核心业务自动降级
STS 自动升级:
先有一次https请求,后面的指定时间内都能将http ⇒ https,Strict-Transport-Security: max-age=3600
另外需要避免:①静态资源防止劫持篡改 ②Feature Policy / Permission Policy策略来避免调起用户的设备权限