보안 공부/소스코드 보안약점 진단

소스코드 보안약점 진단 - 포맷 스트링 삽입

H.J.World 2021. 12. 30. 10:10
728x90
반응형

소스코드 보안약점 진단 // 소프트웨어 보안약점 진단 // SW 보안약점 진단과 같이 다양한 이름으로 불리는 진단 과업 중 하나이다.

SW개발보안은 해킹 등 사이버공격의 원인인 보안약점을 SW개발단계에서 사전에 제거하고 SW 개발 생명주기의 각 단계별로 수행하는 일련의 보안활동을 통하여 안전한 SW를 개발·운영하기 위한 목적으로 적용하는 개발체계이다.

해당 내용은 KISA에서 발간하는 취약점 진단 가이드 항목을 기준으로 작성한다.


15. 메모리 버퍼 오버플로우

가. 개요

외부로부터 입력된 값을 검증하지 않고 입·출력 함수의 포맷 문자열로 그대로 사용하는 경우 발생 할 수 있는 보안약점이다. 공격자는 포맷 문자열을 이용하여 취약한 프로세스를 공격하거나 메모리 내용을 읽거나 쓸 수 있다. 그 결과, 공격자는 취약한 프로세스의 권한을 취득하여 임의의 코드를 실행할 수 있다.

나. 보안대책

printf(), snprintf() 등 포맷 문자열을 사용하는 함수를 사용할 때는 사용자 입력값을 직접적으로 포맷 문자열로 사용하거나 포맷 문자열 생성에 포함시키지 않는다. 포맷문자열을 사용하는 함수에 사용자 입력값을 사용할 때는 사용자가 포맷 스트링을 변경할 수 있는 구조로 쓰지 않는다. 특히, %n, %hn은 공격자가 이를 이용해 특정 메모리 위치에 특정값을 변경할 수 있으므로 포맷 스트링 매개변수로 사 용하지 않는다. 사용자 입력값을 포맷 문자열을 사용하는 함수에 사용할 때는 가능하면 %s 포맷 문 자열을 지정하고, 사용자 입력값은 2번째 이후의 파라미터로 사용한다.

다. 코드예제

포맷 스트링 보안약점은 C 언어에 국한된 것은 아니다. 아래 예제 코드는 입력 자료의 유효성을 검 증하지 않은 Java 프로그램에서도 발생할 수 있음을 보여준다. 이 프로그램에서 공격자 는 %1$tm,%1$te, 또는 %1$tY과 같은 문자열을 입력하여 포맷 문자열에 포함시킴으로써, 실제 유효기간 valid- Date가 출력되도록 할 수 있다.

- 안전하지 않은 코드의 예 JAVA -

// 외부 입력값에 포맷 문자열 포함 여부를 확인하지 않고 포맷 문자열 출력에 값으로 사용
// args[0]의 값으로 “%1$tY-%1$tm-%1$te"를 전달하면 시스템에서 가지고 있는 날짜(2014-10-14)
정보가 노출
1: import java.util.Calendar
2: ......
3: public static void main(String[] args) {
4: Calendar validDate = Calendar.getInstance();
5: validDate.set(2014, Calendar.OCTOBER, 14);
6: System.out.printf( args[0] + " did not match! HINT: It was issued on %1$terd of some 
month", validate);
7: }

- 안전한 코드의 예 JAVA -

사용자로부터 입력받은 문자열을 포맷 문자열에 직접 포함시키지 않고, %s 포맷 문자열을 사용함 으로써 정보유출을 방지한다.

// 외부 입력값이 포맷 문자열 출력에 사용되지 않도록 수정
1: import java.util.Calendar
2: :
3: public static void main(String[] args) {
4: Calendar validDate = Calendar.getInstance();
5: validDate.set(2014, Calendar.OCTOBER, 14);
6: System.out.printf("%s did not match! HINT: It was issued on %2$terd of some
month", args[0], validate);
7:

 

라. 진단방법

포맷 스트링을 이용하는 함수를 사용하는 경우 인자로 포맷 스트링이 포함되어 있는지 반드시 확인 하고, 외부 입력 값이 포맷 스트링에 생성에 사용되는지 확인한다. 포맷 스트링이 함수의 인자로 포함 되어 있고, 외부 입력 값이 포맷 스트링 생성에 사용되지 않으며, 포맷 스트링에서 사용하는 인자의 개수와 매개변수로 포함된 인자의 개수가 일치하는 경우 안전하다고 판단한다. 또한 포맷에 출력할 데이터의 길이를 반드시 한정하도록 한다. 그 외에는 모두 취약하다고 판단한다.

 

- 정탐코드의 예 -

다음 예제는 포맷 스트링이 인자로 존재하지만, 사용자 입력값을 포맷스트링 생성에 사용하기 때문 에 보안약점이 존재하는 코드로 진단할 수 있다. 공격자가 “%1$tm, %1$te, %1$tY”와 같은 입력을 하게 된다면, 예제코드는 문제를 일으키게 된다.

1: class Format {
2: static Calendar c = new GregorianCalendar(1995, GregorianCalendar.MAY, 23);
3: public static void main(String[] args) {
4: System.out.printf(args[0] + “ did not match! HINT: It was issued on %1$terd of
some month”, c);
5: }
6: }
728x90
반응형