10. String Security
Strings
Character Strings
- ํ์ค C ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ง์
charํ์ ์ stringswchar_tํ์ ์ wide strings
Figure 2.1. "hello"์ ๋ฌธ์์ด ํํ
An Example
- size of an array
void clear(int array[]) {
for (size_t i = 0; i < sizeof(array) / sizeof(array[0]); ++i) {
array[i] = 0;
}
}
void dowork(void) {
int dis[12];
clear(dis);
/* ... */
}
multibyte character set
- Basic execution character set
- 26๊ฐ์ ๋๋ฌธ์, 26๊ฐ์ ์๋ฌธ์ ๋ฑ
- UTF-8
- A multibyte character set
- Backward compatible
- 1 ~ 4 bytes
- String literals
L"xyz"- Type
wchar_t
Strings
const char s[3] = "abc";- Array์ ํฌ๊ธฐ๋ 3
- Trailing null byte๋ ์๋ต
const char s[ ] = "abc";
Strings in C++
std::basic_string- Characters์ ์ํ์ค
string์ template specializationbasic_string<char>์ ๋ํ typedefwstring์ template specializationbasic_string<wchar_t>์ ๋ํ typedef
- C++ string class
- ๋ชจ๋ ์ผ๋ฐ์ ์ธ implementation์ null-terminated
- Win32
LSA_UNICODE_STRING๊ณผ ๊ฐ์ ์ผ๋ถ ๋ค๋ฅธ string type์ null-terminated์ผ ํ์๋ ์์.
Character Types
- three types
char,signed char,unsigned char
- Philosophy
- Signed char and unsigned char
- ์์ ์ ์๊ฐ์ ์ ํฉ
- Plain char
- ๋ฌธ์์ด ๋ฆฌํฐ๋ด์ ๊ฐ๊ฐ ์์๋ค์ ํ์
- ์ ์ ๋ฐ์ดํฐ ๋์ ๋ฌธ์(character) ๋ฐ์ดํฐ๋ฅผ ์ํด ์ฌ์ฉ (๋ถํธ์ ์๋ฏธ๊ฐ ์ ์)
- Signed char and unsigned char
- Example
size_t len;
char cstr[] = "char string";
signed char scstr[] = "signed char string";
unsigned char ucstr[] = "unsigned char string";
len = strlen(cstr);
len = strlen(scstr); /* warns when char is unsigned */
len = strlen(ucstr); /* warns when char is signed */
int
EOF(์์ ๊ฐ)- ๋๋
unsigned char๋ก ํด์๋char data int๋ฅผ ๋ฐํํ๋ ํจ์fgetc(),getc(),getchar(),fgetwc(),getwc(),getwchar()
<ctype.h>์ ์ ์ธ๋ char classification functionsint๋ฅผ ์ธ์๋ก ํ์ฉ- ์:
isalpha()
Example
- Code Example ๋ถ์
int main() { char c = 'a'; char b[] = โaโ; wchar_t wc; printf(" size of 'a': %d \n", sizeof('a')); printf(" size of c: %d \n", sizeof(c)); printf(" size of wc: %d \n", sizeof(wc)); } - C์์ sizeof('a') โ ???, sizeof(c) โ ???
- C++์์ sizeof('a') โ ???
unsigned char
- ๊ฐ์ฒด๊ฐ ์ด๋ค type์ด๋ ๋ ์ ์์ ๋ ์ ์ฉ
fwrite()- Pure binary notation์ ์ฌ์ฉํ์ฌ ํํ๋จ์ด ๋ณด์ฅ
- Example
int main() {
unsigned char buf1[6] = { 0xff, 0x56, 0x78, 0xfa, 0xf1, 0};
unsigned char buf2[6];
FILE *stream;
stream = fopen(โout.datโ, โwbโ);
fwrite(buf1, sizeof(char), 6, stream);
fclose(stream);
stream = fopen(โout.datโ, โrbโ);
fread(buf2, sizeof(char), 6, stream); fclose(stream);
for (int i=0; i<6 && buf2[i] != NULL; i++)
printf(โ%x โ, buf2[i]);
printf(โ\nโ);
return 0;
}
Sizing Strings
- Buffer overflows๋ฅผ ์๋ฐฉํ๊ธฐ ์ํด ํ์
- The CERT C Secure Coding Standard
STR31-C. strings์ฉ ์ ์ฅ ๊ณต๊ฐ์ด character data์ null terminator๋ฅผ ์ํ ์ถฉ๋ถํ ๊ณต๊ฐ์ ๊ฐ๋๋ก ๋ณด์ฅ
- ์ฉ์ด
- Size: array์ ํ ๋น๋ byte ์ (
sizeof(array)์ ๋์ผ) - Count: array์ element ์ (Visual Studio 2010์
_countof(array)์ ๋์ผ) - Length: null terminator ์์ character ์ (
strlen()๊ฒฐ๊ณผ)
- Size: array์ ํ ๋น๋ byte ์ (
- Example
wchar_t wide_str1[] = Lโ0123456789โ;
wchar_t *wide_str2 = (wchar_t *) malloc (strlen(wide_str1) +1);
if (wide_str2 == NULL) {
/* handle error */
}
strcpy(wide_str2, wide_str1);
/* โฆ */
free(wide_str2);
wide_str2 = NULL;
Common String Manipulation Errors
- 4๊ฐ์ง ์ผ๋ฐ์ ์ธ ์ค๋ฅ
- unbounded string copies (๋ฌดํ string ๋ณต์ฌ)
- off-by-one errors
- null-termination errors
- String truncation
- String truncation
Improperly Bounded String Copies
- ๋ฐ์ดํฐ๊ฐ ๊ณ ์ ๋ ๊ธธ์ด์ ๋ฌธ์์ด๋ก๋ถํฐ ๋ณต์ฌ๋ ๋
- ์: ๊ณ ์ ๋ ๊ธธ์ด ๋ฒํผ์ ํ์ค ์ ๋ ฅ์ผ๋ก ์ฝ์ด์ค๋ ๊ฒฝ์ฐ
gets()C99์ ์ถ๊ฐ๋์์ผ๋C11์์ ์ ๊ฑฐ- "STR35-C. unbounded source์์๋ถํฐ ๊ณ ์ ๊ธธ์ด ๋ฐฐ์ด์ ๋ณต์ฌํ์ง ๋ง์์ค."
#include <stdio.h>
#include <stdlib.h>
void get_y_or_n(void) {
char response[8];
puts("Continue? [y] n: ");
gets(response);
if (response[0] == 'n')
exit(0);
return;
}
Example 2.1. Reading from
stdin()
Copying and concatenating strings
Improperly Bounded String Copies
- Standard lib functions
strcpy(),strcat(),sprintf()
int main(int argc, char *argv[ ]) ...argv[0]~argv[argc-1]: Null-terminated string์ ๊ฐ๋ฆฌํค๋ pointerargvarray์ ์ด๋ค ์์๋(argv[0]ํฌํจ) null์ด ์๋๋ผ๊ณ ๊ฐ์ ํ์ง ๋ง ๊ฒ
int main(int argc, char *argv[]) {
/* Do not assume that argv[0] can-
not be null */
const char * const name =
argv[0] ? argv[0] : "";
char *prog_name = (char *)mal-
loc(strlen(name) + 1);
if (prog_name != NULL) {
strcpy(prog_name, name);
}
else {
/* Failed to allocate memory -
recover */
}
/* ... */
}
sprintf() function
- array์ output์ ์์ฑ
- ์์ฑ๋ character์ ๋์ null character๊ฐ ์์ฑ
- target array์ ํ์ํ ์ต๋ ํฌ๊ธฐ๋ฅผ ๊ฒฐ์ ํ๊ธฐ ์ด๋ ค์
- ์:
INT_MAXโ ์ต์ 11 characters - ์์ ์ ์, floating-point values๋ ์์ธก์ด ๋ ์ด๋ ค์
- ์:
snprintf()ํจ์- ์ถ๊ฐ parameter:
size_t n - null char๊ฐ ์ถ๊ฐ๋๋ฏ๋ก characters๊ฐ ์์ฑ
- ์ฑ๊ณต ์ ์์ฑ๋ character ์ (excluding null char) ๋ฐํ
- ๋น๊ต์ ์์ ํ์ง๋ง, format string vulnerabilities์ ์ทจ์ฝ
- ์ถ๊ฐ parameter:
C++์ std::cin
- ์ด ๋ํ ๋ฌธ์ ์ ์์.
#include <iostream>
int main(void) {
char buf[12];
std::cin >> buf;
std::cout << "echo: " << buf << '\n';
}
- field width๋ฅผ
ios_base::width๋๋setw()๋ก ์ค์ ๊ฐ๋ฅ - characters๊ฐ ์ถ์ถ๋ ํ null character๊ฐ ์๋์ผ๋ก ์ถ๊ฐ๋จ
#include <iostream>
int main(void) {
char buf[12];
std::cin.width(12);
std::cin >> buf;
std::cout << "echo: " << buf << '\n';
}
Off-by-One Errors
- ๋ ๋ค๋ฅธ ์ผ๋ฐ์ ์ธ ๋ฌธ์
- unbounded string copies์ ์ ์ฌ
- Example
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char s1[] = "012345678";
char s2[] = "0123456789";
char *dest;
int i;
strcpy_s(s1, sizeof(s2), s2);
dest = (char *) malloc (strlen(s1));
for (i = 1; i <= 11; i++) {
dest[i] = s1[i];
}
dest[i] = '\0';
printf("dest = %s", dest);
/* ... */;
}
Null-Termination Errors
- Example
int main(void) {
char a[16];
char b[16];
char c[16];
strncpy(a, "0123456789abcdef", sizeof(a));
strncpy(b, "0123456789abcdef", sizeof(b));
strncpy(c, a);
/* ... */
}
strncpy()๋ ์ฒ์ characters๋ฅผ ๋ณต์ฌ- Null-termination์ ๋ณด์ฅํ์ง ์์.
String Vulnerabilities and Exploits
- C ๋๋ C++์์ String manipulation
- ์ธ๋ถ source์ untrusted data์์ ์๋ํ ๋ ์ํํด์ง
- ๋ชจ๋ ์ธ๋ถ ๋ฐ์ดํฐ๋ฅผ untrusted๋ก ๋ณด๋ ๊ฒ์ด ์์
- Example
bool IsPasswordOK(void) {
char Password[12];
gets(Password);
return 0 == strcmp(Password, "goodpass");
}
int main(void) {
bool PwStatus;
puts("Enter password: ");
PwStatus = IsPasswordOK();
if (PwStatus == false) {
puts("Access denied");
exit(-1);
}
}
Buffer Overflows
- Example

