IgnatiusHeo

구현단계 보안약점 제거 기준-Null Pointer 역참조 본문

자격/SW보안약점진단원

구현단계 보안약점 제거 기준-Null Pointer 역참조

Ignatius Heo 2023. 7. 6. 14:40

작성일: 230706

 

※ 본 게시글은 학습 목적으로 행정안전부·KISA의 소프트웨어 보안약점 진단 가이드, 소프트웨어 개발보안 가이드를 참고하여 작성하였습니다.

 

정리 내용: 소프트웨어 보안약점 진단 가이드(433~444p)

구분 - 입력데이터 검증 및 표현
설계단계 - 보안기능 입력값 검증
https://cryptocurrencyclub.tistory.com/97
개요 널 포인터(Null Pointer) 역참조는 ‘일반적으로 그 객체가 널(Null)이 될 수 없다’라고 하는 가정을 위반했을 때 발생한다.

공격자가 의도적으로 널 포인터 역참조를 발생시키는 경우, 그 결과 발생하는 예외 상황을 이용하여 추후 공격을 계획하는 데 사용될 수 있다.
진단 세부사항
(설계단계)
 ① 사용자의 역할, 권한을 결정하는 정보는 서버에서 관리해야 한다. 사용자 및 권한 확인 절차를 확인하여 서버에서 관리하는 세션정보를 사용하도록 설계하고 있는지 확인한다.
  ㅇ  사용자에 대한 역할을 구분하고 있으며, 각 역할 별 권한의 구분 여부 확인
  ㅇ  사용자의 역할과 권한을 정의하여 저장할 수 있도록 데이터베이스가 설계되어 있는지 확인
  ㅇ  사용자의 역할과 권한을 검증하는 모듈이 설계되어 있거나, 외부 라이브러리를 사용하는 경우 사용자의 권한이나 역할 검증을 위한 정보가 DB 또는 세션에 저장되도록 설계되어 있는 지 확인
  ㅇ  조작된 입력 파라미터, 쿠키 등을 전달하여 사용자의 역할이나 권한 체크가 우회되는지 점검하기 위한 테스트계획이 수립되어 있는지 확인
 
 ② 쿠키값, 환경변수, 파라미터 등 외부입력값이 보안기능을 수행하는 함수의 인자로 사용되는 경우, 입력값에 대한 검증작업을 수행한 뒤 제한적으로 사용해야 한다.
외부입력값을 이용하여 사용자 및 권한 확인 등 보안기능에 사용하는 경우 입력값을 검증하도록 명시하고 있는지 확인한다.
  ㅇ  보안기능 수행에 사용되는 값의 종류, 출처, 의미 등의 정의 여부 확인
  ㅇ  외부 입력값을 사용해야 하는 경우, 타당한 근거/사유가 명시되어 있는지 확인
  ㅇ  보안기능 수행에 외부 입력ㄱ밧이 사용되는 경우, 외부 입력값에 대한 검증 방법 정의 여부 확인(NULL 검사, 정수오버플로우 등)
  ㅇ  외부입력값을 조작하여 보안 기능의 무력화 또는 오작동 여부를 점검하기 위한 테스트 계획의 수립 여부 확인
 
 ③ 중요상태정보나 인증, 권한결정에 사용되는 정보는 쿠키로 전송되지 않아야 하며, 불가피하게 전송하는 경우에는 해당 정보를 암호화해서 전송해야 한다. 생성되는 응답페이지에 외부입력값이 사용되는 경우 사용자 입력값에 스크립트가 포함되어 있는지 검증하도록 설계하고 있는지 확인한다.
  ㅇ  쿠키에 포함될 정보의 이름, 값, 의미, 유효기간 등을 정의하고 있는지 확인(중요정보가 포함되는 경우 근거/사유)
  ㅇ  중요정보를 쿠키로 전달하는 경우 암호화처리방식 설계여부 확인(암호화 통신채널 or 쿠키를 안전한 암호알고리즘을 사용하여 암호화하여 전송)
  ㅇ  쿠키로 전달된 중요정보의 무결성 검사 방법과 모듈의 설계 여부 확인
  ㅇ  쿠키에 포함된 값을 복호화하거나 변조된 쿠키를 전달하여 정보 조작이 가능한지 점검하기 위한 테스트계획 수립 여부 확인
