Experience/SK Shieldus Rookies

[secolab] SW 구현단계에서의 49개 보안약점 (1)

얀 짱 2026. 8. 12. 00:15


1절 - 입력데이터 검증 및 표현

  • SQL 삽입
  • 코드 삽입
  • 경로 조작 및 자원 삽입
  • 크로스사이트 스크립트
  • 운영체제 명령어 삽입
  • 위험한 형식 파일 업로드
  • 신뢰되지 않는 URL 주소로 자동 접속 연결
  • 부적절한 XML 외부 개체 참조
  • XML 삽입
  • LDAP 삽입
  • 크로스사이트 요청 위조
  • 서버사이드 요청 위조
  • HTTP 응답 분할
  • 정수형 오버플로우
  • 보안기능 결정에 사용되는 부적절한 입력값
  • 메모리 버퍼 오버플로우
  • 포맷 스트링 삽입

 

2절 - 보안기능

  • 적절한 인증 없는 중요기능 허용
  • 부적절한 인가
  • 중요한 자원에 대한 잘못된 권한 설정
  • 취약한 암호화 알고리즘 사용
  • 암호화되지 않은 중요정보
  • 하드코드된 중요 정보
  • 충분하지 않은 키 길이 사용
  • 적절하지 않은 난수값 사용
  • 취약한 비밀번호 허용
  • 부적절한 전자서명 확인
  • 부적절한 인증서 유효성 검증
  • 사용자 하드디스크에 저장되는 쿠키를 통한 정보노출
  • 주석문 안에 포함된 시스템 주요정보
  • 솔트 없이 일방향 해쉬함수 사용
  • 무결성 검사 없는 코드 다운로드
  • 반복된 인증시도 제한 기능 부재

 

3절 - 시간 및 상태

  • 경쟁조건: 검사시점과 사용시점 (TOCTOU)
  • 종료되지 않는 반복문 또는 재귀함수

 

4절 - 에러처리

  • 오류 메시지 정보노출
  • 오류 상황 대응 부재
  • 부적절한 예외처리

 

5절 - 코드오류

  • Null Pointer 역참조
  • 부적절한 자원 해제
  • 해제된 자원 사용
  • 초기화되지 않은 변수 사용
  • 신뢰할 수 없는 데이터의 역직렬화

 

6절 - 캡슐화

  • 잘못된 세션에 의한 데이터 정보노출
  • 제거되지 않고 남은 디버그 코드
  • Public 메서드부터 반환된 Private 배열
  • Private 배열에 Public 데이터 할당

SQL 삽입

데이터베이스와 연동된 웹 응용프로그램에서 입력된 데이터에 대한 유효성 검증을 하지 않을 경우,
공격자가 입력 폼 및 URL 입력란에 SQL 문을 삽입하여 DB로부터 정보를 열람하거나 조작할 수 있는 보안약

 

-> 취약한 웹 응용프로그램에서는 사용자로부터 입력된 값을 필터링 과정 없이 넘겨받아 동적 쿼리를 생성하기 때문에 개발자가 의도하지 않은 쿼리가 생성되어 정보유출에 악용될 수 있다.

💡 보안 대책
---
PreparedStatement 객체 등을 이용하여 DB에 컴파일 된 쿼리문을 전달하는 방법을 사용한다.

PreparedStatement를 사용하는 경우에는 DB 쿼리에 사용되는 외부 입력값에 대하여 특수문자 및 쿼리 예약어를 필터링하고, 스트러츠 (Struts), 스프링 (Spring) 등과 같은 프레임워크를 사용하는 경우에는 외부 입력값 검증모듈 및 보안모듈을 상황에 맞추어 적절하게 사용한다. 

 

코드 삽입

공격자가 소프트웨어의 의도된 동작을 변경하도록 임의 코드를 삽입하여 소프트웨어가 비정상적으로 동작하도록 하는 보안약점

 

-> 프로그래밍 언어 자체의 기능에 의해서만 제한된다는 점에서 운영체제 명령어 삽입과는 차이가 있다.

-> 취약한 프로그램에서 사용자의 입력 값에 코드가 포함되는 것을 허용할 경우, 공격자는 개발자가 의도하지 않은 코드를 실행하여 권한을 탈취하거나 인증 우회, 시스템 명령어 실행 등을 할 수 있다.

