可参考本站相关文章辅助理解
《白帽子讲Web安全》笔记
1. 简介
跨站脚本攻击,英文全称是Cross Site Script,本来缩写是CSS,但是为了和层叠样式表(Cascading Style Sheet CSS)有所区别,所以在安全领域叫做“XSS “
XSS攻击,通常指黑客通过“HTML注入”篡改了网页,插入了恶意的脚本,从而在用户
浏览网页时,控制用户浏览器的一种攻击。在一开始,这种攻击的演示案例是跨域的,所以叫做“跨站脚本”。但是发展到今天,由于JavaScript的强大功能以及网站前端应用的复杂化,是否跨域已经不再重要。但是由于历史原因,XSS这个名字却一直保留下来。
1.1. 跨站
大多数情况
A站访客受到的XSS攻击代码是来自于B站
通过攻击得到的数据反馈会传至B站
故称跨站
1.2. 反射型xss
反射型xss只是简单地把用户输入的数据“反射”给浏览器。也就是说,黑客往往需要诱使用户“点击”一个恶意链接,才能攻击成功。反射型xss也叫做非持久型xss(Non-persistent XSS)
1.3. 存储型xss
存储型xss会把用户输入的数据“存储”在服务器端。这种xss具有很强的稳定性。比较常见的一个场景就是,黑客写下一篇包含有恶意Javascript代码的博客文章,文章发表后,所有访问该博客文章的用户,都会在他们的浏览器中执行这段恶意的JavaScript代码。黑客把恶意的脚本保存到服务器端,所以这种XSS攻击就叫做“存储型XSS “
1.4. DOM Based XSS
实际上,这种类型的XSS并非按照“数据是否保存在服务器端”来划分,DOM Based XSS从效果上来说也是反射型XSS。单独划分出来,是因为DOM Based XSS的形成原因比较特别,发现它的安全专家专门提出了这种类型的XSS。出于历史原因,也就把它单独作为一个分类了。
1.4.1. 什么是dom
dom就是一个树状的模型,你可以编写Javascript代码根据dom一层一层的节点,去遍历/获取/修改对应的节点,对象,值。
2. 攻击
2.1. xss payload
XSS攻击成功后,攻击者能够对用户当前浏览的页面植入恶意脚本,通过恶意脚本,控制用户的浏览器。这些用以完成各种具体功能的恶意脚本,被称为“XSS Payload”.
一个最常见的XSS Payload,就是通过读取浏览器的Cookie对象,从而发起“Cookie劫持”攻击。
- 加载一个远程脚本
- 在页面中插入了一张看不见的图片,同时把document.cookie对象作为参数发送
到远程服务器。- 事实上,
http://www.evil.com/log
并不一定要存在,因为这个请求会在远程服务器的Web日志中留下记录
- 事实上,


“COOkIe劫持”并非所有的时候都会有效。有的网站可能会在Set-Cookie时给关键Cookie植入HttpOnly标识;有的网站则可能会把Cookie与客户端IP绑定
2.1.1. 构造GE丁与POST请求

