유형 | 입력데이터 검증 및 표현 |
보안약점 | 정수형 오버플로우 |
개요 |
정수형 오버플로우는 정수값이 증가하면서 허용된 가장 큰 값보다 커져서 실제 저장되는 값이 의도치 않게 아주 작은 수이거나 음수가 되어 발생한다.
특히 반복문 제어, 메모리 할당, 메모리 복사 등을 위한 조건으로 사용자가 제공하는 입력값을 사용하고 그 과정에서 정수형 오버플로우가 발생하는 경우 보안상 문제를 유발할 수 있다.
|
보안대책 |
언어·플랫폼별 정수타입의 범위를 확인하여 사용한다.
정수형 변수를 연산에 사용하는 경우, 결과값의 범위를 체크하는 모듈을 사용한다.
외부 입력값을 동적 메모리 할당에 사용하는 경우, 변수값이 적절한 범위 내에 존재하는 값인지 확인한다.
|
진단방법 |
변수를 사용하여 배열의 크기를 동적으로 결정하고 있는 경우, 변수가 외부 입력값인지 확인하고, 해당 변수가 의도한 범위 내에 존재하는지 확인하는 절차가 있는지 확인한다.
외부 입력값에 대한 검증 절차가 없다면 취약하다.
|
연관된 설계단계 기준 | 보안기능 입력값 검증 |
코드예제
● 안전하지 않은 코드 예 (Java)
String msg_str = "";
String tmp = request.getParameter("slf_msg_param_num");
tmp = StringUtil.isNullTrim(tmp);
if (tmp.equals("0")) {
msg_str = PropertyUtil.getValue(msg_id);
} else {
// 외부 입력값을 정수형으로 사용할 때 입력값의 크기를 검증하지 않고 사용
int param_ct = Integer.parseInt(tmp);
String[] strArr = new String[param_ct];
● 안전한 코드 예 (Java)
String msg_str = "";
String tmp = request.getParameter("slf_msg_param_num");
tmp = StringUtil.isNullTrim(tmp);
if (tmp.equals("0")) {
msg_str = PropertyUtil.getValue(msg_id);
} else {
// 외부 입력값을 정수형으로 사용할 때 입력값의 크기를 검증하고 사용
try {
int param_ct = Integer.parseInt(tmp);
if (param_ct < 0) {
throw new Exception();
}
String[] strArr = new String[param_ct];
} catch(Exception e) {
msg_str = "잘못된 입력(접근) 입니다.";
}
● 안전하지 않은 코드 예 (C#)
public static void Main(string[] args)
{
// 외부 입력값을 사용할 때, 입력 값의 크기가 너무 클 경우 오버플로우 발생
int usrNum = Int32.Parse(args[0]);
string[] array = {"one", "two", "three", "four"};
string num = array[usrNum];
}
● 안전한 코드 예 (C#)
public static void Main(string[] args)
{
// checked 구문을 사용하여 오버플로우의 발생 여부 및 크기 확인
try{
int usrNum = checked(Int32.Parse(args[0]));
string[] array = {"one", "two", "three", "four"};
if(usrNum < 3)string num = array[usrNum];
}
catch (System.OverflowException e) { … }
}
● 안전하지 않은 코드 예 (C)
void main(int argc, char* argv[])
{
// 외부 입력값을 사용할 때, 입력 값의 크기가 너무 클 경우 오버플로우 발생
int usr_num = 0;
char* num_array[] = {"one", "two", "three", "four"};
char* num = NULL;
usr_num = atoi(argv[1]);
num = num_array[usr_num];
}
● 안전한 코드 예 (C)
void main(int argc, char* argv[])
{
// 외부 입력값을 사용할 때, 입력 값의 크기가 너무 클 경우 오버플로우 발생
int usr_num = 0;
char* num_array[] = {"one", "two", "three", "four"};
char* num = NULL;
usr_num = atoi(argv[1]);
if (usr_num >= 0 && usr_num < 4) {
num = num_array[usr_num];
}
}
진단방법

변수를 사용하여 배열의 크기를 동적으로 결정하고 있는 경우(①), 변수가 외부 입력값인지 확인하고(②), 해당 변수가 의도한 범위내에 존재하는지 확인하는 절차가 있는지 확인한다. 외부 입력값에 대한 검증 절차가 없다면 취약하다.
● 일반적인 진단의 예
…
String cnt = request.getParameter("cnt"); ·····························②
if( cnt == null ) {
cnt = "0";
}
int cntI = Integer.parseInt(cnt);
String[] arr = new String[cntI]; ···········································①
for( int i = 0 ; i <cntI ; i++ ) {
arr[i] = request.getParameter("r"+i);
}
…
● 정탐코드
public static Vector parsFileBySize(String parFile, int[] parLen, int parLine) throws Exception {
// 파싱결과 구조체
Vector parResult = new Vector();
// 파일 오픈
String parFile1 = parFile.replace('\\', FILE_SEPARATOR).replace('/', FILE_SEPARATOR);
File file = new File(parFile1);
BufferedReader br = null;
try {
// 파일이며, 존재하면 파싱 시작
if (file.exists() && file.isFile()) {
// 1. 입력된 라인수만큼 파일 텍스트 내용을 읽어서 String[]에 쌓는다.
br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
String [] strArr = new String [parLine];
String line = "";
int readCnt = 0;
while ((line = br.readLine()) != null && readCnt < parLine) {
if (line.length() <= MAX_STR_LEN)
strArr[readCnt++] = line;
}
정수형 변수의 값이 증가하면서 정수형 한계값보다 더 커지는 경우 아주 작은 값이 되거나 음수가 될 수 있다. 이러한 상황에 대한 검사가 이루어지지 않고 진행하는 경우 취약하다.
● 정탐코드
String msg_str = "";
String tmp = request.getParameter("slf_msg_param_num");
tmp = StringUtil.isNullTrim(tmp);
if (tmp.equals("0")) {
msg_str = PropertyUtil.getValue(msg_id);
} else {
// 외부 입력값을 정수형으로 사용할 때 입력값의 크기를 검증하지 않고 사용
int param_ct = Integer.parseInt(tmp);
String[] strArr = new String[param_ct];
......
}
외부의 입력(slf_msg_param_num)으로 받은 값을 배열의 크기(size)를 결정하는데 사용하고 있다. 만일 외부에서 입력받은 값(param_ct)이 음수값인 경우, 배열의 크기가 음수가 되어 시스템에 문제가 발생할 수 있으므로 취약하다고 판단한다.
● 오탐코드
try {
URL url = Util.class.getClassLoader().getResource(publicKeyFilepath);
pubKey = url.openStream();
} catch (MalformedURLException e) {
pubKey = new FileInputStream(publicKeyFilepath);
}
byte[] bytes = new byte[pubKey.available()];
pubKey.available() 함수는 int 값을 리턴 한다. 그러므로 정수값 한계를 벗어난 값은 발생하지 않는다.
● 오탐코드
String[] referer_split = Util.split(request.getHeader("Referer").toString(),"/");
String refererValue = referer_split[referer_split.length-1];
입력 값은 HTTP 헤더의 한계값이 있으므로 정수의 한계를 초과할 가능성이 없다.
● 오탐코드
public static void main(String[] args) {
String[] jsargs = {"-j="+args[0]};
String[] allArgs = new String[jsargs.length + args.length];
인자의 개수가 정수의 한계 이상으로 입력된다는 것은 실현 가능성이 희박하므로 취약하지 않은 것으로 판단한다.
'소프트웨어(SW) 보안약점 진단원 > 구현단계 보안약점 제거 기준' 카테고리의 다른 글
구현단계 보안약점 기준 - 메모리 버퍼 오버플로우 (0) | 2025.05.27 |
---|---|
구현단계 보안약점 기준 - 보안기능 결정에 사용되는 부적절한 입력값 (1) | 2025.05.27 |
구현단계 보안약점 기준 - HTTP 응답분할 (0) | 2025.05.27 |
구현단계 보안약점 기준 - 서버사이드 요청 위조 (1) | 2025.05.26 |
구현단계 보안약점 기준 - 크로스사이트 요청 위조 (0) | 2025.05.26 |