Notice
Recent Posts
Recent Comments
Link
IgnatiusHeo
구현단계 보안약점 제거 기준-솔트 없이 일방향 해쉬 함수 사용 본문
작성일: 230706
※ 본 게시글은 학습 목적으로 행정안전부·KISA의 소프트웨어 보안약점 진단 가이드, 소프트웨어 개발보안 가이드를 참고하여 작성하였습니다.
정리 내용: 소프트웨어 보안약점 진단 가이드(390~393p)
구분 | - 보안기능 |
설계단계 | - 암호연산 https://cryptocurrencyclub.tistory.com/105 |
개요 | 비밀번호를 저장시 일방향 해시함수의 성질을 이용하여 비밀번호의 해시값을 저장한다. 만약 비밀번호를 솔트(Salt)없이 해시하여 저장한다면, 공격자는 레인보우 테이블과 같이 해시값을 미리 계산 하여 비밀번호를 찾을 수 있게 된다. |
진단 세부사항 (설계단계) |
① 대칭키 또는 비대칭키를 이용해서 암복호화를 수행해야 하는 경우 KISA의 암호이용안내서에서 정의하고 있는 암호화 알고리즘과 안전성이 보장되는 암호키 길이를 사용해야 한다. ㅇ 암복호화 기능 설계 시 안전한 암호 알고리즘을 사용하도록 설계되었는지 확인 - 대칭키: SEED, ARIA, AES 등 - 비대칭키: RSA, KCDSA, ECC 등 ㅇ 암복호화 기능 설계 시 안전한 암호키 길이를 사용하도록 설계되었는지 확인 - 대칭키: 128bit 이상 - 비대칭키: 2048bit 이상 ② 복호화되지 않는 암호화를 수행하기 위해 해시함수를 사용하는 경우 안전한 해시 알고리즘과 솔트값을 적용하여 암호화해야 한다. ㅇ 복호화되지 않는 암호화 기능설계시 안전한 암호화 알고리즘을 사용하도록 설계되어 있는지 확인 - ex)SHA-2 (SHA-3는 왜 안보일까?) ㅇ 해시함수의 보안을 강화하기 위해 솔트값(난수발생기를 이용해 생성한 안전한 난수값)을 사용하여 암호화하도록 설계되어 있는지 확인 ③ 난수 생성 시 안전한 난수 생성 알고리즘을 사용해야 한다. ㅇ 개발가이드에 안전한 난수 생성알고리즘을 사용하도록 코딩규칙을 정의하고 있는지 확인 - JAVA: java.security.SecureRandom, java.util.Random - C: randomize(seed) |
보안대책 (구현단계) |
비밀번호를 저장시 비밀번호와 솔트를 해시함수에 함께 입력하여 얻은 해시값을 저장한다. |
진단방법 (구현단계) |
① getInstance 함수로 안전한 해시 알고리즘을 인자로 하여 MessageDigest 객체를 생성하는지 확인 하고 ② 해시 값을 반환() 하기 전에 update 함수에 솔트를 사용하여 데이터를 해시하는지 확인한다. |
다. 코드예제
ㅇ 분석
1: public String getPasswordHash(String password) throws Exception {
2: MessageDigest md = MessageDigest.getInstance("SHA-256");
//해시에 솔트를 적용하지 않아 안전하지 않다.
3: md.update(password.getBytes());
4: byte byteData[] = md.digest();
5: StringBuffer hexString = new StringBuffer();
6: for (int i=0; i<byteData.length i++) {
7: String hex=Integer.toHexString(0xff & byteData[i]);
8: if (hex.length() == 1) {
9: hexString.append('0');
10: }
11: hexString.append(hex);
12: }
13: return hexString.toString();
14:}
ㅇ 내용
1. 솔트없이 그대로 해시 수행
ㅇ 수정
1: public String getPasswordHash(String password, byte[] salt) throws +Exception {
2: MessageDigest md = MessageDigest.getInstance("SHA-256");
3: md.update(password.getBytes());
//해시사용시에는 원문을 찾을 수 없도록 솔트를 사용하여야한다.
4: md.update(salt);
5: byte byteData[] = md.digest();
6: StringBuffer hexString = new StringBuffer();
7: for (int i=0; i<byteData.length i++) {
8: String hex=Integer.toHexString(0xff & byteData[i]);
9: if (hex.length() == 1) {
10: hexString.append('0');
11: }
12: hexString.append(hex);
13: }
14: return hexString.toString();
15:}
ㅇ 내용
1. 솔트 포함
ㅇ 분석
1: static void HashWithoutSalt()
2: {
//해시에 솔트를 적용하지 않아 안전하지 않다.
3: var bytes = new byte[100];
4: (new Random()).NextBytes(bytes);
5: var source = bytes;
6: var sha256 = new SHA256CryptoServiceProvider();
7: sha256.ComputeHash(source);
8: }
ㅇ 내용
1. 솔트 누락
ㅇ 수정
1: static void HashWithSalt(int saltLength)
2: {
//해시에 솔트를 적용하여 원문을 찾을 수 없게 한다.
3: var bytes = new byte[100];
4: (new Random()).NextBytes(bytes);
5: var source = bytes;
6: var sha256 = new SHA256CryptoServiceProvider();
7: byte[] saltBytes = GenerateRandomCryptographicBytes(saltLength);
8: List<byte> sourceWithSaltBytes = new List<byte>();
9: sourceWithSaltBytes.AddRange(source);
10: sourceWithSaltBytes.AddRange(sourceWithSaltBytes);
11: sha256.ComputeHash(sourceWithSaltBytes.ToArray());
12:}
ㅇ 내용
1. 솔트 포함
ㅇ 분석
1: void GenerateHash(char* data)
2: {
3: char[512] hashedData = {0};
//솔트 값 부분이 NULL 로 되어있어 들어가지 않는다.
4: MD5HashAlgorithm( data, hashedData, NULL );
5: ...
ㅇ 내용
1. 솔트가 NULL
ㅇ 수정
1: void GenerateHash(char* data, char* salt)
2: {
3: char hashedData[512] = {0};
4: MD5HashAlgorithm( data, hashedData, salt );
5: ...
6: }
ㅇ 내용
1. 솔트 받아 사용
끝.
'자격 > SW보안약점진단원' 카테고리의 다른 글
구현단계 보안약점 제거 기준-반복된 인증시도 제한 기능 부재 (0) | 2023.07.06 |
---|---|
구현단계 보안약점 제거 기준-무결성 검사 없는 코드 다운로드 (0) | 2023.07.06 |
구현단계 보안약점 제거 기준-주석문 안에 포함된 시스템 주요정보 (0) | 2023.07.06 |
구현단계 보안약점 제거 기준-사용자 하드디스크에 저장되는 쿠키를 통한 정보 노출 (0) | 2023.07.06 |
구현단계 보안약점 제거 기준-부적절한 인증서 유효성 검증 (0) | 2023.07.04 |