https://xss.tesla-space.com/
xss-labs靶场实战全通关详细过程(xss靶场详解)-优快云博客
第一关
在网页右键选择查看网页源代码(之后每一关都在查看主页面后查看源代码)
可见JavaScript脚本把alert弹窗设置为了下一关的入口,绑定给了test。
我们修改网页url把test替换为
<script>alert()</script>
回车访问后成功通过这一关
第二关
可见test被绑定给了页面的输入框,为了实现我们的JavaScript代码就必须先闭合test外的两个双引号“”和input的两个书名号><。
"> <script>alert()</script> <"
构造上述代码输入进页面输入框,成功通过这一关。
第三关
比较上一关可以发现上一关的input使用双引号“”,这一关使用了单引号''。
先构建如下代码尝试
'> <script>alert()</script> <'
发现未能成功通过。
观察源代码可见我们输入的书名号被htmlspecialchars函数改成了文本的形式,但是输入的单引号‘没有被修改。
我们只用单引号,利用onmouseover函数构建一个新的测试代码
' onmouseover=javascript:alert() '
成功过关
附:htmlspecialchars函数用法
pikachu漏洞练习第二章节xss之htmlspecialchars练习收获-优快云博客
htmlspecialchars()函数把预定义的字符转换为html实体。
预定义的字符是:
&(和号)成为 &
“”(双引号)成为 "
‘’(单引号)成为 '
<(小于)成为 <
>(大于)成为 >
可用的引号类型:
ENT_COMPAT-默认。仅编码双引号。
ENT _QUOTES-编码双引号和单引号。
ENT_NOQUOTES-不编码任何引号。
附:onmouseover函数用法
onmouseover 事件发生在鼠标指针移动到元素或它的子元素上时。
将鼠标指针移动到图像上时执行 JavaScript:
<img onmouseover="bigImg(this)" src="smiley.gif" alt="Smiley">
第四关
可见中间的try harder!为输入框内容,会被h2打印出来。使用了双引号
我们构建与第三关所用类似的代码
" onmouseover=javascript:alert() "
输入到输入框中提示我们通过。
第五关
看上去和第四关的情况类似,先输入第四关代码试试。
不出意外失败了。查看源代码可见我们写入的onmouseover函数被添加一个下划线屏蔽掉了。
既然不准我们使用onmouseover函数,我们就换一种方法插入我们要输入的代码。
"> <a href=javascript:alert()>xss</a> <"
该代码利用a标签的herf属性,让我们点击到a标签时就访问对应herf网址。
出现了我们输入的a标签xss,点击就可以通过此关卡。
附:a标签的herf属性
创建指向 w3school.com.cn 的链接:
<a href="https://www.w3school.com.cn">访问 w3school.com.cn!</a>
第六关
尝试使用之前我们使用过的方法
"> <script>alert()</script> <"
" onmouseover=javascript:alert() "
"> <a href=javascript:alert()>xss</a> <"
可以看到我们输入的所有标签全部被加了下划线屏蔽掉了。
只能另外再用别的方法解题,尝试利用大小写解开。
"> <sCript>alert()</sCript> <"
成功解开题目。
第七关
我们把我们在第六关所用的测试步骤简化为一条代码
" OnMouseOver <sCriPt> <a hReF=javascript:alert()>
输入进行测试
输出后的结果在网页里变成了
"" mouseover <> <a =java:alert()>"
对比可知可能该这关使用了某种代码方法,不仅把我们输入的所有大写字符变成了小写,而且把我们输入的代码中的关键词直接删去了。比如script,herf,on。
针对这种情况我们用双写法来应对。原理是输入oonnmouseover,系统检测到on关键词删去后,剩下的字符组成onmouseover生效。
" oonnmouseover=javascrscriptipt:alert() "
尝试一下成功通过。
第八关
测试代码测试一下看看
" OnMouseOver <sCriPt> <a hReF=javascript:alert()>
所有的关键词都被在中间添加了下划线,变成了小写。说明大小写方法和双写法都不管用了。
但是可以看到这一次的代码被直接放到了href链接下,猜测可能这次并不需要像之前一下闭合代码。直接构造alert函数输入就行。
javascript:alert()
把这段代码在unicode在线编码站上在线 Unicode 编码转换 | 菜鸟工具 (jyshare.com)进行unicode编码,选择ascii转为unicode
javascript:alert()
把目标代码Unicode编码输入后就成功破解了此关。
附:unicode编码
XSS基础——浏览器自解码机制 | XUPTSEC's blog
浏览器自解码机制
浏览器在解析HTML文档时无论按照什么顺序,主要有三个过程:HTML解析、CSS解析、JS解析和URL解析,每个解析器负责HTML文档中各自对应部分的解析工作。
从图中可以看出浏览器主要做了三部分的工作。
1. HTML/SVG/XHTML 解析。解析这三种文件会产生一个DOM Tree。
2. CSS 解析,解析CSS会产生CSS规则树。
3. Javascript 解析。(暂时讨论JavaScript动态操作DOM Tree)。
4. URL解析。(这一步的先后顺序不一定,看语境)
众所周知,计算机是通过二进制流的方式进行通信的。对于浏览器与服务器的通信,可以简单的理解为服务器给浏览器返回了一长串字符串。浏览器需要识别这一长串字符串中哪些是文本字符(浏览器不需要解析,只需要显示出来),哪些是控制字符(对于HTML来说就是能够被解析为DOM Tree的字符)。作为攻击者,尽可能将用户输入的值让浏览器识别为控制字符,这样就可以造成反射XSS。
举个例子吧,比如一个意见反馈处,输入一个<img/src=1 onerror=alert(1)>
而服务器过滤了()
,所以输出给浏览器的值是<img/src=1 onerror=alert1>
。
开发者心里想:“我过滤了括号,你没有办法执行函数啦~看你怎么办~”。
所以我们可以猜出来后台大概是这么写的:
str_replace("(","",$request_value);
str_replace(")","",$request_value);
这个时候我们可以将()
替换为()
,所以$request_value == "<img/src=1 onerror=alert(1)>"
,服务器一看,OK,没什么问题,于是就写入到数据库中。所以服务器给浏览器返回的同样也是<img/src=1 onerror=alert(1)>
,但是浏览器认识()
呀,就会自动转换为<img/src=1 onerror=alert(1)>
。所以服务器根本就不认识()
,也不会进行解码,解码的过程是浏览器完成的。(真实案例)
HTML自解码
HTML有两种编码方式,进制编码和实体编码。
对于<img/src=1 onerror=alert(1)>
可以进行下面两种编码。
HTML 10进制
<img/src="1" onerror=alert(1)>
HTML 16进制
<img/src="1" onerror=alert(1)>
浏览器在解析HTML的时候将自动解码。那我们能不能将onerror=
一起编码了呢?
<img/src="1" alert(1)>
答案是不行的,因为onerror=
是控制字符,编码后将识别为文本字符,浏览器不会解析为DOM Tree。下面这种方式同理。
<div><a>test</a></div>
a标签被识别为文本字符,只显示,不解析。
实体编码一个意思,只不过把一些保留字符给解析为更加特殊的形式了而已。& < > " => < ......
JavaScript自解码
onerror=
后的字符串为js代码,所以会被js解释器自动解码,有三种编码方式:Unicode,十进制,十六进制。(下面都是用Unicode编码)
使用Unicode对js代码进行编码。
<img src="1" onerror=\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0029>
我们发现浏览器并不执行js代码,这是因为js解释器认为上面的js代码都是文本字符。所以当然不解析。在js中,单引号,双引号和圆括号等属于控制字符,编码后将无法识别。所以对于防御来说,应该编码这些控制字符。下面这种方式可以解析。
<img src="1" onerror=\u0061\u006c\u0065\u0072\u0074('\u0031')>
从浏览器解析过程中可以知道浏览器先进行HTML自解码,所以可以使用多种编码。
<img src="1" οnerrοr=\u0061\u006c\u0065\
第九关
" OnMouseOver <sCriPt> <a hReF=javascript:alert()> a "
学会unicode编码后我们的测试代码就得再加一点在后面,先输入进去。
输入之后提示我们的连接不合法。判断是系统利用某种算法将我们输入的代码替换为了这段文字进行输入。
这个网页的功能是我们输入一个链接,输入后把图片上的a标签,友情链接,跟我们输入的链接绑定herf属性。如果这个网页想要实现他正常的功能,那么当我们输入正常网页地址时他就不能执行替换操作。先输入https://www.baidu.com/试试。
最后尝试得到当我们输入http://www.baidu.com/时,我们成功点击友情链接访问了百度。
现在把百度地址和我们的攻击代码结合,用双斜杆//或/* */符号把百度的链接注释掉。
javascript:alert()//http://www.baidu.com/
依旧失败,但是可以看到我们的输入代码并没有被替换掉了。
把原代码替换为unicode编码的版本试一试(注释的部分就不替换成unicode编码了)
javascript:alert() //http://www.baidu.com
成功。
第十关
主页面没有了输入框。但是查看源代码可以看见三个属性为hidden的隐藏输入框。
利用这三个隐藏的输入框,看能不能用onmouseover函数打开alert提示框。
t_link="onmouseover="alert()"type="text
构造该代码,使得input选框代码变为
<input name="t_link" value="t_link="onmouseover="alert()"type="text" type="hidden">
第一个双引号闭合value的第一个双引号,最后text前的双引号闭合value的第二个双引号。value变成"t_link="字符,onmouseover作为我们弹出提示框的代码,而type="text"的作用是让隐藏的输入框显形。这样我们就实现代码的改写。
要把我们构造的代码插入进去就需要利用url。复制网址url,把属于h2标签的keyword=welldone字符删去组合成新的url。
http://xss.tesla-space.com/level10.php?t_link="onmouseover="alert()"type="text
http://xss.tesla-space.com/level10.php?t_history="onmouseover="alert()"type="text
http://xss.tesla-space.com/level10.php?t_sort="onmouseover="alert()"type="text
三个挨个挨个试,输入进入浏览器访问,发现只有第三个能弹出提示框
完成该题的解密。
附:html的input框标签属性
属性 | 值 | 描述 |
---|---|---|
accept |
| 规定通过文件上传来提交的文件的类型。 规定用户可以从文件输入对话框中选择哪些文件类型的过滤器(仅适用于 type="file")。 |
alt | 文本 | 规定图像的替代文本(仅适用于 type="image")。 |
autocomplete |
| 规定 <input> 元素是否应该启用自动完成。 |
autofocus | autofocus | 规定 <input> 元素应在页面加载时应自动获得焦点。 |
checked | checked | 规定在页面加载时应预先选中 <input> 元素(适用于 type="checkbox" 或 type="radio")。 |
dirname | inputname.dir | 规定将被提交的文本方向。 |
disabled | disabled | 规定应禁用 <input> 元素。 |
form | 表单 id | 规定 <input> 元素所属的表单。 |
formaction | URL | 规定提交表单时将处理输入控件的文件的 URL(适用于 type="submit" 和 type="image")。 |
formenctype |
| 规定将表单数据提交到服务器时应如何对其进行编码(适用于 type="submit" 和 type="image")。 |
formmethod |
| 定义用于将数据发送到 action URL 的 HTTP 方法(适用于 type="submit" 和 type="image")。 |
formnovalidate | formnovalidate | 定义在提交表单元素时不应对其进行验证。 |
formtarget |
| 规定在何处显示提交表单后收到的响应(适用于 type="submit" 和 type="image")。 |
height | 像素 | 规定 <input> 元素的高度(仅适用于 type="image")。 |
list | datalist_id | 引用包含 <input> 元素的预定义选项的 <datalist> 元素。 |
max |
| 规定 <input> 元素的最大值。 |
maxlength | 数字 | 规定 <input> 元素允许的最大字符数。 |
min |
| 规定 <input> 元素的最小值。 |
minlength | 数字 | 规定 <input> 元素中所需的最少字符数。 |
multiple | multiple | 规定用户可以在 <input> 元素中输入多个值。 |
name | 文本 | 规定 <input> 元素的名称。 |
pattern | 正则表达式 | 规定检查 <input> 元素值的正则表达式。 |
placeholder | 文本 | 规定描述 <input> 元素预期值的简短提示。 |
popovertarget | 元素 id | 规定要调用的弹出框元素(仅适用于 type="button")。 |
popovertargetaction |
| 规定当您单击按钮时弹出框元素会发生什么(仅适用于 type="button")。 |
readonly | readonly | 规定输入字段是只读的。 |
required | required | 规定在提交表单之前必须填写输入字段。 |
size | 数字 | 规定 <input> 元素的宽度(以字符数为单位)。 |
src | URL | 规定用作提交按钮的图像的 URL(仅适用于 type="image")。 |
step |
| 规定输入字段中合法数字之间的间隔。 |
type |
| 规定要显示的 <input> 元素的类型。 |
value | 文本 | 规定 <input> 元素的值。 |
width | 像素 | 规定 <input> 元素的宽度(仅适用于 type="image")。 |