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

소스코드 보안약점 진단 - 부적절한 자원 해제

H.J.World 2022. 2. 1. 10:10
728x90
반응형

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

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

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

 

제 5절 코드오류

타입 변환 오류, 자원(메모리 등)의 부적절한 반환 등과 같이 개발자가 범할 수 있는 코딩오류로 인해 유발되는 보안약점이다.


2. 부적절한 자원 해제

가. 개요

프로그램의 자원, 예를 들면 열린 파일디스크립터(Open File Descriptor), 힙 메모리(Heap Memory), 소켓(Socket) 등은 유한한 자원이다. 이러한 자원을 할당받아 사용한 후, 더 이상 사용하지 않는 경우 에는 적절히 반환하여야 하는데, 프로그램 오류 또는 에러로 사용이 끝난 자원을 반환하지 못하는 경우이다.

나. 보안대책

자원을 획득하여 사용한 다음에는 반드시 자원을 해제하여 반환한다.

다. 코드예제

try구문 내 처리 중 오류가 발생할 경우, close()메서드가 실행되지 않아 사용한 자원이 반환되지 않을 수 있다.

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

1: InputStream in = null;
2: OutputStream out = null;
3: try {
4: in = new FileInputStream(inputFile);
5: out = new FileOutputStream(outputFile);
6: ...
7: FileCopyUtils.copy(fis, os);
8: //자원반환 실행 전에 오류가 발생할 경우 자원이 반환되지 않으며, 할당된 모든 자원을 반환해야
한다.
9: in.close();
10: out.close();
11: } catch (IOException e) {
12: logger.error(e);
13: }

 

- 안전한 코드의 예 JAVA -

예외상황이 발생하여 함수가 종료될 때, 예외의 발생 여부와 상관없이 항상 실행되는 finally 블록에서 할당받은 모든 자원을 반드시 반환하도록 한다.

1: InputStream in = null;
2: OutputStream out = null;
3: try {
4: in = new FileInputStream(inputFile);
5: out = new FileOutputStream(outputFile);
6: ...
7: FileCopyUtils.copy(fis, os);
8: } catch (IOException e) {
9: logger.error(e);
10: //항상 수행되는 finally 블록에서 할당받은 모든 자원에 대해 각각 null검사를 수행 후 예외처리를
하여 자원을 해제하여야 한다.
11: } finally {
12: if (in != null) {
13: try {
14: in.close();
15: } catch (IOException e) {
16: logger.error(e);
17: }
18: }
19: if (out != null) {
20: try {
21: out.close();
22: } catch (IOException e) {
23: logger.error(e);
24: }
25: }
26: }

 

라. 진단방법

자원(파일기술자, 힙메모리, 소켓)이 선언되고, 선언된 자원이 할당된 경우 해제되는지 확인한다. 진단자는 제어문, 예외처리문 등의 분기 등에 따라 모든 흐름(control flow)을 판단하여 자원해제 여부를 체크해야 한다. 할당된 자원이 해제될 경우 안전하다고 판단하고 자원이 해제되지 않는 분기 가 존재할 경우 취약하다.

1: …
2: try {
3: Class.forName(“com.mysql.jdbc.Driver”);
4: conn = DriverManager.getConnection(url);
5: …
6: } catch (ClassNotFoundException e) {
7: conn.rollback();
8: } finally {
9: if(conn != null) conn.close();
10: }

 

- 정탐코드의 예 -

다음과 같은 예제는 rs.close(), pstmt.close() 등 자원 해제가 try catch 문안에서 함께 이루어지고 있다. 이 경우 rs.close()문에서 예외가 발생하면 pstmt.close() 이하의 자원 해제는 이루어지지 않으므로 자원유출이 일어난다. 

1: try {
2: String sqlSelect = “SELECT USER_ID, PWD FROM USER”
3: String sqlUpdate = “UPDATE USER SET PASSWD = ? WHERE USER_ID = ?”
4: Class.forName(“oracle.jdbc.driver.OracleDriver”);
5: conn = 
DriverManager.getConnection(“jdbc:oracle:thin:@192.168.1.1:1521:db”, “aaa”, “AAA”);
6: pstmt = conn.prepareStatement(sqlSelect);
7: pstmt1 = conn.prepareStatement(sqlUpdate);
8: rs = pstmt.executeQuery();
9: while( rs.next()) {
10: System.out.println(“#################### user_id : “ +
rs.getString(“US- ER_ID”));
11: pstmt1.setString(1, CryptUtils.encrypt(rs.getString(“PWD”)));
12: pstmt1.setString(2, rs.getString(“USER_ID”));
13: pstmt1.executeUpdate();
14: pstmt1.clearParameters();
15: System.out.println(“#################### 01 : “);
16: }
17: conn.commit();
18: } catch(Exception e) {
19: e.printStackTrace();
20: try {
21: conn.rollback();
22: } catch(Exception ex) {}
23: } finally {
24: try {
25: rs.close();
26: pstmt.close();
27: pstmt1.close();
28: conn.close();
29: } catch(Exception e) { }
30: }

 

- 정탐코드의 예 -

다음의 예제와 같이 finally 절에서 connection을 close 해주고 있으므로 자원의 부적절한 반환이 이루어지지 않는다.

1: try {
2: String sqlSelect = “SELECT USER_ID, PWD FROM USER”
3: String sqlUpdate = “UPDATE USER SET PASSWD = ? WHERE USER_ID = ?”
4: Class.forName(“oracle.jdbc.driver.OracleDriver”);
5: conn =
DriverManager.getConnection(“jdbc:oracle:thin:@192.168.1.1:1521:db”, “aaa”, “AAA”);
6: pstmt = conn.prepareStatement(sqlSelect);
7: pstmt1 = conn.prepareStatement(sqlUpdate);
8: rs = pstmt.executeQuery();
9: while( rs.next()) {
10: System.out.println(“#################### user_id : “ + rs.getString(“USER_ID”));
11: pstmt1.setString(1, CryptUtils.encrypt(rs.getString(“PWD”)));
12: pstmt1.setString(2, rs.getString(“USER_ID”));
13: pstmt1.executeUpdate();
14: pstmt1.clearParameters();
15: System.out.println(“#################### 01 : “);
16: }
17: conn.commit();
18: } catch(Exception e) {
19: e.printStackTrace();
20: try {
21: conn.rollback();
22: } catch (Exception ex) { }
23: } finally {
24: try {
25: rs.close();
26: } catch (Exception e) { }
27: try {
28: pstmt.close();
29: } catch(Exception e) { }
30: try {
31: pstmt1.close();
32: } catch (Exception e) { }
33: try {
34: conn.close();
35: } catch (Exception e) { }
36: }

 

728x90
반응형