본문 바로가기
SK Shieldus Rookies 19th/애플리케이션 보안

[SK shieldus Rookies 19기][애플리케이션 보안] - Python 시큐어코딩 가이드 2

by En_Geon 2024. 4. 2.

1. 보안 기능

보안과 관련한 기능을 구현하지 않거나 부적절하게 구현한 경우 발생

 

인증, 인가, 접근통제, 암호화, 권한관리 등을 부적절하게 구현 시 발생하는 보안 약점은 적절한 인증 없는 중요기능 허용, 부적절한 인가 등이 있다.

 

중요한 정보가 있을 때, 이 중요한 정보를 보호하기 위해서는 인가된 사용자만 접근할 수 있도록 접근 통제를 하고, 식별, 인증, 인가를 해야 한다.

 

접근 통제에 문제가 생기는 것은 중요 정보에 권한이 없는 사용자에게 중요 정보가 노출된다고 한다. 권한이 없는 사용자가 중요 정보를 획득했을 때 중요 정보를 알지 못하도록 방어하기 위해서 암호화한다. 

 

 

1) 적절한 인증 없는 중요 기능 허용

인증된 사용자인지 확인하지 않고 기능을 제공할 때 발생 

 

Django 에서 기본적인 인증 로그인, 로그아웃 기능을 제공하고, DRF에서는 토큰 및 세션 인증을 제공하고 있다.

 

(1) 안전한 코딩기법

클라이언트의 보안 검사를 우회하여 서버에 접근하지 못 하도록 설계하고 중요한 정보가 있는 페이지는 재인증을 적용해야 한다. 검증된 라이브러리, 프레임워크를 사용해야 한다.

 

 

2) 부적절한 인가

(1) 접근통제 유형

  • 화면에서의 접근통제
    • 권한 있는 사용자에게만 기능 버튼, 링크, 메뉴를 제공
  • 기능에서의 접근통제
    • 모든 요청을 처리하는 것이 아니고, 권한이 있는 사용자의 요청만 처리
  • 데이터에서의 접근통제
    • 접근할 수 있는 데이터에 대해서 처리를 제공

 

접근통제를 검사하지 않거나 불완전하게 검사하는 경우 공격자는 접근할 수 있는 실행경로를 통해 정보를 유출할 수 있다.

 

(2) 안전한 코딩기법

프로그램이 제공하는 정보와 기능이 가지는 역할에 맞게 분리 개발함으로써 공격자에게 노출되는 공격 정보를 최소화하고 사용자의 권한에 따른 ACL을 관리한다.

 

 

3) 중요한 자원에 대한 잘못된 권한 설정

파일을 생성할 때 과도한 권한을 부여 하면 의도하지 않은 사용자가 해당 자원을 사용하게 된다.

 

(1) 안전한 코딩기법

중요한 파일(설정 파일, 실행 파일, 라이브러리 등)은 관리자만 읽고 쓰기가 가능하도록 설정하고 중요한 파일 같이 중요한 자원을 사용하는 경우 허가 받지 않은 사용자의 접근을 검증, 제한한다.

 

 

4) 취약한 암호화 알고리즘 사용

암호화는 접근통제에 문제가 생겼을 때 그 정보를 보호하기 위한 수단이다. 정보보호 측면에서 취약하거나 위험한 암호화 알고리즘을 사용해서는 안 된다. 오래된 암호화 알고리즘의 경우는 컴퓨터의 성능이 향상됨에 따라 취약해지기도 한다.

 

(1) 안전한 코딩기법

  • 안전한 암호화 알고리즘 사용
    • 보안성이 검증된 알고리즘
    • 보안 강도를 보장하는 알고리즘
    • 인코딩 / 디코딩 방법은 암호화 처리에 사용하면 안 됨
  • 안전한 암호화 알고리즘이 보안 강도를 보장할 수 있는 충분한 키 길이 사용
  • 암호화에 사용되는 키를 안전하게 생성하고 관리
  • 취약한 암호화 알고리즘 사용 금지
    • RC2(ARC2)
    • RC4(ARC4)
    • RC5,
    • RC6
    • MD4
    • MD5
    • SHA1
    • DES

 

