Exploit research

1. Initial findings

1.1 checksec

$ pwn checksec gn-httpd
[*] '/home/user/linksys-e1200-v2/gn-httpd'
    Arch:     mips-32-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x400000)
    RWX:      Has RWX segments

We can see that the gn-httpd binary does not have any form of protection

1.2 objdump

Note that the objdump binary used is from the binutils-mipsel-linux-gnu library

$ sudo apt install binutils-mipsel-linux-gnu
$ ls /usr/mipsel-linux-gnu/bin
ar  as  gold  ld  ld.bfd  ld.gold  nm  objcopy  objdump  ranlib  readelf  strip

$ /usr/mipsel-linux-gnu/bin/objdump -d --disassemble=get_merge_ipaddr gn-httpd

2. GDB, gdbserver

2.1 Compile gdbserver for the target's architecture

To start off, we have to retrieve the gdbserver binary for our target architecture mipsel (mips little-endian):

Due to limited space on the device, we can only store a few selected binaries at once. In this case, this will be gdbserver.

Remember to always check the available memory space available on the device, before transferring files

2.2 gdbserver on target router

Next, we can run gdbserver on the target router:

We can use the steps outlined in the previous sectionsarrow-up-right to transfer the gdbserver binary from host to the device

Alternatively, launch from PID of a running program:

2.3 Connect to remote target from host machine

  • To debug (using gdb-multiarch) from the host machine

NOTE: the normal gdb will not work since it does not support the mips architecture

  • Since we know that our router uses the mipsel architecture (simply mips with little-endian), we have to set it up appropriately

3. Initial enumeration

3.1 Webpage @port 80

Upon navigating to the side, we are prompted for a username and password. A simple search in a search engine for "linksys e1200 default credentials" yields the following results:

https://netstorage.ringcentral.com/datasheets/routers/linksys/e1200_v06.1.pdfarrow-up-right

The username and password combination is admin, admin

3.2 index.asp

file-download
59KB

Note that this web page automatically loads the index.asp file. This information will be useful for further analysis in the later steps

The index.asp file can be found in the /www directory (/www/index.asp)

From the initial research (in the Initial research page), we can understand that most of the CVEs found are relating to the httpd binary. Looking further into the description of each, we can see that quite a few of them involves CGI functions (CVE-2025-60689arrow-up-right, CVE-2025-60690arrow-up-right, CVE-2025-60691arrow-up-right, CVE-2025-60693arrow-up-right, CVE-2025-60694arrow-up-right)

Let's start off by searching for the term ".cgi" in the index.asp file. Right off the bat, we find the following code snippet:

3.2.1 Extract information

  • We can extract the following information:

  1. Identifier for this form (name=setup)

  • likely referenced by:

    • document.setup

    • document.forms["setup"]

  1. CGI action (action=apply.cgi)

  • The /apply.cgi path will be called

3.2.2 Identifying form identifier locations

We can attempt to identify the functions that handles the form action by searching for the following values:

  • document.setup

    • multiple results

  • document.forms["setup"] (or document.forms['setup'])

    • none

3.2.3 Interesting code locations of document.setup

  1. Passed as arguments to functions

The following shows a code snippet where document.setup was passed as argument to the reboot() function:

  • From the reboot() function, we can observe that it accepts the argument value of document.setup as the variable F

  • We can also observe similar patterns for other functions:

    • ppp_enable_disable

    • dhcp_enable_disable

    • dslite_enable_disable

    • mtu_enable_disable

  1. Assigned to local variable in a function

  • This can be found in the selpptppmode() function too

3.2.4 Identifying form action handler(s)

In JavaScript, the submit method can be called on the document.name instance to trigger a form action

Thus, we can perform a search for the value .submit (or more specifically .submit()), in order to identify the functions that handles the form action

NOTE: we can also search directly for the term: F.submit()

The code snippet can be found in the following functions:

  1. selWan

  2. selPPP

  3. reboot

  4. to_submit

  5. selLang

From the results, we should observe that most of the functions will have the following code:

  • This supports our observation from the previous analysis, where the variable name F is commonly used to reference the document.setup instance

The following functions are invoked by a certain HTML form present on the web page:

  1. selWan

  2. reboot

  3. selLang

Refer to the subsequent CVE sections to understand how we can trigger the found functions

Last updated