XSS 攻击与防护

AI summary
date
Aug 13, 2024
slug
xss-effect
status
Published
tags
技术
summary
web 生存指南:永远不要相信用户的输入
type
Post

啥是 XSS ?

XSS 是 Cross Site Scripting 的缩写,意思为 “跨站脚本”。
说人话,就是让被攻击者执行一些本不属于原网站的代码
 
假设我们是一个超级大黑客,如何把恶意代码携带给用户?
这是一个很有趣的问题,要解答这个问题,首先要理清我们的袭击目标的行为。
notion image
输入是我们可以蛊惑小可爱的地方,然后利用服务器和客户端代码的漏洞修改其输出,实现代码注入。
notion image
 

反射型 XSS

有时候,服务器返回的页面,是有用户的参数动态生成的。这就给了我门可乘之机。而如果这个参数是通过 url params 传递的,那就天助我也。
notion image
 
上面这个游戏可体验 XSS 攻击,他提供了一个根据用户参数动态生成页面内容的网站,并且不对输入做过滤
比如我们输入 <h1> hello </h1> ,他会在访问时携带 ?search=<h1>hello</h1>
notion image
notion image
 
网站部分源码:
观察这里标亮的代码,会直接根据用户的参数动态生成 html,这就是这个页面的漏洞,而这个参数是通过 URL params 传递,所以我只要给 URL 中添加恶意脚本 params,用户点击就会执行
我上边留的链接:
 
上述的这种攻击方式,通过 params 参数,输入给服务器,在服务器输出含有恶意代码的 html,被称为反射 XSS。
啥?为啥叫反射?
notion image
因为他是一个自己打自己的过程,用户请求时自己携带了恶意参数(小可爱用户并没有发现),他是通过请求时携带,响应时生成,是一个非持久化的攻击方式。
 

存储型 XSS

我懂了,我再也不会点击别人的链接了,我无敌了。
不好意思,并不能。
 
只要你不乱点,黑客确实不能突破你,但他可以直接突破数据库。
notion image
👾
体验 点击这个小游戏,可以体验 存储型 XSS 攻击
notion image
点击上方游戏链接,可以看到这是一个论坛,大家都可以发言。黑客只需要通过 “发帖子” 就能把恶意代码存到数据库,当你访问这个论坛,就会请求到黑客在此处留下的发言,然后就寄,可见,这种攻击是非常严重的,因为他是大范围被动杀伤技能。
 
现在我们实操一下,留言 <h1>hello</h1>
notion image
 
发现它渲染了,那还不简单,直接往里插 script。
但这个网站稍微聪明点,他过滤了你的 script 标签。这次并没有起效果
notion image
notion image
 
那就没办法攻击了吗?不是,img 标签有个 onerror 属性,在图片加载失败时就会执行其中的回调
notion image
notion image
 
可以看到,尽管这个网站过滤了 script 标签,但黑客利用 img 的特点(网站没有过滤 img),依旧实现了注入。
只要访问到这个帖子的人,就会执行 Img 的 onerror 回调,就会被攻击。
 
因为直接把恶意脚本存在了数据库,所以这种攻击叫 存储型XSS。

DOM型 XSS

前两种攻击方式,都是针对服务器,一种是利用了服务器输出时的漏洞,一种是利用数据存储时的漏洞。还有一种攻击方式,是利用客户端运行时的漏洞。
打开上面这个网址,现在你的目标是注入恶意代码,让用户访问你的 URL 时,显示一个 alert 弹窗。
 
先随便点点试试
notion image
当我们点击图片的 tab 时,发现图片发生了变化,同时 url 中的 # (hash)发生了变化。
🗯️
关于 # 参数 params 参数,即 后面的参数,是会携带给服务器的。 而 hash 参数,即 # 后面的参数,是运行时参数,不会携带给服务器,通过 js 脚本访问
因此可以想到,客户端脚本一定用到了 hash 参数,我们随便输入一个值试试
notion image
输入 4 后,发现确实在运行时使用了 hash 参数,通过控制台打开源码也可以看到:
notion image
前端在拼接图片地址时,使用到了 hash 的值,这就是他的漏洞,他使用了 url 参数拼接 DOM!
这还不简单,提前截断他的 img 标签并加入 onerror 事件
这个 URL 便实现了攻击,原理是,截断了原来的 img 标签拼接,插入了 onerror 事件,并将后面的代码注释
 
这个攻击利用了前端代码的漏洞(客户端运行时),被称为 DOM 攻击。
 

防御策略

网站访问与渲染的过程,本质上是一个数据输入输出的过程。
输入:
  • 输入向服务器的运行时(params 参数)
  • 输入向服务器的数据库(表单 参数)
  • 输入向客户端的运行时 (比如 hash 参数)
输出:
  • 服务器输出 (利用服务器动态生成 html 的漏洞)
  • 客户端输出 (利用客户端动态生成 html 的漏洞)
 
因此防御的根本就是
  1. 预防输入:白名单过滤,清洗(转译)输入
  1. 预防输出:尽量避免动态生成 html ,输出用户输入时,使用安全模版编译
 
 

总结

XSS 攻击,利用了用户对网站的信任,但整个输入输出的链路上都可能发生漏洞。
web 生存指南:永远不要相信用户的输入