암호화 알고리즘은 이미 검증된 알고리즘을 사용해야 하며 자신만의 암호화 알고리즘을 개발하는 것은 위험하다.

 

 

5) 암호화되지 않은 중요정보

중요 정보를 암호화하지 않고 전송하거나 저장할 때 발생

 

중요 정보가 포함된 데이터를 평문으로 전송 또는 저장 시 인가되지 않은 사용자에게 민감한 정보가 노출될 수 있다.

 

(1) 안전한 코딩기법

중요 정보를 전송할 때는 반드시 암호화 처리를 하고, 읽거나 쓸 경우에 권한 인증을 통해 인가된 사용자만 중요 정보에 접근하도록 해야 한다. 데이터를 전송할 때 암호화 해서 전송하거나 HTTPS, SSH, SSL과 보안 통신을 이용해서 전송한다.

 

쿠키에 중요 데이터를 저장하는 경우 쿠키 객체에 보안 속성을 설정해 중요 정보의 노출을 방지할 수 있다.

 

 

6) 하드 코드 된 중요 정보

주요 정책이나 코드를 신규로 적용하는 것과 일관되게 변경하기가 어렵다.

 

코드 내부에 하드 코드 된 패스워드를 포함하고, 이를 이용해 내부 인증에 사용하거나 외부 컴포넌트와 통신을 하는 경우 관리자의 정보가 노출될 수 있다. 하드 코드 된 암호화 키를 사용해 암호화할 때 암호키의 해시를 계산해 저장하더라도 역계산이 가능해 Brute Force 공격에는 취약하다.

 

 (1) 안전한 코딩기법

패스워드는 암호화 후 별도의 파일에 저장해야 한다. 중요 정보 암호화 시 상수가 아닌 암호화 키를 사용하고, 암호화가 잘 되었더라도 소스코드 내부에 상수 형태의 암호화 키를 주석으로 달거나 저장하면 안 된다.

 

 

7) 충분하지 않은 키 길이 사용

 

암호화에 안정성을 보장할 수 있는 길이의 암호화 키를 사용하지 않아서 발생한다.

 

(1) 안전한 코딩기법

RSA 알고리즘은 적어도 2,048비트 이상의 길이를 가진 키와 함께 사용해야 하고, 대칭 암호화 알고리즘의 경우에는 적어도 128비트 이상의 키를 사용해야 한다

 

 

8) 적절하지 않은 난수 값 사용

예측 불가능한 숫자가 필요한 상황에서 예측할 수 있는 난수를 사용한다면 공격자가 생성되는 다음 숫자를 예상해 시스템을 공격할 수 있다.

 

(1) 안전한 코딩기법

난수 함수에서 시드를 사용하는 경우에는 고정된 값을 사용하지 않고 예측하기 어려운 방법으로 생성된 값을 사용한다.

난수 함수를 사용할 때는 시드를 설정할 수 없는 난수 함수를 사용하면 안 된다.

 

9) 취약한 패스워드 허용

패스워드 선택 및 이용 안내서

 

패스워드를 생성할 때 사용자에게 강한 조합 규칙을 요구하지 않으면 계정이 취약해지기 때문에 패스워드 선택 및 이용 안내서에서 제시하는 패스워드 설정 규칙을 사용한다.

 

(1) 안전한 코딩기법

패스워드 선택 및 이용 안내서에도 나오듯이 패스워드는 숫자, 영문자, 특수문자 등을 혼합하여 글자 수를 제한해서 사용해야 하고 주기적으로 변경하도록 해야 한다.

 

 

10) 부적절한 전자서명 확인

프로그램 코드의 전자서명에 대한 유효성 검증이 적절하지 않아 공격자의 악의적인 코드를 실행할 수 있는 보안 약점으로, 클라이언트와 서버 사이의 주요 데이터 전송, 파일 다운로드 시 발생할 수 있다.

 

(1) 안전한 코딩기법

