설정값 한 줄이 스택을 넘어설 때 — 임베디드 CGI의 오래된 병

설정값 한 줄이 스택을 넘어설 때 — 임베디드 CGI의 오래된 병

분류: CVE · 네이티브·임베디드 · 스택 오버플로우→RCE(추정) · CVE-2026-77946 · [표준]

덱. TRENDnet TEW-821DAP 무선 AP(액세스 포인트)의 시간대 설정 화면이, 사용자가 넣은 NTP 서버 주소 같은 설정값을 고정 크기 스택 버퍼에 검증 없이 복사하다 넘칩니다(CVSS 3.1 만점 10.0). 웹 취약점을 다루다 보면 드물게 만나는 부류 — 파라미터 하나가 SQL이나 스크립트가 아니라 네이티브 메모리를 건드리는 경우입니다. 왜 이 흔한 병이 유독 임베디드 CGI에서 반복되는지가 이 글의 주제입니다.

개요

CVE-2026-77946은 TRENDnet TEW-821DAP 펌웨어 2.2.01b05의 스택 기반 버퍼 오버플로우입니다. 취약한 곳은 /cgi-bin/apply_time.cgi가 처리하는 **NTP 시간대 설정 핸들러(NTP Timezone Configuration Handler)**이고, 문제의 함수는 uci_safe_get입니다. 공격자가 system.ntp.server, system.ntp.enable_server, cameo.time.time_zone, cameo.cameo.syslog_server 같은 설정 인자를 조작하면 스택 버퍼가 넘칩니다. 원격에서 트리거할 수 있고, 기술 write-up과 PoC(개념 증명)가 이미 공개된 상태입니다.

CVSS는 3.1 기준 10.0(치명적), 벡터는 AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H — 네트워크 너머에서, 낮은 공격 난이도로, 권한도 사용자 조작도 없이, 심지어 **범위 변경(S:C)**까지 걸린 만점입니다. CVSS 4.0으로는 9.3(치명적)이고, 분류는 CWE-119(버퍼 경계 밖 접근)와 CWE-121(스택 기반 버퍼 오버플로우)입니다. CVE 발급 CNA는 VulDB로 자동화 비중이 큰 출처이며, 이 CVE의 실질 기술 근거는 dxz0069의 공개 write-up입니다(아래 참고자료). NVD 등재는 2026-08-22, 상태는 Deferred입니다. (참고로 write-up 저자의 자가 채점은 CVSS 9.8/S:U였으나, CVE 공식 레코드는 범위 변경을 반영해 10.0/S:C로 등재됐습니다 — 본 글은 공식값을 따릅니다.) 확정된 advisory 범위는 “원격 트리거 가능한 스택 오버플로우”까지이고, 완성된 원격 코드 실행(RCE)은 이 부류에서 흔히 이어지는 결과로 예상되는 것이지 advisory가 별도로 확정한 사실은 아닙니다.

기술 배경 (30초)

스택 버퍼 오버플로우는 프로그램이 함수 실행 중 임시로 쓰는 메모리 공간(스택)에 마련한 **고정 크기 상자(버퍼)**에, 상자보다 큰 데이터를 넣을 때 생깁니다. 넘친 데이터는 옆 칸을 덮어씁니다. 스택에는 “이 함수가 끝나면 어디로 돌아갈지”를 적어 둔 반환 주소가 함께 놓여 있어서, 이 값을 공격자가 원하는 대로 덮으면 프로그램의 실행 흐름을 가로챌 여지가 생깁니다 — 이것이 이 부류가 단순한 오작동을 넘어 코드 실행으로 이어질 수 있는 이유입니다.

임베디드 기기의 웹 설정 화면은 대개 CGI(Common Gateway Interface) 프로그램으로 돌아갑니다. PHP 같은 관리 언어가 아니라, 대부분 C로 짠 작은 네이티브 실행 파일이 요청을 직접 파싱합니다. 이 CVE의 uci_safe_get은 이름으로 미루어(uci = OpenWrt 계열 기기가 널리 쓰는 통합 설정 인터페이스, Unified Configuration Interface) 설정 저장소에서 값을 읽어 오는 함수로 보입니다. “safe”라는 이름이 붙어 있지만, 여기서 안전이 보장되는 지점이 어디까지인지가 이 사건의 핵심입니다.

CVE 분석 요약

공개된 write-up과 advisory에 근거하면, 결함의 골격은 임베디드 세계에서 교과서처럼 반복되는 형태입니다. 사용자가 설정 화면에서 NTP 서버 주소나 시간대, syslog 서버 같은 값을 넘기면 apply_time.cgi가 이를 받아 처리하는데, 이 과정에서 길이 확인 없이 고정 크기 스택 버퍼로 문자열을 복사한다는 것입니다. 넣는 값의 길이를 공격자가 정하므로, 버퍼 크기를 넘기는 순간 스택이 넘칩니다.

개념적으로 단순화하면 다음과 같은 구조입니다.