보안대책
(구현단계)
널이 될 수 있는 레퍼런스(Reference)는 참조하기 전에 널 값인지를 검사하여 안전한 경우에만 사용한다.
진단방법
(구현단계)
표현된 객체가 널(Null) 값이 될 수 있는지 확인한다. 만약 널(Null) 값이 될 수 있는지 체크하여 예외 처리를 한 경우 안전으로 판단하고 널(Null) 체크를 하지 않은 경우 취약한 것으로 판단한다.

널값이 될 가능성(출처: 소프트웨어 보안약점 진단 가이드 2021, 행정안전부·KISA)

다. 코드예제

 

ㅇ 분석

1: public static int cardinality (Object obj, final Collection col) {
2: int count = 0;
3: if (col == null) {
4: return count;
5: }
6: Iterator it = col.iterator();
7: while (it.hasNext()) {
8: Object elt = it.next();
//obj가 null이고 elt가 null이 아닐 경우, Null.equals 가 되어 널(Null) 포인터 역참조가 발생한다.
9: if ((null == obj && null == elt) || obj.equals(elt)) {
10: count++;
11: }
12: }
13: return count;
14: }

ㅇ 내용

1. 저 조건문은 obj = elt = null이거나 obj=elt면 카운트 추가

2. 주석처럼 obj=null이고 elt!=null이면 두번째 조건을 만족함. 이 조건을 수정해야함

 

ㅇ 수정

1: public static int cardinality (Object obj, final Collection col) {
2: int count = 0;
3: if (col == null) {
4: return count;
5: }
6: Iterator it = col.iterator();
7: while (it.hasNext()) {
8: Object elt = it.next();
//obj가 null이 아닌 경우에만 obj.equal를 실행한다.
9: if ((null == obj && null == elt) || (null != obj && obj.equals(elt))) {
10: count++;
11: }
12: }
13: return count;
14:}

ㅇ 내용

1. 두번째 조건에 obj!=null 추가함

 


ㅇ분석

1: String url = reuqest.getParamter("url");
2: //url 에 null이 들어오면 널(Null) 포인터 역참조가 발생한다.
3: if (url.equals(""))

ㅇ수정

1: String url = reuqest.getParamter("url");
2: //null값을 가지는 참조 변수를 사용할 경우, null 검사를 수행하고 사용한다.
3: if ( url != null || url.equals("") )

 


ㅇ분석

1: protected void Page_Load(object sender, EventArgs e) {
2: // url 파라미터에 name이 없으면 username은 null 값을 가지게 된다.
3: string username = Request.QueryString[“name”];
4: // null 값을 가지는 username을 참조하여 널(Null) 포인터 역참조가 발생한다.
5: if (username.Length > 20) {
6: // length error
7: }
8: }

ㅇ내용

ㅇ수정

1: protected void Page_Load(object sender, EventArgs e) {
2: // url 파라미터에 name 이 없으면 username은 null 값을 가지게 된다.
3: string username = Request.QueryString[“name”];
4: // null 값을 가지는 username을 참조하기 전에 null 검사를 수행하므로 안전하다.
5: if ( username != null && username > 20) {
6: // length error
7: }
8: }

ㅇ내용

 


ㅇ분석

1: void NullPointerDereference(int count) {
// IntegerAddressReturn()이 0을 return 하면 p는 null 값을 가지게 된다.
2: int *p = IntegerAddressReturn();
// null 값을 가지는 p 값을 참조하여 널(Null) 포인터 역참조가 발생한다.
3: *p = count;
4: }

ㅇ내용

ㅇ수정

1: void NullPointerDereference(int count) {
// IntegerAddressReturn()이 0을 return 하면 p는 null 값을 가지게 된다.
2: int *p = IntegerAddressReturn();
// 참조하기전에 null 검사를 수행하므로 안전하다.
3: If(p != 0) *p = count;

ㅇ내용

 

 

 

 

끝.