주요 데이터 전송 또는 다운로드 시 데이터에 대한 전자서명을 함께 전송하고 수신 측에서는 전달받은 전자 서명을 검증해 파일의 변조 여부를 확인해야 한다.

 

비대칭 키 알고리즘을 사용한다. 비대칭 키 알고리즘은 암호화에 사용하는 키와 복호화에 사용하는 키가 상이한 알고리즘이다. 개인키로 암호화하면 공개키로 복호화하고, 공개키로 암호화하면 개인키로 복호화할 수 있다.

 

송신자의 개인키로 암호화해서 전달하면 수신자가 송신자의 공개키를 취득해서 복호화할 수 있다. 송신자의 공개키는 누구나가 취득할 수 있으므로 복호화가 가능하다. 송신자의 공개키로 복호화한다는 것은 송신자만 가지고 있는 개인키로 암호화했다는 것을 반증하고 송신자가 만든 것이 맞다는 것을 증명하는데 이를 부인방지, 원본증명, 인증했다고 할 수 있다.

송신자의 개인 키로 암호화하는 것을 전자서명이라고 하고, 송신자의 공개키로 복호화하는 것을 서명 검증한다고 한다.

 

송신자가 수신자의 공개키를 취득해서 암호화해서 전달하면 수신자는 자신의 개인키로 복호화할 수 있다. 이때는 암호화된 데이터는 누구나 받을 수 있지만, 복호화는 할 수 없게 된다. 이를 기밀성이 보장된다고 한다.

 

 

 11) 부적절한 인증서 유효성 검증

인증서가 유효하지 않거나 악성인 경우 공격자가 호스트와 클라이언트 사이의 통신 구간을 가로채 신뢰하는 엔티티인 것처럼 속일 수 있다.

 

신뢰하는 호스트로부터 전달받은 것처럼 보이는 스푸핑 된 데이터 또는 변조된 데이터를 아무런 의심 없이 수신하는 상황이 발생할 수 있다.

 

(1) 유효성 검사

  • 날짜
  • 폐기 여부
  • 신뢰할 수 있는 기간

 

(2) 안전한 코딩기법

인증서를 사용하는 경우 송신 측에서 전달한 인증서가 유효한지 검증한 후 데이터를 송수신해야 한다.

 

 

12) 사용자 하드디스크에 저장되는 쿠키를 통한 정보 노출

쿠키의 유효 기간 또는 지속 시간을 필요 이상으로 길게 잡는 경우

 

쿠키는 메모리에 상주하며, 브라우저가 종료되면 사라진다. 개발자가 원하는 경우, 브라우저 세션과 관계없이 지속해서 쿠키값을 저장하도록 설정할 수 있다. 이렇게 영속적인 쿠키에 저장하면 공격자는 쿠키에 접근할 기회를 많이 가지게 되고 시스템을 취약하게 만든다.

 

(1) 안전한 코딩기법

  • 중요 정보를 쿠키에 저장하지 않음
  • 중요 정보를 포함하는 경우 반드시 암호화해서 저장
  • 유효 기간, 지속 시간을 필요한 만큼만 최소로 설정
  • 보안 속성을 설정
    • HTTPS 통신을 할 때만 쿠키를 서버로 전달하도록 제한
  • HttpOnly 속성 설정
    • JavaScript 등을 이용해서 쿠키에 접근하는 것을 방지

 

13) 주석문 안에 포함된 시스템 주요 정보

개발자가 편의를 위해서 주석문에 패스워드를 적어둔 경우

 

소프트웨어가 완성된 후에는 그것을 제거하는 것이 매우 어렵게 된다. 만약 공격자가 소스코드에 접근할 수 있다면 시스템에 손쉽게 침입할 수 있다.

 

(1) 안전한 코딩기법

주석에는 아이디, 패스워드 등 보안과 관련된 내용을 기입하지 않는다.

 

 

14) 솔트 없이 일방향 해시 함수 사용

 

중요 정보를 솔트 없이 일방향 해시함수를 사용해 저장한다면 공격자는 미리 계산된 레인보우 테이블을 이용해 해시값을 알아낼 수 있다.

 

