계: Input Validation and Representation
입력 검증 및 표현 문제는 메타 문자, 대체 인코딩 및 숫자 표현 때문에 발생합니다. 보안 문제는 입력을 신뢰하기 때문에 발생합니다. 문제로는 "Buffer Overflows", "Cross-Site Scripting" 공격, "SQL Injection", 그 외 여러 가지가 있습니다.
Integer Overflow
Abstract
Integer overflow를 다루지 않으면 로직 오류 또는 buffer overflow가 발생할 수 있습니다.
Explanation
정수 오버플로 오류는 산술 연산의 결과값이 데이터 형식의 최대값보다 크거나 최소값보다 작을 수 있다는 것을 프로그램이 고려하지 못할 때 발생합니다. 이러한 오류는 종종 사용자 입력이 부호 있는 값과 부호 없는 값 사이의 암묵적 변환과 충돌하는 메모리 할당 함수에서 문제를 일으킵니다. 프로그램이 메모리를 과소 할당하거나 부호 있는 값을 메모리 연산에서 부호 없는 값으로 해석하도록 공격자가 만들 수 있는 경우, 해당 프로그램은 버퍼 오버플로에 취약할 수 있습니다.
예제 1: OpenSSH 3.3에서 발췌한 다음 코드는 integer overflow의 전형적인 경우를 보여 줍니다.
예제 2: 이 예제에서는 일련의 가변 길이 구조로 구성된 사용자 입력을 처리합니다. 입력의 첫 2바이트는 처리할 구조의 크기를 지정합니다.
프로그래머가 구조 크기에 끼치는 상한을 설정했습니다. 구조 크기가
예제 1: OpenSSH 3.3에서 발췌한 다음 코드는 integer overflow의 전형적인 경우를 보여 줍니다.
nresp = packet_get_int();
if (nresp > 0) {
response = xmalloc(nresp*sizeof(char*));
for (i = 0; i < nresp; i++)
response[i] = packet_get_string(NULL);
}
nresp
의 값이 1073741824
이고 sizeof(char*)
의 값이 일반적으로 사용되는 4
이면 nresp*sizeof(char*)
작업의 결과가 overflow되며, xmalloc()
의 인수는 0
이 됩니다. malloc()
구현은 대부분 0바이트 버퍼의 할당을 허용하여 이후 루프가 반복되어 heap buffer response
가 overflow됩니다.예제 2: 이 예제에서는 일련의 가변 길이 구조로 구성된 사용자 입력을 처리합니다. 입력의 첫 2바이트는 처리할 구조의 크기를 지정합니다.
char* processNext(char* strm) {
char buf[512];
short len = *(short*) strm;
strm += sizeof(len);
if (len <= 512) {
memcpy(buf, strm, len);
process(buf);
return strm + len;
} else {
return -1;
}
}
프로그래머가 구조 크기에 끼치는 상한을 설정했습니다. 구조 크기가
512
보다 크면 입력이 처리되지 않습니다. 문제는 len
이 부호 있는 정수여서 최대 구조 길이가 부호 있는 정수를 사용해 확인되지만 memcpy()
호출에서는 len
이 부호 없는 정수로 변환된다는 점입니다. len
이 음수이면 구조의 크기가 적절한 것으로 표시되지만(if
분기를 가져옴) memcpy()
에서 복사하는 메모리 양이 상당히 많아 공격자가 strm
의 데이터로 스택을 overflow할 수 있습니다.References
[1] blexim Basic Integer Overflows Phrack
[2] D. Plakosh Coding Flaws That Lead to Security Failures 2nd Annual Hampton University Information Assurance Symposium
[3] Les Hatton Safer C: Developing Software for High-integrity and Safety-critical Systems McGraw-Hill Companies
desc.dataflow.cpp.integer_overflow
Abstract
정수 오버플로를 고려하지 않으면 논리 오류나 버퍼 오버플로를 일으킬 수 있습니다.
Explanation
정수 오버플로 오류는 산술 연산의 결과값이 데이터 형식의 최대값보다 크거나 최소값보다 작을 수 있다는 것을 프로그램이 고려하지 못할 때 발생합니다. 이러한 오류는 종종 사용자 입력이 부호 있는 값과 부호 없는 값 사이의 암묵적 변환과 충돌하는 메모리 할당 함수에서 문제를 일으킵니다. 프로그램이 메모리를 과소 할당하거나 부호 있는 값을 메모리 연산에서 부호 없는 값으로 해석하도록 공격자가 만들 수 있는 경우, 해당 프로그램은 버퍼 오버플로에 취약할 수 있습니다.
예제: 다음 코드 발췌는 정수 오버플로의 전형적인 경우를 보여줍니다.
예제: 다음 코드 발췌는 정수 오버플로의 전형적인 경우를 보여줍니다.
77 accept-in PIC 9(10).
77 num PIC X(4) COMP-5. *> native 32-bit unsigned integer
77 mem-size PIC X(4) COMP-5.
...
ACCEPT accept-in
MOVE accept-in TO num
MULTIPLY 4 BY num GIVING mem-size
CALL "CBL_ALLOC_MEM" USING
mem-pointer
BY VALUE mem-size
BY VALUE 0
RETURNING status-code
END-CALL
num
에 1073741824
값이 있으면 MULTIPLY 4 BY num
연산의 결과가 오버플로되며, malloc()
에 대한 mem-size
인수는 0
이 됩니다. 대부분의 malloc()
구현에서는 0바이트 버퍼를 할당하는 것이 허용되므로 힙 버퍼 mem-pointer
가 후속 명령문에서 오버플로됩니다.References
[1] blexim Basic Integer Overflows Phrack
[2] D. Plakosh Coding Flaws That Lead to Security Failures 2nd Annual Hampton University Information Assurance Symposium
[3] Les Hatton Safer C: Developing Software for High-integrity and Safety-critical Systems McGraw-Hill Companies
desc.dataflow.cobol.integer_overflow
Abstract
함수가 정수 계산을 잘못 처리하므로 오버플로/언더플로가 발생합니다.
Explanation
정수 오버플로/언더플로란 계산이나 산술 연산의 결과 값이 정수 유형의 최대값보다 크거나 최소값보다 작아서 결과 값의 하한/상한으로 루프백된 후 하한/상한 값에서 계산이 계속 반복되는 상황입니다. 산술 연산의 결과 값은 사실상 상한/하한 경계부터 시작되는 정수 범위의 계수입니다.
예를 들어
예제 1: 다음 공개 함수는 산술 연산을 사용하여
예를 들어
uint256
유형으로 저장되는 숫자는 0에서 2^256-1 범위의 256비트 부호 없는 숫자로 저장됩니니다. 산술 연산 결과가 상한보다 큰 숫자이면 오버플로가 발생하며 시작 값(0)에 나머지 값을 더합니다. 산술 연산 결과가 하한보다 작은 숫자이면 언더플로가 발생하며 최대값(2^256-1)에서 나머지 값을 뺍니다.예제 1: 다음 공개 함수는 산술 연산을 사용하여
uint256
매핑을 업데이트합니다. 이 산술 연산으로 인해 정수 오버플로/언더플로가 발생할 수 있으며, 해당 현상은 맵에서 의도하지 않은 인덱스에 영향을 줄 수 있습니다.
contract overflow {
mapping(uint256 => uint256) map;
function init(uint256 k, uint256 v) public {
map[k] -= v;
}
}
References
[1] Enterprise Ethereum Alliance No Overflow/Underflow
desc.structural.solidity.swc101