Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
도구/GitHubGitHub/ozcanpng/cve-2026-76070
Embedded Systems SecurityIoT SecurityVulnerability AnalysisExploitationReverse EngineeringFirmware AnalysisBinary Exploitation
GitHubozcanpng/cve-2026-76070

CVE-2026-76070

Netis NC63 login.cgi에서 인증 전 Base64 디코딩된 비밀번호 스택 버퍼 오버플로에 대한 독자적 연구 및 비파괴적 PoC

저장소 보기
14일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-76070: Netis NC63 login.cgi의 Base64 디코딩된 비밀번호를 통한 인증되지 않은 사전 인증 스택 버퍼 오버플로로 인한 RCE

연구자: Özcan Ersan (@ozcanpng)

공개 상태

  • CVE: CVE-2026-76070
  • 벤더: Netis Systems Co., Ltd.
  • 제품: Netis NC63 Wireless AC1200 Router
  • 테스트된 펌웨어: NC63_V3.0.0.3327
  • 영향받는 구성 요소: /bin/netis.cgi
  • 엔드포인트: POST /cgi-bin/login.cgi
  • 파라미터: Base64 인코딩된 password
  • 인증: 없음; 안전하지 않은 디코딩이 자격 증명 비교 이전에 발생
  • 아키텍처: MIPS32r2 little-endian, o32 ABI, uClibc
  • 취약점 분류: 저장된 반환 주소 제어가 가능한 스택 기반 버퍼 오버플로
  • 검증: 격리된 QEMU user-mode 런타임에서 원본 해시가 일치하는 프로덕션 CGI
  • 준비 시점의 CVE 레코드 상태: 배정됨; CNA 레코드 세부 정보는 아직 채워지지 않음

요약

Netis NC63 펌웨어 V3.0.0.3327의 공개 로그인 핸들러는 공격자가 제어하는 password 파라미터를 검색하여 사용자 정의 Base64 루틴 FUN_00402bd4로 디코딩합니다. 호출자는 64바이트 로컬 스택 버퍼를 제공하지만 해당 용량을 디코더에 전달하지 않습니다. 디코더는 인코딩된 입력에서 작업량을 결정하고 대상 끝을 확인하지 않은 채 디코딩된 바이트를 기록합니다.

저장된 MIPS 반환 주소는 디코딩된 버퍼의 시작에서 136바이트 떨어져 있습니다. 원본 해시가 일치하는 프로덕션 CGI에 대한 동적 테스트는 다음을 확인했습니다:

  1. 디코딩된 140바이트 B 패턴이 0x42424242에서 오류를 발생시킵니다.
  2. 저장된 ra를 0x0041a2e0으로 교체하면 로그인 핸들러에서 두 번째로 관찰된 진입이 발생하여 프로그램 카운터 제어를 입증합니다.
  3. 격리된 관찰 전용 테스트는 공격자가 선택한 MIPS a0 값으로 원본 바이너리의 직접 system() 호출에 도달합니다. 교체된 /bin/sh는 /bin/sh -c NC63_RCE_PROOF를 기록했으며 어떤 명령도 실행하지 않았습니다.

이 저장소의 공개 PoC는 의도적으로 크래시 패턴에서 중단됩니다. 반환 체인, 셸코드, 명령, 리버스 셸 또는 지속성(persistence)을 포함하지 않습니다.

영향받는 아티팩트 무결성

root@kitploit:~
193f6a5e2ce65972b1805bf076f8d3521379a8441c8aaeb5ad0ba174bbee0792  netis_NC63_V3.0.0.3327.bin
23faa747b7d2f067aa5431bcc227ceca97a7977cf3e7c372f715cbba57f9209b  squashfs-root/bin/boa
eb298774c27070dc595fefcabb4e8c12a46cb5f4fd08f91c3ca92282c3a289a2  squashfs-root/bin/netis.cgi

동적으로 테스트된 /bin/netis.cgi 사본은 벤더가 추출한 실행 파일과 동일한 SHA-256 해시를 가집니다.

원본 및 런타임 해시

공격 표면 및 인증 상태

벤더 프런트엔드는 비밀번호를 공개 엔드포인트로 Base64 인코딩하여 전송합니다:

root@kitploit:~
obj.password = base64encode(utf16to8(password));
request({
    url: "/cgi-bin/login.cgi",
    data: obj
});