- C ๋ฐ C++๊ฐ buffer overflows์ ์ทจ์ฝํ ์ด์
- Strings๋ฅผ null-terminated arrays of characters๋ก ์ ์
- ์๋ฌต์ ์ธ bounds checking์ ์ํํ์ง ์์.
- Bounds checking์ ๊ฐ์ ํ์ง ์๋ strings์ ๋ํ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํธ์ถ ์ ๊ณต
Process Memory Organization

Programs and Processes

Figure 10.4 Program Loading into Process Memory
Stack Buffer Overflows
- Buffer๊ฐ stack์ ์์นํ ๋ ๋ฐ์
- Stack smashing์ด๋ผ๊ณ ๋ ํจ
- Morris Worm์ ์ํด ์ฌ์ฉ
- exploits๋ unchecked buffer overflow๋ฅผ ํฌํจ
- ์ฌ์ ํ ๋๋ฆฌ ์ ์ฉ๋๊ณ ์์.
- Stack frame
- ํ ํจ์๊ฐ ๋ค๋ฅธ ํจ์๋ฅผ ํธ์ถํ ๋ return address๋ฅผ ์ ์ฅํ ๊ณต๊ฐ ํ์
- ํธ์ถ๋ ํจ์์ ์ ๋ฌ๋ parameters์ register values๋ฅผ ์ ์ฅํ ์์น๋ ํ์
Stack Frame with Functions P and Q
โโโโโโโโโโโโโโโโโโโโโ
P:โ Return Addr โ
โโโโโโโโโโโโโโโโโโโโโค
โ Old Frame Pointer โโโโโ
โโโโโโโโโโโโโโโโโโโโโค โ
โ param 2 โ โ
โโโโโโโโโโโโโโโโโโโโโค โ
โ param 1 โ โ
โโโโโโโโโโโโโโโโโโโโโค โ
Q:โ Return Addr in P โ โ
โโโโโโโโโโโโโโโโโโโโโค โ
โ Old Frame Pointer โโโโโดโโโโโโโ Frame
โโโโโโโโโโโโโโโโโโโโโค Pointer
โ local 1 โ
โโโโโโโโโโโโโโโโโโโโโค
โ local 2 โโโโโโโโโโโโ Stack
โโโโโโโโโโโโโโโโโโโโโค Pointer
โ โ โ
โ โผ โ
Figure 10.3 Examples Stack Frame with Functions P and Q
Stack Management
- Stack์ automatic process-state data๋ฅผ ์ ์งํ์ฌ program execution์ ์ง์
Figure 2.6. Stack management

