CVE-2022-3236复现笔记
发表于:2024-04-04 |
字数统计: 1.1k | 阅读时长: 6分钟 | 阅读量:

CVE-2022-3236复现笔记

当数据传给通过299端口传递给csc服务后,csc调用/_conf/cscvalidation/CyberAPIArch.pm 来检查传入的json对象,当json对象中有__discriminator 键时,会进入getValidationHash 函数中

Untitled

函数代码如下,可以发现调用了eval函数,并且$objNameToFetch 是可控制的,因此只要构造合适的json对象,即可进行perl的代码注入。

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
sub getValidationHash{
my $obj=shift;
my $hashObj=shift;
my $request=shift;
my $refDetails=shift;
my $secondHashObj = { %$hashObj };
#Replacing Hash Objects with sub objects
# open(FHLOG,">>/log/validationError.log");
# print FHLOG "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\n";

foreach my $key ( keys % {$hashObj}) { #key = _idscriminator
if($key eq "_discriminator"){
foreach my $curKeyDisc ( keys % {$hashObj->{$key}}) { #curkeydisc = type
print FHLOG "curKeyDisc:$curKeyDisc\\n";
$curDischash={};
$curDischash=$hashObj->{$key}->{$curKeyDisc}; #curDischash={red50:red50,}
#print "\\n\\n _discriminator Key name $key";
#This is for value loop:::
foreach my $curvalue ( keys % {$curDischash}) {
print FHLOG "curvalue:$curvalue\\n";
$objNameToFetch=$curDischash->{$curvalue}; #objNameToFetch=red50
print FHLOG "objNameToFetch:$objNameToFetch\\n";
if($curvalue eq $hashObj->{$curKeyDisc}{value}){
my $Packagei="";
if(defined $refDetails && $refDetails ne ''){
$Packagei=$refDetails;
}else{
$Packagei=ref($hashObj);
}
eval "use $Packagei";
print FHLOG "\\$$Packagei"."::"."$objNameToFetch\\n";
my $subObj=eval "\\$$Packagei"."::"."$objNameToFetch";
#Getting All keys in subobject : e.g. netid,netmask
foreach my $cKeySubObj ( keys % {$subObj}) {
$subObj->{$cKeySubObj}{value}=$request->{$cKeySubObj};
if(defined $hashObj->{$cKeySubObj} && $hashObj->{$cKeySubObj} ne ''){
my $subEntityElemtn=dclone($subObj->{$cKeySubObj});
my $hashElemnt=dclone($hashObj->{$cKeySubObj});
delete($hashElemnt->{refentity});
my %newHash=(%{$subEntityElemtn},%{$hashElemnt});
$hashObj->{$cKeySubObj}=\\%newHash;
}else{
$hashObj->{$cKeySubObj}=$subObj->{$cKeySubObj};
}
#$hashObj->{$cKeySubObj}=$subObj->{$cKeySubObj};
}
}
}
}
}
}
return $hashObj;
}

漏洞的原理就是这样,不难理解,但构造是最麻烦的,因为不知道要传一个什么样的对象。

那么如何找到正确的格式呢,笔者这里修改了csc的配置文件。

csc加载配置文件时,先对其进行解密,然后解包,逆向解密代码后发现,它每次读0x420字节,但只解密了0x10~0x410这0x400字节,其余0x20字节没有动,但同时代码也没有这0x20字节进行检查,因此是可以还原.bin配置文件的。

Untitled

修改配置文件,添加输出命令,将传入的json对象解析并输出到log中,就可以知道对象结构了。

Untitled

一些日志如下

Untitled

Untitled

