重放攻击
- 攻击者通过某种手段获取到请求的报文,并将报文重新发送到浏览器
防范手段
- 无论何时,只允许提交一次报文,每次请求带上一个随机数,当服务器接收到请求时,判断之前是否有收到相同的请求,有的话则认为是重放,拒绝请求,但这种方法有个缺点,就是是数据库需要记录大量的历史请求(随机数)
- 一段时间内,只允许处理一次请求,每个报文带上时间戳,一般请求的到达耗时约60s,所以服务器对比当前时间,如果间隔大于60s,则认为是重放,这个方法的缺点是,客户端和服务器系统时间需要保持同步,并且如果是1分钟内到达的请求是无法限制重放的
- 请求添加连续的流水号,每次请求都会增加一,当接收到不连续的流水号时,对应的请求就有重放的嫌疑,这样无需记录大量的随机数,但由于流水号很容易被伪造,所以一遍不用这种方式
- 一般采用随机数和时间戳相结合的方式,60s内到达的请求,对比随机数,如果一致就认为是重放,60s外到达的请求直接认为是重放,且可以清除记录的随机数
除了重放攻击,有可能客户端的快速点击也会重复发送请求,在服务端可以用上面的方法处理,客户端可以使用节流和防抖限制
- 防抖,连续重复多个动作,只对最后一个动作响应
- 节流,一个时间间隔内,只允许一个动作生效
XSS(跨站脚本攻击)
- XSS攻击的原理就是,利用网页本身的漏洞,例如会从网页链接中读取信息,并拼接到html文本中,通过这种方式,向网页植入恶意脚本,泄露用户信息,如可以通过XSS获取用户cookie
攻击形式一:
- 网页拼接,网页接收输入文本或从链接获取参数后,直接展示在页面上,则攻击者可通过构造<script>标签伪造输入,让页面执行脚本
- 防范方法,对获取到的输入进行转义,浏览器不会执行转义后的输入
攻击形式二:
- 页面上某a标签,从链接中会获取参数,拼接到href后面,攻击者通过构造javascript:XXX,由于转义并不会处理"javascript"这种字符串,当点击a标签时,恶意代码被执行
- 防范方法,页面内部保存一组黑名单,当获取到的参数带有某特定字符串时,拒绝使用这个参数
xss攻击分类:
- 储存型:构造的恶意代码提交到数据库,通过数据库返回给浏览器执行
- 反射型:访问的时候就在url上带有恶意代码,服务器读取url参数把他拼接到html上,返回浏览器被执行
- DOM型:html本身会读取输入或url参数,拼接到html上时执行了恶意代码
防范:
- 输入过滤,前后端都对接受的参数进行过滤以及转义,但有个缺点,某些正常输入的字符也会被转义导致后续使用或展示时有误
- 通过dom操作进行前端的渲染,使用innerText(不要使用或谨慎使用innerHTML),setAttribute这种api,可以防止恶意代码被拼接,vue的模板机制和react的jsx就是利用的这个方法避免xss,但这种方式依然无法避免onload事件的插入,以及利用href的xss
- 针对href的xss输入,需要注意避免使用
.innerHTML
、.outerHTML
、document.write()
以及vue和react的v-html
/dangerouslySetInnerHTML
CSP(content security policy)
- 启用CSP可以禁止加载外域代码,或只允许执行受信任的域名下的代码
- 禁止提交请求到不受信的服务器
- 禁止执行内联脚本
- 上报异常信息以供分析
- HTTP-only Cookie:在cookie中设置httponly,则cookie无法被js脚本获取到
- 验证码,针对敏感操作,需要验证码才能放行
CSRF(跨站请求伪造)
- Cross-site request forgery
- 攻击者诱导用户进入第三方网站,在第三方网址中,通过img或href等标签的src属性,向被攻击网站发送跨站请求,若此时用户已经获取了被攻击网站的登录授权,跨站请求就有可能带上用户的cookie,从而绕过后台的验证,导致攻击请求被后台执行
- 正常来讲,由于浏览器本身带有同源限制,js无法直接对不同域名下的资源进行操作,但img或script标签不受同源策略的限制,所以存在CSRF的可能
攻击类型:
- GET类型,通过src属性发起请求
- POST类型,需要构造form,进行提交,同时因为form提交会发生页面跳转,一般为了不让用户识别到提交,会有一个iframe装着
<form action="http://bank.example/withdraw" method=POST> <input type="hidden" name="account" value="xiaoming" /> <input type="hidden" name="amount" value="10000" /> <input type="hidden" name="for" value="hacker" /> </form> <script> document.forms[0].submit(); </script>
- 链接类型,请求写在a标签的href在中,诱使用户点击,从而发出请求
防范策略:
同源检测:利用请求头的Origin和Referer,可以在meta或csp中设置referer policy,控制请求是否带referer
- 但referer是有可能被修改的,并不是完全安全
- 同时由于SEO(搜索引擎优化)的需求,请求页面(html)的请求是会需要被允许的,如果这个页面本身会触发某些get请求,就很可能被攻击
- 另外如果,页面本身允许输入评论等,也可能被发起攻击
CSRF Token:构造一个攻击者无法获取的token,在请求时带着这个token访问服务器,不能放在cookie中,而是作为报文body的一部分
- 打开页面时,访问服务器,返回一个token,通过js遍历,把token带在a标签和form标签中,但是这种方法无法处理由js发起的请求,或后续动态生成的dom元素,针对这两种情况,需要手动添加token,然后服务器接受请求时验证token
- 通常该token由客户id,随机数以及时间戳生成,并加密,服务器验证时会对比有效性
- 但是这种验证需要额外储存token,对服务器而言是额外的负担
双重cookie验证:利用无法跨域获取cookie的限制,在访问页面时往cookie添加一个csrfcookie的随机数,后续发起请求时,页面获取该cookie,并设置到请求参数里,后续验证,服务器只需要验证cookie中的值和请求里的参数是否一致即可
- 这种方法无需存储额外的数据,直接对比cookie即可
- 但前提是不存在xss漏洞,不然还是有可能泄露cookie,或者被修改cookie,从而利用伪造的cookie发起请求,造成用户损失
samesite cookie:新的提案
Set-Cookie: xxx; Samesite=Strict
,则该cookie除了从自身网站下发起请求,其余包括新页面打开,或不同域名下的异步请求,都不会带上cookieSet-Cookie: xxx; Samesite=Lax
,当这个请求是从自身网站下发起的请求,或者打开了新页面,如从百度打开某个页面,同时他是个get请求,那么允许带上cookie- 但这种方案有个缺点,不支持子域,即启用了samesite后,子域无法使用父域的cookie
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。