回到我们的web安全篇,这次要和大家分享的是XSS(Cross-SiteScripting跨站脚本攻击)漏洞,这个在web层面一直危害在前Top3的安全漏洞,本质因浏览器混淆了“数据”和“代码”,将用户输入的数据当作代码来执行从而导致的出现恶意弹窗问题。我们先从简单的前端知识聊起,再到浏览器的安全机制(十分关键),最后我们通过pikachu靶场将所有类型的XSS漏洞进行演示。

一、理解上下文 - XSS的灵魂所在

  • 标签:<div> <img> <a> <script>

  • 属性:src="" href="" onclick=""

由于XSS发生的位置并不同,我们payload的写法也不同,所以我们需要简单掌握HTML的几种“上下文”

1、文本环境上下文

HTML文本节点:<div>用户输入内容</div>

哪怕用户输入payload只会显示出来,不会执行。下面演示一个在文本环境中的XSS攻击示例:

用户输入:<script>alert('XSS')</script>
最终输出:<p><script>alert('XSS')</script></p>

2、属性环境上下文

HTML属性节点: <img src="用户输入">
<!-- 搜索功能:<input value="搜索关键词"> -->
<input type="text" value="用户输入内容">

用户输入被放在HTML的属性值里,我们在利用XSS的时候其实只需要提前构造好value属性和整个<input>闭合就可以实现:

用户输入:"><script>alert(1)</script>
最终输出:<input value=""><script>alert(1)</script>">
用户输入:" onmouseover="alert('XSS')
最终输出:<input value="" onmouseover="alert('XSS')">

这些在我们的靶场演示中会具体看见浏览器给我们的实际回显,在使用payload之前,我们一定要知道这些payload形成的内在逻辑,而抓上下文关系就是XSS漏洞的基础和核心。

3、JavaScript上下文

这里的JavaScript上下文是指在HTML文本中的script标签。

script标签中的javaScript上下文
<script>
var a = "用户输入";
</script>

这里我们的思路和上述的属性环境上下文类似,还是通过构造闭合字符串,添加JS代码,并用注释符处理掉后面的内容:

用户输入:"; alert('XSS'); //
<script>
    var username = ""; alert('XSS'); //";
</script>

JavaScript上下文是是XSS攻击中最精妙、最多变的部分。千变万化的payload造成的成百上千的攻击效果,但是与之相对应的,利用好JS上下文需要攻击者对JavaScript语言烂熟于心,这样才能做到所谓“以编译器的视角”审视代码,完成对XSS攻击的完全掌握。

4、URL上下文

这里的标识是用户输入被放在hrefsrcaction等属性中。

<a href="用户输入的链接">点击这里</a>
<img src="用户输入的图片地址">

我们只需要构造用户输入的链接来进行一些恶意的操作,比如利用JavaScript伪协议来执行URL中的代码从而达到窃取Cookie的一个目的:

用户输入:javascript:alert(document.cookie)
最终输出:<a href="javascript:alert(document.cookie)">点击我</a>

这种XSS利用的危害同样十分巨大,而且多数攻击者的攻击会通过这样的方式去隐藏和伪装,从而获取用户会话的一个劫持。

二、浏览器安全机制 - 理解XSS为何危险

1、同源策略(SOP)

简单来讲述同源策略,这个浏览器最重要的安全策略:

来自不同源的脚本,在没有明确授权的情况下,不能读写对方的资源。

关于“源”是什么,这里需要简单说说:

  • 源由协议 + 域名 + 端口组成

  • https://www.example.com:443 是一个源

  • http://www.example.com(不同协议)是不同源

  • https://api.example.com(不同子域)是不同源

通过这样的对比,大家一定可以理解所谓同源,就是使用相同协议相同域名。

了解”同源“这一概念以后,我们就可以聊聊SOP限制的具体内容,简单来说就是:

1)限制读取:另一个源的的DOM、Cookie、LocalStorage以及AJAX响应;

2)可以写入但不能读取响应:链接跳转、表单提交以及嵌入资源。

而XSS恰好可以绕过SOP,由于XSS脚本和所在的界面同源,所以实现随性的读取和写入,让同源安全机制浮于表面。

2、Cookie安全机制

Cookie作为XSS攻击的主要猎物,这同样是因为浏览器赋予Cookie标识用户会话的重要机制,然而一个完整的Cookie安全机制体系是不会那么容易收到XSS攻击的,这是因为Cookie自身的一些关键属性配置:

1)HttpOnly:Cookie只能通过HTTP请求发送,JS无法访问 document.cookie;

2)Secure:只能通过HTTPS连接发送;

3)SameSite:限制第三方请求携带Cookie。

有了这些关键的属性,处在风口浪尖的Cookie就相当于有了一些自保的手段,用户的会话也不会那么容易被其他人窃取。

关于浏览器的安全机制我们目前先聊到这里,XSS漏洞之所以危险是因为它的出身就是在绕过SOP同源策略的基础上进行的攻击,并且对Cookie造成的威胁是十分巨大的,接下来我们在靶场上把XSS漏洞的常见类型进行演示和分析。

三、Pikachu靶场XSS漏洞实战

这张图片就直观阐释了XSS漏洞的运行原理,可以让大家对XSS先有一个直观的感受,接下来我们开始细化对XSS漏洞的理解。

1、反射型XSS

拿到题目,让我们submit一个喜欢的NBA球员,现在我们的目的是执行XSS攻击,我们可以先尝试输入单双引号和左右尖括号去看看我们构造的payload是否会被过滤掉。

这样看来,我们构造payload所用的常见字符都没有被过滤,我们可以安心在输入框内构造payload,在构造之前我们需要对前端源码的上下文结构做出明确的判断,我们打开页面源码搜索我们刚刚输入的内容:

注意到我们找到了我们输入到的位置,是在一个<p>标签下,我们输入的内容会直接输出,这也就是我们在上文提到的文本环境上下文的典型代表,我们直接讲构造的payload输入:

<script>alert("xss")</script>

这里又出现了新的问题,我们发现输入payload的时候,我们构造的payload超过了前端设置的最大字符串长度限制,我们无法输入完整的payload。

这时我们只需要打开开发者界面去查看该网页限制输入的字符串长度是20,并把它的上限修改成20000(足够我们构造的payload完整放入即可)

接下来,我们把自己构造好的payload直接输入就可以了:

我们点击submit提交一下:

成功反射回一个XSS,这也是为什么会把这种基于文本环境的上下文叫做反射型XSS的原因,我们插入的内容只是一串文本弹窗,不需要我们手动构造闭合。

本篇文章到这里结束了,Web安全篇中关于XSS漏洞的讲解才刚刚开始,有了本篇文章的铺垫,我们将在下一篇文章中把XSS漏洞常见类型的全貌向大家演示。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