모범 사례 : 암호에 소금을 칠하고 후추를 바르는가?
나는 내가하고있는 일이 실제로 암호에 소금을 뿌리는 것이 아니라 후추를 뿌리는 것이라는 것을 알게 된 토론을 보았고 그 이후로 다음과 같은 기능으로 두 가지를 모두 시작했습니다.
hash_function($salt.hash_function($pepper.$password)) [multiple iterations]
선택한 해시 알고리즘을 무시합니다 (이것은 소금과 후추에 대한 토론이며 특정 알고리즘은 아니지만 안전한 알고리즘을 사용하고 싶습니다), 이것은 안전한 옵션입니까 아니면 다른 일을해야합니까? 용어에 익숙하지 않은 사람들을 위해 :
소금은 보통 불가능 암호를 해독하기 위해 해시 테이블을 사용 할 수 있도록 설계 데이터베이스의 문자열로 저장 무작위로 생성 된 값입니다. 각 암호에는 고유 한 소금이 있으므로 암호를 해독하려면 모두 개별적으로 무차별 적으로 시행해야합니다. 그러나 소금이 암호 해시와 함께 데이터베이스에 저장되므로 데이터베이스가 손상되면 두 가지를 모두 잃게됩니다.
고추는 비밀하기위한 것입니다 (일반적으로 응용 프로그램의 소스 코드에 하드 코딩) 데이터베이스에 별도로 저장 사이트 전체 정적 값입니다. 데이터베이스가 손상되어 전체 응용 프로그램의 암호 테이블이 무차별 화되지 않도록 사용됩니다.
내가 잃어버린 것이 있습니까? 내 비밀번호를 소금에 절이고 피핑하는 것이 사용자의 보안을 보호하는 가장 좋은 옵션입니까? 이 방법으로 수행 할 수있는 잠재적 인 보안 결함이 있습니까?
참고 : 토론의 목적으로 응용 프로그램 및 데이터베이스가 별도의 컴퓨터에 저장되어 있고 암호 등을 공유하지 않으므로 데이터베이스 서버의 위반이 자동으로 응용 프로그램 서버의 위반을 의미하지는 않습니다.
확인. 나는 이것에 대해 쓸 필요로 보는 이상 과 이상 , 나 혼자 고추에 마지막 정규 대답을 할 것이다.
고추의 명백한 거꾸로
고추가 해시 함수를 더 안전하게 만들어야한다는 것은 분명합니다. 공격자가 데이터베이스 만 가져 오면 사용자 암호는 안전해야합니다. 논리적 인 것 같습니까?
그래서 많은 사람들이 고추가 좋은 생각이라고 믿습니다. 말이 되는군요".
고추의 현실
보안 및 암호화 영역에서는 "이해하기"만으로는 충분하지 않습니다. 뭔가 증명이어야 하고 이 안전한 것으로 간주되는 순서를 의미합니다. 또한 유지 관리 가능한 방식으로 구현할 수 있어야합니다. 유지 관리 할 수없는 가장 안전한 시스템은 안전하지 않은 것으로 간주됩니다 (보안의 일부가 고장 나면 전체 시스템이 분리되므로).
그리고 고추는 입증 가능한 모델이나 유지 가능한 모델에 맞지 않습니다 ...
고추의 이론적 문제
이제 무대를 설정 했으므로 고추의 문제점을 살펴 보겠습니다.
하나의 해시를 다른 해시에 공급하는 것은 위험 할 수 있습니다.
귀하의 예에서는을 수행
hash_function($salt . hash_function($pepper . $password))
합니다.우리는 과거의 경험을 통해 하나의 해시 결과를 다른 해시 함수에 "그냥 공급"하면 전반적인 보안이 저하 될 수 있음을 알고 있습니다. 그 이유는 두 해시 함수가 모두 공격의 대상이 될 수 있기 때문입니다.
그렇기 때문에 PBKDF2 와 같은 알고리즘은 특수 연산을 사용하여 결합합니다 (이 경우 hmac).
요점은 큰 문제는 아니지만 그냥 버리는 것도 사소한 일이 아니라는 것입니다. 암호화 시스템은 "작동해야하는"사례를 피하기 위해 설계되었으며 대신 "작동하도록 설계된"사례에 중점을 둡니다.
이것은 순전히 이론적으로 보일 수 있지만 실제로는 그렇지 않습니다. 예를 들어 Bcrypt는 임의의 비밀번호를 허용 할 수 없습니다 . 따라서 전달
bcrypt(hash(pw), salt)
하면 실제로 이진 문자열을 반환하는bcrypt(pw, salt)
경우 보다 훨씬 약한 해시가 발생할 수 있습니다hash()
.디자인에 대한 작업
bcrypt (및 기타 암호 해싱 알고리즘)가 설계된 방식은 솔트를 사용하는 것입니다. 후추의 개념은 소개되지 않았습니다. 이것은 사소한 것처럼 보이지만 그렇지 않습니다. 그 이유는 소금이 비밀이 아니기 때문입니다. 공격자에게 알려진 값일뿐입니다. 반면에 후추는 정의상 암호화 비밀입니다.
현재 비밀번호 해싱 알고리즘 (bcrypt, pbkdf2 등)은 모두 하나의 비밀 값 (비밀번호) 만 사용하도록 설계되었습니다. 알고리즘에 다른 비밀을 추가하는 것은 전혀 연구되지 않았습니다.
그렇다고 안전하지 않다는 의미는 아닙니다. 그것은 우리가 안전한지 모른다는 것을 의미합니다. 그리고 보안 및 암호화에 대한 일반적인 권장 사항은 우리가 모른다면 그렇지 않다는 것입니다.
따라서 비밀 값 (고추)과 함께 사용하기 위해 암호 작성자가 알고리즘을 설계하고 검사 할 때까지 현재 알고리즘을 사용해서는 안됩니다.
복잡성은 보안의 적입니다
믿거 나 말거나, 복잡성은 보안의 적 입니다. 복잡해 보이는 알고리즘을 만드는 것은 안전하거나 그렇지 않을 수 있습니다. 그러나 안전하지 않을 가능성은 상당히 높습니다.
고추의 중요한 문제
유지할 수 없습니다
페퍼를 구현하면 페퍼 키를 회전시킬 수 없습니다. 후추는 단방향 함수에 대한 입력에서 사용되므로 값의 수명 동안 후추를 변경할 수 없습니다. 즉, 키 회전을 지원하기 위해 약간의 해킹이 필요합니다.
이다 매우 당신이 암호의 비밀을 저장할 때마다이 필요한 것으로 중요합니다. 주기적으로 그리고 위반 후 키를 회전시키는 메커니즘이없는 것은 큰 보안 취약점입니다.
그리고 현재의 후추 접근 방식은 모든 사용자가 회전에 의해 암호를 완전히 무효화하거나 다음 로그인이 회전 할 때까지 기다려야합니다 (절대 절대는 아닙니다) ...
기본적으로 귀하의 접근 방식은 즉각적으로 진행됩니다.
자신의 암호를 굴려야합니다.
현재 고추는 고추의 개념을 지원하지 않으므로 고추를 지원하기 위해 알고리즘을 구성하거나 새로운 알고리즘을 발명해야합니다. 그리고 왜 이것이 정말 나쁜지 즉시 볼 수 없다면 :
가장 단서가없는 아마추어에서 최고의 암호 전문가에 이르기까지 누구나 자신이 깰 수없는 알고리즘을 만들 수 있습니다.
NEVER roll your own crypto...
The Better Way
So, out of all the problems detailed above, there are two ways of handling the situation.
Just Use The Algorithms As They Exist
If you use bcrypt or scrypt correctly (with a high cost), all but the weakest dictionary passwords should be statistically safe. The current record for hashing bcrypt at cost 5 is 71k hashes per second. At that rate even a 6 character random password would take years to crack. And considering my minimum recommended cost is 10, that reduces the hashes per second by a factor of 32. So we'd be talking only about 2200 hashes per second. At that rate, even some dictionary phrases or modificaitons may be safe.
Additionally, we should be checking for those weak classes of passwords at the door and not allowing them in. As password cracking gets more advanced, so should password quality requirements. It's still a statistical game, but with a proper storage technique, and strong passwords, everyone should be practically very safe...
Encrypt The Output Hash Prior To Storage
There exists in the security realm an algorithm designed to handle everything we've said above. It's a block cipher. It's good, because it's reversible, so we can rotate keys (yay! maintainability!). It's good because it's being used as designed. It's good because it gives the user no information.
Let's look at that line again. Let's say that an attacker knows your algorithm (which is required for security, otherwise it's security through obscurity). With a traditional pepper approach, the attacker can create a sentinel password, and since he knows the salt and the output, he can brute force the pepper. Ok, that's a long shot, but it's possible. With a cipher, the attacker gets nothing. And since the salt is randomized, a sentinel password won't even help him/her. So the best they are left with is to attack the encrypted form. Which means that they first have to attack your encrypted hash to recover the encryption key, and then attack the hashes. But there's a lot of research into the attacking of ciphers, so we want to rely on that.
TL/DR
Don't use peppers. There are a host of problems with them, and there are two better ways: not using any server-side secret (yes, it's ok) and encrypting the output hash using a block cipher prior to storage.
Fist we should talk about the exact advantage of a pepper:
- The pepper can protect weak passwords from a dictionary attack, in the special case, where the attacker has read-access to the database (containing the hashes) but does not have access to the source code with the pepper.
A typical scenario would be SQL-injection, thrown away backups, discarded servers... These situations are not as uncommon as it sounds, and often not under your control (server-hosting). If you use...
- A unique salt per password
- A slow hashing algorithm like BCrypt
...strong passwords are well protected. It's nearly impossible to brute force a strong password under those conditions, even when the salt is known. The problem are the weak passwords, that are part of a brute-force dictionary or are derivations of them. A dictionary attack will reveal those very fast, because you test only the most common passwords.
The second question is how to apply the pepper ?
An often recommended way to apply a pepper, is to combine the password and the pepper before passing it to the hash function:
$pepperedPassword = hash_hmac('sha512', $password, $pepper);
$passwordHash = bcrypt($pepperedPassword);
There is another even better way though:
$passwordHash = bcrypt($password);
$encryptedHash = encrypt($passwordHash, $serverSideKey);
This not only allows to add a server side secret, it also allows to exchange the $serverSideKey, should this be necessary. This method involves a bit more work, but if the code once exists (library) there is no reason not to use it.
The point of salt and pepper is to increase the cost of a pre-computed password lookup, called a rainbow table.
In general trying to find a collision for a single hash is hard (assuming the hash is secure). However, with short hashes, it is possible to use computer to generate all possible hashes into a lookup onto a hard disk. This is called a Rainbow Table. If you create a rainbow table you can then go out into the world and quickly find plausable passwords for any (unsalted unpeppered) hash.
The point of a pepper is to make the rainbow table needed to hack your password list unique. Thus wasting more time on the attacker to construct the rainbow table.
The point of the salt however is to make the rainbow table for each user be unique to the user, further increasing the complexity of the attack.
Really the point of computer security is almost never to make it (mathematically) impossible, just mathematically and physically impractical (for example in secure systems it would take all the entropy in the universe (and more) to compute a single user's password).
Can't see storing a hardcoded value in your source code as having any security relevance. It's security through obscurity.
If a hacker acquires your database, he will be able to start brute forcing your user passwords. It won't take long for that hacker to identify your pepper if he manages to crack a few passwords.
참고URL : https://stackoverflow.com/questions/16891729/best-practices-salting-peppering-passwords
'programing tip' 카테고리의 다른 글
배열이 다른 배열의 부분 집합인지 확인 (0) | 2020.06.20 |
---|---|
ID가 다른 테이블과 일치하지 않는 SQL 행 삭제 (0) | 2020.06.20 |
gradle로 소스 jar을 빌드하는 방법 (0) | 2020.06.20 |
UNION [ALL]과 함께 SELECT INTO 절을 사용할 수 있습니까? (0) | 2020.06.20 |
Visual Studio 2015 Broken Razor Intellisense (0) | 2020.06.20 |