// 개념용 단순화 — 실제 소스/페이로드 아님
void handle_ntp_config(request) {
    char buf[64];                       // 고정 크기 스택 버퍼(크기는 예시)
    char *val = uci_safe_get("system.ntp.server");  // 사용자가 넣은 값
    // (빠진 단계) val 길이가 buf 크기 이하인지 검사 X
    strcpy(buf, val);                   // 길이 무관하게 통째로 복사 → 넘침
    // ... buf 사용 ...
}

개념용 단순화 — 실제 소스/페이로드 아님. 함수·인자 이름과 복사 방식(strcpy)은 advisory·write-up에 근거하며, 버퍼 크기·오프셋은 무해화를 위해 옮기지 않았습니다(바이너리 직접 재확인은 안 함).

핵심은 화려한 결함이 아니라 **“바깥에서 들어온 길이 모를 문자열을, 크기가 정해진 그릇에 확인 없이 부었다”**는 한 지점입니다. system.ntp.server 하나든 cameo.cameo.syslog_server든, advisory가 나열한 네 인자는 결국 같은 실수의 서로 다른 입구입니다. 여기서 uci_safe_get은 값을 “가져오는” 일까지는 하지만, 그 값을 어떤 그릇에 담을지에 대한 안전은 호출하는 쪽 책임입니다 — 이름의 “safe”가 커버하지 못하는 경계가 바로 여기입니다.

주의(정직성). 위 코드는 개념 설명용입니다. 공개 write-up은 취약 복사를 미검증 strcpy() 로 특정하고, 심볼릭 실행(symbolic execution)으로 반환 주소(PC) 제어까지 확인했습니다. 다만 실제 기기에서의 결과는 “충돌 가능성(may crash)” 수준으로만 기술돼 있어, 심볼릭 모델에서 확인된 PC 제어가 실기기 코드 실행으로 그대로 이어지는지는 write-up 자체가 검증하지 않았습니다. 정확한 버퍼 크기·스택 레이아웃·오프셋은 무해화를 위해 본문에 옮기지 않았고, 바이너리를 직접 열어 재확인하지도 않았습니다. 따라서 “코드 실행이 어디까지 실제로 되는가(RCE 성립)“는 공개 write-up의 서술과 이 부류의 일반적 성질에 기댄 추정으로 둡니다.

공격 시나리오 · 영향도 + 대응방안

시나리오(개념). ① 원격 공격자가 AP의 웹 관리 인터페이스(/cgi-bin/apply_time.cgi)에 도달합니다. → ② 시간대·NTP 설정 요청에 문제의 인자(예: system.ntp.server)를 버퍼 크기를 넘는 긴 값으로 채워 보냅니다. → ③ 핸들러가 길이 검사 없이 스택 버퍼로 복사하며 스택이 넘칩니다. → ④ 넘친 데이터가 반환 주소 등을 덮어 실행 흐름이 교란되고, 조건이 맞으면 공격자가 심은 흐름으로 넘어갈 수 있습니다. (작동하는 익스플로잇·셸코드·페이로드는 싣지 않습니다.)

영향도. 확정된 범위는 원격 트리거 가능한 스택 오버플로우입니다. 최소한 기기의 비정상 종료·재부팅(가용성 훼손)이 예상되며, 이 부류에서 흔히 그렇듯 조건이 갖춰지면 네이티브 코드 실행으로 이어질 가능성이 있습니다(예상 — advisory가 별도 확정한 것은 아님). AP/라우터에서 코드 실행이 성립하면 네트워크 관문 장악, 트래픽 가로채기, 내부망 침투 발판으로 번질 수 있습니다. CVSS 벡터의 S:C(범위 변경)는 취약 컴포넌트를 넘어 다른 자원까지 영향이 퍼질 수 있다는 평가를 반영합니다. 노출 조건은 “취약 펌웨어(2.2.01b05)로 동작하며 관리 인터페이스에 공격자가 도달 가능”입니다.

