[시큐어코딩 가이드] 적절하지 않은 난수 값 사용
- 정보보안/시큐어코딩 가이드
- 2022. 8. 12.
■ 보안기능
보안기능(인증, 접근제어, 기밀성, 암호화, 권한관리 등)을 부적절하게 구현 시 발생할 수 있는 보안약점으로 적절한 인증 없는 중요기능 허용, 부적절한 인가 등이 포함된다.
적절하지 않은 난수 값 사용
■ 개요
예측 가능한 난수를 사용하는 것은 시스템에 보안약점을 유발한다. 예측 불가능한 숫자가 필요한 상황에서 예측 가능한 난수를 사용한다면, 공격자는 SW에서 생성되는 다음 숫자를 예상하여 시스템을 공격하는 것이 가능하다.
■ 안전한 코딩 기법
난수 발생기에서 시드(Seed)를 사용하는 경우에는 고정된 값을 사용하지 않고 예측하기 어려운 방법으로 생성된 값을 사용한다. python에서 random 모듈은 주로 보안목적이 아닌 게임, 퀴즈 및 시뮬레이션을 위해 설계되었다. 세션 ID, 암호화키 등 보안결정을 위한 값을 생성하고 보안결정을 수행하는 경우에는 암호화 목적으로 설계된 secrets 모듈을 사용한다.
secrets 모듈은 python 3.6 이상에서만 사용할 수 있으며 암호, 계정 인증, 보안 토큰과 같은 데이터를 관리하는데 적합한 강력한 난수를 생성하는 데 사용된다.
python 3.6 이하에서는 os.urandom(), random.SystemRandom 클래스를 사용하는 것이 안전하다.
코드예제
random 라이브러리 사용시에는 반드시 유추하기 어려운 seed 값을 이용하여 난수를 생성하여야 하며 이렇게 생성된 난수라 하더라도 강도가 낮기 때문에 보안결정을 위한 난수 이용시에는 안전하지 않다. 아래는 안전하지 않은 코드 예제로 고정된 seed 값을 사용하였고 보안이나 암호를 목적으로 사용하기에 random 모듈은 안전하지 않다.
안전하지 않은 코드의 예 |
import random def get_otp_number(): random_str = '' # 시스템 현재 시간 값을 시드로 사용, 보안결정을 위한 # 난수로는 안전하지 않다. for i in range(6): random_str += str(random.randrange(10)) return random_str |
다음 예제 코드는 secrets 라이브러리를 사용하여 6자리의 난수값을 생성하는 안전한 예제이다.
안전한 코드의 예 |
import secrets def get_otp_number(): random_str = '' # 보안기능에 적합한 난수 생성용 secrets 라이브러리 사용 for i in range(6): random_str += str(secrets.randbelow(10)) return random_str |
다음은 세션 토큰값을 생성하는 예제로 random 라이브러리를 사용하여 안전하지 않은 예제이다.
안전하지 않은 코드의 예 |
import random import string def generate_session_key(): RANDOM_STRING_CHARS = string.ascii_letters+string.digits # random 라이브러리는 보안기능에 사용하면 위험하다 return “”.join(random.choice(RANDOM_STRING_CHARS) for i in range(32)) |
비밀번호나 인증정보 및 보안토큰 생성에 사용하는 경우 좀더 안전한 secrets 라이브러리를 사용하여 생성된 난수를 이용하여야 한다.
안전한 코드의 예 |
import secrets import string def generate_session_key(): RANDOM_STRING_CHARS = string.ascii_letters+string.digits # 보안기능과 관련된 난수는 secrets 라이브러리를 사용해야 안전하다. return “”.join(secrets.choice(RANDOM_STRING_CHARS) for i in range(32)) |