카테고리 없음

NX CVE

whffu0123 2026. 6. 24. 16:23

NX(DEP) 완화 기법과 CVE — 미적용 사례부터 ROP 우회까지

시스템 해킹 공부 정리. NX가 무엇이고, NX가 적용되지 않아 취약점이 발생한 실제 CVE 사례들, 그리고 NX가 있어도 뚫는 ROP 우회 개념까지 정리한다.

NX란 무엇인가

NX(Non-eXecutable), DEP(Data Execution Prevention) 는 메모리 영역을 "쓰기 가능"과 "실행 가능"으로 구분해, 데이터 영역(스택·힙)에서의 코드 실행을 막는 보안 완화(mitigation) 기법이다.

 

NX 자체는 결함이 아니라 방어 기술이다. 따라서 CVE는 보통 다음 두 경우에 발급된다.

  1. NX가 적용되지 않아 셸코드 직행이 성립한 경우
  2. NX 강제 메커니즘 자체에 구현 결함이 있는 경우

ROP 같은 우회 기법은 그 자체로 CVE가 아니다.


1. NX가 적용되지 않아 발생한 CVE 사례

CVE는 결함의 근본 원인(buffer overflow 등)만 기술하고, NX 부재는 그 버그를 셸코드 직행으로 익스플로잇 가능하게 만드는 환경 조건으로서 익스플로잇 라이트업에 드러난다.

그래서 NX 미적용 사례는 거의 전적으로 임베디드/IoT 펌웨어(특히 MIPS·ARM) 영역에 몰려 있다. 이 기기들은 NX를 아예 안 켜서 고전적 셸코드 인젝션이 그대로 통한다.

사례 A — o2 HomeBox 6441 라우터 (MIPS)

가장 교과서적인 사례. 분석에 따르면 ASLR은 부분적으로만(스택만 랜덤화, 힙은 고정) 적용됐고 NX는 전혀 사용되지 않아 힙과 스택이 실행 가능 상태였다. 그 결과 공격자가 힙이나 스택에 셸코드를 주입하고 리턴 주소(EIP)를 그 주소로 덮어써서 실행할 수 있었다. 힙이 ASLR 영향을 안 받아 셸코드를 신뢰성 있게 배치·호출할 수 있었던 것이 핵ㄱ심이다.

사례 B — Tenda F453 라우터 (CVE-2026-3726)

/goform/webExcptypemanFilter 엔드포인트의 스택 버퍼 오버플로. page 인자의 길이를 검증 없이 고정 크기 스택 버퍼에 복사해, 원격·비인증 공격자가 실행 흐름을 탈취하고 셸코드로 리다이렉트할 수 있다. Tenda 계열은 NX 미적용 펌웨어의 단골이다.

사례 C — D-Link 라우터 (MIPS)

Qiling 에뮬레이션 익스플로잇 연구에서, 연구자는 "스택의 코드가 실행 가능하다(NX 비트 없음)"는 것을 안전한 가정으로 두고 진행했다. 이런 저가 라우터들에서 NX 부재는 거의 기본 전제다.

공통 패턴: checksec

이 부류 바이너리를 checksec으로 보면 다음처럼 뜬다.

Arch:     mips-32-little
RELRO:    Partial RELRO
Stack:    No canary found
NX:       NX disabled          ← 스택/힙 실행 가능
PIE:      No PIE (0x400000)
RWX:      Has RWX segments     ← 쓰기+실행 가능 영역 존재

checksec은 바이너리에 어떤 보안 완화 기법이 걸려 있는지 한눈에 보여주는 도구다. 이 출력 한 장이 "이 바이너리를 어떻게 공략할지" 작전을 짜는 출발점이 된다. 각 줄을 해부하면 다음과 같다.

줄 의미 공격자 입장

Arch: mips-32-little 아키텍처(ISA)·비트·엔디안. MIPS 32비트 리틀엔디안 페이로드를 이 아키텍처에 맞춰 작성해야 함 (x86 셸코드 못 씀)
RELRO: Partial RELRO GOT를 읽기 전용으로 만들어 GOT 덮어쓰기를 막는 기법. Partial은 일부만 보호 GOT 일부를 여전히 덮어쓸 수 있음
Stack: No canary found 버퍼와 리턴 주소 사이의 "경비병" 값(카나리)이 없음 BOF로 리턴 주소를 덮어도 탐지 없이 통과
NX: NX disabled 데이터 영역(스택·힙)이 실행 가능 상태 셸코드를 올리고 그 주소로 점프하면 그대로 실행
PIE: No PIE (0x400000) 코드가 항상 고정 주소(0x400000)에 적재됨 코드·함수 주소를 미리 알 수 있어 점프·가젯 탐색이 쉬움
RWX: Has RWX segments 읽기·쓰기·실행이 동시에 허용된 영역 존재 (W^X 원칙 깨짐) 셸코드를 써넣고 바로 실행 가능

왜 "NX disabled + Has RWX"가 결정적인가

이 둘은 같은 사실의 양면이다. NX의 역할이 "쓰기 가능한 영역을 실행 불가로 묶는 것"인데, NX가 꺼지면 그 결과로 쓰기+실행이 동시에 되는 RWX 영역이 생긴다. 그래서 둘이 세트로 뜬다.