💡 보안 대책
---
동적코드를 실행할 수 있는 함수를 사용하지 않는다.

필요 시에는 실행 가능한 동적 코드를 입력값으로 받지 않도록, 외부 입력값에 대하여 화이트리스트 방식으로 구현한다.
또한 유효한 문자만 포함하도록 동적 코드에 사용되는 사용자 입력값을 필터링한다.

 

경로 조작 및 자원 삽입

검증되지 않은 외부 입력값으로 파일 및 서버 등 시스템 자원에 대한 접근 혹은 식별을 허용할 경우, 입력값 조작으로 시스템이 보호하는 자원에 임의로 접근할 수 있는 보안 약점

 

-> 경로조작 및 자원삽입 약점을 이용하여 공격자는 자원의 수정, 삭제, 시스템 정보누출, 시스템 자원 간 충돌로 인한 서비스 장애 등을 유발시킬 수 있다.

-> 즉, 경로 조작 및 자원 삽입으로 공격자가 허용되지 않은 권한을 획득하여, 설정에 관계된 파일을 변경하거나 실행시킬 수 있다.

💡 보안 대책
---
외부의 입력을 자원 (파일, 소켓의 포트 등)의 식별자로 사용하는 경우, 
적절한 검증을 거치도록 하거나, 사전에 정의된 적합한 리스트에서 선택되도록 한다.
특히, 외부의 입력이 파일명인 경우에는 경로순회 (directory traversal) 공격의 위험이 있는 문자 ("/\.. 등)를 제거할 수 있는 필터를 이용한다.

 

크로스사이트 스크립트 (XSS)

웹 페이지에 악의적인 스크립트를 포함시켜 사용자 측에서 실행되게 유도하는 보안약점

 

-> 검증되지 않은 외부 입력이 동적 웹페이지 생성에 사용될 경우, 전송된 동적 웹 페이지를 열람하는 접속자의 권한으로 부적절한 스크립트가 수행되어 정보유출 등의 공격을 유발할 수 있다. 

💡 보안 대책
---
외부 입력값 또는 출력값에 스크립트가 삽입되지 못하도록 문자열 치환 함수를 사용하여 &, <, >, ", ', /, (, ) 등을 &amp; &lt; &gt; &quot; &#27; &#x2F; &#x28; &#x29; 로 치환하거나, JSTL 또는 잘 알려진 크로스 사이트 스크립트 방지 라이브러리를 활용한다.

HTML 태그를 허용하는 게시판에서는 허용되는 HTML 태그들을 화이트리스트로 만들어 해당 태그만 지원하도록 한다.

 

Reflected XSS 공격

검색 결과, 에러 메시지 등으로 서버가 외부에서 입력받은 악성 스크립트가 포함된 URL 파라미터 값을 사용자 브라우저에서 응답할 때 발생!

공격 스크립트가 삽입된 URL을 사용자가 쉽게 확인할 수 없도록 변형하여, 이메일, 메신저, 파일 등으로 실행을 유도하는 공격

 

Stored XSS 공격

웹 사이트의 게시판, 코멘트 필드, 사용자 프로필 등과 같은 입력 form으로 악성 스크립트를 삽입하여 DB에 저장되면, 사용자가 사이트를 방문하여 저장되어 있는 페이지에 정보를 요청할 때,

서버는 악성 스크립트를 사용자에게 전달하여 사용자 브라우저에서 스크립트가 실행되어 발생!

 

DOM 기반 XSS 공격

외부에서 입력받은 악성 스크립트가 포함된 URL 파라미터 값이 서버를 거치지 않고, DOM 생성의 일부로 실행되면서 발생!
Reflected XSS 및 Stored XSS 공격은 서버 애플리케이션 취약점으로 인해, 응답 페이지에 악성 스크립트가 포함되어 브라우저로 전달되면서 공격하는 것이지만,

반면에 DOM 기반 XSS 공격은 서버와 관계없이 발생!

 

운영체제 명령어 삽입

적절한 검증절차를 거치지 않은 사용자 입력값이 운영체제 명령어의 일부 또는 전부로 구성되어 실행되는 경우에 발생하는 보안약점

 

-> 의도하지 않은 시스템 명령어가 실행되어 부적절하게 권한이 변경되거나 시스템 동작 및 운영에 악영향을 미칠 수 있다.

-> 명령어 라인의 파라미터나 스트림 입력 등 외부 입력을 사용하여 시스템 명령어를 생성하는 프로그램들의 경우, 신뢰할 수 없는 외부 입력 문자열에 대한 적절한 처리를 해주지 않으면, 공격자가 원하는 명령어 실행이 가능하게 된다.

💡 보안 대책
---
웹 인터페이스를 통해 서버 내부로 시스템 명령어를 전달시키지 않도록 응용프로그램을 구성하고, 외부에서 전달되는 값을 검증 없이 시스템 내부 명령어로 사용하지 않는다.

외부 입력에 따라 명령어를 생성하거나 선택이 필요한 경우에는 명령어 생성에 필요한 값들을 미리 지정해 놓고 외부 입력에 따라 선택하여 사용한다.

 

위험한 형식 파일 업로드

서버 측에서 실행될 수 있는 스크립트 파일이 업로드 가능하고, 이 파일을 공격자가 웹으로 직접 실행시킬 수 있는 경우에 발생 가능한 보안약점

 

-> 시스템 내부 명령어를 실행하거나 외부와 연결하여 시스템을 제어할 수 있다. 

💡 보안 대책
---
화이트 리스트 방식으로 허용된 확장자만 업로드를 허용한다.

업로드 되는 파일을 저장할 때에는 파일명과 확장자를 외부 사용자가 추측할 수 없는 문자열로 변경하여 저장하며,
저장 경로는 'web document root' 밖에 위치시켜서 공격자의 웹으로 직접 접근을 차단한다.
또한 파일 실행 여부를 설정할 수 있는 경우, 실행 속성을 제거한다.

 

신뢰되지 않는 URL 주소로 자동접속 연결

사용자로부터 입력되는 값을 외부 사이트의 주소로 사용하여
피싱 공격에 노출되는 보안약점

 

-> 일반적으로 클라이언트에서 전송된 URL 주소로 연결하기 때문에 안전하다고 생각할 수 있으나, 공격자는 해당 폼의 요청을 변조함으로써 사용자가 위험한 URL로 접속할 수 있도록 공격할 수 있다.

💡 보안 대책
---
자동 연결할 외부 사이트의 URL과 도메인은 화이트 리스트로 관리하고,

사용자 입력값을 자동 연결할 사이트 주소로 사용하는 경우에는 입력된 값이 화이트 리스트에 존재하는지 확인해야 한다.

 

부적절한 XML 외부개체 참조

서버에서 XML 외부 개체를 처리할 수 있도록 설정된 경우에 발생 가능한 보안약점

 

-> XML 문서에는 DTD (Documnet Type Definition)를 포함할 수 있으며, DTD는 XML 엔티티를 정의한다.

-> 취약한 XML Parser가 외부 값을 참조하는 XML 값을 처리할 때, 공격자가 삽입한 공격 구문이 동작되어 서버 파일 접근, 불필요한 자원 사용, 인증 우회, 정보 노출 등이 발생할 수 있다.

💡 보안 대책
---
로컬 정적 DTD를 사용하도록 설정하고, 외부에서 전송된 XML 문서에 포함된 DTD를 완전하게 비활성화해야 한다.

비활성화를 할 수 없는 경우에는 외부 엔티티 및 외부 문서 유형 선언을 각 파서에 맞는 고유한 방식으로 비활성화한다.

 

XML 삽입

검증되지 않은 외부 입력값이 XQuery, XPath 쿼리문을 생성하는 문자열로 사용되어 공격자가 쿼리문의 구조를 임의로 변경하고, 임의의 쿼리를 실행하여 허가되지 않은 데이터를 열람하거나 인증절차를 우회할 수 있는 보안약점

 

-> XPath 삽입 보안약점 + XQuery 삽입 보안약점 => XML 삽입 보안약점

💡 보안 대책
---
XQuery 또는 XPath 쿼리에 사용되는 외부 입력데이터에 대하여
특수문자 및 쿼리 예약어를 필터링하고
파라미터화된 쿼리문을 지원하는 XQuery를 사용한다. 

 

LDAP 삽입

공격자가 외부 입력으로 의도하지 않은 LDAP 명령어를 수행할 수 있게 되는 보안약점

 

-> 이로 인해 프로세스가 명령을 실행한 컴포넌트와 동일한 권한을 가지고 동작하게 된다.

-> 외부 입력값을 적절한 처리 없이 LDAP 쿼리문이나 결과의 일부로 사용하는 경우에는 LDAP 쿼리문이 실행될 때, 공격자는 LDAP 쿼리문의 내용을 마음대로 변경할 수 있다.

💡 보안 대책
---
DN (Distinguished Name)과 필터에 사용되는 사용자 입력값에는 특수문자가 포함되지 않도록 특수문자를 제거한다.
만약 특수문자를 사용해야 하는 경우에는 특수문자 (= + < > # ; \ 등) 가 실행명령이 아닌 일반문자로 인식되도록 처리한다.

 

크로스사이트 요청 위조

특정 웹사이트에 대해서 사용자가 인지하지 못한 상황에서 사용자의 의도와는 무관하게 공격자가 의도한 행위 (수정, 삭제, 등록 등)을 요청하게 하는 보안약점

 

-> 사용자로부터 받은 요청에 대해서 사용자가 의도한 대로 작성되고 전송된 것인지 확인하지 않는 경우에 발생 가능하다.

-> 공격자는 사용자가 인증한 세션이 특정 동작을 수행하여도 계속 유지되어, 정상적인 요청과 비정상적인 요청을 구분하지 못하는 점을 악용한다.

-> 웹 응용프로그램에 요청을 전달할 경우, 해당 요청의 적법성을 입증하기 위하여 전달되는 값이 고정되어 있고 GET 방식으로 전달된다면, 공격자가 이를 쉽게 알아내어 원하는 요청을 보냄으로써 위험한 작업을 요청할 수 있게 된다.

💡 보안 대책
---
입력화면 폼 작성 시 GET 방식보다는 POST 방식을 사용하고
입력화면 폼과 해당 입력을 처리하는 프로그램 사이에 토큰을 사용하여, 공격자의 직접적인 URL 사용이 동작하지 않도록 처리한다.
특히 중요한 기능에 대해서는 사용자 세션검증과 더불어 재인증을 유도한다.

 

서버사이드 요청 위조

적절한 검증절차를 거치지 않은 사용자 입력 값을 서버 간 요청에 사용하여 악의적인 행위가 발생할 수 있는 보안약점

 

-> 외부에 노출된 웹 서버에 취약한 애플리케이션이 존재하는 경우, 공격자는 URL 또는 요청문을 위조하여 접근통제를 우회하는 방식을 통해 비정상적인 동작을 유도하거나 신뢰할 수 있는 네트워크에 있는 데이터를 획득할 수 있다.

💡 보안 대책
---
식별할 수 있는 범위 내에서 사용자의 입력값을 다른 시스템의 서비스 호출에 사용하는 경우, 사용자의 입력값을 화이트리스트 방식으로 필터링한다.
사용자가 지정하는 무작위의 URL을 받아들여야 한다면 내부의 URL을 블랙리스트로 지정하여 필터링한다.
또한 동일한 내부 네트워크에 있더라도 기기 인증, 접근권한을 확인하여 요청이 이루어질 수 있도록 한다.

 

HTTP 응답 분할

HTTP 요청에 들어 있는 파라미터가 HTTP 응답 헤더에 포함되어 사용자에게 다시 전달될 때,
입력값에 CR (Carriage Return)이나 LF (Line Feed)와 같은 개행문자에 의해 HTTP 응답이 2개 이상으로 분리되어 발생하는 보안약점

 

-> 공격자는 개행문자를 이용하여 첫 번째 응답을 종료시키고, 두 번째 응답에 악의적인 코드를 주입하여 XSS 및 캐시 훼손 공격 등을 수행할 수 있다.

💡 보안 대책
---
요청 파라미터의 값을 HTTP 응답헤더 (예를 들어, Set-Cookie 등)에 포함시킬 경우 CR, LF와 같은 개행문자를 제거한다.

 

정수형 오버플로우

정수형 크기는 고정되어 있는데 저장할 수 있는 범위를 넘어서, 크기보다 큰 값을 저장하려 할 때 실제 저장되는 값이 의도치 않게 아주 작은 수이거나 음수가 되어 프로그램이 예기치 않게 동작되는 보안약점

 

-> 특히 반복문 제어, 메모리 할당, 메모리 복사 등을 위한 조건으로 사용자가 제공하는 입력값을 사용하는 과정에서 정수형 오버플로우가 발생하는 경우에는 보안상 문제를 유발할 수 있다.

💡 보안 대책
---
언어/플랫폼별 정수타입의 범위를 확인하여 사용한다.
정수형 변수를 연산에 사용하는 경우, 결과 값의 범위를 체크하는 모듈을 사용한다.
특히 외부입력값을 동적 메모리 할당에 사용하는 경우, 변수 값이 적절한 범위 내에 존재하는 값인지 확인한다.

 

보안기능 결정에 사용되는 부적절한 입력값

응용프로그램이 외부 입력값에 대한 신뢰를 전제로 보호 메커니즘을 사용하는 경우,
공격자가 입력값을 조작할 수 있다면 보호 메커니즘을 우회할 수 있게 되어 발생하는 보안약점

 

-> 흔히 쿠키, 환경변수 또는 히든 필드와 같은 입력값이 조작될 수 없다고 가정하지만, 공격자는 다양한 방법으로 이러한 입력값들을 변경할 수 있으며, 조작된 내용은 탐지되지 않을 수 있다.

-> 따라서 인증이나 인가와 같은 보안결정이 이런 입력값 (쿠키, 환경변수, 히든필드 등)에 기반해 수행되는 경우, 공격자는 이런 입력값을 조작하여 응용프로그램의 보안을 우회할 수 있으므로 충분한 암호화, 무결성 체크를 수행하고 이와 같은 메커니즘이 없는 경우엔 외부사용자에 의한 입력값을 신뢰해서는 안 된다.

💡 보안 대책
---
중요한 정보는 서버에 저장하고 보안확인 절차도 서버에서 실행한다.
보안설계관점에서 신뢰할 수 없는 입력값이 응용프로그램 내부로 들어올 수 있는 지점과 보안결정에 사용되는 입력값을 식별하고
제공되는 입력값에 의존할 필요가 없는 구조로 변경할 수 있는지 검토한다.

 

메모리 버퍼 오버플로우

연속된 메모리 공간을 사용하는 프로그램에서
할당된 메모리의 범위를 넘어선 위치에 자료를 읽거나 쓰려고 할 때 발생하는 보안약점

 

-> 메모리 버퍼 오버플로우는 프로그램의 오동작을 유발시키거나, 악의적인 코드를 실행시킴으로써 공격자 프로그램을 통제할 수 있는 권한을 획득하게 한다.

-> 메모리 버퍼 오버플로우에는 스택 메모리 버퍼 오버플로우와 힙 메모리 버퍼 오버플로우가 있다.

💡 보안 대책
---
프로그램 상에서 메모리 버퍼를 사용할 경우 적절한 버퍼의 크기를 설정하고, 설정된 범위의 메모리 내에서 올바르게 읽거나 쓸 수 있게 통제하여야 한다.

특히, 문자열 저장 시 널 (Null) 문자로 종료하지 않으면 의도하지 않은 결과를 가져오게 되므로
널 (Null) 문자를 버퍼 범위 내에 삽입하여 널 (Null) 문자로 종료되도록 해야 한다.

 

포맷 스트링 삽입

외부로부터 입력된 값을 검증하지 않고
입출력 함수의 포맷 문자열로 그대로 사용하는 경우 발생할 수 있는 보안약점

 

-> 공격자는 포맷 문자열을 이용하여 취약한 프로세스를 공격하거나 메모리 내용을 읽거나 쓸 수 있고 그 결과, 공격자는 취약한 프로세스의 권한을 취득하여 임의의 코드를 실행할 수 있다.

💡 보안 대책
---
printf(), snprintf() 등 포맷 문자열을 사용하는 함수를 사용할 때는
사용자 입력값을 직접적으로 포맷 문자열로 사용하거나 포맷 문자열 생성에 포함시키지 않는다.

포맷문자열을 사용하는 함수에 사용자 입력값을 사용할 때는 사용자가 포맷 스트링을 변경할 수 있는 구조로 쓰지 않아야 하고, 가능하면 %s 포맷 문자열을 지정하고, 사용자 입력값은 2번째 이후의 파라미터로 사용한다.

특히, %n, %hn은 공격자가 이를 이용해 특정 메모리 위치에 특정값을 변경할 수 있으므로 포맷 스트링 매개변수로 사용하지 않는다.