(1) 안전한 코딩기법

  • 안전한 해시 함수 사용
  • 솔트를 적용
  • 솔트는 안전하게 적용
  • 솔트값은 사용자별로 유일하게 생성
  • 사용자별 솔트 값을 별도로 저장

 

15) 무결성 검사 없는 코드 다운로드

외부에서 가져온 코드를 검증, 제한하지 않고 사용

 

외부에서 가져온 소스코드 또는 실행 파일을 검증, 제한 억이 다운로드 후 실행하는 프로그램이 있다. 이런 프로그램은 호스트 서버의 변조, DNS 스푸핑, 전송 시의 코드 변조 등의 방법을 이용해 악의적인 코드를 실행할 수 있다.

 

패일 무결성을 확인하는 두 가지 주요 방법은 암호화 해시 및 디지털 서명이 있다.

 

(1) 안전한 코딩기법

DNS 스푸핑을 방어할 수 있는 DNS lookup을 수행하고 코드 전송 시 신뢰할 수 있는 암호화 알고리즘으로 암호화한다.

파일의 인증서 또는 해시값을 검사해 변조되지 않은 파일인지 확인한다.

 

 

16) 반복된 인증 시도 제한 기능 부재

일정 시간 내에 여러 번의 인증 시도 시 계정 잠금 또는 추가 인증 방법 등의 조치가 있어야 한다. 그렇지 않으면 공격자는 Brute Force 공격으로 로그인 성공 및 권한 획득을 할 수 있다.

 

(1) 안전한 코딩기법

최대 인증 시도 횟수를 제한하고, 횟수를 초과할 경수 계정을 잠금 하거나 추가적인 인증 과정을 거치도록 한다.

CAPTCHA는 Two Factor 인증 방법도 있다.

 

 

2. 시간 및 상태

동시 또는 거의 동시에 여러 코드 수행을 지원하는 병렬 시스템이나 하나 이상의 프로세스가 동작하는 환경에서 시간 및 상태를 부적절하게 관리하여 발생할 수 있는 보안 약점이다.

 

1) 경쟁 조건(Race condition): 검사 시점과 사용 시점

한정된 자원을 동시에 이용하려는 여러 프로세스가 자원의 이용을 위해 경쟁을 벌이는 현상

 

자원을 사용하기 전에 자원의 상태를 검사하지만, 자원을 사용하는 시점과 검사하는 시점이 다르기 때문에 검사하는 시점에 존재하던 자원이 사용하던 시점에 사라지는 등 자원의 상태가 변하는 경우 발생한다.

하나의 자원에 대해 동시에 검사 시점과 사용 시점이 달라 생기는 보안 약점으로 인해 동기화 오류뿐만 아니라 교착상태 등과 같은 문제점이 발생할 수 있다.

 

(1) 안전한 코딩기법

변수, 파일과 같은 공유자원을 여러 프로세스가 접근하여 사용할 경우 동기화 구문을 사용하여 한 번에 하나의 프로세스만 접근할 수 있게 해야 한다.

 

 

2) 종료되지 않는 반복문 또는 재귀 함수

재귀 함수 구현 시 재귀문을 빠져나가는 조건을 구현하지 않으면 무한 재귀에 빠지게 되어 오류 발생

 

재귀 함수의 순환 횟수를 제어하지 못해 할당된 메모리나 스택 등의 자원이 의도한 범위를 과도하게 초과할 수 있다.

파이썬에서는 재귀 함수의 재귀 반복 제한이 적용되어 있어 무한루프가 발생하지 않는다.

 

(1) 안전한 코딩기법

재귀 함수 호출 시 횟수를 제한하거나 재귀 함수 종료 조건을 명확히 정의해야 한다.

 

 

3. 예외 처리

예외를 처리하지 않거나 불충분하게 처리하여 에러 정보에 중요정보가 포함될 때 발생할 수 있는 보안 약점

 

1) 오류 메시지 정보 노출

