恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。XSS攻击针对的是用户层面的攻击!
反射型XSS 是非持久性、参数型的跨站脚本。反射型XSS 的JS 代码在Web应用的参数(变量)中,如搜索框的反射型XSS。在搜索框中,提交PoC[scriptalert(/xss/)/script],点击搜索,即可触发反射型XSS。注意到,我们提交的poc 会出现在search.php 页面的keywords 参数中。
存储型XSS 是持久性跨站脚本。持久性体现在XSS 代码不是在某个参数(变量)中,而是写进数据库或文件等可以永久保存数据的介质中。存储型XSS 通常发生在留言板等地方。我们在留言板位置留言,将恶意代码写进数据库中。此时,我们只完成了第一步,将恶意代码写入数据库。因为XSS 使用的JS 代码,JS 代码的运行环境是浏览器,所以需要浏览器从服务器载入恶意的XSS 代码,才能真正触发XSS。此时,需要我们模拟网站后台管理员的身份,查看留言。
DOM XSS 比较特殊。owasp 关于DOM 型号XSS 的定义是基于DOM 的XSS 是一种XSS 攻击,其中攻击的payload由于修改受害者浏览器页面的DOM 树而执行的。其特殊的地方就是payload 在浏览器本地修改DOM 树而执行, 并不会传到服务器上,这也就使得DOM XSS 比较难以检测。
从上图源码可知,在箭头1处将get方式传递到服务器端的keyword参数的值赋给str变量。在箭头2处是用htmlspecialchars()函数对变量str进行处理之后显示到网页上。但是在箭头3处却是直接将变量值插入到了input标签value属性值中,因为这里并没有对敏感字符进行编码和过滤,所以可以通过构造实现XSS攻击。
<input name=keyword value="" > scriptalert('xss')/script //"
Level 3
onfocus是javascript中在对象获得焦点时发生的事件,最简单的实例就是网页上的一个输入框,当使用鼠标点击该输入框时输入框被选中可以输入内容的时候就是该输入框获得焦点的时候,此时输入框就会触发onfocus事件.因此点击当前页面的输入框就可以完成弹框了。
http://localhost/level3.php?keyword=scriptalert('xss')/script&submit=搜索
Level 4
原来如此,在服务器端先是将传递过来的keyword参数的值赋给str变量,然后经过箭头1和箭头2处的处理将变量值中包含的<、>符号删除。最后在箭头3处对变量值进行编码处理之后显示在页面之上,在箭头4处将去除特殊符号后的变量值插入到input标签的value属性值中。
http://localhost/level4.php?keyword="οnfοcus=javascript:alert('xss') "
Level 5
从源码来看,服务器端先是将传递过来的参数值转换为全小写之后赋值给变量str,接着就是通过str_replace()函数来破坏变量值中的敏感字符的语义。最后在箭头4处通过htmlspecialchars()函数处理之后显示到网页上,在箭头5处直接将进行敏感字符处理之后的变量值插入到input标签的value属性值中。
http://localhost/level5.php?keyword="> <a href=javascript:alert('xss') > xss/a//
Level 6
从源码来看服务器端做的防护措施比我们想象的要多得多。接下来也会根据图中的一些代码来提一提在前五关中没有提过的执行js代码的其他一些方式。
从箭头1的地方可以看到是用字符
于是直接显示
RCDATA`元素(RCDATA elements)包括`textarea`和`title
6
<textarea><script>alert(6)</script></textarea>
同5,不解释
7
<button onclick="confirm('7');">Button</button>
这里onclick
中为标签的属性值(类比2中的href
),会被HTML解码,得到
然后被执行
8
<button onclick="confirm('8\u0027);">Button</button>
onclick
中的值会交给JS处理,在JS中只有字符串和标识符能用Unicode表示,'
显然不行,JS执行失败
9
<script>alert(9);</script>
script
属于原始文本元素(Raw text elements),只可以容纳文本,注意没有字符引用,于是直接由JS处理,JS也认不出来,执行失败
原始文本元素(Raw text elements)有和
10
<script>\u0061\u006c\u0065\u0072\u0074(10);</script>
同8,函数名alert
属于标识符,直接被JS执行
11
<script>\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0031\u0029</script>
同8,不解释
12
<script>\u0061\u006c\u0065\u0072\u0074(\u0031\u0032)</script>
这里看似将没毛病,但是这里\u0031\u0032
在解码的时候会被解码为字符串12
,注意是字符串,不是数字,文字显然是需要引号的,JS执行失败
13
<script>alert('13\u0027)</script>
同8
14
<script>alert('14\u000a')</script>
\u000a
在JavaScript里是换行,就是\n
,直接执行
Java菜鸡才知道在Java里\u000a
是换行,相当于在源码里直接按一下回车键,后面的代码都换行了
15
<a href="javascript:%5c%75%30%30%36%31%5c%75%30%30%36%63%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(15)"></a>
先HTML解码,得到
在href中由URL模块处理,解码得到
javascript:\u0061\u006c\u0065\u0072\u0074(15)
识别JS协议,然后由JS模块处理,解码得到
javascript:alert(15)
最后被执行
1. 空元素(Void elements),如<area>,<br>,<base>等等
2. 原始文本元素(Raw text elements),有<script>和<style>
3. RCDATA元素(RCDATA elements),有<textarea>和<title>
4. 外部元素(Foreign elements),例如MathML命名空间或者SVG命名空间的元素
5. 基本元素(Normal elements),即除了以上4种元素以外的元素
1. 空元素,不能容纳任何内容(因为它们没有闭合标签,没有内容能够放在开始标签和闭合标签中间)。
2. 原始文本元素,可以容纳文本。
3. RCDATA元素,可以容纳文本和字符引用。
4. 外部元素,可以容纳文本、字符引用、CDATA段、其他元素和注释
5. 基本元素,可以容纳文本、字符引用、其他元素和注释
这里涉及三轮解码,顺序是HTML>URL>JavaScript