HTML 필드는 maxlength="63"을 사용하지만 이는 브라우저 측 제한일 뿐입니다. 직접 HTTP 클라이언트는 더 큰 인코딩된 값을 제출할 수 있습니다.

프런트엔드 요청 및 클라이언트 전용 제한

login.cgi는 인증 전에 반드시 도달 가능해야 합니다. 안전하지 않은 디코딩은 디코딩된 비밀번호가 구성된 관리자 비밀번호와 비교되기 전에 발생합니다. 유효한 세션, Cookie 헤더, Authorization 헤더 또는 올바른 비밀번호는 필요하지 않습니다.

소스-싱크 추적

root@kitploit:~
Unauthenticated HTTP client
  |
  | POST /cgi-bin/login.cgi
  | password=<attacker-controlled Base64>
  v
/bin/netis.cgi: FUN_0041a2e0
  |
  | get_request_param("password")
  v
FUN_00402bd4(decoded_stack_buffer, encoded_password)
  |
  | no destination-capacity argument
  | decoded output exceeds 64 bytes
  v
saved s8 at decoded offset 132
saved ra at decoded offset 136
  |
  v
attacker-selected MIPS PC

취약한 코드

가독성을 위해 이름을 정규화한 Ghidra 기반 유사 코드(pseudocode):

root@kitploit:~
int login_cgi(void *request)
{
    char decoded[64];
    char stored[68];
    char *password;

    memset(decoded, 0, 64);
    memset(stored, 0, 64);
    password = get_request_param(request, "password");
    if (password != NULL)
        FUN_00402bd4(decoded, password); /* no capacity argument */

    apmib_get(0x15e, stored);
    if (strcmp(decoded, stored) == 0)
        printf("[\"SUCCESS\"]");
    else {
        system("echo 0 >/tmp/boa_auth");
        printf("[\"%d\"]", 0x15);
    }
    return 0;
}

취약한 로그인 핸들러

FUN_00402bd4의 디코더는 대상(destination) 포인터와 소스 포인터만 받습니다. 루프는 대상 포인터를 전진시키며 Base64 기호 4개마다 최대 3바이트의 디코딩된 바이트를 저장합니다. 대상을 decoded + 64와 비교하는 검사는 없습니다.

사용자 정의 Base64 디코더 쓰기 루프

Base64는 입력 변환이지 근본적인 결함이 아닙니다. 근본 원인은 공격자가 제어하는 디코딩된 길이와 용량이 전혀 강제되지 않는 고정 크기 대상 간의 불일치입니다. 일반적인 패딩 입력의 경우 인코딩된 문자 4개는 최대 3바이트의 디코딩된 바이트를 나타냅니다. 따라서 서버 측 검사는 쓰기 전에 디코딩된 크기를 계산하고 검증해야 합니다.

스택 손상 분석

FUN_0041a2e0은 0x0041a2e0에서 시작하여 0xa8바이트 프레임을 생성합니다:

root@kitploit:~
0041a2e0  addiu sp,sp,-168
0041a2e4  sw    ra,164(sp)
0041a2e8  sw    s8,160(sp)
0041a2ec  move  s8,sp

디코딩된 대상은 s8+0x1c에서 시작합니다. 저장된 s8와 저장된 ra는 각각 s8+0xa0과 s8+0xa4에 있습니다:

root@kitploit:~
decoded[64]  s8+0x1c   decoded offset 0
saved s8     s8+0xa0   decoded offset 132
saved ra     s8+0xa4   decoded offset 136

정확한 반환 주소 거리는 0xa4 - 0x1c = 0x88, 즉 136바이트입니다.

스택 프레임 및 저장된 ra 오프셋

동적 검증

저장된 반환 주소 덮어쓰기

디코딩된 140바이트 B 패턴이 4바이트 저장된 반환 주소를 교체했습니다:

root@kitploit:~
--- SIGSEGV {si_signo=SIGSEGV, si_code=1, si_addr=0x42424242} ---
qemu: uncaught target signal 11 (Segmentation fault)

공격자가 선택한 반환 주소에서의 오류

프로그램 카운터 제어

별도의 140바이트 입력이 저장된 ra를 0x0041a2e0으로 설정했습니다. QEMU CPU 추적은 일반적인 첫 번째 핸들러 진입 후 s8=0x41414141, ra=0x0041a2e0인 두 번째 진입을 기록했습니다.