重打包代码

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
num1=[0x7F,0x90,0x0F9,0x0AB,0x0E,0x0CE,0x0B2,0x90,0x0AE,0x2F,0x59,0x0F1,0x0D0,0x0AD,0x0B7,0x11,0x7A,0x6A,0x4B,0x54,0x1A,0x9B,0x4D,0x71,0x0C5,0x8F,0x0ED,0x65,0x0D2,0x19,0x5C,0x0CD,0x0E8,0x1A,0x0EE,0x0D9,0x5D,0x1F,0x0F1,0x90,0x0B7,0x8E,0x5D,0x0D7,0x8,0x0E0,0x0C3,0x98,0x0C9,0x65,0x0ED,0x3B,0x0AC,0x0A0,0x0A1,0x0A3,0x0C2,0x0B3,0x0F,0x0DD,0x0EE,0x0A6,0x9A,0x0E9]
num2=[0x0B3,0x0C0,0x0D4,0x0AC,0x24,0x0B9,0x93,0x0D8,0x62,0x5E,0x5D,0x0FC,0x18,0x37,0x0F4,0x3F,0x4A,0x39,0x94,0x4C,0x0E4,0x12,0x98,0x0DC,0x36,0x0A0,0x4E,0x4D,0x1F,0x10,0x5C,0x5C,0x3D,0x6B,0x46,0x61,0x0E,0x5C,0x6F,0x4A,0x0BB,0x73,0x0BA,0x0A7,0x34,0x0A7,0x21,0x0EF,0x79,0x32,0x51,0x7A,0x0A4,0x0DC,0x90,0x0F6,0x16,0x87,0x0FA,0x0C0,0x58,0x64,0x12,0x44]
num3=[0x0AD,0x27,0x5A,0x0BD,0x5E,0x56,0x0A,0x0CA,0x5A,0x7F,0x0D0,0x0A0,0x87,0x2A,0x0A6,0x6B,0x83,0x34,0x0D8,0x0CD,0x6A,0x58,0x5F,0x1C,0x0B2,0x0B7,0x0BC,0x40,0x9E,0x44,0x25,0x8F,0x0F3,0x0C2,0x74,0x1F,0x50,0x0F1,0x7A,0x76,0x45,0x7C,0x50,0x99,0x29,0x0F6,0x90,0x0AA,0x20,0x8F,0x4D,0x64,0x18,0x0DA,0x46,0x0E9,0x9B,0x9C,0x48,0x7C,0x0B7,0x0DA,0x0F,0x46]
num_key=[0]*64
file_64_int=[0]*1024
file_64_int_18=[0]*1024

for i in range(64):
num_key[i] = num3[i] ^ ((num2[i] * num1[i]) % 0xFF)
#print(len(num_key))
with open('cscconf18.bin','rb') as f:
f.seek(0,2)
file_len=f.tell()
#print(file_len)
f.seek(0,0)
t = open('cscconf18_5.bin','wb')
g = open('cscconf18_5.tar.gz','rb')
g.seek(0,2)
file_len_18=g.tell()
#print(file_len)
g.seek(0,0)
# print(file_len)
# print(file_len_18)
for a in range((file_len_18//0x400) + 1):
if file_len > 0x41f:
file_64_bytes=f.read(0x420)
#print(len(file_64_int))
t.write(bytes(file_64_bytes[:0x10]))


# t = open('cscconf18.bin','wb')

if file_len_18 > 0x3ff:
file_64_bytes_18=g.read(0x400)
#print(len(file_64_int))
j = 0
for i in range(1024):
#print(i)
file_64_int_18[i] = file_64_bytes_18[i] ^ (num_key[j])
j += 1
if j > 63:
j = 0

t.write(bytes(file_64_int_18))
file_len_18 -= 0x400
else:

break

t.write(bytes(file_64_bytes[0x410:]))
file_len -= 0x420
elif file_len_18 > 0x3ff:
t.write(b'\\xff'*0x10)
file_64_bytes_18=g.read(0x400)
#print(len(file_64_int))
j = 0
for i in range(1024):
#print(i)
file_64_int_18[i] = file_64_bytes_18[i] ^ (num_key[j])
j += 1
if j > 63:
j = 0

t.write(bytes(file_64_int_18))
t.write(b'\\xff'*0x10)
file_len_18 -= 0x400
else:
t.write(b'\\xff'*0x10)
file_64_bytes_18_remain=g.read(file_len_18)
j = 0
for i in range(file_len_18):
#print(i)
file_64_int_18[i] = file_64_bytes_18_remain[i] ^ (num_key[j])
j += 1
if j > 63:
j = 0
t.write(bytes(file_64_int_18[:file_len_18]))
t.write(b'\\xff'*0x10)
break

t.close()
g.close()

Untitled

参考

CVE-2022-3236:SOPHOS防火墙用户门户和WEB管理代码注入 | CN-SEC 中文网

Zero Day Initiative — CVE-2022-3236: Sophos Firewall User Portal and Web Admin Code Injection

上一篇:
日志
下一篇:
CVE-2022-1040复现笔记