Firmware Name | Firmware Version | Download Link |
---|---|---|
DAP-1562 | DAP_1562_REVA_FIRMWARE_1.10 | DAP-1562_FIRMWARE_1.10.ZIP |
The vulnerability is triggered in the pure_auth_check
function, where a NULL
pointer is dereferenced.
pure_auth_check
(located at address 0x004129E4
), the following pseudocode for the function is obtained:bool __fastcall pure_auth_check(char *a1)
{
char *v3; // $v0
char *v4; // $s3
char *v5; // $v0
const char *v6; // $s1
FILE *v7; // $v0
FILE *v8; // $s0
char *v9; // $v0
size_t v10; // $s0
char v11[100]; // [sp+18h] [-35Ch] BYREF
char v12[256]; // [sp+7Ch] [-2F8h] BYREF
char v13[500]; // [sp+17Ch] [-1F8h] BYREF
if ( !a1 || strncmp(a1, "Basic ", 6u) )
return 0;
memset(v13, 0, sizeof(v13));
v13[b64_decode(a1 + 6, v13, 500)] = 0;
v3 = strchr(v13, ':');
*v3 = 0;
v4 = v3;
if ( v13[0] )
{
memset(v11, 0, sizeof(v11));
v5 = strtok(v13, ":");
v6 = 0;
strcpy(v11, v5);
memset(v12, 0, sizeof(v12));
v7 = (FILE *)fopen64("/var/log/admin.txt", "r");
v8 = v7;
if ( v7 )
{
v6 = 0;
if ( fgets(v12, 0x100, v7) )
{
v9 = strchr(v12, ':');
v6 = v9 + 1;
*v9 = 0;
}
fclose(v8);
}
v10 = strlen(v6) - 1;
if ( v10 == strlen(v4 + 1) )
return strncmp(v6, v4 + 1, v10) == 0;
return False;
}
return False;
}
pure_auth_check
function is designed to authenticate a given input string (a1
) using a Base64-encoded credential format. It decodes the input, extracts the username and password, and compares them against stored credentials in a file (/var/log/admin.txt
). However, several security vulnerabilities and potential issues have been identified in this function.Potential Null Pointer Dereference
Description:
The function attempts to find a colon (:
) in the decoded string and null-terminate it:
v3 = strchr(v13, ':');
*v3 = 0;
If strchr
does not find a colon in v3
, it returns NULL
. Dereferencing v3
without checking if it is NULL
will result in a null pointer dereference, causing a crash.
Impact:
This can lead to a denial-of-service (DoS) condition if the input does not contain a colon.
Mitigation:
Check if v3
is NULL
before dereferencing it:
v3 = strchr(v13, ':');
if (v3) {
*v3 = 0;
} else {
return False; // Handle the error appropriately
}
Unsafe Use of strcpy
Description:
The function uses strcpy
to copy the username into the buffer v11
of size 100
bytes:
strcpy(v11, v5);
If the username extracted from the decoded string exceeds 100
bytes, this will result in a buffer overflow.
Impact:
An attacker can craft an input with a long username to overflow the buffer, potentially corrupting the stack and leading to arbitrary code execution.
Mitigation:
Use strncpy
or snprintf
to safely copy strings with a specified maximum length:
strncpy(v11, v5, sizeof(v11) - 1);
v11[sizeof(v11) - 1] = '\\0';
Uninitialized Variable v6
Description:
The variable v6
is used to store the password extracted from the file. However, if the file is empty or does not contain a valid password, v6
remains uninitialized:
v6 = 0;
if (fgets(v12, 0x100, v7)) {
v9 = strchr(v12, ':');
v6 = v9 + 1;
*v9 = 0;
}
If fgets
fails or does not find a ':
', v6
will be used uninitialized, leading to undefined behavior.
Impact:
This can cause crashes or unpredictable behavior, potentially leading to security vulnerabilities.
Mitigation:
Ensure v6
is properly initialized before use:
Potential Logic Flaw in Password Comparison
Description:
The function compares the password lengths and then performs a string comparison:
v10 = strlen(v6) - 1;
if (v10 == strlen(v4 + 1) && strncmp(v6, v4 + 1, v10) == 0)
return True;
If v6
is empty or contains only one character, strlen(v6) - 1
will result in a negative value, leading to undefined behavior in strncmp
.
Impact:
This can cause incorrect authentication results or crashes.
Mitigation:
Ensure proper handling of edge cases:
if (v6 && v6[0] != '\\0') {
v10 = strlen(v6) - 1;
if (v10 == strlen(v4 + 1) && strncmp(v6, v4 + 1, v10) == 0)
return True;
}
#!/usr/bin/env python3
import socket
host = "172.17.0.26"
port = 80
file = "./payload.txt"
f = open(file, "rb")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
request = f.read()
s.send(request)
response = s.recv(4096)
print(response.decode())
s.close()
Note the use of CRLF (Carriage Return and Line Feed) for line breaks.
GET / HTTP/1.1
SOAPAction: xxxxxxxx
Host: xxxxxxxx
Authorization: Basic xxxxxxxx
xxxxxxxx