[시큐어코딩 가이드] 2-2-10. 부적절한 전자서명 확인

부적절한 전자서명 확인

정의

  • 프로그램, 라이브러리, 코드의 전자서명에 대한 유효성 검증이 적절하지 않아 공격자의 악의적인 코드가 실행 가능한 보안약점
  • 데이터 전송 또는 다운로드 시 함께 전달되는 전자서명은 원문 데이터의 암호화된 해시 값으로, 수신 측에서 이 서명을 검증해 데이터 변조 여부를 확인할 수 있다.

 

안전한 코딩기법

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

 

 

코드예제

다음은 안전하지 않은 코드예제입니다. 송신측이 데이터와 함께 전달한 전자서명을 수신 측에서 별도로 처리하지 않고 그대로 신뢰해 데이터 내부에 포함된 파이썬 코드가 실행되는 취약한 코드입니다.

#부적절한 전자서명 확인(안전X)
def decrypt_with_symmetric_key(key, code):
    pass
def verify_data_bad(request):
    #클라이언트로부터 전달받은 데이터
    encrypted_code = request.POST.get('encrypted_msg',) #암호화된 파이썬코드
    #서버의 대칭키 로드(송수신측이 대칭키를 이미 공유했다고 가정)
    with open(f'{PATH}/keys/secret_key.out', 'rb') as f:
        secret_key = f.read()
    
    #대칭키로 클라이언트가 전달한 파이썬 코드 복호화
    origin_python_code = decrypt_with_symmetric_key(secret_key, encrypted_code)
    #클라이언트로부터 전달받은 파이썬코드 실행
    eval(origin_python_code)
    return render(request, 'success.html', {'msg': '파이썬코드실행'})

 

다음은 안전한 코드예제입니다. 중요한 정보 또는 기능실행으로 연결되는 데이터를 전달할 때, 반드시 전자서명을 함께 전송해야 하며 수신 측에서는 전자서명을 확인해 송신 측에서 보낸 데이터의 무결성을 검증해야 합니다.

#부적절한 전자서명 확인(안전O)
def verify_digit_signature(origin_data: bytes, origin_signature: bytes, client_pub_key: str) -> bool:
    hashed_data = SHA256.new(origin_data)
    signer = SIGNATURE_PKCS1_v1_5.new(RSA.importKey(client_pub_key))
    return signer.verify(hashed_data, base64.b64decode(origin_signature))

def verify_data_good(request):
    encrypted_code = request.POST.get('encrypted_msg',) #암호화된 파이썬코드
    encrypted_sign = request.POST.get('encrypted_sign', ) #암호화된 전자서명

    #서버의 대칭(비밀)키 및 공개키 로드
    with open(f'{PATH}/keys/secret_key.out', 'rb') as f:
        secret_key = f.read()
    with open(f'{PATH}/keys/secret_key.out', 'rb') as f:
        public_key = f.read()

    #대칭키로 파이썬 코드 및 전자서명 복호화
    origin_python_code = decrypt_with_symmetric_key(symmetric_key, encrypted_code)
    origin_signature = decrypt_with_symmetric_key(symmetric_key, encrypted_sign)

    #클라이언트의 공개키를 통해 파이썬코드와 전자서명을 검증
    verify_result = verify_digit_signature(origin_python_code, origin_signature, client_pub_key)

    #전자서명 검증을 통과했으면 파이썬 코드 실행
    if verify_result:
        eval(origin_python_code)
        return render(request, 'success.html', {'msg': '전자서명 검증 통과 및 파이썬 코드를 실행했습니다'})
    else:
        return render(request, 'error.html', {'msg': '전자서명 또는 파이썬 코드가 위/변조 되었습니다'})

 

 

 

보안기능/부적절한 전자서명 확인

[참고문헌] Python 시큐어코딩 가이드(2022) / KISA(한국인터넷진흥원)