제어된 두 번째 핸들러 진입

관찰 전용 명령 경계

원본 바이너리에는 0x0041a3cc에 직접 jal system 호출이 포함되어 있습니다. 비공개 격리 검증에서 기존 고정 베이스 명령이 a0에 마커를 로드하고 해당 호출에 도달했습니다. /bin/sh 위에 정적 관찰 프로그램이 마운트되어 명령 해석기 인수를 기록하고 아무것도 실행하지 않았습니다:

root@kitploit:~
argv[0]=</bin/sh>
argv[1]=<-c>
argv[2]=<NC63_RCE_PROOF>
CONTROLLED_MARKER_REACHED
PASS: attacker-controlled a0 reached system() and /bin/sh argv.
PASS: the guard logged the request and executed no command.

이것은 격리된 프로덕션 코드 경로에서 RCE 프리미티브를 입증합니다. 배포된 커널 및 스택 랜덤화 구성 하에서 물리적 라우터에서 동일한 익스플로잇 신뢰성을 확립하는 것은 아닙니다.

권한 및 바이너리 하드닝 컨텍스트

원본 Boa 구성은 User root, Group root, 그리고 /bin 및 /web/cgi-bin을 포함하는 CGI 경로를 지정합니다. 프로덕션 실행 파일은 고정 베이스(0x00400000)이며 스택 카나리 또는 RELRO가 없고 RWX 세그먼트가 있는 실행 가능한 GNU 스택을 선언합니다.

프로덕션 Boa 권한 구성

바이너리 하드닝 상태

안전한 공개 PoC

포함된 스크립트는 기본적으로 드라이런(dry-run) 모드이며 디코딩 후 140개의 B 바이트를 포함하는 Base64 폼 본문만 생성합니다:

root@kitploit:~
python3 poc/poc.py

전송하려면 명시적으로 승인된 대상과 --send가 필요합니다:

root@kitploit:~
python3 poc/poc.py --target http://192.168.1.1 --send

패턴을 전송하면 CGI 프로세스가 크래시할 수 있습니다. 승인된 일회용 환경에서만 사용하십시오. PoC는 비공개 RCE 검증 체인을 구현하지 않습니다.

영향

성공적인 익스플로잇은 라우터 관리 컨텍스트에서 공격자가 선택한 코드 또는 명령을 실행할 수 있습니다. 원본 Boa 구성에서는 해당 컨텍스트가 root로 실행됩니다. 잠재적 결과로는 구성 및 비밀 노출, DNS/방화벽/라우팅 조작, 트래픽 리디렉션, 서비스 중단, 완전한 장치 장악이 포함됩니다.

수정 방안

  1. 사용자 정의 디코더를 대상 용량을 허용하는 API로 교체하십시오.
  2. 계산된 디코딩 길이가 63바이트를 초과하는 입력을 거부하고 종결자(terminator) 공간을 확보하십시오.
  3. 디코딩 전에 서버 측에서 길이와 Base64 구문을 검증하십시오.
  4. FUN_00402bd4의 모든 호출자를 감사하십시오.
  5. 스택 카나리, PIE, NX 및 RELRO를 사용하여 다시 빌드하십시오.
  6. CGI 프로세스를 최소 권한으로 실행하십시오.

증거 자료 목록

스크린샷 및 추적 매핑은 evidence/README.md를 참조하십시오. 정규화된 Ghidra 발췌문은 attachments/decompiled-functions/ 아래에 있습니다.

공개 타임라인

  • 2026-08-16: 발견 및 격리된 프로덕션 바이너리 검증 완료.
  • 2026년 8월: VulnCheck에 보고.
  • 2026-08-20: VulnCheck가 CVE-2026-76070을 배정하고 공개를 승인했습니다.
  • 2026-08-20: 공개 패키지 게시.

참고 자료

  • CVE-2026-76070
  • VulnCheck
  • Netis NC63 지원 페이지
  • CVE-2026-73673

물리적 라우터에는 펌웨어가 플래시되지 않았습니다. 실제 셸 명령, 리버스 셸, 지속성, 외부 연결, 자격 증명 탈취 또는 파괴적인 펌웨어 작업은 사용되지 않았습니다.

도구 다운로드