第二届帕鲁杯【parloo杯】Web WriteUp

一、前言

好久没打ctf了,帕鲁杯第二届来了,应急响应环境需要70G,燃尽了,应急响应不打了,所以来看看Web题目。
在这里插入图片描述

二、解题过程

1、CatBank解题思路

第一步,启动题目环境,分别创建test1和test2两个账户
第二步,登陆test账户,直接向test2账户转账1000000

在这里插入图片描述
第三步,登陆test2账户,向Morscerta的猫猫转账1000000,得到flag
在这里插入图片描述

2、猫猫的秘密解题思路

第一步,启动题目环境,查看网页源码,发现如下js代码,从代码中得知存在get_secret接口,同时需要Authorization进行认证,Authorization一些常见的认证授权方案如:Basic认证、Digest认证、Beare认证、JWT认证等,经过测试这里为JWT认证

<script>
        let token = '';
        
        document.getElementById('loginBtn').addEventListener('click', async () => {
            const username = document.getElementById('username').value;
            const password = document.getElementById('password').value;
            
            try {
                const response = await fetch('/login', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({ username, password })
                });
                
                const data = await response.json();
                
                if (response.ok) {
                    token = data.token;
                    document.getElementById('loginResult').textContent = `登录成功: ${data.message}`;
                    document.getElementById('loginResult').classList.remove('hidden');
                    document.getElementById('loginSection').classList.add('hidden');
                    document.getElementById('secretSection').classList.remove('hidden');
                } else {
                    document.getElementById('loginResult').textContent = `错误: ${data.error}`;
                    document.getElementById('loginResult').classList.remove('hidden');
                }
            } catch (error) {
                document.getElementById('loginResult').textContent = `发生错误: ${error.message}`;
                document.getElementById('loginResult').classList.remove('hidden');
            }
        });
        
        document.getElementById('getSecretBtn').addEventListener('click', async () => {
            try {
                const response = await fetch('/get_secret', {
                    method: 'GET',
                    headers: {
                        'Authorization': token
                    }
                });
                
                const data = await response.json();
                
                if (response.ok) {
                    let resultText = `${data.message}\n\n`;
                    
                    if (data.public) {
                        resultText += `${data.public}\n\n`;
                    }
                    
                    if (data.confidential) {
                        resultText += `猫猫信息: ${data.confidential}\n\n`;
                    }
                    
                    if (data.flag) {
                        resultText += `Flag: ${data.flag}`;
                    }
                    
                    document.getElementById('secretResult').textContent = resultText;
                } else {
                    document.getElementById('secretResult').textContent = `错误: ${data.error}`;
                }
                
                document.getElementById('secretResult').classList.remove('hidden');
            } catch (error) {
                document.getElementById('secretResult').textContent = `发生错误: ${error.message}`;
                document.getElementById('secretResult').classList.remove('hidden');
            }
        });
        
        document.getElementById('logoutBtn').addEventListener('click', () => {
            token = '';
            document.getElementById('username').value = '';
            document.getElementById('password').value = '';
            document.getElementById('loginResult').classList.add('hidden');
            document.getElementById('secretResult').classList.add('hidden');
            document.getElementById('secretSection').classList.add('hidden');
            document.getElementById('loginSection').classList.remove('hidden');
        });
    </script>

在这里插入图片描述
第二步,发现报错“Invalid token: Invalid algorithm”,意思是说jwt的算法无效,jwt算法存在漏洞CVE-2015-9235,可以将header中签名算法改为none进行绕过
在这里插入图片描述
在这里插入图片描述
第三步,这里已经成功利用了漏洞,并且或得到了public数据,但是距离获得flag还差一步,既然是public那就是公共的,猜测可能是权限不够高,于是尝试构造jwt的payload部分,和权限相关的常见字符串如:role,account,isAdmin等,这里发现是role,于是构造jwt的payload部分如下所示,成功得到flag
在这里插入图片描述

3、CatNet解题思路

第一步,启动题目环境,使用dirsearch可以直接扫描出admin目录
在这里插入图片描述
第二步,访问admin目录发现无权限,并且提示只有本地可以访问,显而易见是xff伪造
在这里插入图片描述
在这里插入图片描述
第三步,点击Get Flag功能出线报错,报错提示同样需要xff伪造
在这里插入图片描述
在这里插入图片描述
第四步,xff伪造之后又提示Incorrect code,查看网页源码发现如下js代码,大概意思就是点击getflag功能会调用/admin/flag接口,同时设置请求头X-Internal-Auth: cateye-internal-000,根据提示Incorrect code猜测不是000
在这里插入图片描述
第五步,截取数据包,利用burp进行爆破,得到正确code为123
在这里插入图片描述

4、ezblog解题思路

第一步,启动题目环境,下载题目附件,使用反编译工具审计代码,在dashboard.class中有一个backdoor路由,realkey是不知道的,想要得到flag就必须得知道realkey
在这里插入图片描述
第二步,继续审计App.class文件,App.class中路由了一个/assets,FileStaticRepository设置了基础目录/app/assets
在这里插入图片描述
第三步,从App.class跟踪到FileStaticRepository.class文件,代码如图所示,这里的relativePath是一个可控参数,solon框架中这个参数是通过url路径传输过来的,relativePath就是/assets/后面的内容,如果构造恶意payload在url中表现为:http://x.x.x.x/assets/…/etc/passwd
在这里插入图片描述
第四步,在App.class中提到了基础目录为/app/assets,再结合backdoor中需要知道realkey,所以猜测/app目录下可能存在真实的app.jar,于是构造payload为:/assets/…/app.jar,这里需要注意,直接在url中访问会一直跳转,所以这里用burp截包forward之后下载,如下图所示
在这里插入图片描述
在这里插入图片描述
第五步,利用反编译工具打开下载后的app.jar得到realkey,利用realkey成功得到flag
在这里插入图片描述
在这里插入图片描述

5、catshell解题思路

太难了,我最讨厌绕过waf😄

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值