오류 메시지를 통한 시스템 정보의 과도한 노출

 

민감한 정보를 포함하는 오류 메시지를 생성해 외부에 제공하는 경우 공격자는 프로그램 내부 구조를 쉽게 파악할 수 있어 악성 행위로 이어질 수 있다.

 

(1) 안전한 코딩기법

오류 메시지는 사용자에게 추상적인 내용 또는 최소한의 유용한 정보만 포함해야 한다. 민감한 정보를 포함하지 않고 미리 정의된 메시지를 제공해야 한다. 

 

 

2) 오류 상황 대응 부재

오류에 대해 예외 처리를 하지 않을 경우 발생

 

오류에 대해 예외 처리를 하지 않을 경우 공격자는 오류 상황을 악용해 개발자가 의도하지 않은 방향으로 동작하도록 할 수 있다.

 

(1) 안전한 코딩기법

예외 처리는 코드를 견고하게 만들고 오류가 발생할 수 있는 부분에 대하여 제어문을 사용해 적절하게 예외 처리한다.

 

 

3) 부적절한 예외 처리

함수의 결괏값에 대한 적절한 처리 또는 예외 상황에 대한 조건을 적절하게 검사하지 않을 경우 발생한다.

 

(1) 안전한 코딩기법

값을 반환하는 모든 함수의 결괏값을 검사해야 한다. 결괏값이 개발자가 의도했던 값인지 검사하고 예외 처리를 사용하는 경우에 광범위한 예외 처리 대신 구체적인 예외 처리를 수행한다.

 

 

4. 코드 오류

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

 

1) Null Pointer 역참조

공격자가 의도적으로 널 포인터 역참조를 발생시키는 경우 공격자는 그 결과로 발생하는 예와 상황을 이용해 추후 공격 계획에 활용할 수 있다.

 

파이썬에서는 Null 객체가 사용되지 않으며 대신 None 키워드를 사용해 null 개체와 변수를 정의한다.

 

(1) 안전한 코딩기법

None을 반환하는 함수를 사용하면 조건문에서 False로 평가될 수 있기 때문에 실수하기 쉽다. None이 될 수 있는 데이터를 참조하기 전에 해당 데이터의 값이 None인지 검사하여 시스템 오류를 줄일 수 있다.

 

 

2) 부적절한 자원 해제

자원을 사용하고 해제하지 않거나 잘못된 방법으로 해제할 때 발생한다. 

 

(1) 안전한 코딩기법

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

 

 

3) 신뢰할 수 없는 데이터의 역직렬화

역직렬화는 반대 연산으로 바이너리 파일이나 바이트 스트림으로부터 객체 구조로 복원하는 과정이다. 바이너리 파일로 사람은 읽을 수가 없는데 역직렬화를 통해 읽을 수 있는 언어로 바꿀 수 있다.

 

파이썬에서는 pickle 모듈을 통해 직렬화, 역직렬화를 수행할 수 있다. pickle 모듈은 데이터 변조에 대한 검증 과정이 없기 때문에 임의 코드를 실행하는 악의적인 pickle 데이터를 구성할 수 있어 pickle을 사용해 역직렬화하는 경우 hmac으로 데이터에 서명하거나 json 모듈을 사용하는 것을 고려해야 한다.

 

(1) 안전한 코딩기법

모든 변수를 사용 전에 반드시 올바른 초깃값을 할당해야 한다. 신뢰할 수 없는 데이터를 역직렬화 하지 않도록 구성해야 한다. 

 

 

5. 캡슐화

중요한 데이터 또는 기능성을 불충분하게 캡슐화하거나 잘못 사용함으로써 발생하는 보안 약점으로 정보 노출, 권한 문제 등이 발생

 

1) 잘못된 세션에 의한 데이터 정보 노출

다중 스레드 환경에서는 싱글톤(Singleton) 객체 필드에 경쟁 조건(Race Condition)이 발생할 수 있다. 

 

(1) 안전한 코딩기법

