0 x01 preface
Recently, Tenable disclosed Arcadyna network device authentication bypass vulnerability, and many manufacturers use components that generate vulnerability. Because Arcadyan device firmware manufacturers do not open source, the files downloaded from the official website support are the client software connected to the device under Windows and Linux. The vulnerability point cannot be analyzed. Here, we use the firmware of asus product DSL-AC3100, which is also affected, for device analysis. In addition, the remote command execution vulnerability of network detection ping function in the network device is solved, so as to enable the device Telentd.
0x02 Asus DSL-AC3100 firmware
We downloaded the firmware from asustek’s website. Device name: DSL-AC3100 Firmware version: DSL-AC3100_V1.10.05_build503
0x03 Authentication Bypass Vulnerability Analysis
Extract firmware package
Download the firmware package dSL-AC3100_v1.10.05_build503.w from Asus’s official website. This is a firmware file with a. W suffix that can be extracted using binwalk. This is a vulnerability in the HTTP service. The HTTPD file is in /usr/sbin/httpd.
HTTPD binary file analysis
Import HTTPD file in GHidra, automatically analyze the file, identify the various functions of the file.
FUN_0001d0c0() : FUN_0001d0c0() : FUN_0001d0c0()
undefined4 FUN_0001d0c0(int iParm1) { int iVar1; undefined4 uVar2; int iVar3; undefined4 local_52c; undefined4 local_528; undefined4 local_524; undefined4 uStack1312; undefined4 local_51c; char acStack1304 [1024]; char acStack280 [260]; Memset (acStack280, 0, 0 x100); Memset (acStack1304, 0, 0 x400); local_52c = 0; local_528 = 0; local_524 = 0; uStack1312 = 0; local_51c = 0; iVar1 = FUN_00017df0(); if (iVar1 == -1) { uVar2 = 1; } else { iVar3 = mapi_ccfg_match_str(iVar1,"ARC_SYS_LogEnable",&DAT_00046b48); iVar1 = mapi_ccfg_match_str(iVar1,"ARC_SYS_MPTEST",&DAT_00046b48); if (iVar1 == 0) { if (iVar3 ! = 0) { iVar3 = 1; } if (iVar3 ! = 0) { FUN_00017738(iParm1 + 0x76f0,&local_52c); } if (*(int *)(iParm1 + 0x774c) == 0) { uVar2 = FUN_0001b6f4(iParm1 + 0x771e,*(undefined4 *)(iParm1 + 0x76ec)); FUN_0001b8c8(iParm1,uVar2); } iVar1 = FUN_0001ce8c(*(undefined4 *)(iParm1 + 0x774c),*(undefined4 *)(iParm1 + 0x76b0), *(undefined4 *)(iParm1 + 0x76b4),*(undefined4 *)(iParm1 + 0x76b8), *(undefined4 *)(iParm1 + 0x76bc),*(undefined4 *)(iParm1 + 0x76c0), *(undefined4 *)(iParm1 + 0x76c4),*(undefined4 *)(iParm1 + 0x76c8), *(undefined4 *)(iParm1 + 0x7b34)); if (iVar1 == 1) { printf("[%s] %s login time out, reauth\n","check_auth",iParm1 + 0x76f0); FUN_00039088(1); Snprintf (acStack1304, 0 x400, "the Location: / relogin. HTM \ n \ n"); } else { if (iVar1 == 2) { printf("[%s] new user %s(%s) comes to login, check user and auth\n","check_auth", iParm1 + 0x76f0,iParm1 + 0x4c); Snprintf (acStack1304, 0 x400, "the Location: / relogin. HTM \ n \ n"); } else { if (iVar1 == 0) { printf("[%s] %s has already granted, pass\n","check_auth",iParm1 + 0x76f0); return 0; } } } if (iVar3 ! = 0) {snprintf(acStack280,0x100,"User from %s(%s) Authentication Fail.",&local_52c,iParm1 +0x76f0); append_to_file("/tmp/security_log.txt",acStack280); } FUN_00015338(iParm1,acStack1304); uVar2 = 1; } else { uVar2 = 0; } } return uVar2; }Copy the code
FUN_0001ce8c returns iVar1. If iVar1 is 2, it indicates that a new user has logged in and needs to check the user name and authentication. If the value of iVar1 is 0, the authentication succeeds. If the value of iVar1 is 1, it indicates that the verification times out and the login page is returned.
Next, check that the FUN_0001d0c0() function is referenced in FUN_0001d578(). The FUN_0001d0c0() function is the evaluate_access() function for the vulnerability.
// evaluate_access() undefined4 FUN_0001d578(undefined4 uParm1,undefined4 uParm2,int iParm3) { int iVar1; undefined4 uVar2; if (iParm3 == 0) { return 0; } iVar1 = FUN_0001d2e0(iParm3); if (iVar1 ! = 0) { if (*(int *)(iParm3 + 0x76a8) ! = 0) { return 0; } uVar2 = FUN_0001d0c0(iParm3); return uVar2; } FUN_00014510 (iParm3, 0 x193, "Unauthorized."); return 1; }Copy the code
FUN_0001d2e0() in FUN_0001d578() uses a regular expression to verify whether the IP and port in the URL comply with the specification. The FUN_0001d0c0() function is also in there, so this function is used for authentication in HTTPD, namely evaluate_access() in vulnerability analysis.
Next, let’s look at where the evaluate_access() function is called, where the real vulnerability is, and see how it circumvents authentication. Here we come to the FUN_00015058 function, which is the function of process_request.
void FUN_00015058(int iParm1) { undefined4 uVar1; char *pcVar2; char *__src; int iVar3; char *__dest; iVar3 = iParm1 + 0xd5; UVar1 = FUN_00016a84 (iVar3, 0 xd); *(undefined4 *)(iParm1 + 0x27f0) = uVar1; *(undefined4 *)(iParm1 + 0x76a4) = 0xffffffff; *(undefined4 *)(iParm1 + 0x76ac) = 0xffffffff; __src = (char *) FUN_00016a84 (iVar3, 0 x20); *(int *)(iParm1 + 0x7b18) = iVar3; pcVar2 = (char *)FUN_00016a84(__src,0x20); uVar1 = FUN_00016a84(__src,0x3f); *(undefined4 *)(iParm1 + 0x7b14) = uVar1; __dest = (char *)(iParm1 + 0x7994); strncpy(__dest,__src,0xff); *(undefined *)(iParm1 + 0x7a93) = 0; FUN_00016e3c(__dest); printf("[%s] url=[%s], args=[%s], method=[%s]\n","process_request",__dest, *(undefined4 *)(iParm1 + 0x7b14),*(undefined4 *)(iParm1 + 0x7b18)); iVar3 = FUN_00018c70(iParm1); if (iVar3 < 0) { return; } if (*pcVar2 == '\0') { *(undefined4 *)(iParm1 + 0x7988) = 1; } else { *(undefined4 *)(iParm1 + 0x7988) = 0; iVar3 = FUN_00018cb8(iParm1); if (iVar3 < 0) { return; } iVar3 = strncasecmp(*(char **)(iParm1 + 0x7620),"multipart/form-data",0x13); if ((((iVar3 ! = 0) && (*(char **)(iParm1 + 0x7b24) ! = (char *)0x0)) && (__src = strcasestr(*(char **)(iParm1 + 0x7b24),"FirmwareUpload"), __src == (char *)0x0))&& (0 < (int)(*(int *)(iParm1 + 0x7984) + (uint)(64000 < *(uint *)(iParm1 + 0x7980))))) { FUN_0000bef4(iParm1,*(undefined4 *)(iParm1 + 0xc)); FUN_00014510(iParm1,0x193,"The Content-Length is extreme large!" ); return; } } uVar1 = FUN_0000deb0(__dest); *(undefined4 *)(iParm1 + 0x76a8) = uVar1; // evaluate_access() if (((*(code **)(PTR_PTR_DAT_00054fac + 0x14) == (code *)0x0) || (iVar3 = (**(code **)(PTR_PTR_DAT_00054fac + 0x14))(iParm1), iVar3 ! = 2)) && ((*(int *)(iParm1 + 0x76a8) ! = 0 || (iVar3 = FUN_0001d578(__dest,0,iParm1), iVar3 == 0)))) { *(undefined4 *)(iParm1 + 0x798c) = 0; __src = *(char **)(iParm1 + 0x7b18); iVar3 = strcmp(__src,"HEAD"); if (iVar3 == 0) { *(undefined4 *)(iParm1 + 0x798c) = 1; if (*(int *)(iParm1 + 0x7988) == 0) { FUN_0000eb98(iParm1); } else { *(undefined4 *)(iParm1 + 0x798c) = 0; FUN_00014510 (iParm1, 400, "gave the HTTP / 0.9 method"); } } else { iVar3 = strcmp(__src,"GET"); if (iVar3 == 0) { FUN_0000eb98(iParm1); } else { iVar3 = strcmp(__src,"POST"); if (iVar3 == 0) { FUN_00014c30(iParm1); Else {FUN_00014510(iParm1,400,"Invalid or unsupported method."); } } } } return; }Copy the code
&& : logical and, and the expression is true if the conditions before and after satisfy at the same time;
Conditions before and after the | | : logic and, as long as there is a meet the expression is true.
The code below, because the logical operators && priority than | |, so will first calculating the value of &&. IParm1 + 0x76a8. If the value is not zero, then the implementation of logical operators | | expression.
((((code )(PTR_PTR_DAT_00054fac + 0x14) == (code )0x0) || (iVar3 = ((code )(PTR_PTR_DAT_00054fac + 0x14))(iParm1), iVar3 ! = 2)) && (((int )(iParm1 + 0x76a8) ! = 0 || (iVar3 = FUN_0001d578(__dest,0,iParm1), iVar3 == 0))))Copy the code
According to the FUN_00015058() function code, you can see that the value of iParm1 + 0x76a8 is obtained from FUN_0000deb0(__dest), and the value of “_dest” is shown earlier as the URL requested by the user.
If iParm1 + 0x76a8 is not 0, you can skip the authentication function evaluate_access() and execute the FUN_00014c30 function that handles the POST request directly.
Now go to the FUN_0000deb0() function and see what happens to urls
undefined4 FUN_0000deb0(char *pcParm1) { size_t __n; int iVar1; char *__s; undefined **ppuVar2; ppuVar2 = &PTR_s_/images/_00054f70; __s = PTR_s_/images/_00054f70; if (PTR_s_/images/_00054f70 == (undefined *)0x0) { return 0; } do { __n = strlen(__s); iVar1 = strncasecmp(pcParm1,__s,__n); if (iVar1 == 0) { return 1; } ppuVar2 = ppuVar2 + 1; __s = *ppuVar2; } while (*ppuVar2 ! = (char *)0x0); return 0; }Copy the code
The function compares the URL to &ptrs /images/00054f70 until it matches, and the value of &ptr_S /images/ _00054F70 is “/images/”, so you only need to request a URL with the string “/images/”, You can bypass the authentication function to access other pages.
Authentication bypass vulnerabilities have been analyzed previously, but it is not possible to bypass authentication to access any interface because the correct HTToken value is required for access. Next, we will analyze how the httoken of the device is obtained and generated. In this device, httoken is the token value of the device, and accessing the page of the device requires a given HTtoken value. According to the vulnerability disclosure, httoken is generated at the server, decrypted in the front-end JS, and finally added to the request data when requesting the server. However, the vulnerability disclosure does not specify which string httoken is generated.
I reverse engineered HTTPD to find the function that generates htToken,
undefined4 FUN_00022520(int iParm1) { int iVar1; undefined4 uVar2; undefined *puVar3; size_t sVar4; char cStack120; undefined auStack119 [107]; Memset (& cStack120, 0, 0 x65); iVar1 = FUN_00017df0(); if (iVar1 == -1) { uVar2 = 0; } else { puVar3 = (undefined *)(iParm1 + 0x7994); if (puVar3 == (undefined *)0x0) { puVar3 = &DAT_0003d274; } uVar2 = FUN_000393e0(puVar3); sprintf(&cStack120,"%lu",uVar2); sVar4 = strlen(&cStack120); FUN_00017e78 (& cStack120 sVar4, auStack119 + sVar4, 100 - sVar4); uVar2 = so_printf(iParm1, "<img title=spacersrc=\"data:image/gif; base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7%s\" border=0>" ,auStack119 + sVar4); } return uVar2;Copy the code
Next, let’s analyze the FUN_00022520 function. In the function, we can see that an img tag is generated and the SRC value is “data:image/ GIF; Base64, R0lGODlhAQABAIAAAAAAAP / / / yH5BAEAAAAALAAAAAABAAEAAAIBRAA7 + auStack119 + sVar4 “string, The value of auStack119 + sVar4 is a string processed from FUN_00017e78 function base64 and other ways, and this string is the value of htToken.
The generated IMG tag will appear in the HTML code of the device’s login.html, as shown below.
According to the method of generating httoken function to splicing the string and decrypting the token by using script pair, “372646849” in the following figure can be determined as the token of the device.
ArcBase. Decode (” image/GIF. Base64, R0lGODlhAQABAIAAAAAAAP / / / yH5BAEAAAAALAAAAAABAAEAAAIBRAA7MTU2OTQzNDE0OA = = “) according to decrypt the message, “;” The string 372646849 is the decrypted HTToken value.
0x04 Ping Command Infuses + Configuration option
In this part, vulnerability disclosure is relatively detailed. A large number of historical vulnerabilities have appeared in the function of ping network diagnosis in many network devices, such as NetGear and D-Link. Therefore, some command spliching in ping step will not be described. However, the difference of this vulnerability is that the internal configuration option ARC_TELNETD_ENABLE is used to enable telentd of the device, which can provide different ways to execute commands when the command cannot be executed in the future vulnerability mining. Let’s focus on the ARC_TELNETD_ENABLE configuration. You can view the file contents in the /sbin/arc_telnetd file. The file can obtain the ARC_TELNETD_ENABLE value. When the ARC_TELNETD_ENABLE value is 1, telnetd is enabled.
Vulnerability emersion
0 x05 summary
The root cause of this authentication bypass vulnerability lies in the lax URL authentication of the request. Originally, “/image” was used for users to request front-end static resources, but by default, no authentication was required. Finally, “/image/” was used to bypass login.
In addition, the NetGear DGN2200v1 device disclosed a while ago also has a path through the front-end static resources to bypass authentication. And I found a similar problem in the firmware of another network device.
Penetration Testing/Security Learning (full set of video, big factory face, boutique manual. Essential kit)