대응방안.

  1. 근본 — 패치 펌웨어 확인, 다만 현실적으로는 기기 교체를 검토. 이 기기(TEW-821DAP v1.xR 계열)는 TRENDnet 공식 다운로드 페이지 기준 2023년 4월(2.02B01) 이후 펌웨어 갱신이 없고, 공식 지원 페이지도 “현재 판매하지 않는 제품”으로만 응답합니다. 복수의 독립 보안 인텔리전스 소스는 이 제품군이 **이미 수년 전 단종(EOL)**되어 벤더가 더 이상 업데이트를 제공하지 않는다고 전합니다(단, TRENDnet의 공식 EOL 공지 원문 URL은 이 팩트체크에서 직접 확보하지 못했으므로 “확정 사실”이 아니라 “강한 정황 증거”로 표기합니다). 따라서 아래 완화조치는 “패치 나올 때까지의 임시 방편”이 아니라 사실상 영구적인 대응으로 취급하는 것이 현실적이며, 가능하다면 지원되는 기기로 교체를 검토해야 합니다.
  2. 완화(패치 전 / 업데이트 불가 시).관리 인터페이스 노출 차단 — 웹 관리 화면을 인터넷은 물론 일반 사용자 네트워크에서도 접근 못 하게 막고, 관리 접속을 별도 관리망/VLAN으로 세그먼트 분리합니다(이 부류의 원격성은 “관리 화면에 도달 가능”에 전적으로 기댑니다). ▲기본 관리자 자격증명 변경 및 원격 관리 기능 비활성화. ▲가능하면 앞단 방화벽/리버스 프록시에서 /cgi-bin/apply_time.cgi로 향하는 외부 요청과 비정상적으로 긴 설정 파라미터를 차단.
  3. 탐지 관점. 설정 CGI 엔드포인트로 들어오는 요청 중 비정상적으로 긴 NTP/시간대/syslog 파라미터, 그리고 설정 저장 직후의 기기 재부팅·프로세스 크래시 로그를 신호로 봅니다. 관리 화면에 대한 인증 실패·비정상 접근 시도의 급증도 함께 살핍니다.

결론

한 줄 요약. 임베디드 기기의 설정 화면은 “폼 하나”처럼 보이지만, 그 값을 받는 쪽은 길이를 스스로 지켜야 하는 C 코드입니다. 그 한 걸음 — 그릇 크기 확인 — 을 빼먹으면 설정값 한 줄이 스택을 넘어섭니다.

이 부류가 임베디드 CGI에서 유독 반복되는 이유는 구조적입니다. 첫째, 요청을 파싱하는 주체가 메모리 안전을 언어 차원에서 보장하지 않는 C 네이티브 코드입니다. 둘째, 자원이 빠듯한 기기라 값을 고정 크기 스택 버퍼에 담는 관행이 흔하고, 셋째, 설정값은 “관리자가 넣는 신뢰할 만한 값”이라는 암묵적 전제가 길이 검증을 건너뛰게 만듭니다. 웹 개발자에게는 낯선 실수지만, 네이티브 세계에서는 40년 된 고전입니다 — 다만 무대가 서버에서 라우터·AP·IoT로 옮겨 왔을 뿐입니다. 이번 한 틈은 (패치가 나오면) 고쳐지겠지만, “바깥 입력의 길이를 그릇이 감당하는지 확인한다”는 방법은 다음 CGI, 다음 펌웨어에서 또 필요해집니다 — 그래서 우리는 개별 CVE가 아니라 그 방법을 남깁니다.

References / 참고자료

  1. dxz0069 (GitHub) — 이 글이 재구성한 원 분석(공개 기술 write-up + PoC). ⚠️ 저장소 이름은 다른 기기(WAVLINK 커맨드 인젝션)에서 따온 것이며, 본 CVE는 TRENDnet의 스택 오버플로우입니다(커맨드 인젝션과 혼동 금지). “TEW-821DAP ssi NTP Timezone Config Stack Overflow.” https://github.com/dxz0069/WAVLINK-WN530H4-Command-Injection-in-set_add_routing/blob/main/TEW-821DAP_ssi_NTP_Timezone_Config_Stack_Overflow.md
  2. VulDB — CVE-2026-77946 (발급 CNA, cna@vuldb.com). CVSS·CWE·영향 버전 근거. https://vuldb.com/cve/CVE-2026-77946
  3. NVD — CVE-2026-77946. CVSS 3.1 = 10.0 / 4.0 = 9.3, CWE-119·CWE-121, 등재 2026-08-22, 상태 Deferred.
  4. infiltr8 Lab, “서버가 ‘믿을 만한 데이터’라고 착각하는 순간 — React2Shell” — “시스템이 바깥에서 넘어온 입력을 검증 없이 신뢰했다”는 같은 뿌리를 다른 계층(웹)에서 다룬 우리 글.

이 글은 위 공개 write-up과 VulDB/NVD advisory를 우리 관점에서 다시 쓰고 논평을 더한 것입니다. 특정 문장·코드를 그대로 옮기지 않았으며, 작동하는 익스플로잇/셸코드/페이로드는 싣지 않았습니다. 바이너리·소스는 직접 확인하지 않았고(코드 예시는 개념 설명용), 버퍼 크기·오프셋·정확한 코드 실행 성립 여부는 미확인 상태입니다(심볼릭 실행으로 PC 제어까지는 확인됐으나 실기기 결과는 write-up상 “충돌 가능성” 수준). 패치 상태는 공식 EOL 공지 원문을 직접 확보하지 못했으나, 벤더 다운로드 페이지 무갱신(2023-04 이후)·지원 페이지 단종 응답·복수 독립 소스가 전하는 EOL 정황을 근거로 사실상 무패치·단종으로 판단했습니다. 자세한 재현 절차는 원문 write-up을 참고하세요. 이 초안은 RN-11 독립 팩트체크(2026-08-31)를 통과했습니다.