IgnatiusHeo

구현단계 보안약점 제거 기준-취약한 API 사용 본문

자격/SW보안약점진단원

구현단계 보안약점 제거 기준-취약한 API 사용

Ignatius Heo 2023. 7. 6. 16:09

작성일: 230706

 

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

 

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

구분 - API 오용
설계단계  
개요 취약한 API는 보안상 금지된(banned) 함수이거나, 부주의하게 사용될 가능성이 많은 API를 의미한다.

이들 범주의 API에 대해 확인하지 않고 사용할 때 보안 문제를 발생시킬 수 있다.

금지된 API의 대표적인 예로는 스트링 자료와 관련된 strcat(), strcpy(), strncat(), strncpy(), sprintf() 등이 있다.
또한 보안상 문제가 없다 하더라도 잘못된 방식으로 함수를 사용할 때도 역시 보안 문제를 발생 시킬 수 있다.
진단 세부사항
(설계단계)
 
보안대책
(구현단계)
보안 문제로 인해 금지된 함수는 이를 대체할 수 있는 안전한 함수를 사용한다.

그 예로, 위에 언급된 API 대신에 strcat_s(), strcpy_s(), strncat_s(), strncpy_s(), sprintf_s()과 같은 안전한 함수를 사용하는 것이 권장된다.

또한 금지된 API는 아니지만 취약한 API의 예시로, 문자열을 정수로 변환할 때 사용하는 strtol()과 같은 함수는 작은 크기의 부호 있는 정수인 int, short, char와 같은 자료형 변환에 사용하면 범위 제한 없이 값을 평가할 수 있다.

취약한 API의 분류는 일반적인 것은 아니지만 개발 조직에 따라 이를 명시한 경우가 있다면 반드시
준수한다.
진단방법
(구현단계)
취약한 API의 리스트를 작성하고 검사하고자 하는 프로그램에서 해당 API를 사용하는지 확인한다.

해당 API를 사용하는 경우 프로그램에 예기치 않은 문제가 발생할 수 있으므로 취약한 것으로 판단한다.

만약 취약한 API를 대체할 수 있는 API가 없을 경우, 해당 API의 인자와 반환 값에 대한 검사가 이루어지는지 확인한다.

 

다. 코드예제

 

ㅇ 분석

1:#include <stdio.h>
2:void requestString()
3:{
4: char str[100];
5://gets() 함수는 문자열 길이를 제한 할 수 없어 안전하지 않다.
6: gets(str);
7:}

ㅇ 수정

1: #include <stdio.h>
2: void requestString()
3: {
4: char str[100];
5: //gets_s() 함수는 문자열 길이 제한이 가능하다.
6: gets_s(str, sizeof(str));
7: }

ㅇ 내용

1. gets를 gets_s ?


ㅇ 분석

1: public class S246 extends javax.servlet.http.HttpServlet {
2: private Socket socket
3: protected void doGet(HttpServletRequest request,
4: HttpServletResponse response) throws ServletException {
5: try {
6: //프레임워크의 메소드 호출 대신 소켓을 직접 사용하고 있어 프레임워크에서 제공하는 보안기능을
제공받지 못해 안전하지 않다.
7: socket = new Socket("kisa.or.kr", 8080);
8: } catch (UnknownHostException e) {
9: .......

ㅇ 수정

1: public class S246 extends javax.servlet.http.HttpServlet {
2: protected void doGet(HttpServletRequest request,
3: HttpServletResponse response) throws ServletException {
4: ObjectOutputStream oos = null;
5: ObjectInputStream ois = null;
6: try {
7: URL url = new URL("http://127.0.0.1:8080/DataServlet");
8: //보안기능을 제공하는 프레임워크의 메소드를 사용하여야한다.
9: URLConnection urlConn = url.openConnection();
10: urlConn.setDoOutput(true);
11: .......

ㅇ 내용

1. 타겟이 WAS면 URL connection을 사용해야함.


ㅇ 분석

1: public class U382 extends HttpServlet {
2: public void doPost(HttpServletRequest request, HttpServletResponse response)
3: throws ServletException, IOException {
4: try {
5: do_something(logger);
6: } catch (IOException ase) {
7: logger.info("ERROR");
8: // J2EE 프로그램에서 System.exit()을 사용하여 서비스가 종료 될 수 있다.
9: System.exit(1);
10: }

ㅇ 수정

1: public class U382 extends HttpServlet {
2: public void doPost(HttpServletRequest request, HttpServletResponse response)
3: throws ServletException, IOException {
4: try {
5: do_something(logger);
6: } catch (IOException ase) {
7: logger.info("ERROR");
8: //서비스 종료를 막기 위해 J2EE에서는 System.exit()를 사용하지 않는다.
9: }

ㅇ 내용


ㅇ 분석

1: try{
2: ...
3: } catch (Exception e){
4: ...
5: //Application.Exit() 은 즉시 프로그램을 종료하기 때문에, Form.Closed 혹은 Form.Closing
이벤트가 처리되지 않습니다.
6: Application.Exit();
7: }

ㅇ 수정

1: try{
2: ...
3: } catch (Exception e){
4: ...
5: // Application.Exit() 을 사용하지 않으면, 이벤트를 처리하지 못하고 프로그램이 종료되는 것을
방지할 수 있습니다.
6: this.Close();
7: }

ㅇ 내용

 

 

 

 

 

 

 

끝.