Search

System Vulnerabilities

1. Uninitialized Access (초기화되지 않은 접근)

1.1 정의 및 원리

C/C++ 등 low-level 언어에서 변수, 포인터, 배열, 구조체 등이 선언만 되고 값이 대입되지 않은 상태(“uninitialized”)에서 접근할 때 발생.
컴파일러는 자동으로 메모리를 0으로 초기화하지 않는다(성능 이유).
→ 실제 값은 이전에 해당 메모리 영역에 존재하던 임의 데이터(“garbage value”)가 남아 있음.
공격자는 이 “쓰레기 값”의 내용을 예측하거나 조작할 수 있음.

1.2 공격 벡터

읽기(read):
개인정보, 패스워드, 암호키 등 민감 데이터가 남아있는 메모리 영역 유출.
쓰기(write):
예를 들어, 초기화되지 않은 포인터 사용 시, 해당 포인터가 가리키는 주소에 임의 데이터 덮어쓰기 가능.
Use-after-free 취약점으로 연결되기 쉬움(해제된 메모리 영역의 내용이 재활용).

1.3 실제 사례

CVE-2015-2411:
Internet Explorer uninitialized memory disclosure.
공격자는 uninitialized memory에 남아있는 정보를 추출 가능.
CVE-2009-1721 (libpng):
부적절하게 초기화된 힙 메모리 노출, crafted 이미지 파일로 익스플로잇.
이미지/폰트 파서:
공격자가 설계한 파일(이미지, 폰트, etc.)을 읽게 하여 uninitialized pointer를 통한 크래시, 임의코드 실행 유발.

1.4 예시 코드

c CopyEdit typedef struct { int isAdmin; char password[32]; } User; User u; // 선언만 하고 초기화 X printf("%d %s", u.isAdmin, u.password); // 이전 프로세스 또는 사용자의 데이터가 노출될 수 있음
C
복사

1.5 방어/예방

모든 변수, 포인터 선언 시 명시적 초기화.
C/C++에서는 memset, 생성자(constructor) 활용.
보안/정적분석 도구로 uninitialized 변수 탐지.

2. Return Oriented Programming (ROP) & Code Reuse Attack

2.1 기존 공격 우회 배경

Buffer Overflow/Stack-based Code Injection:
전통적 공격은 악성 shellcode(머신코드)를 스택에 삽입, 함수 리턴주소 덮어써 실행.
현대 시스템은 스택/힙에 NX/DEP(Non-Executable/데이터 영역 실행 금지) 적용, 단순 삽입 공격 차단.

2.2 Code Reuse: ret2libc 공격

원리:
이미 존재하는 라이브러리 함수(system, execve 등)의 주소로 리턴 포인터 덮어써 코드 실행.
악성 페이로드:
1.
오버플로우로 리턴주소 → system() 함수 주소
2.
스택에 파라미터(/bin/sh 등), 추가적으로 exit() 등 후속함수 주소 배치
메모리 구조 예시:
python-repl CopyEdit ... | system() | return address | "/bin/sh" string | ...
Plain Text
복사
효과:
스택 자체에 코드 삽입 없이 OS 명령 실행.

2.3 ROP(Return Oriented Programming)

원리:
바이너리/라이브러리 내에 흩어져 있는 작은 명령어 조각(“gadget”)을 ret(0xC3)로 연결해 원하는 로직 구현.
공격자는 스택을 조작해 gadget chain이 차례로 실행되도록 만듦.
각 gadget은 일반적으로 pop, mov, add, syscall, ret 등의 단일/간단한 연산.
공격 단계:
1.
바이너리 또는 라이브러리 내 ret 명령어로 끝나는 gadget 수집(ROPgadget, gdb-peda 등 활용)
2.
원하는 기능(예: 레지스터 조작, 메모리 쓰기, 시스템 콜 실행)을 gadget 조합으로 설계
3.
Buffer overflow로 조작된 스택프레임 생성
4.
함수 리턴시 ret 명령어에 따라 gadget chain 실행
ROP의 위력:
Turing-complete(이론적으로 임의 코드 실행 가능)
shellcode, 스택 실행권한 불필요
실제로 exploit 난이도는 높으나, 성공 시 강력한 권한 획득 가능

2.4 Gadget 예시 및 공격 예시

Gadget:
pop rdi; ret (x86_64에서 인자 전달 레지스터 설정)
mov [rdi], rax; ret (메모리 쓰기)
syscall; ret (시스템콜 호출)
공격 페이로드 예시:
1.
pop rdi; ret → "/bin/sh" 주소
2.
pop rsi; ret → NULL
3.
pop rax; ret → 59 (execve syscall)
4.
syscall; ret

3. ROP Gadget 자동탐색 및 우회 기술

도구:
ROPgadget, Ropper, gdb peda, pwntools 등
Gadget source:
바이너리, libc 등 표준 라이브러리
함수의 중간에서 시작하거나, 정상 코드가 아니어도 유효한 명령어 시퀀스가 될 수 있음

4. 방어 기술

4.1 ASLR (Address Space Layout Randomization)

동작 원리:
프로그램/라이브러리/스택/힙의 시작주소 무작위화
공격자가 정확한 gadget·함수 위치를 예측·활용하기 어렵게 만듦
한계 및 우회:
정보 유출 취약점(leak)이 있으면 ASLR 무력화 가능
32bit 시스템은 엔트로피(난수화 정도)가 낮음
PIC 미지원 모듈, 정적 링크 등으로 무작위화가 적용 안 되는 경우 gadget 고정

4.2 Stack Canaries, NX/DEP

Stack Canaries:
함수 리턴 직전 스택에 무작위값(canary) 확인, 손상 시 프로그램 종료
NX/DEP:
스택, 힙 등 데이터를 코드로 실행 금지

4.3 Fine-grained Randomization & CFI

Fine-grained Randomization:
함수, 블록, instruction-level 단위로 위치를 무작위화
Control Flow Integrity(CFI):
정해진 제어흐름 이외의 실행을 차단
간접 분기 제한, 불법적인 ret chain 실행 불가

4.4 Attack Surface Reduction

불필요한 코드, 라이브러리, 함수, 시스템콜 제거
Gadget pool 자체를 줄임(공격 난이도 증가)

5. 실전 공격 시나리오 예

공격자: 원격 공격 대상 C 프로그램에 buffer overflow 취약점 존재 확인
도구로 libc, 바이너리 내 gadget 수집 → ROP chain 설계
ASLR, NX 우회법(메모리 leak, PIE/PIC 분석, 여러 번 시도)
스택포인터·리턴주소 덮어써 payload 투입 → shell 획득 또는 임의명령 실행

6. 용어 정리

Uninitialized Access: 초기화 안된 변수·포인터 사용, 메모리 leak, 임의 코드 실행
ret2libc: 기존 라이브러리 함수 주소·파라미터 조작 공격
ROP: 코드 조각(gadget) 체인을 통한 제어 흐름 장악, 임의 명령 실행
Gadget: ret 명령어로 끝나는 짧은 기계어 명령 조각
ASLR: 메모리 구조 무작위화로 gadget·함수 위치 예측 방지
CFI: 비허용적 제어흐름 변경 차단