- Stack frame์ ์ ๋ณด
- return address
- local variables
- frame pointer
- (Disassembly using Intel Notation)

foo()ํจ์ prologue
void foo(int i, char *name) {
char LocalChar[24];
int LocalInt;
push ebp # Save the frame pointer.
mov ebp, esp # Frame pointer for subroutine is set to the
# current stack pointer.
sub esp, 28 # Allocates space for local variables.
/* ... */
foo()ํจ์ Epilogue
/* ... */
return;
mov esp, ebp # Restores the stack pointer.
pop ebp # Restores the frame pointer.
ret # Pops the return address off the stack
# and transfers control to that location.
}
foo()ํธ์ถ ํ Stack frame
| Address | Value | Description (์ค๋ช ) | Length |
|---|---|---|---|
0x0012FF4C | ? | ๋ง์ง๋ง local variableโinteger: LocalInt | 4 |
0x0012FF50 | ? | ์ฒซ ๋ฒ์งธ local variableโstring: LocalChar | 24 |
0x0012FF68 | 0x12FF80 | ํธ์ถ ํจ์ main()์ calling frame | 4 |
0x0012FF6C | 0x401040 | ํธ์ถ ํจ์ main()์ return address | 4 |
0x0012FF70 | 1 | ์ฒซ ๋ฒ์งธ argument: MyInt (int) | 4 |
0x0012FF74 | 0x40703C | ๋ ๋ฒ์งธ argument: pointer toMyString (char *) | 4 |
Stack Smashing
- Stack smashing
- Buffer overflow๊ฐ execution stack์ ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ์ ๋ฐ์ดํฐ๋ฅผ ๋ฎ์ด์ธ ๋ ๋ฐ์
- Stack segment์ buffer overflow๋ ๊ณต๊ฒฉ์๊ฐ arbitrary code๋ฅผ ์คํํ๋๋ก ์ ๋ ๊ฐ๋ฅ
- Example


Corrupted program stack


- Carefully crafted input string
j = 0x6A,= 0x10,* = 0x2A,! = 0x21
Code Injection
- Return address๊ฐ ๋ฎ์ด์ฐ์ฌ์ง ๋
- ์ ์ด ํ๋ฆ์ ์ ์ฃผ์๋ก ์ ๋ฌํ๋ ๊ฒ์ ์ผ๋ฐ์ ์ผ๋ก trap์ ์ ๋ฐํ๊ณ corrupted stack์ ์ด๋
- ๊ณต๊ฒฉ์๊ฐ ์ ์ฑ code์ ๋ํ pointer๋ฅผ ํฌํจํ๋ specially crafted string์ ์์ฑํ๋ ๊ฒ์ด ๊ฐ๋ฅ
- ์ ์ฑ code๋ ์ทจ์ฝํ program์ด ๊ฐ์ง ๊ถํ์ผ๋ก ์คํ
- Malicious arguments
- ์ทจ์ฝํ program์ ์ํด legitimate input์ผ๋ก ์์ฉ๋์ด์ผ ํจ
- ๋ค๋ฅธ ์ ์ด ๊ฐ๋ฅํ ์ ๋ ฅ๊ณผ ํจ๊ป ์ธ์๊ฐ ์ทจ์ฝํ code path์ ์คํ์ ์ด๋ํด์ผ ํจ
- Shellcode๋ก ์ ์ด๊ฐ ์ ๋ฌ๋๊ธฐ ์ ์ ์ธ์๊ฐ program์ ๋น์ ์์ ์ผ๋ก ์ข ๋ฃ์ํค์ง ์์์ผ ํจ
- Example
./BufferOverflow < exploit.bin
- ์ฒซ ๋ฒ์งธ
movinstruction์ %eax register์0xBํ ๋น execve()ํจ์ ํธ์ถ์ ์ํ ์ธ ์ธ์๋ ํ์ ์ธ instructions์์ ์ค์ int $0x50instruction์execve()๋ฅผ ํธ์ถํ์ฌ Linux calendar program์ ์คํ
Modified Example

gets()๋์fgets()์ฌ์ฉ- Buffer overflow๊ฐ ์ฌ์ ํ ๋ฐ์ํ ์ ์์.
- Modified Example
- Exploit Code

