Search

Twice the Bits, Twice the Trouble: Vulnerabilities Induced by Migrating to 64-Bit Platforms

Created
2022/04/06 07:55
Tags
64-bit
Memory Bugs
Conference
CCS
Published
2016
CCS 2016
Python
복사

0. 소개

본 논문은 대부분의 운영체제가 32bit에서 64bit로 옮겨가면서 발생하는 취약점들에 대해서 탐구한 논문입니다. 본 논문은 주로 다음 3가지에 대한 연구를 진행하였습니다.
64-bit migration으로 인한 취약점
Emperical study (경험적 연구)
Practical case-studies
특히 Integer관련 취약점에 대해서 중점적으로 탐구하였으며, 분석한 case study를 기반으로 6개의 새로운 취약점을 발견했습니다.

1. 배경지식

Integer Type와 관련 식

본 논문에서는 32bit과 64bit에서의 가장 큰 차이점은 data model의 전환을 통한 고성능 계산이라고 하고 있습니다. 따라서, 본 논문에서 발견한 취약점들은 data model간의 차이를 통해 설명하고 있으며, platform과 독립적인 몇 가지 특성들을 미리 정의하였습니다. C언어를 기준으로 설명하고 있으며, 그 내용은 다음과 같습니다.
Signedness
C언어의 5가지 integer 종류(char, short, int, long, long long)는 모두 각각 signed와 unsigned type이 존재합니다. 앞으로는 해당 내용을 integer 종류 TT에 대하여 다음과 같이 표기합니다.
S(T){0,1}S(T)∈ \big\{ 0, 1\big\}
S(T)=0S(T)=0인 경우 unsigned type를 뜻하며, S(T)=1S(T)=1의 경우 signed type를 뜻합니다.
Conversion Rank
Integer 종류 TT에 대해서, 크기에 따른 conversion rank를 지정하였습니다.
R(T)NR(T) ∈N, R(R(char)<R() <R(short)<R()<R(int)<R()<R(long)<R()<R(long long))
Width, Range
Conversion Rank는 integer 종류를 크기에 따라 정렬합니다. 그러나 conversion rank는 대소관계를 비교할 뿐, 정확한 integer의 범위는 data model에 의해 정해집니다. 그에 관련해 width와 range를 다음과 같이 선언합니다. Integer 종류 TT에 대하여 width는 다음과 같습니다.
W(T){1,2,4,8}W(T)∈\big\{1,2,4,8\big\}
W(T)W(T)S(T)S(T)를 알고 있으면 다음과 같이 integer 종류의 범위인 I(T)I(T)를 구할 수 있습니다.
I(T)={[0,28W(T)1]if S(T)=0[28W(T)1,28W(T)11]otherwise I(T)= \begin{dcases} [0,2^{8*W(T)}-1] & \text{if } S(T)=0\\ [-2^{8*W(T)-1}, 2^{8*W(T)-1}-1] & \text{otherwise} \end{dcases}

Data Model

Data Model은 특정 플랫폼의 integer width를 결정합니다. 모든 model에 대하여 size_t의 크기는 architecture의 register 크기와 동일합니다. Data model에 따라서 같은 integer type이라도 사용하는 메모리 크기가 달라지기 때문에 이에 대해 중점적으로 연구합니다. 본 논문은 주로 32bit에서 64bit의 전환에 대해서 연구하기 때문에, 주로 ILP32LLP64/LP64를 비교할 예정입니다.

Integer 관련 취약점

본 논문은 Integer 관련 취약점을 중심적으로 분석합니다. 논문에서 중심적으로 분석한 3가지의 취약점 종류에 대해서 소개합니다.
Integer Truncations
Integer Truncations는 type casting 과정에서 width가 더 작은 integer type로 옮겨지는 경우 데이터의 일부가 소멸되는 취약점을 뜻합니다. 즉 x=cx=c라는 코드에서 xx라는 변수에 cc라는 표현식을 대입할 때, W(<x>)<W(<c>)W(<x>)<W(<c>)인 경우 Integer Truncation이 발생합니다. (단, <x><x><c><c>는 각각 x,cx,c의 integer type)
unsigned int x = attacker_controlled(); unsigned short y = x; char *buffer = malloc(y); memcpy(buffer, src, x);
C
복사
위 코드는 Integer Truncation으로 인해 Buffer Overflow 취약점이 발생하는 예시 코드입니다. ILP32, LLP64, LP64 data model 모두 shortint보다 width가 작기 때문에 integer truncation이 발생합니다. 예를 들어 x의 값이 0xffffffff인 경우, malloc은 0x0000ffff만큼 할당되는 반면 memcpy는 0xffffffff만큼 할당되기 때문에 결론적으로 buffer overflow가 발생합니다.
이 취약점의 핵심은 integer type의 width에 의해 발생하는 취약점이기 때문에, data model에 따라서 취약점 여부가 결정된다는 것입니다.
Integer Overflow
Integer Overflow는 임의의 계산 e1e2e_1·e_2에 대하여 그 결과가 I(<e1e2>)I(<e_1·e_2>)를 벗어나는 경우 발생합니다.
unsigned int x = attacker_controlled(); char *buffer = malloc(x+CONST); memcpy(buffer, src, x);
C
복사
위 코드는 Integer Overflow로 인한 Buffer Overflow가 발생하는 예시 코드입니다. xx의 값이 0xffffffff이고, CONST의 값이 0x100이라고 가정하면, malloc함수의 파라미터는 size_t타입이기 때문에 buffer에는 0x000000ff이 할당됩니다. 따라서 결론적으로 buffer에는 더 큰 크기의 값이 memcpy되면서 Buffer Overflow가 발생하게 됩니다.
Integer type의 범위는 data model이 결정하기 때문에, Integer Overflow 취약점은 data model에 따라서 취약점 여부가 결정됩니다.
Integer Signedness Issues
Integer Signedness Issues는 type casting에 있어서 S(<x>)S(<e>)S(<x>) \neq S(<e>)이고 W(<x>)W(<e>)W(<x>) \ge W(<e>)인 경우 발생합니다.
short x = attacker_controlled(); char *buffer = malloc((unsigned short) x); memcpy(buffer, src, x);
C
복사
위 코드는 잘못된 Sign-extension으로 인해 Buffer Overflow가 발생하는 코드입니다. xx-1을 대입하는 경우, 잘못된 Sign-extension을 통해 0x0000ffff만큼 할당이 되며, memcpy의 원형은 void *memcpy(void *dest, const void *src, size_t n); 이기 때문에 3번줄에서 x의 값은 0xffffffff로 전달되게 됩니다.
int x = attacker_controlled(); unsigned short BUF_SIZE = 10; if(x >= BUF_SIZE) return; memcpy(buffer, src, x);
C
복사
위 코드는 잘못된 Integer Signedness Comparison로 인해 Buffer Overflow가 발생하는 예시 코드입니다. 이 경우는 xx가 BUF_SIZE보다 작은지 확인하는 코드가 존재하는데, 이는 xx에 음수를 대입하는 경우 쉽게 bypass가 가능하게 됩니다.
Integer Signedness Issue또한 width에 의해 발생하는 취약점이기 때문에, data model에 따라서 취약점 여부가 결정됩니다.

2. 논문 내용

Integer flaws와 관련된 기존의 연구들은 대부분 코드 자체의 취약점에 대하여 집중하였습니다. 그러나 본 논문은 64bit로 전환하면서 발생하는 취약점들에 대해 집중합니다. 구체적으로 전환 과정에서 발생할 수 있는 취약점의 종류 및 실제 case들에 대해서 분석합니다.

64-Bit Migration Vulnerabilities

Integer width 변경
앞서서도 언급되었던 3가지 취약점은(Integer Truncation, Integer Overflow, Integer Signedness Issue) integer width간의 차이가 발생하는 경우 발생합니다. 이는 data model에 따라서도 달라질 수 있기 때문에, 32bit에서는 문제가 없었던 코드도 64bit로 전환을 시키면서 문제가 발생할 수 있습니다. 아래 Table 2 Table 3은 이 내용을 표로 정리한 것입니다.
Table 2는 integer type별로 분류된 할당(assignment)으로 인해 발생할 수 있는 truncation에 대해서 정리한 것입니다. 까만색 동그라미(●)로 표시된 것은 truncation이 발생되는 경우입니다. 특히 size_t에서 unsigned int로 변환하거나 long에서 int로 변환하는 경우는 64bit data model에서만 truncation이 발생하기 때문에 64bit로의 전환에서 발생할 수 있는 고유한 취약점이라고 볼 수 있습니다.
이러한 truncation의 대상이 pointer인 경우에는 다른 취약점을 유발할 수 있습니다. 본 논문에서는 이를 Incorrect pointer differences, 그리고 Casting pointers to integers로 나누어 분류하였습니다.
Incorrect pointer differences의 경우, 원래 ptrdiff_t라는 타입을 통해 포인터 주소 사이의 차이를 저장합니다. 그러나 32bit의 경우 WILP32(ptrdiff_t)=WILP32(int)W_{ILP32}(ptrdiff\_t) = W_{ILP32}(int)이므로 int형에 이를 저장해도 문제가 발생하지 않았습니다. 그러나 64bit로 넘어오면서 WM(int)<WM(ptrdiff_t)W_{M}(int)<W_{M}(ptrdiff\_t) (단, W{LP64,LLP64}W∈ \big\{ LP64, LLP64\big\})으로 바뀌었습니다. 따라서 경우에 따라 주소의 정보가 truncation되는 경우가 발생할 수 있습니다.
Casting pointers to integers의 경우, 비록 권장되는 코딩 방법은 아니지만 pointer정보를 int형 변수에 저장하는 것은 32bit에서 문제가 되지 않습니다. 그러나 64bit부터는 latent pointer truncation이 발생합니다. ‘latent’라는 단어를 쓴 이유는, 포인터의 값이 처음 4GB를 넘어가지 않는 경우 truncation이 발생하지 않기 때문입니다. 공격자가 임의적으로 포인터 값을 증가시킬 수 있는 방법은 있지만, 현실적으로 ASLR등의 보호기법때문에 exploit은 힘든 부분이 있습니다.
Table 3은 왼쪽부터 순서대로 ILP32, LLP64, 그리고 LP64를 대상으로 발생할 수 있는 Signedness Issue를 정리한 것입니다. 까만색 동그라미(●)는 Unsigned형식으로 비교하는 형태를 뜻하며, 하얀색 동그라미는 signed형식으로 비교하는 형태를 뜻합니다. 본 논문에서는 Signedness Issue를 통해 발생할 수 있는 취약점을 크데 두 가지로 분류합니다: Sign extensions, Signedness of Comparisons.
Sign extensions의 경우 signed type 정수가 ILP32에서 width보다 넓은 unsigned type으로 변환될 때 sign extension이 발생할 수 있습니다. 예를 들어 ILP32에서 LLP64로 변환하는 경우, intlong에서 size_t로 변환하는 경우, 그리고 LP64의 경우 int에서 unsigned longsize_t로 바꾸는 경우 sign extension이 발생합니다. 이와 관련된 내용은 Table 2의 회색 동그라미로도 정리되어있습니다.
Signedness of Comparisons의 경우 buffer overflow가 발생하지 않도록 체크하는 것은 관련된 정수의 signed type를 올바르게 고려하는 경우에만 유효합니다. 이 경우 대부분의 과정이 unsigned type로 변환 후 비교를 하기 때문에, 경우에 따라서 이 과정을 bypass할 수 있게 됩니다. 이는 Table 3에도 정리되어 있으며, 묵시적 변환하는 과정에서 이 취약점이 많이 발생하기 때문에 취약점이 발생할 가능성이 크다고 평가하고 있습니다.
Effects of a Larger Address Space
64bit 환경에서 실행되는 코드는 정수 width의 변경으로 인한 취약점뿐만 아니라 주소 공간의 크기가 4GB에서 TB단위로 증가했기 때문에 더 많은 양의 메모리를 처리할 수 있어야 합니다. 따라서 이로 인해 32bit 환경에서는 구조적으로 불가능했었던 새로운 취약점이 발생할 수 있으며, 본 논문에서는 Dormant Integer Overflows, Dormant Signedness Issues, 그리고 Unexpected Behavior of Library Functions로 나누어 설명합니다.
Dormant Integer Overflow는 더 넓은 주소공간으로 인해 더 크고 많은 변수를 사용하게 됨으로서 발생하는 취약점 중 하나입니다. Integer Overflow는 단순히 어떤 변수의 크기 뿐만아니라 연산 결과의 범위에 따라 해당 취약점의 후보가 될 수 있습니다.
unsigned int i; size_t len = attacker_controlled(); char *buf = malloc(len); for(i=0; i<len; i++){ *buf++ = get_next_byte(); }
C
복사
위 예시는 compiler warning이 발생하지 않으며, 변수의 크기에 따라 integer overflow가 가능한 경우입니다. LP64LP64LLP64LLP64의 경우에는 unsigned intsize_t보다 width가 작기 때문에, WM(W_M(unsigned int)<WM()<W_M(size_t))이 성립합니다. 이 경우에서 lenUINT_MAX보다 값이 커지는 경우 unsigned int형인 ilen보다 커질 수 없어 무한루프에 갇히게 됩니다. 만일 data model이 ILP32ILP32였다면 unsigned intsize_t의 width가 같기 때문에 무한루프는 발생할 수 없습니다. 본 논문은 이와 관련된 취약점을 통해 Boost C++ Libraries, Chromium, 그리고 GNU Standard C++에서 관련 취약점을 찾을 수 있었습니다.
Dormant Signedness Issues는 위 취약점과 비슷하게, 32bit에서는 구조적으로 불가능했던 취약점이 더 넓은 주소공간으로 인해 Signedness 관련 취약점이 발생하는 것을 뜻합니다. 이에 대한 대표적인 예시는 strlen함수의 리턴 값을 int형 변수에 저장하는 것입니다. 만약 strlen함수의 리턴 값이 INT_MAX를 넘어갈 경우, 이 값은 음수가 되어버립니다. 원래 32bit 환경에서는 제한된 메모리 크기때문에 거의 불가능하다고 여겨졌지만, 64bit 환경에서는 쉽게 발생할 수 있는 취약점입니다.
char buffer[128]; int len = strlen(attacker_str); if(len >= 128) return; memcpy(buffer, attacker_str, len);
C
복사
위는 해당 취약점의 예시 코드입니다. 이 경우 위에서 언급되었던 strlen의 함수의 리턴 값이 int형 변수에 저장되게 되는데, strlen의 리턴값 llIM(<len>)<l<maxIM(I_M(<len>)<l<maxI_M(unsigned int))가 되는 경우 len은 음수가 되면서 len변수의 검사 루틴은 우회가 가능해집니다. 또한 len함수는 다시 memcpy함수에서 unsigned int로 간주되며 buffer overflow가 발생하게 됩니다.
Unexpected Behavior of Library Functions는 여러 standard C library 함수들이 예상치 못한 결과를 리턴하며 발생하는 취약점들을 말합니다. 본 연구에서는 크게 String Formatting, 그리고 File Processing과정에서 취약점을 발견할 수 있었습니다. 주로 String Formatting의 경우 내부적으로 size_t로 처리를 한 뒤 int형으로 리턴값을 내보내주는 함수들에게서 취약점이 발생했습니다.
다음은 File Processing입니다. ftell, fseek, 그리고 fgetpos등의 함수들은 4GB 이상의 파일을 고려하지 않은 상태로 개발되었습니다. 이를 고려하기 위해 ftello, ftello64, 그리고 __ftelli64등의 함수가 새로 생겼지만, 본 연구에서 아직 ftell같은 이전 함수들이 많이 사용되고 있다는 것을 알 수 있었습니다. 특히 연구팀은 ftell 함수의 경우 4GB보다 큰 파일을 다룰 때 예상치 못한 행동을 한다는 것을 찾아낼 수 있었습니다.

Empirical Study

본 연구는 앞서 찾아낸 취약점들이 실제 소프트웨어에서도 발생되는지에 대해서 연구하였습니다. 본 논문에서는 묵시적 변환을 포함하여 분류한 취약점들이 발생하는지 확인하고, 찾아낸 취약점들의 패턴을 기반으로 취약점들을 자동으로 찾아내었습니다.
Implicit Type Conversions
먼저 type conversion에서의 취약점에 대해서 알아보았습니다. 본 연구에서는 Debia stable에서 Required, Important, 그리고 Standard로 태그된 198개의 소스 패키지를 모두 분석하였습니다. 기본적으로 이와 관련한 위험이 있다면 GCC, LLVM clang등의 컴파일러단에서 플래그를 통해 warning을 생성할 수 있지만, 현실적으로 발생할 수 있는 경고의 양이 너무 많기 때문에 이는 대부분 무시됩니다. 본 연구에서는 -Wconversion, -Wsign-conversion, -Wsign-compare, -Wfloat-conversion을 추가하여 이를 확인하였습니다. 이에 대한 결과는 아래와 같습니다.
이를 수행한 결과, 대부분의 warning들은 width 및 sign conversion에 의한 것임을 확인할 수 있었습니다. 위 두 취약점은 모두 64bit 환경에서만 발생한다는 특징이 있었습니다. 반면에 sign comparison 취약점의 경우 비교적 덜 발생하였지만, 위에서 다룬 것처럼 해당 취약점은 unsigned형으로 변환되면서 발생한다기보다는 비교를 하는 과정에서 문제가 발생하게 됩니다. 이러한 점에서 본 연구는 32bit 환경에서의 warning의 양을 비교하였습니다. 따라서 본 논문에서는 경구의 총 15%가 중대하다고 간주될 수 있습니다.
마지막으로 묵시적 타입 변환에 대해서 설명합니다. Table 5는 32bit 환경(ILP32)에서는 width가 4바이트였지만, 64bit 환경(LP64)에서는 width가 8바이트인 경우에 대한 경고의 수를 나타내고 있습니다. 이는 결론적으로 45,000개 이상의 warning이 발생한다는 것을 알 수 있고, 잠재적인 취약점을 가지고 있다는 것을 볼 수 있습니다. 특히 size_t에서 int로의 변환이나 그 반대가 21,000개인 것으로 보아 개발자들이 이에 대해서 가장 인지하지 못하고 있음을 유추할 수 있습니다.
Patterns of 64-bit Migration Issues
앞서 이야기한 묵시적 변환이 모두 취약점으로 이어지는 것은 아닙니다. 따라서 본 연구에서는 앞서 논의한 취약점들을 바탕으로, 크게 5가지의 취약점이 발생할 수 있는 경우를 나누었습니다. 이를 기반으로 가장 인기있는 C/C++ GitHub 프로젝트 200개를 대상으로 취약점을 분석하였으며, 5가지 분류는 다음과 같습니다.
1.
New truncations: atol
2.
New signedness issues: memcpy
3.
Dormant integer overflows: loops
4.
Dormant signedness issues: strlen
5.
Unexpected behavior of library functions: snprintf, ftell
위 5가지 취약점이 64bit 전환과정에서 발생할 수 있는 모든 취약점을 내포하고 있지는 않지만, 전반적인 동향에 대해서 파악할 수 있기 때문에 의미가 있다고 판단하였습니다.
Table 6은 결과를 나타내는 표입니다. P1의 경우, 평균적으로 21%의 atol함수의 리턴 값이 int에 assign되고 있으며, 이는 truncation을 유발합니다. 이와 같은 개념으로 최소 10%에서부터 최대 평균 68%까지 취약점이 발생할 수 있는 코드가 사용되는 것을 확인할 수 있었습니다. 또한, 평균적으로 GitHub의 프로젝트들이 Debian Jessie의 프로젝트보다 더 많은 문제를 내포하고 있음을 확인할 수 있었습니다.

Case Study

Case Study에서는 앞서 64-Bit Migration Vulnerabilities에서 언급한 내용을 실제로 적용한 방법론에 대하여 서술합니다. 본 장에서는 새롭게 발견한 6개의 취약점과, 기존의 2개의 취약점에 대해서 width change와 increased memory of address space로 나누어 분류합니다. 내용은 다음과 같습니다.
New Truncations
이 부분에 대해서는 기존 One-day 취약점인 PHP RCE(CVE-2007-1884), 그리고 연구를 통해 발견한 Linux Kernel 취약점에 대해서 이야기합니다.
먼저 PHP RCE(CVE-2007-1884)의 경우, 4.4.5 그리고 5.2.1이전 버전에서 발생합니다. PHP의 php_sprintf_getnumber라는 함수에서는 format string을 처리한 뒤 long형태로 리턴을 하지만, 그에 대한 값은 int형에 저장되기 때문에 64bit에서 truncation이 발생하게 됩니다. LP64 data model에서만 취약점이 발생했지만, INT_MAX이상의 string을 전달할 경우 RCE까지 이어질 수 있기 때문에 취약점의 심각성이 높습니다.
Linux kernel의 경우, C standard library 함수가 자체적으로 구현되어있습니다. 본 취약점은 Linux kernel ver. 4.6 이전의 버전의 snprintf함수가 큰 값을 확인하지 않기 때문에 취약점이 발생합니다. 이의 내용은 64-bit Migration Vulnerabilities의 ‘Integer Width 변경’에서 설명한 예시와 같습니다.
New Signedness Issue
New Signedness Issue의 경우, one-day 취약점인 libarchive sign-comparison과 연구진이 발견한 zlib sign-extension이 있습니다.
zlib의 sign-extension의 경우 zlib 1.2.8버전의 gzprintf함수에서 발생합니다. gzprintf함수는 formatted string을 buffer안에 쓰는 역할을 하는데, 이때 이 함수가 처리하는 string의 길이가 INT_MAX보다 커지면 이를 제대로 저장하지 못합니다. 함수 내부적으로는 크기를 unsigned int형으로 관리하는 방면, 중간에 int형으로 casting하게 됩니다. 이로 인해 truncation이 발생하게 되며, 이후 이 값은 size_t형인 vsnprintf의 두 번째 파라미터로 사용되게 됩니다. 이때 이 파라미터는 버퍼에 얼마나 값을 쓸 지 결정하기 때문에, buffer overflow가 가능하게 합니다.
libarchive에서 발생한 sign-comparison 문제의 경우, libarchive ver.3.1.2의 archive_write_zip_data함수에서 취약점을 발견했습니다. 이 함수는 zip archive를 쓰고, 그에 대한 버퍼의 주소 및 크기를 전달받습니다. 이 함수는 데이터를 쓰기 전, 지정된 버퍼가 zip archive에 쓸 수 있는 최대 바이트 수를 초과하는지에 대한 검증을 진행합니다. 이 과정에서 size_t에서 int64_t로의 명시적 변환이 진행되는데, 여기서 문제가 발생합니다. 32bit 시스템에서는 INT64_MAX가 SIZE_MAX보다 크기 때문에 값이 SIZE_MAX보다 더 큰지 확인이 가능하지만, 64bit 시스템에서는 두 값이 동일하기 때문에 최대 허용 바이트 수와 관계없이 수행이 되게 됩니다.
Dormant Integer Overflows
Dormant Integer Overflow의 경우, GNU C Library와 C++ shared pointer에서 취약점을 발견하였습니다.
GNU C Library의 경우, ver.2.23의 wcswidth 함수에서 integer overflow가 발생하게 됩니다. 이 함수는 wide-character string을 표현하는데 필요한 열의 수를 카운트합니다. 이때 이 카운터는 함수의 반환값에 따라 int형 변수로 정의되는데, 64bit 시스템에서는 입력값이 INT_MAX보다 긴 string을 넘겨줄 수 있기 때문에 overflow가 발생합니다. 나아가 이 값이 UINT_MAX보다 큰 길이를 가지는 경우, integer overflow가 발생하여 buffer overflow가 발생하게 됩니다.
C++의 shared pointer는 사용되는지 추적하고, 참조 수를 관리하는 원시 포인터의 컨테이너입니다. 이 shared pointer의 특징은 모든 참조가 삭제되면 마지막 인스턴스가 호스트된 원시 포인터도 삭제된다는 점입니다. 이때 참조 카운터는 int형의 정수로 구현이 되는데, 64bit로 변환되며 더 많은 저장공간을 사용할 수 있고, 결론적으로 integer overflow가 일어날 만큼 shared pointer를 생성할 수 있어 취약점이 발생했습니다. 이 상태에서 파괴되는 shared pointer는 원시 포인터도 함께 해제하며, 결론적으로 UINT_MAX 인스턴스는 이미 해제된 곳을 가리키게 되며 Use After Free취약점이 발생합니다.이 취약점은 Boost C++ Library ver.1.6 뿐만아니라 Chronium ver.52.0, 그리고 GCC ver. 6.1.0을 사용하는 모든 GNU Standard C++ Library들은 모두 이 취약점의 영향을 받았습니다.
Dormant Signedness Issues
Dormant Signedness Issues의 경우, libarchive ver. 3.2.0에서 64bit 환경에서만 exploit이 가능한 취약점을 발견하였습니다.
본 취약점은 iso9660 컨테이너가 처리하는 과정에서 Joliet 식별자의 최대 길이를 확인하는 과정에서 발생합니다. 검증과정에서 이름의 길이는 size_t형에 저장되지만, 중간에 int형으로 변환됩니다. 이 과정에서 길이 검증 과정을 bypass할 수 있고, 이는 더 큰 메모리를 관리하는 64bit 시스템에서만 본 취약점이 발생합니다. libarchive는 이름을 UTF-16, 그리고 multi-byte version으로 관리하기 때문에, 이론적으로 bypass에 필요한 메모리의 3배를 할당하게 됩니다.

Conclusion

본 연구를 통해서 64-bit로의 전환이 10년간 진행된 지금에도 잘못된 implicit conversion은 아직 완성도가 높은 소프트웨어에서도 발견되는 것을 확인할 수 있었습니다. 본 논문은 이와 관련된 취약점들에 대해 체계적으로 분류하고 정의합니다.
이런 발견을 바탕으로 실제 프로젝트에 적용한 결과, Debian stable의 C/C++ 프로젝트에서 type conversion과 관련한 경고가 평균적으로 1,798개가 생성되며, 이 중 703개는 64-bit 시스템에 한정된다는 것을 확인할 수 있었습니다.
끝으로, 본 연구과정에서 이루어낸 시스템화와 그 경험을 활용하여 Linux kernel, Chromium, Boost C++ 라이브러리, libarchive 그리고 zlib에서 총 6개의 새로운 취약점을 발견했습니다.
나아가 앞으로 이런 취약점을 줄이기 위해서는 소프트웨어 보안의 특정 측면에 대한 인식을 높이고 implicit conversion을 피하는 것이라고 제언합니다.

3. 결론

코드 자체에 대한 취약점이 아니라, 환경에 차이로 인해 발생하는 취약점에 대해서 연구한 것이 인상적인 논문이었습니다. 그리고 분석을 통해 하나의 시스템화를 하고, 나아가 새로운 취약점을 찾았다는 점 또한 의미가 깊었다고 생각합니다.
저희의 연구와 관련지어서는, 디컴파일러들은 대부분 취약점 분석가들이 취약점을 찾기 위해 사용하기 때문에, 취약점이 존재하는 바이너리에 대해 어떻게 디컴파일 하는지도 평가 요소에 포함시키면 좋을 것 같다고 생각합니다.

4. Reference