[php] 사용자 암호 정리

사용자가 제공 한 암호를 해시하고 데이터베이스에 저장하기 전에 어떻게 이스케이프하거나 정리해야합니까?

PHP 개발자는 보안 목적으로 사용자의 암호를 해싱하는 것을 고려할 때 종종 다른 사용자가 제공 한 데이터처럼 해당 암호를 생각하는 경향이 있습니다. 이 주제는 암호 저장과 관련된 PHP 질문에서 자주 등장합니다. 개발자는 종종 escape_string()(다양한 반복에서) htmlspecialchars(), addslashes()및 기타 기능을 사용하여 암호를 정리하고 해싱하고 데이터베이스에 저장하기를 원합니다 .



답변

password_hash()여러 가지 이유로 PHP로 해싱 할 비밀번호에 대해 다른 정리 메커니즘을 이스케이프, 트리밍 또는 사용해서는 안됩니다. 가장 큰 이유는 비밀번호를 추가로 정리하려면 불필요한 추가 코드가 필요하기 때문입니다.

우리는 모든 사용자 입력을 정리해야하며 우리가 사용자로부터받는 다른 모든 정보에 대해 귀하가 옳다고 주장 할 것입니다 (그리고 귀하의 시스템에서 사용자 데이터가 허용되는 모든 게시물에서 볼 수 있습니다). 암호가 다릅니다. 해시 된 암호는 데이터베이스에 저장하기 전에 문자열이 해시로 바뀌기 때문에 SQL 주입 위협을 제공 할 수 없습니다.

암호 해싱 작업은 암호를 데이터베이스에 안전하게 저장하는 작업입니다. 해시 함수는 바이트에 특별한 의미를 부여하지 않으므로 보안상의 이유로 입력을 정리할 필요가 없습니다.

사용자가 원하는 암호 / 구문 을 사용할 수 있도록 허용하는 만트라를 따르고 암호를 제한하지 않고 길이, 공백 및 특수 문자 해싱을 허용하면 내용이 무엇이든간에 암호 / 암호를 안전하게 만들 수 있습니다. 비밀번호. 현재 가장 일반적인 해시 (기본값) 인은 (는) PASSWORD_BCRYPT해시 된 암호 정보 및 비용 (해시 생성의 알고리즘 비용)과 함께 임의의 솔트를 포함하는 60 자 폭의 문자열로 암호를 변환합니다.

PASSWORD_BCRYPT는 CRYPT_BLOWFISH 알고리즘을 사용하여 새 암호 해시를 만드는 데 사용됩니다. 이렇게하면 항상 폭이 항상 60자인 “$ 2y $”암호화 형식을 사용하는 해시가 생성됩니다.

해시를 저장하기위한 공간 요구 사항 때문에 같은 저장된 해시의 열 유형에 더 큰 이동하는 것이 낫다, 다른 해싱 방법은 함수에 추가됨에 따라 변경 될 수 있습니다 VARCHAR(255)또는 TEXT.

완전한 SQL 쿼리를 암호로 사용할 수 있으며 해시되어 SQL 엔진에서 실행할 수 없게됩니다. 예 :

SELECT * FROM `users`;

해시 될 수 있습니다. $2y$10$1tOKcWUWBW5gBka04tGMO.BH7gs/qjAHZsC5wyG0zmI2C.KgaqU5G

다양한 삭제 방법이 비밀번호에 어떤 영향을 미치는지 살펴 보겠습니다.

암호는 I'm a "dessert topping" & a <floor wax>!(여기에 표시되지 않는 암호 끝에 5 개의 공백이 있습니다.)

다음 트리밍 방법을 적용하면 약간의 다른 결과가 나타납니다.

var_dump(trim($_POST['upassword']));
var_dump(htmlentities($_POST['upassword']));
var_dump(htmlspecialchars($_POST['upassword']));
var_dump(addslashes($_POST['upassword']));
var_dump(strip_tags($_POST['upassword']));

결과 :

string(40) "I'm a "dessert topping" & a <floor wax>!" // spaces at the end are missing
string(65) "I'm a &quot;dessert topping&quot; &amp; a &lt;floor wax&gt;!     " // double quotes, ampersand and braces have been changed
string(65) "I'm a &quot;dessert topping&quot; &amp; a &lt;floor wax&gt;!     " // same here
string(48) "I\'m a \"dessert topping\" & a <floor wax>!     " // escape characters have been added
string(34) "I'm a "dessert topping" & a !     " // looks like we have something missing

이것들을 보내면 password_hash()어떻게 되나요? 위의 쿼리처럼 모두 해시됩니다. 암호를 확인하려고 할 때 문제가 발생합니다. 이러한 방법 중 하나 이상을 사용하는 경우 .NET과 비교하기 전에 다시 사용해야합니다 password_verify(). 다음은 실패합니다.

password_verify($_POST['upassword'], $hashed_password); // where $hashed_password comes from a database query

게시 된 암호는 암호 확인에 사용하기 전에 선택한 정리 방법을 통해 실행해야합니다. 불필요한 단계 집합이며 해시를 더 좋게 만들지 않습니다.


5.5 미만의 PHP 버전을 사용하십니까? password_hash() 호환성 팩을 사용할 수 있습니다 .

정말 MD5 암호 해시를 사용해서는 안됩니다 .


답변

암호를 해싱하기 전에 RFC 7613의 섹션 4에 설명 된대로 정규화해야합니다 . 특히:

  1. 추가 매핑 규칙 : ASCII가 아닌 공간의 모든 인스턴스는 반드시 ASCII 공간 (U + 0020)으로 매핑되어야합니다. 비 ASCII 공간은 유니 코드 일반 범주가 “Zs”(U + 0020 제외) 인 유니 코드 코드 포인트입니다.

과:

  1. 정규화 규칙 : 모든 문자에 유니 코드 NFC (Normalization Form C)를 적용해야합니다.

이렇게하면 사용자가 동일한 암호를 입력하지만 다른 입력 방법을 사용하는 경우에도 암호를 수락해야합니다.


답변