IgnatiusHeo

구현단계 보안약점 제거 기준-취약한 암호화 알고리즘 사용 본문

자격/SW보안약점진단원

구현단계 보안약점 제거 기준-취약한 암호화 알고리즘 사용

Ignatius Heo 2023. 7. 4. 19:50

작성일: 230704

 

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

 

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

 

구분 - 보안기능
설계단계 - 암호연산
https://cryptocurrencyclub.tistory.com/105
개요 SW 개발자들은 환경설정 파일에 저장된 비밀번호를 보호하기 위하여 간단한 인코딩 함수를 이용하여 비밀번호를 감추는 방법을 사용하기도 한다. 그렇지만 base64와 같은 지나치게 간단한 인코딩 함수로는 비밀번호를 제대로 보호할 수 없다.

정보보호 측면에서 취약하거나 위험한 암호화 알고리즘을 사용해서는 안 된다. 표준화되지 않은 암호화
알고리즘을 사용하는 것은 공격자가 알고리즘을 분석하여 무력화시킬 수 있는 가능성을 높일 수도 있다.

몇몇 오래된 암호화 알고리즘의 경우는 컴퓨터의 성능이 향상됨에 따라 취약해지기도 해서, 예전에는 해독하는데 오랜 시간이 걸릴 것이라고 예상되던 알고리즘이 며칠이나 몇 시간 내에 해독되기도 한다. RC2, RC4, RC5, RC6, MD4, MD5, SHA1, DES 알고리즘이 여기에 해당된다.

진단 세부사항
(설계단계)
 ① 대칭키 또는 비대칭키를 이용해서 암복호화를 수행해야 하는 경우 KISA의 암호이용안내서에서 정의하고 있는 암호화 알고리즘과 안전성이 보장되는 암호키 길이를 사용해야 한다.
  ㅇ  암복호화 기능 설계 시 안전한 암호 알고리즘을 사용하도록 설계되었는지 확인
      - 대칭키: SEED, ARIA, AES 등
      - 비대칭키: RSA, KCDSA, ECC 등
  ㅇ  암복호화 기능 설계 시 안전한 암호키 길이를 사용하도록 설계되었는지 확인
      - 대칭키: 128bit 이상
      - 비대칭키: 2048bit 이상
 
 ② 복호화되지 않는 암호화를 수행하기 위해 해시함수를 사용하는 경우 안전한 해시 알고리즘과 솔트값을 적용하여 암호화해야 한다.
  ㅇ  복호화되지 않는 암호화 기능설계시 안전한 암호화 알고리즘을 사용하도록 설계되어 있는지 확인
      - ex)SHA-2 (SHA-3는 왜 안보일까?)
  ㅇ  해시함수의 보안을 강화하기 위해 솔트값(난수발생기를 이용해 생성한 안전한 난수값)을 사용하여 암호화하도록 설계되어 있는지 확인
 
 ③ 난수 생성 시 안전한 난수 생성 알고리즘을 사용해야 한다.
  ㅇ  개발가이드에 안전한 난수 생성알고리즘을 사용하도록 코딩규칙을 정의하고 있는지 확인
      - JAVA: java.security.SecureRandom, java.util.Random
      - C: randomize(seed)
보안대책
(구현단계)

자신만의 암호화 알고리즘을 개발하는 것은 위험하며, 학계 및 업계에서 이미 검증된 표준화된 알고
리즘을 사용한다.

기존에 취약하다고 알려진 DES, RC5 등의 암호알고리즘을 대신하여, 3DES, AES, SEED 등의 안전한 암호알고리즘으로 대체하여 사용한다.

또한, 업무관련 내용, 개인정보 등에 대한 암호 알고리즘 적용시, IT보안인증 사무국이 안전성을 확인한 검증필 암호모듈을 사용해야한다.

진단방법
(구현단계)

자체 구현한 암호화 관련 알고리즘을 사용하는지 확인하고 자체 구현한 암호알고리즘을 사용할 경우 취약함으로 판단한다. 만약, 암호전문가가 존재할 경우 해당 암호함수의 암호알고리즘의 적절성을 판단하여 보증하는 것은 가능하다.

특정언어에서 제공하는 암호관련 함수를 호출하는지 식별한다.
- 취약한 알고리즘 : RC2, RC4, RC5, RC6, MD4, MD5, SHA1, DES 등
- 안전한 알고리즘 : SHA-256, AES, SEED, ARIA 등

 

다. 코드예제

 

ㅇ 분석

1: import java.security.*;
2: import javax.crypto.Cipher;
3: import javax.crypto.NoSuchPaddingException;
4: public class CryptoUtils {
5: public byte[] encrypt(byte[] msg, Key k) {
6: byte[] rslt = null;
7: try {
//키 길이가 짧아 취약함 암호와 알고리즘인 DES를 사용하여 안전하지 않다.
8: Cipher c = Cipher.getInstance("DES");
9: c.init(Cipher.ENCRYPT_MODE, k);
10: rslt = c.update(msg);
11: }

ㅇ 내용

1. 와 DES를  ????

 

ㅇ 수정

1: import java.security.*;
2: import javax.crypto.Cipher;
3: import javax.crypto.NoSuchPaddingException;
4: public class CryptoUtils {
5: public byte[] encrypt(byte[] msg, Key k) {
6: byte[] rslt = null;
7: try {
//키 길이가 길어 강력한 알고리즘인 AES를 사용하여 안전하다.
8: Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
9: c.init(Cipher.ENCRYPT_MODE, k);
10: rslt = c.update(msg);
11: }

ㅇ 내용

1. AES로 변경


ㅇ 분석

1: static string Enc(string input) {
//키 길이가 짧아 취약함 암호와 알고리즘인 DES를 사용하여 안전하지 않다.
2: var des = new DESCryptoServiceProvider();
3: ...
4: }

ㅇ 내용

1. 이것도 DES씀..

 

ㅇ 수정

1: static string Enc(string input) {
//키 길이가 길어 강력한 알고리즘인 AES를 사용하여 안전하다.
2: var des = new AesCryptoServiceProvider();
3: ...
4: }

ㅇ 내용

1. AES로 바꿈


ㅇ 분석

1: EVP_CIPHER_CTX ctx;
2: EVP_CIPHER_CTX_init(&ctx);
// 취약한 DES 알고리즘을 사용한다.
3: EVP_EncryptInit(&ctx, EVP_des_ecb(), NULL, NULL);

ㅇ 내용

1. DES 싫어하나 왤케 DES만 나옴

 

ㅇ 수정

1: EVP_CIPHER_CTX ctx;
2: EVP_CIPHER_CTX_init(&ctx);
// 안전한 AES 알고리즘을 사용한다.
3: EVP_EncryptInit(&ctx, EVP_aes_128_cbc(), key, iv);

ㅇ 내용

1. AES로 바꿈

 

 

 

 

 

 

끝.