이 조합이 의미하는 건, 공격자가 (1) 버퍼에 셸코드를 써넣고 (2) 리턴 주소를 그 셸코드 위치로 덮은 뒤 (3) 함수가 리턴하면서 셸코드로 점프 → 실행, 이 고전적인 "스택 셸코드 직행"이 아무 우회 기법 없이 통한다는 것이다. 위 출력은 보호 기법이 거의 다 꺼진, 연습용 또는 구형 임베디드 바이너리의 전형적인 모습이다.


2. NX가 있으면 어떻게 막히나

NX가 켜지면 스택 페이지가 rw-(읽기·쓰기 가능, 실행 불가)로 표시된다.

고전 방식대로 스택에 셸코드를 올리고 그 주소로 점프하면, CPU가 "데이터 영역에서 실행하려 한다"며 거부하고 SIGSEGV로 죽는다. 셸코드 직행이 막힌 것이다.

스택 권한 rwx (실행 가능) rw- (실행 불가)
스택에 올린 셸코드로 점프 실행됨 → 성공 거부 → SIGSEGV

3. ROP — NX가 있어도 뚫는 우회

NX가 막혔다고 끝이 아니다. 공격자는 발상을 바꾼다.

새 코드를 안 올리면 된다. 이미 프로그램·라이브러리(libc 등) 안에 있는 코드는 어차피 실행 권한(r-x)이 있으니, 그걸 재조립해서 쓰자.

가젯(gadget)과 체인

프로그램 안에는 pop rdi; ret, pop rsi; ret, system 호출부처럼 끝이 ret로 끝나는 짧은 코드 조각이 널려 있다. 이걸 가젯이라 부른다.

공격자는 스택에 셸코드 대신 가젯들의 주소를 줄줄이 나열한다. ret 명령은 "스택에서 주소 하나 꺼내서 그리로 점프"하는 동작이라, 가젯이 끝날 때마다 다음 가젯으로 점프가 이어진다. 이렇게 가젯들이 사슬(chain)처럼 연결돼 원하는 동작을 수행한다.

스택 (rw-, 실행 불가)          기존 코드 (r-x, 실행 가능)
┌────────────────────┐        ┌──────────────────────┐
│ 가젯1 주소  ────────┼───────▶│ pop rdi; ret         │
│ "/bin/sh" 주소(인자)│        │ system()             │
│ 가젯2 주소  ────────┼───────▶│ ...                  │
└────────────────────┘        └──────────────────────┘
   주소 목록만 담음               실행은 전부 여기서

핵심: NX 규칙을 위반하지 않는다

실행되는 코드는 전부 원래 .text나 libc의 실행 가능 영역에 있다. 스택은 여전히 데이터로만 쓰인다(가젯 주소 목록을 담는 용도). NX 규칙을 단 한 번도 어기지 않는다.

그래서 "NX가 있어도 ROP로 우회했다"는 건 NX를 뚫거나 끈 게 아니라, 셸코드를 안 올리고 기존 코드 조각을 재조립해 같은 효과를 냈다는 뜻이다. ROP는 익스플로잇 기법이지 결함이 아니므로, CVE는 ROP를 가능케 한 원래의 메모리 손상 버그에 발급된다.


4. 방어의 진화 사슬

ROP는 "기존 코드의 주소를 정확히 알아야" 성립한다. 그래서 다음 방어가 나온다.

스택 셸코드 직행
   │  (셸코드를 데이터 영역에서 실행)
   ▼
NX / DEP 도입
   │  데이터 영역 실행 금지
   ▼
ROP / ret2libc
   │  기존 코드 재활용으로 우회 (NX 위반 없음)
   ▼
ASLR 도입
   │  코드·라이브러리 주소를 매번 랜덤화 → 가젯 주소를 모르게
   ▼
메모리 누수(leak) + ROP
      주소를 흘려 알아낸 뒤 ROP 체인 구성

실전 익스플로잇은 보통 "메모리 누수로 주소 알아내기(ASLR 우회) → ROP 체인(NX 우회)" 두 단계를 함께 쓴다. NX 하나만 우회하는 게 아니라, 완화 기법들이 쌓인 만큼 우회도 겹겹이 쌓는 것.


정리

  • NX는 데이터 영역의 실행을 막는 완화 기법이지 그 자체가 결함이 아니다.
  • "NX 미적용 CVE"는 CVE 설명문이 아니라 익스플로잇 라이트업에서 드러나며, 거의 임베디드/IoT 펌웨어(MIPS·ARM)에 몰려 있다. checksec의 NX disabled + Has RWX segments가 그 신호.
  • ROP는 NX를 뚫는 게 아니라 위반하지 않고 우회한다. 기존 코드 가젯을 ret으로 연결해 재활용하므로, CVE는 기반이 된 메모리 손상 버그에 귀속된다.
  • 방어는 NX → ROP → ASLR → leak+ROP로 진화해 왔다.

참고

  • o2 HomeBox 6441 라우터 익스플로잇 분석 (NSIDE Attack Logic)
  • Tenda F453 스택 오버플로 (CVE-2026-3726)
  • D-Link 라우터 MIPS 익스플로잇 (Qiling 에뮬레이션 연구)