다중 스레드 환경에서는 정보를 저장하는 전역 변수가 포함되지 않도록 코드를 작성해 서로 다른 세션에서 데이터를 공유하지 않도록 해야 한다.

다중 스레드 환경에서 클래스 변수의 값은 하위 메소드와 공유되므로 필요한 경우 인스턴스 변수로 선언하여 사용한다.

 

 

2) 제거되지 않고 남은 디버그 코드

디버그 코드는 성정 등의 민감한 정보 또는 의도하지 않은 시스템 제어로 이어질 수 있는 정보를 담고 있을 수 있다.

만일 디버그 코드가 남겨진 채로 배포될 경우 공격자가 식별 과정을 우회하거나 의도하지 않은 정보 노출로 이어질 수 있다.

 

(1) 안전한 코딩기법

배포 전 반드시 디버그 코드 확인 및 삭제와 디버그 모드를 비화성화한다.

 

 

3) Public 메소드로부터 반환된 Private 배열

파이썬은 명시적인 private 선언이 없다. 이름 앞에 밑줄로 시작하면 private로 처리된다. public으로 선언된 메소드에서 배열을 반환하면 해당 배열의 참조 객체가 외부에 공개되어 외부에서 배열 수정과 객체 속성 변경이 가능해진다.

 

(1) 안전한 코딩기법

private로 선언된 배열을 public으로 선언된 메소드로 반환하지 않도록 한다. 

 

 

4) Private 배열에 Public 데이터 할당

public으로 선언된 메소드의 인자가 private로 선언된 배열에 저장되면 private 배열을 외부에서 접근하여 
배열 수정과 객체 속성 변경이 가능해진다.

 

(1) 안전한 코딩기법

public으로 선언된 메소드의 인자를 private로 선언된 배열에 저장하지 않도록 한다. 사용자가 전달한 값으로 
클래스 외부에서 private 값을 변경해서는 안 되며, 필요한 경우 별도의 인스턴스 변수로 정의하거나 의도한 
기능이라면 전달된 값의 정상여부를 검증한 후 적용해야 한다.

 

 

6. API 오용

의도된 사용에 반하는 방법으로 API를 사용하거나 보안에 취약한 API를 사용하여 발생할 수 있는 보안 약점

 

1) DNS lookup에 의존한 보안 결정

로컬 DNS 서버의 캐시가 공격자에 의해 오염된 상황이라면 사용자와 특정 서버 간의 네트워크 트래픽이 공격자를 경유하도록 할 수도 있다. 또한 공격자가 마치 동일 도메인에 속한 서버인 것처럼 위장할 수도 있다.

 

(1) 안전한 코딩기법

도메인명을 이용한 DNS lookup을 하지 않도록 한다. 도메인명에 의존에서 보안 결정(인증 및 접근 통제 등)을 하지 않아야 한다. 

 

 

2) 취약한 API 사용

취약한 API는 보안상 금지된 함수이거나 부주의하게 사용될 가능성이 많은 API를 의미한다.

 

외부 패키지 사용 시 보안 문제가 발생하게 되는 원인을 크게 두 가지로 분류할 수 있다.

  • 사용자 배포 패키지 내의 결함으로 인한 취약점
  • 언어 엔진 자체의 결함으로 인한 취약점 

 

(1) 안전한 API 선택

취약한 API를 코드에 사용하지 않는 것이 제일 좋다. 하지만 이는 파이썬 생태계에서는 적용이 어려운 방법이다. 안전하다고 알려진 API라고 하더라도 취약점이 발견되지 않을 것이라는 보장이 없다.

 

최초 패키지 사용 시 가장 현실적인 방법

 

  • 사용 통계
    • 얼마나 많은 사람들이 해당 패키지를 다운로드 샜고, 선호하고 있는지
  • 이슈 관리
    • 지속해서 발견되는 버그 또는 이슈를 어떻게 처리하고 있는지
  • 마지막 버전
    • 코드 유지관리가 잘 되고 있는지
  • 발견된 취약점
    • 특정 버전에서 취약점이 발견되었는지
    • 결함이 제거된 버전이 공개되어 있는지

댓글