- Corrupted Stack
- Exploit Code
| Row | Address | Content | Description |
|---|---|---|---|
| 1 | 0xbffff9c0 -0xbffff9cf | "123456789012456" | Password(16 bytes) ๋ฐ padding์ ์ํ ์ ์ฅ ๊ณต๊ฐ |
| 2 | 0xbffff9d0 -0xbffff9db | "789012345678" | ์ถ๊ฐ padding |
| 3 | 0xbffff9dc | (0xbffff9e0) | ์๋ก์ด return address |
| 4 | 0xbffff9e0 | xor %eax,%eax | eax๋ฅผ 0์ผ๋ก ์ค์ |
| 5 | 0xbffff9e2 | mov %eax,0xbffff9ff | Null pointer๋ก pointer array ์ข ๋ฃ |
| 6 | 0xbffff9e7 | mov $0xb,%al | execve() function call์ ์ํ code ์ค์ |
| 7 | 0xbffff9e9 | mov $0xbffffa03,%ebx | execve()์ ์ฒซ ๋ฒ์งธ argument๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ebx ์ค์ |
| 8 | 0xbffff9ee | mov $0xbffff9fb,%ecx | execve()์ ๋ ๋ฒ์งธ argument๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ecx ์ค์ |
| 9 | 0xbffff9f3 | mov 0xbffff9ff,%edx | execve()์ ์ธ ๋ฒ์งธ argument๋ฅผ ๊ฐ๋ฆฌํค๋๋ก edx ์ค์ |
| 10 | 0xbffff9f9 | int $80 | execve() system call ํธ์ถ |
| 11 | 0xbffff9fb | 0xbffff9ff | ์ program์ ์ ๋ฌ๋๋ argument string๋ค์ array |
| 12 | 0xbffff9ff | "1111" | Pointer array๋ฅผ ์ข ๋ฃํ๊ธฐ ์ํด 0x00000000์ผ๋ก ๋ณ๊ฒฝ ๋ฐ ์ธ ๋ฒ์งธ argument๋ก ์ฌ์ฉ |
| 13 | 0xbffffa03 -0xbffffa0f | "/usr/bin/cal\0" | ์คํํ command |
Arc Injection
- Arc injection technique
- ์ด๋ฏธ process memory์ ์กด์ฌํ๋ code๋ก ์ ์ด๋ฅผ ์ ๋ฌ
- ์๋ก์ด arc (control-flow transfer) ์ฝ์
system()๋๋exec()์ ์ฌ์ฉํ์ฌ commands ์คํ ๊ฐ๋ฅ- ์ฌ๋ฌ ํจ์๋ฅผ ์์ฐจ์ ์ผ๋ก ํธ์ถ ๊ฐ๋ฅ
- ๊ณต๊ฒฉ์๊ฐ code injection๋ณด๋ค arc injection์ ์ ํธํ ์ ์๋ ์ด์
- ๋์ ์์คํ ์ ๋ฉ๋ชจ๋ฆฌ์ ์ด๋ฏธ code๊ฐ ์กด์ฌ
- Footprint๋ฅผ ํ์ ํ ์๊ฒ ์ ์ง ๊ฐ๋ฅ
- Memory-based protection schemes๋ก ๋ณดํธํ ์ ์์.
- Example
#inclue <string.h>
int get_buff(char *user_input, size_t size) {
char buff[40];
memcpy(buff, user_input, size);
return 0;
}
int main(void) {
/* ... */
get_buff(tainted_char_array, tainted_size);
/* ... */
}
Mitigation Strategies
- ์ฌ๋ฌ ์ ๋ต์ ๊ฒฐํฉํ๋ defense-in-depth tactic ์ฑํ
- String handling์ ๋ํ secure technique
- ํ๋ ์ด์์ runtime detection
- String handling
- Character strings ์ฒ๋ฆฌ์ ๋ํ ๋จ์ผ ์ ๊ทผ ๋ฐฉ์ ์ ํ ๊ถ์ฅ
- Character strings ์ฒ๋ฆฌ์ ๋ํ ๋จ์ผ ์ ๊ทผ ๋ฐฉ์ ์ ํ ๊ถ์ฅ
- String-handling functions๋ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ๋ฐฉ์์ ๋ฐ๋ผ ๋ถ๋ฅ
- Caller allocates, caller frees (
C99,OpenBSD,C11Annex K) - Callee allocates, caller frees (
ISO/IEC TR 24731-2) - Callee allocates, callee frees (
C++std::basic_string)
- Caller allocates, caller frees (
C11 Annex K Bounds-Checking
- ์ฒซ ๋ฒ์งธ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ model (caller allocatesํ๊ณ caller freeํ๋ ๋ฐฉ๋ฒ)
C11Annex K- ๋์์ ์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์ ์ ๊ณต
- output buffers๊ฐ ์๋ํ ๊ฒฐ๊ณผ๋ฅผ ๋ด์ ๋งํผ ์ถฉ๋ถํ ํฐ์ง ํ์ธ
- ์ถฉ๋ถํ์ง ์์ผ๋ฉด failure indicator ๋ฐํ
- ๋ชจ๋ string results๋ null-terminated
- ์:
strcpy_s(),strcat_s(),strncpy_s(),strncat_s(), ... ์ ์ ISO/IEC TR 24731-1๋ก ๊ฒ์ โ ๋์ค์C11์ optional extensions ์ธํธ๋ก ํตํฉ__STDC_LIB_EXT1__macro ์ ์ ํ์C11Annex K๋ normative์ด์ง๋ง optimal annexgcc์์๋ implemented๋์ง ์์.- ์ ํจํ์ง ์์ ํฌ๊ธฐ๊ฐ ํจ์์ ์ ๋ฌ๋๋ฉด buffer overflow problems๋ฅผ ๊ฒช์ ์ ์์.
C11 Annex K
- Example:
gets_s()
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdlib.h>
void get_y_or_n(void) {
char response[8];
size_t len = sizeof(response);
puts("Continue? [y] n: ");
gets_s(response, len);
if (response[0] == n)
exit(0);
}
Runtime-constraint-handler function
- ์ค๋ฅ ๊ฐ์ง ์ ํน์ runtime-constraint-handler function ํธ์ถ
- ์ค๋ฅ ๋ฉ์์ง ์ถ๋ ฅ ๋ฐ/๋๋ program ์ค๋จ ๊ฐ๋ฅ
set_constraint_handler_s()ํจ์๋ฅผ ํตํด ํธ์ถ๋๋ handler function ์ ์ด ๊ฐ๋ฅ- "
ERR03-C. Use runtime-constraint handlers when calling functions defined by TR24731-1"- Implementation-defined behavior๋ฅผ ์ ๊ฑฐํ๊ธฐ ์ํด runtime-constraint handler ์ค์น ๊ถ์ฅ
C11 Annex K
- Example 2.6.
gets_s()(Improved)
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdlib.h>
void get_y_or_n(void) {
char response[8];
size_t len = sizeof(response);
puts("Continue? [y] n: ");
if ((gets_s(response, len) == NULL) || (response[0] == 'n')) {
exit(0);
}
}
int main(void) {
constraint_handler_t oconstraint = set_constraint_handler_s(ignore_handler_s);
get_y_or_n();
}
Runtime-constraint-handler function
ignore_handler_s()ํจ์๋ก ์ค์ ๋ ๊ฒฝ์ฐ- ๋ชจ๋ ์๋ฐ์ caller์๊ฒ ๋ฐํ
- ๋๋ถ๋ถ์ bounds-checking functions๋ nonzero
errno_t๋ฐํgets_s()ํจ์๋ null pointer ๋ฐํ (compatibility๋ฅผ ์ํด)
- "
ERR00-C. ์ผ๊ด๋๊ณ ํฌ๊ด์ ์ธ ์ค๋ฅ ์ฒ๋ฆฌ ์ ์ฑ ์ ์ฑํํ๊ณ ์ํ" - Original constraint handler
- ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์๊ฐ constraint handler๋ฅผ ์ค์ ํ๋ ๊ฒฝ์ฐ, ํจ์๋ ๋ฐํ ๋๋ ์ข ๋ฃ ์ ์ original constraint handler๋ฅผ ๋ณต์ํด์ค์ผ ํจ
Dynamic Allocation Functions
- ๋ ๋ฒ์งธ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ model (callee allocates, caller frees)
ISO/IEC TR 24731-2ISO/IEC TR 24731-2
- ์ด๋ฌํ ํจ์ ์ฌ์ฉ์ ๋์ค์ buffers๋ฅผ freeํ๊ธฐ ์ํ ์ถ๊ฐ ํธ์ถ์ด ํ์
ISO/IEC TR 24731-2์ ์ค๋ช ๋ ํจ์๋ ๋ฒํผ๊ฐ ํญ์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ด์ ์ ์๋๋ก ์๋ ํฌ๊ธฐ ์กฐ์ โ ๋ ํฐ ๋ณด์ฅ ์ ๊ณต- Denial-of-service attacks๋ฅผ ๊ฒช์ ์ ์์.
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdlib.h>
void get_y_or_n(void) {
char response[8];
size_t len = sizeof(response);
puts("Continue? [y] n: ");
if ((getline(&response, &len, stdin) < 0) || (len && response[0] == 'n')) {
free(response);
exit(0);
}
free(response);
}
- Example:
getline()- Buffer๋ฅผ dynamically allocate
- Buffer๋ฅผ
freeํด์ผ ํจ
String stream
fmemopen(),open_memstream()- ํจ์ prototypes
FILE *fmemopen(
void * restrict buf, size_t size, const char * restrict mode
);
FILE *open_memstream(
char ** restrict bufp, size_t * restrict sizep
);
)
open_memstream()์ ์ํด ์ด๋ฆฐ stream์ ๊ฒฝ์ฐ- write operations๋ฅผ ์์ฉํ๊ธฐ ์ํด ๋ฉ๋ชจ๋ฆฌ ์์ญ์ด dynamically ์ฆ๊ฐ
- Caller๋ ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ freeํด์ผ ํจ (line 16)
- Dynamic allocation์ safety-critical systems์์ ์ข ์ข ํ์ฉ๋์ง ์์.
- Example
#include <stdio.h>
int main(void) {
char *buf;
size_t size;
FILE *stream;
stream = open_memstream(&buf, &size);
if (stream == NULL) { /* handle error */ };
fprintf(stream, "hello");
fflusth(stream);
printf("buf = '%s', size = %zu\n", buf, size);
fprintf(stream, ", world");
fclose(stream);
printf("buf = '%s', size = %zu\n", buf, size);
free(buf);
return 0;
}
C++ std::basic_string
- C++ extraction operator
operator>>- Field width๋ฅผ ์ค์ ํ์ฌ buffer overflow vulnerability ์ ๊ฑฐ
- Truncation ๋ฌธ์
- ์์์น ๋ชปํ program behavior๊ฐ ๋ฐ์ํ ์ ์์.
- ISO/IEC 14882์ ์ ์๋ ํ์ค
std::string class- type
char์ ๋ํstd::basic_string template์ specialization
- type
basic_string class- Strings์ ๋ํ dynamic approach ์ฌ์ฉ
- "callee allocates, callee frees" ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ์ ๋ต โ ๊ฐ์ฅ ์์ ํ ์ ๊ทผ ๋ฐฉ์
- Example
string str1 = โhello, โ;
string str2 = โworldโ;
string str3 = str1 + str2;
Example: std::cin
#include <iostream>
#include <string>
using namepsace std;
int main(void) {
string str;
cin >> str;
cout << "str 1: " << str << '\n';
}
std::out_of_range
- Subscript member
std::string::operator[]- Exception์ ๋์ง์ง ์์.
- Example
string bs(โ01234567โ); size_t i = 10; bs[i] = โ\0โ;
at()methodoperator[]์ ์ ์ฌํ์ง๋ง,pos >= size()์ด๋ฉด out_of_range exception ๋ฐ์
- Example
string bs("01234567");
try {
size_t i = f();
bs.at(i) = '\0';
}
catch (out_of_range& oor) {
cerr << "Out of Range error: " << oor.what() << '\n';
}
c_str()
string์ null-terminated byte string์ผ๋ก ๋ณํc_str()method- Example
string str(โabcdโ); cout << strlen(str.c_str());
String-Handling Functions
gets()- ์ ๋
gets()ํจ์ ํธ์ถ ๊ธ์ง - ์ข
๋ฃ newline ๋๋
EOF๊ฐ ๋ฐ๊ฒฌ๋ ๋๊น์ง ํ์ค ์ ๋ ฅ์์ buffer๋ก ํ ์ค์ ์ฝ์. C11์์ ์ ๊ฑฐC11์์ ์ ๊ฑฐ
- ์ ๋
- ๋์ฒด ํจ์
C99fgets()getchar()
fgets()
char buf[LINE_MAX];
int ch;
char *p;
if (fgets(buf, sizeof(buf), stdin)) {
/* fgets succeeds, scan for newline character */
p = strchr(buf, '\n');
if (p) {
*p = '\0';
}
else {
/* newline not found, flush stdin to end of line */
while (((ch = getchar()) != '\n')
&& !feof(stdin)
&& !ferror(stdin)
);
}
}
else {
/* fgets failed, handle error */
}
fgets() and getchar()
fgets()- Newline character๋ฅผ ์ ์ง
- Truncation: ์ฌ์ฉ์ ์ ๋ ฅ์ด ์๋ฆด ์ ์์.
- ์ ๋ ฅํ character ์๊ฐ destination buffer์ ๊ธธ์ด๋ณด๋ค ํฌ๋ฉด buffer overflow ๋ฐ์ ๊ฐ๋ฅ
getchar()stdin์ด ๊ฐ๋ฆฌํค๋ ์ ๋ ฅ stream์์ ๋ค์ character ๋ฐํ- Stream์ด
EOF์ ์๊ฑฐ๋ read error ๋ฐ์ ์EOF๋ฐํ
getchar()
- Example 2.10.
getchar()
char buf[BUFSIZ];
int ch;
int index = 0;
int chars_read = 0;
while (((ch = getchar()) != '\n')
&& !feof(stdin)
&& !ferror(stdin))
{
if (index < BUFSIZ - 1) {
buf[index++] = (unsigned char)ch;
}
chars_read++;
} /* end while */
buf[index] = '\0'; /* null-terminate */
if (feof(stdin)) {
/* handle EOF */
}
if (ferror(stdin)) {
/* handle error */
}
if (chars_read > index) {
/* handle truncation */
}
C11 Annext K gets_s()
C11gets_s()ํจ์gets()์ ํธํ- ๋ ์์ ํ version
stdin์์ ์ฝ์.- Newline character๋ฅผ ์ ์งํ์ง ์์.
- ์ค๋ฅ ๋ฐ์ ์
- ์ ๋ ฅ ์ํ ์ ํจ
- Char array ์์ ์ ํจ
- ๊ทธ ์ธ์ ๊ฒฝ์ฐ
- ์ง์ ๋ char ์๋ณด๋ค ์ต๋ ํ๋ ์ ๊ฒ ์ฝ์.
- ๋ง์ง๋ง char ๋ค์์ null char ์์ฑ
gets_s()ํจ์- ์์ ํ ํ ์ค์ ์ฝ์ ๋๋ง ์ฑ๊ณต
- ์์ ํ ์ค์ ์ฝ์ ์ ์์ผ๋ฉด
NULL๋ฐํ, buffer๋ฅผ null string์ผ๋ก ์ค์ , ์ ๋ ฅ stream์ ๋ค์ newline char๊น์ง ์ ๋ฆฌ
Dynamic Allocation Functions
getline()ํจ์ISO/IEC TR 24731-2์ ์ค๋ชISO/IEC TR 24731-2์ ์ค๋ชfgets()์ ์ ์ฌํ์ง๋ง ์ถ๊ฐ ๊ธฐ๋ฅ ํฌํจ- Destination buffer๋ฅผ dynamically resize
- ์ฝ์ character ์ ๋ฐํ
- Destination buffer๊ฐ
malloc()์ผ๋ก ํ ๋น๋ ๊ฒฝ์ฐ์๋ง ์๋ - ์ฌ์ฉ์๋ ๋์ค์ buffer๋ฅผ ๋ช
์์ ์ผ๋ก
free()ํด์ผ ํจ
getline()
int ch;
char *p;
size_t buffer_size = 10;
char *buffer = malloc(buffer_size);
ssize_t size;
if ((size = getline(&buffer, &buffer_size, stdin)) == -1) {
/* handle error */
} else {
p = strchr(buffer, '\n');
if (p) {
*p = '\0';
} else {
/* newline not found, flush stdin to end of line */
while (((ch = getchar()) != '\n')
&& !feof(stdin)
&& !ferror(stdin)
);
}
}
/* ... work with buffer ... */
free(buffer);
Alternative functions for gets()
Table 2.4. Alternative Functions for gets()
| Standard/TR | Retains Newline Character | Dynamically Allocates Memory | |
|---|---|---|---|
fgets() | C99 | Yes | No |
getline() | TR 24731-2 | Yes | Yes |
gets_s() | C11 | No | No |
strcpy() and strcat()
C99- C ํ์ค
strncpy()ํจ์๊ฐ ์ข ์ข ๋์์ผ๋ก ๊ถ์ฅstrncpy()๋ null-termination errors ๋ฐ ๊ธฐํ ๋ฌธ์ ์ ์ทจ์ฝ
- C ํ์ค
OpenBSDstrlcpy()๋ฐstrlcat()- Size parameter๋ก destination string์ ์ ์ฒด ํฌ๊ธฐ ์ฌ์ฉ
- Destination string์ด null-terminated์์ ๋ณด์ฅ
- ์์ฑํ๋ ค๊ณ ์๋ํ string์ ์ด ๊ธธ์ด ๋ฐํ
C11 Annex K Bounds-Checking interfaces
strcpy_s()๋ฐstrcat_s()- ์ฑ๊ณต ์
0๋ฐํ - ๊ทธ ์ธ์ ๊ฒฝ์ฐ nonzero value ๋ฐํ
- ๋ค์ํ runtime constraints ๊ฐ์
- s1 ๋๋ s2๊ฐ null pointer์ธ ๊ฒฝ์ฐ
- Destination buffer์ ํฌ๊ธฐ๊ฐ
0,RSIZE_MAX๋ณด๋ค ํฌ๊ฑฐ๋, source string์ ๊ธธ์ด๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์ ๊ฒฝ์ฐ
- ์ฑ๊ณต ์
String copy functions
Table 2.5. String Copy Functions
| Standard/TR | Buffer Overflow Protection | Guarantees Null Termination | May Truncate String | Allocates Dynamic Memory | |
|---|---|---|---|---|---|
strcpy() | C99 | No | No | No | No |
strncpy() | C99 | Yes | No | Yes | No |
strlcpy() | OpenBSD | Yes | Yes | Yes | No |
strdup() | TR 24731-2 | Yes | Yes | No | Yes |
strcpy_s() | C11 | Yes | Yes | No | No |
Table 2.6. String Concatenation Functions
| Standard/TR | Buffer Overflow Protection | Guarantees Null Termination | May Truncate String | Allocates Dynamic Memory | |
|---|---|---|---|---|---|
strcat() | C99 | No | No | No | No |
strncat() | C99 | Yes | No | Yes | No |
strlcat() | OpenBSD | Yes | Yes | Yes | No |
strcat_s() | C11 | Yes | Yes | No | No |
strncpy() and strncat()
size_t parameter n์ถ๊ฐstrncpy()- Destination string์ null-terminate๋ฅผ ๋ณด์ฅํ์ง ์์.
- String termination errors์ ์ทจ์ฝ
strncat(s1, s2, n)- S1 buffer์ ์ต์ ํฌ๊ธฐ๋
strlen(s1) + n + 1์ด์ด์ผ ํจ - S1 buffer์ ์ต์ ํฌ๊ธฐ๋
strlen(s1) + n + 1์ด์ด์ผ ํจ strncat()์ ๋ง์ง๋ง ์ธ์๋ ์ด buffer length๊ฐ ์๋์ด์ผ ํจstrncat(dest, source, dest_size โ strlen(dest) โ 1)
- S1 buffer์ ์ต์ ํฌ๊ธฐ๋
- ๊ฒฐ๊ณผ string์ด ์๋ฆด ๋ status code ์์.
strncpy_s()
errno_t strncpy_s (
char * restrict s1,
rsize_t s1max,
const char * restrict s2,
rsize_t n
);
- Runtime-constraint violation ๋ฐ์ ์ destination array๋ empty string์ผ๋ก ์ค์
- Null terminator ์ถ๊ฐ๋จ
- ์ฑ๊ณต์ ๋ํ๋ด๊ธฐ ์ํด
0๋ฐํ - ์ ๋ ฅ ์ธ์๊ฐ ์ ํจํ์ง ์์ผ๋ฉด nonzero value ๋ฐํ
- No truncation!
- Example
char src1[100] = "hello";
char src2[7] = { 'g', 'o', 'o', 'd', 'b', 'y', 'e' };
char dst1[6], dst2[5], dst3[5];
errno t r1, r2, r3;
r1 = strncpy_s(dst1, sizeof(dst1), src1, sizeof(src1));r1 = 0, dst1 = โhello\0โ
r2 = strncpy_s(dst2, sizeof(dst2), src2, 4);r2 = 0, dst2 = โgood\0โ
r3 = strncpy_s(dst3, sizeof(dst3), src1, sizeof(src1));r3 = nonzero value, dst3[0] = โ\0โ
Summary of strcpy() and strcat()
Table 2.7. Truncating Copy Functions
| Standard/TR | Buffer Overflow Protection | Guarantees Null Termination | May Truncate String | Allocates Dynamic Memory | Checks Runtime Constraints | |
|---|---|---|---|---|---|---|
strncpy() | C99 | Yes | No | Yes | No | No |
strlcpy() | OpenBSD | Yes | Yes | Yes | No | No |
strndup() | TR 24731-2 | Yes | Yes | Yes | Yes | No |
strncpy_s() | C11 | Yes | Yes | No | No | Yes |
| Standard/TR | Buffer Overflow Protection | Guarantees Null Termination | May Truncate String | Allocates Dynamic Memory | Checks Runtime Constraints | |
|---|---|---|---|---|---|---|
strncat() | C99 | Yes | No | Yes | No | No |
strlcat() | OpenBSD | Yes | Yes | Yes | No | No |
strncat_s() | C11 | Yes | Yes | No | No | Yes |
Runtime Protection Strategies
- Programmer๊ฐ ๋ถ์์ ํ detection and recovery strategy๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ค๊ณ ์๋ชป๋ ํ์ ์ ๊ฐ์ง ์ํ
- Buffer overflow mitigation strategies
- Mitigation mechanism์ ์ ๊ณตํ๋ ์์คํ
์ component์ ๋ฐ๋ผ ๋ถ๋ฅ ๊ฐ๋ฅ
- ๊ฐ๋ฐ์ (์ ๋ ฅ validation์ ํตํด)
- Compiler ๋ฐ ๊ด๋ จ runtime system
- Operating system
- Mitigation mechanism์ ์ ๊ณตํ๋ ์์คํ
์ component์ ๋ฐ๋ผ ๋ถ๋ฅ ๊ฐ๋ฅ
Input validation
- Buffer overflows๋ฅผ ์ํํ๋ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ
void f(const char *arg) {
char buff[100];
if (strlen(arg) >= sizeof(buff)) {
abort();
}
strncpy(buff, arg);
/* ... */
}
- Trust boundary๋ฅผ ๋์ด program interface์ ๋๋ฌํ๋ ๋ชจ๋ ๋ฐ์ดํฐ๋ validation ํ์
- ์:
argv๋ฐargc, environment variables,sockets/files/devices์์ ์ฝ์ ๋ฐ์ดํฐ
- ์:
Object Size Checking
- GCC
- Pointer๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฐ์ฒด์ ํฌ๊ธฐ์ ์ ๊ทผํ๊ธฐ ์ํ ์ ํ๋ ๊ธฐ๋ฅ ์ ๊ณต
- GCC 4.1:
size_t __builtin_object_size(void *ptr, int type)ptr: ๊ฐ์ฒด์ ์์ ๋ถ๋ถ์ ๊ฐ๋ฆฌ์ผ์ผ ํจtype:- ๋๋ : ์ฐธ์กฐ๋ ๊ฐ์ฒด๋ ๊ฐ๋ฆฌํค๋ byte๋ฅผ ํฌํจํ๋ ๊ฐ์ฅ ํฐ ๊ฐ์ฒด
- ๊ทธ ์ธ: ๊ฐ์ฒด๋ ๊ฐ์ฅ ์์ ๊ฐ์ฒด
- Byte ์ ๋ฐํ
- Example
struct V { char buf1[10]; int b; char buf2[10]; } var;
void *ptr = &var.b;
__builtin_object_size(ptr, 0)__builtin_object_size(ptr, 1)__builtin_object_size()ํจ์_FORTIFY_SOURCE๊ฐ ์ ์๋ ๋ ์ฌ์ฉ
| Value of type Argument | Operates on | If Unknown, Returns |
|---|---|---|
| 0 | Maximum object | (size_t) -1 |
| 1 | Minimum object | (size_t) -1 |
| 2 | Maximum object | (size_t) 0 |
| 3 | Minimum object | (size_t) 0 |
- ํฌ๊ธฐ ๊ฒฐ์ ๋ถ๊ฐ
src_end=โ\0โ๋ฅผ ํฌํจํ byte ์- Example
char dest[BUFFER_SIZE];
char *src = /* valid pointer */;
size_t src_end = __builtin_object_size(src, 0);
if (src_end == (size_t) -1 && /* don't know if src is too big */
strlen(src) < BUFFER_SIZE) {
strcpy(dest, src);
} else if (src_end <= BUFFER_SIZE) {
strcpy(dest, src);
} else {
/* src would overflow dest */
}
Visual Studio Compiler-Generated Runtime Checks
- Visual C++ 2010
/RTCscompiler flag- Arrays์ ๊ฐ์ local variables์ overflows
- ์ด๊ธฐํ๋์ง ์์ variables ์ฌ์ฉ
- Stack pointer corruption
- ๋ฑ์ runtime checks ํ์ฑํ
/GS- Pragma๋ฅผ ์ฌ์ฉํ์ฌ flags ์กฐ์ ๊ฐ๋ฅ
Stack-Smashing Protector (ProPolice)
GCC 4.1- Stack-Smashing Protector (SSP) ๊ธฐ๋ฅ ๋์
- Buffers ๋ค์ pointers๋ฅผ ๋ฐฐ์นํ๋๋ก local variables ์ฌ์ ๋ ฌ
- ํจ์ ์ธ์์ pointers๋ฅผ local variable buffers ์ ์์ญ์ผ๋ก ๋ณต์ฌ
SSP
- Canary๋ฅผ ๋์ ํ์ฌ ๋ณ๊ฒฝ ์ฌํญ ๊ฐ์ง
SSP stack structure
Stack โโโโโโโโโโโโโโโโโโโโโโโโโโ โฒ pointerโโโบ โ ... โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโค โ local variables (C) โ โโโโโโโโโโโโโโโโโโโโโโโโโโค โ arrays (B) โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโค โ Frame โ guard โโผโโผโโโ stack pointerโโโบ โโโโโโโโโโโโโโโโโโโโโโโโโโค โ guard โ previous frame pointer โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโค โ โ return address โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโค โ arguments (A) โ โโโโโโโโโโโโโโโโโโโโโโโโโโค โ ... โ โโโโโโโโโโโโโโโโโโโโโโโโโโ- ์์น (A): array ๋๋ pointer variables ์์.
- ์์น (B): arrays๋ฅผ ํฌํจํ๋ arrays ๋๋ structures
- ์์น (B) ๋ค์ guard ๋ฐฐ์น
- ์์น (C): arrays ์์.
- Stack guard
Operating System Strategies
- Address space layout randomization (ASLR)
- Arbitrary code execution ๋ฐฉ์ง
- Linux, Windows Vista ์ดํ ์ฌ์ฉ ๊ฐ๋ฅ
- ๊ฐ๋ฐ์๋
/DYNAMICBASElinker option์ ์ฌ์ฉํ์ฌ ASLR ์ง์์ opt in ํด์ผ ํจ
- Nonexecutable stacks
- ๊ณต๊ฒฉ์๊ฐ stack์์ executable code๋ฅผ ์คํํ๋ ๊ฒ์ ํ์ฉํ์ง ์์.
- W ^ X (W xor X)
- Process address space์ ์ด๋ค ๋ถ๋ถ๋ writable์ด๋ฉด์ executable์ด์ง ์์.
- ์ฌ๋ฌ CPU์์ No eXecute (NX) bit ์ฌ์ฉ์ผ๋ก ์ง์
- Data Execution Prevention (DEP)
- Microsoft Visual Studio์ฉ W ^ X ์ ์ฑ ์ implementation
- NX technology๋ฅผ ์ฌ์ฉํ์ฌ data segments์ ์ ์ฅ๋ instructions์ ์คํ ๋ฐฉ์ง
/NXCOMPACT๋ก code๋ฅผ linkํ๊ฑฐ๋SetProcessDEPPolicy()ํธ์ถ๋ก DEP ํ์ฑํ
- PaX
- Linux kernel security patch
- Nonexecutable stack, ASLR ๋ฑ
- Denial of Service (DoS) ์ ๋ฐ ๊ฐ๋ฅ
- ํ์ฌ grsecurity project์ ์ผ๋ถ
- StackGap
- Stack memory ํ ๋น ์ randomly sized gap ๋์
Future Direction
Figure 2.19. A possible Safe-Secure C/C++(SSCC) implementation
- ๊ฐ๋ฅํ Safe-Secure C/C++ (SSCC) implementation
Notable Vulnerabilities
- Remote Login (rlogin)
- Buffer overflow:
TERM environment variable์ local stack variable๋ก ์ ์ธ๋ 1,024 characters array๋ก ๋ณต์ฌ
- Buffer overflow:
- Kerberos
- Network authentication protocol
- http://web.mit.edu/Kerberos/
krb_rd_req()ํจ์์์ buffer overflow- ๊ณต๊ฒฉ์๊ฐ ๋คํธ์ํฌ๋ฅผ ํตํด root access ์ป์ ์ ์์.
Summary
- C ๋ฐ C++์์ buffer overflows๊ฐ ์์ฃผ ๋ฐ์ํ๋ ์ด์
- Strings๋ฅผ null-terminated arrays of characters๋ก ์ ์
- ์๋ฌต์ ์ธ bounds checking์ ์ํํ์ง ์์.
- Bounds checking์ ๊ฐ์ ํ์ง ์๋ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํธ์ถ ์ ๊ณต
- ์ผ๋ฐ์ ์ธ ์ํ ์ ๋ต์ ์๋ก์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฑํ
- ์ค์ฉ์ ์ธ ์ํ ์ ๋ต์ static analysis ๋ฐ dynamic analysis ํฌํจ
- Runtime solutions
- Bounds checkers, canaries, safe libraries
- Defense-in-depth strategy
์ํ ์ ๋ณด
์ฅ์: 501ํธ