2.1.2. redirect
url?redirect=javascript:alert(document.domain);
2.1.3. XSS钓鱼
比如在前文提到的“通过POST表单发消息”的案例中,如果在提交表单时要求用户输入验证码,那么一般的XSS Payload都会失效;此外,在大多数“修改用户密码”的功能中,在提交新密码前,都会要求用户输入“Old Password”。而这个“Old Password”,对于攻击者来说,往往是不知道的。
- 验证码,
- XSS Payload可以通过读取页面内容,将验证码的图片URL发送到远程服务器上来实施:攻击者可以在远程XSS后台接收当前验证码,并将验证码的值返回给当前的XSS Payload,从而绕过验证码。
- 修改密码
- 利用JavaScript在当前页面上“画出”一个伪造的登录框,当用户在登录框中输入用户名与密码后,其密码将被发送至黑客的服务器上
2.1.4. CSS History Hack
通过CSS,来发现一个用户曾经访问过的网站
其原理是利用style的visited属性—如果用户曾经访问过某个链接,那么这个链接的颜色会变得与众不同
2.1.5. 获取用户的真实IP地址
- JavaScript本身并没有提供获取本地IP地址的能力
- 调用环境API的接口获取客户端的本地IP地址
2.2. xss内网渗透
安全测试人员在测试XSS漏洞的时候,用得最多的方式是利用XSS钓鱼攻击,盗取会话凭证,挟持会话。当然还有很多其他利用方式,但是却很少涉及内网渗透环节。
利用sciprt标签加载js函数执行,然后利用html onload事件结合img标签,再把加载成功的IP,端口信息传回我们的接收端
1 | function post_data(ip,port){ |

2.3. XSS Worm

2.4. 其他
- 识别浏览器
alert(navigator.userAgent)
- 识别用户安装的软件
new ActiveObject(XunLeiBHO.Helper);
- 如果异常说明没有
2.5. XSS构造技巧
- 利用字符编码
- 利用编码不统一吃掉转义字符
- 绕过长度限制(服务器端)
- 利用事件(event):
onclick
- 更好的办法:最好的办法是把XSS Payload写到别处,再通过简短的代码加载这段XSS Payload
onclick=eval(location.hash.substr(1))
- 利用事件(event):

2.5.1. window.name

1 | <script> |
2.5.2.
需要特别注意的是,在有的技术文档中,提到<base>标签只能用于<head>标签之内,其实这是不对的。<base>标签可以出现在贞面的任何地方,并作用于位于该标签之后的所有标签。
攻击者如果在页面中插入了<base>标签,就可以通过在远程服务器上伪造图片、链接或脚本,劫持当前页面中的所有使用“相对路径”的标签。
2.5.3. 回旋镖
为浏览器同源策略的原因,XSS也受到同源策略的限制—发生在A域上的XSS很难影响到B域的用户。
回旋镖的思路就是:如果在B域上存在一个反射型“XSS_ B”,在A域上存在一个存储型”XSS_A”,当用户访问A域上的“XSS_ A”时,同时嵌入B域上的“XSS_B”,则可以达到在A域的XSS攻击B域用户的目的。
先在XSS一上写入一个<form>,自动提交到XSS_ B,然后在XSS_ B中再跳转回原来的XSS_A,即完成一个“回旋镖”的过程。但是这种攻击的缺点是,尽管跳转花费的时间很短,但用户还是会看到浏览器地址栏的变化。
3. XSS防御
3.1. HttpOnly
浏览器禁止页面的JavaScript访问带有HttpOnly属性的Cookie
- 微软提出并在IE6中实现
- 严格地说,HttpOnly并非为了对抗XSS—HttpOnly解决的是XSS后的Cookie劫持攻击。
1 | set-cookie: cookie2=test2;httponly |

HttpOnly is an additional flag included in a Set-Cookie HTTP response header
HttpOnly属性指示浏览器不要通过HTTP(和HTTPS)请求以外的渠道暴露cookie。这意味着该cookie无法通过客户端脚本语言(尤其是JavaScript)进行访问,因此无法通过跨站脚本(一种普遍的攻击技术)轻易窃取。(比如document.write(url.cookie)之类的)
例如在nginx中:
1 | server { proxy_cookie_path / "/; HTTPOnly; Secure";} |
- 整个路径“ /”将被替换
3.1.1. 攻击
Apache支持的一个Header是TRACEo TRACE一般用于调试,它会将请求头作为HTTPResponse Body返回。
3.2. 输入检查
- XSS Filter
- 如果发现存在特殊字符,则将这些字符过滤或者编码。
3.3. 输出检查
一般来说,除了富文本的输出外,在变量输出到HTML页面时,可以使用编码或转义的方式来防御XSS攻击。
- HtmlEncode
- 将字符转换成HTMLEntities
3.3.1. 富文本格式
富文本格式(Rich Text Format)即RTF格式,又称多文本格式,是由微软公司开发的跨平台文档格式。大多数的文字处理软件都能读取和保存RTF文档。

var y='"' escapeJavascript($evil)+'"'
3.3.2. 处理富文本
禁止危险标签
- iframe
- script
- base
- form
3.4. 模板的auto-excape
XSS攻击主要发生在MVC架构中的View层。大部分的XSS漏洞可以在模板系统中解决。
3.5. url xss
一般来说,如果变量是整个URL,则应该先检查变量是否以“http”开头(如果不是则自动添加),以保证不会出现伪协议类的XSS攻击
JavaScript伪协议:把j
avascript:
后面的代码当JavaScript来执行,并将结果值返回给当前页面
3.6. 防御Dom Base XSS
