CSS 1타 강사 · CONCEPT 21/25
C 배열의 끝을 넘어 쓰면 왜 다른 데이터와 제어 흐름까지 위험할까요?
C의 char buffer는 정해진 바이트 수만 가집니다. 더 긴 데이터를 쓰면 옆 memory를 덮을 수 있고 crash, data corruption, control-flow hijack으로 이어질 수 있습니다.
전문 용어를 보기 전에 이 장면부터 잡으세요
10칸짜리 서랍에 20개 물건을 억지로 넣어 옆 서랍의 내용까지 밀어내는 상황입니다.
배열은 자동으로 늘어나지 않습니다
00
한 장면으로 문제를 시작해 봅시다
이번 페이지에서 끝까지 따라갈 예시
8-byte char buffer에 null terminator를 포함해 20 bytes의 attacker input을 복사하는 함수를 생각합니다.
비유와 실제 시스템을 정확히 연결하기
- 8칸짜리 사물함`char name[8]`이라는 고정 크기 buffer
- 옆 사물함의 관리자 표지buffer 뒤에 놓인 다른 변수나 pointer
- 칸 수를 보지 않고 계속 미는 사람길이 검사를 하지 않는 copy/write 연산
이 예시에서 사람·장치·데이터·화살표를 먼저 찾습니다. 아직 용어를 완벽히 몰라도 “누가 무엇을 가지고, 어떤 처리를 거쳐, 무엇이 달라지는가”를 말할 수 있으면 출발점은 충분합니다.
01
긴 이름을 작은 용어로 분리하기
한 제목에 여러 단어가 들어 있어도 같은 기능을 뜻하지 않습니다. 아래 카드를 하나씩 읽고 각 용어의 대상과 역할을 따로 잡으세요.
C의 buffer와 length 없는 sprintf
C의 char array는 정해진 크기의 연속된 memory 공간이다. Buffer에 들어갈 문자열 길이를 확인하지 않고 sprintf로 쓰면 경계를 넘어 인접 memory를 덮을 수 있다. 이를 buffer overflow라고 하며 crash, data corruption, 경우에 따라 code execution으로 이어질 수 있다. snprintf는 최대 길이를 받지만 반환값과 null termination 조건도 확인해야 한다.
TERMS FROM ZERO
C의 buffer와 length 없는 sprintf 핵심 용어
아래 단어는 이미 안다고 가정하지 않습니다. 먼저 쉬운 뜻을 읽고, 본문에서 같은 단어가 나오면 이 정의로 다시 바꾸어 읽으세요.
Buffer
프로그램이 byte나 문자를 잠시 저장하도록 확보한 연속 memory 공간입니다.
Boundary / Bounds
Buffer가 합법적으로 사용할 수 있는 시작과 끝 범위입니다.
Null terminator
C 문자열의 끝을 표시하는 값 `\0`으로, 저장 공간 1바이트를 차지합니다.
Stack frame
한 함수 호출의 local variable, 저장된 register, return 관련 정보가 놓이는 stack 영역입니다.
Buffer overflow
확보한 buffer 범위를 넘어 write하여 인접 memory를 손상시키는 오류입니다.
02
실제 시스템에서는 이 순서로 움직입니다
예시를 단계별로 해체하기
- 1단계Stack 또는 heap에 고정 크기 destination buffer가 배치됩니다.
- 2단계프로그램이 attacker-controlled input length를 제대로 확인하지 않습니다.
- 3단계Buffer 끝 이후의 인접 memory까지 write가 계속됩니다.
- 4단계다른 변수·pointer·return address가 손상될 수 있습니다.
- 5단계결과는 crash부터 data corruption·control-flow hijack까지 이어질 수 있습니다.
- 6단계근본 수정은 destination 크기와 null terminator를 고려한 bounded operation과 정확한 length check입니다.
이 단계들은 시험 답안에서 원인과 결과가 빠지지 않도록 만든 설명 순서입니다.
손으로 따라가는 초보 예제
8칸짜리 이름 상자에 12글자를 넣으면 어디까지 밀릴까?
`char name[8]` 바로 뒤에 `int is_admin = 0`이 놓였다고 단순화해 봅시다. 입력은 `ABCDEFGHIJKL` 12글자이고, C는 배열 경계를 자동으로 검사하지 않는다고 가정합니다.
- 1단계입력의 A부터 H까지 8글자는 `name[0]`부터 `name[7]`까지 정상 범위에 들어갑니다.
- 2단계아홉 번째 I를 쓸 때부터 `name`의 경계를 벗어납니다. C는 여기서 자동으로 멈추거나 예외를 던져 주지 않습니다.
- 3단계I, J, K, L 네 바이트는 옆 memory를 덮습니다. 실제 배치는 compiler와 platform에 따라 다르지만 다른 변수·pointer·control data가 대상이 될 수 있습니다.
- 4단계옆의 `is_admin` 값이 우연히 0이 아닌 값으로 바뀌면 논리 결과가 달라질 수 있고, return address가 손상되면 crash나 control-flow hijack 가능성이 생깁니다.
- 5단계수정할 때는 입력이 ‘문자열인지’만 보지 말고 destination 8바이트 중 문자열 7바이트와 마지막 `\0` 한 바이트를 계산해야 합니다.
- 6단계완화책인 stack canary·NX·ASLR은 exploit을 어렵게 하지만, 경계 밖 write 자체를 없애는 길이 검사와 안전한 API가 근본 수정입니다.
그래서 무엇을 배웠나? 핵심은 ‘긴 입력이 위험하다’가 아니라 ‘목적지의 실제 바이트 수보다 더 많이 쓰는 순간 인접 memory가 공격자 입력의 영향을 받는다’는 것입니다.
03
관련 개념도 하나씩 따로 이해하기
C의 buffer와 length 없는 sprintf
비유에서 실제 시스템으로 옮겨 보기
먼저 떠올릴 장면 · 10칸짜리 서랍에 30개 물건을 밀어 넣으면 옆 서랍의 물건까지 밀어내는 것과 같다. C는 자동으로 벽을 만들어 막아 주지 않는다.
정확한 뜻 · C의 char array는 정해진 크기의 연속된 memory 공간이다. Buffer에 들어갈 문자열 길이를 확인하지 않고 sprintf로 쓰면 경계를 넘어 인접 memory를 덮을 수 있다. 이를 buffer overflow라고 하며 crash, data corruption, 경우에 따라 code execution으로 이어질 수 있다. snprintf는 최대 길이를 받지만 반환값과 null termination 조건도 확인해야 한다.
- 1단계목적지 buffer 크기를 확인한다.
- 2단계공격자가 제어하는 문자열의 최대 길이를 확인한다.
- 3단계Format 후 필요한 길이가 buffer보다 큰지 계산한다.
- 4단계Bounded API와 반환값 검사, 명시적 길이 검증을 적용한다.
04
강의 스크립트 원본과 연결하기
Memory boundary·overflow escalation·stack canary를 보여 주는 대표 슬라이드입니다. 먼저 위의 초보 설명을 읽고, 원본에서는 같은 개념이 어떤 기호와 독일어·영어 용어로 표현되는지 확인하세요.
Vorlesung/11_software-security 10.pdf · p.12, p.21, p.27 · Memory boundary·overflow escalation·stack canary11_software-security 10.pdf· p.12, p.21, p.27
05
시험 함정과 답안에 적용하기
- C의 buffer와 length 없는 sprintf · sprintf의 format string이 고정되어 있어도 출력 전체 길이가 제한되지 않으면 overflow가 생길 수 있다.
서술형 답안 골격
destination size, attacker-controlled length, overwrite 대상, impact를 순서대로 씁니다.
정의 → 등장 주체 또는 입력 → 작동 순서 → 보안 효과 → 조건과 한계 순서로 쓰고, 위 단계별 예시에서 필요한 문장을 골라 붙이세요.
책을 덮고 “C 배열의 끝을 넘어 쓰면 왜 다른 데이터와 제어 흐름까지 위험할까요?”에 대해 핵심 용어 두 개, 작동 단계 세 개, 대표 함정 하나를 말해 보세요.
다음 개념으로 넘어가기 전 확인
- `char name[8]`에 안전하게 저장할 수 있는 일반 문자열의 최대 문자 수가 왜 7인지 설명할 수 있나요?
- buffer overflow와 단순한 긴 입력의 차이를 ‘경계 밖 write’라는 말로 설명할 수 있나요?
- stack canary가 근본 수정이 아닌 이유를 말할 수 있나요?