it-gundan.com

"기억하기"기능을 안전하게 구현하는 방법

모든 표준 로그인 항목을 구현하는 웹 사이트가 있다고 가정하면 사용자가 특정 기간 동안 자동으로 로그인 할 수있는 정확하고 안전한 방법은 무엇입니까 (30 일이라고 가정)? 이 기간은 엄격하게 시행되어야합니다. 즉, 유효한 솔루션이 쿠키에 만료 날짜를 부여하고 사용자의 브라우저가 적시에 쿠키를 삭제하기를 희망한다고 생각하지 않습니다.

기존 로그인 시스템의 세부 사항 :

  • 사용자는 사용자 이름과 비밀번호를 입력해야합니다
  • 데이터베이스는 strong_hash_function (password + user_specific_random_salt)뿐만 아니라 사용자 이름을 저장합니다
  • 모든 후속 페이지와 마찬가지로 로그인 양식이 SSL을 통해로드 및 제출됩니다.

거기에는 많은 예가 있으며 많은 보안 결함이 있습니다. PHP를 대상 언어로 사용하지만 개념은 모든 언어에 적용 가능해야합니다.

57
colithium

내 대답이 불완전하고 사소한 결함이있는 경우도 있습니다. 대신 @ Scott 's answer 를 참조하십시오.


내 대답에는 두 부분이 있습니다.

첫째, 위협 모델이 클라이언트 쪽 쿠키 의 노출에 대해 걱정하지 않는다고 가정하면 서버 쪽에서 nonce를 생성하고 저장할 수 있습니다. 사용자 이름 및 기타 정보 (예 : 클라이언트 IP, 컴퓨터 이름, 타임 스탬프, 유사한 것들)를 쿠키에 보냅니다. nonce는 만료 날짜와 함께 데이터베이스에 저장해야하며 쿠키가 돌아올 때 확인해야합니다.
세션 쿠키가 아닌 "기억"쿠키 여야합니다. 즉, 세션없이 쿠키를 받으면 새 일반 세션 쿠키를 다시 발행하십시오. 또한 세션 쿠키와 마찬가지로 https를 통해서만 전달되고 securehttpOnly 속성을 사용하여 쿠키의 범위를 정해야합니다.

둘째, 기억 된 사용자의 경우 민감도에 따라 특정 민감한 작업에 대해 재 인증 프로세스를 호출해야합니다. 즉, 때로는 어쨌든 비밀번호를 다시 입력해야하지만 민감한 작업은 거의하지 않습니다. 이는 CSRF 및 공유 데스크톱 노출과 같은 공격을 방지하기위한 것입니다.

31
AviD

보안 로그인 및 "기억하기"체크 상자 에 대해 아주 긴 글을 썼습니다. 받아 들여진 대답은 틀리지 않지만, 나는 그것이 필요보다 한 측면에서 조금 더 복잡하다고 주장하고 조금 더 복잡한 부분이 무시됩니다.

서버 측에 nonce를 생성하고 저장하고 사용자 이름과 다른 정보 (예 : 클라이언트 IP, 컴퓨터 이름, 타임 스탬프 등)로 해시 한 다음 쿠키로 보냅니다. nonce는 만료 날짜와 함께 데이터베이스에 저장해야하며 쿠키가 돌아올 때 확인해야합니다.

따라서 정보를 클라이언트에 노출시키지 않는 구현은 다음과 같습니다.

// Storage:
setcookie(
    'rememberme',
    hash_hmac('sha256', $username . $_SERVER['REMOTE_ADDR'], $storedNonce),
    time() + 8640000 // 100 days, for example
);
// Validation:
$valid = hash_equals(
    $_COOKIE['rememberme'],
    hash_hmac('sha256', $username . $_SERVER['REMOTE_ADDR'], $storedNonce)
);

여기서 명백한 제한은 IP 주소 (또는 기타 정보)가 변경되면 쿠키가 쓸모 없다는 것입니다. 어떤 사람들은 이것을 좋은 것으로 볼 수 있습니다. Tor 사용자의 유용성에 대해 불필요하게 적대적이라고 생각합니다.

가난한 사람의 JSON 웹 토큰과 같은 다른 의미로 위의 인용문을 확실히 해석 할 수 있습니다. 그러나 HTTP 쿠키는 도메인 당 4 KiB로 제한됩니다. 공간이 부족합니다.

또 다른 문제 : 데이터베이스 쿼리가 응용 프로그램에 대해 얼마나 많은 정보를 유출합니까? (예, 사이드 채널에 대해 이야기하고 있습니다.)


Paragon Initiative의 안전한 "기억하십시오"전략

저장:

  1. random_bytes() (PHP 7.0+ 또는 random_compat 을 통해)에서 임의의 9 바이트 문자열을 생성하고 base64는 12로 인코딩합니다. 데이터베이스 조회에 사용됩니다.
  2. 다른 임의의 문자열, 바람직하게는 18 바이트 이상의 길이를 생성하고 다시 base64로 인코딩하십시오 (24+까지). 실제로 인증에 사용됩니다.
  3. 데이터베이스에 $lookuphash('sha256, $validator)을 저장하십시오. 물론 특정 사용자 계정과 연결되어 있습니다.
  4. 사용자의 HTTP 쿠키에 $lookup . $validator를 저장하십시오 (예 : rememberme).

유효성 검사 (자동 로그인) :

  1. 쿠키를 $lookup$validator로 분할하십시오.
  2. $lookup를 기반으로 데이터베이스 조회를 수행하십시오. 여기에 타이밍 사이드 채널이 있으면 괜찮습니다.
  3. hash_equals($row['hashedValdator'], hash('sha256', $validator))을 확인하십시오.
  4. 3 단계가 TRUE을 리턴하면 현재 세션을 적절한 사용자 계정과 연관 시키십시오.

보안 분석 :

  • 어떤 사이드 채널이 완화됩니까?
    가장 크게 : 데이터베이스 조회에 사용 된 문자열 비교 작업에 대한 타이밍 정보 유출의 영향을 완화합니다.

    순진한 임의 토큰 인증을 구현 한 경우 공격자는 사용자에 대한 유효한 인증 토큰을 찾을 때까지 많은 요청을 보낼 수 있습니다. (아마도 자신이 가장하고있는 희생자를 선택할 수 없을 것입니다.)

  • 공격자가 장기 인증 데이터베이스 테이블을 유출 할 수 있다면 어떨까요?
    데이터베이스에 $validator의 SHA256 해시를 저장했지만 해시의 일반 텍스트는 쿠키에 저장됩니다. 입력 값이 엔트로피 값이 높기 때문에 무차별 검색에서는 결과가 나오지 않습니다. (이는 또한 예를 들어 bcrypt의 필요성을 완화시킵니다.)

이 전략은 Gatekeeper 에서 구현됩니다.

10

흥미로운 질문입니다. 먼저 애플리케이션의 보안을 약화시키지 않으면 서 수행 할 수 있는지 확신 할 수 없지만 트레이드 오프 가치가 있다고 간주 될 수있는 사이트에 따라 시작할 수 있습니다.

하나의 접근 방식은

세션 상태 데이터베이스는 토큰이 설정된 시간과 토큰을 비교할 수 있도록 기억해야하는 기간을 기록해야합니다.

사용자가 응용 프로그램에 로그인하면 사용자가 선택할 수있는 일정 기간 동안 로그인 상태를 유지할 수있는 확인란이 있습니다.

세션 토큰이 설정되면 해당 기간이 쿠키 만료로 사용됩니다. 다음 방문시 쿠키가 응용 프로그램에 제공되며 서버는 쿠키가 여전히 유효한지 확인해야합니다 (즉, 저장 기억 기능의 만료 기간이 맞지 않았습니다). 토큰이 여전히 유효하면 사용자는 인증 된 것으로 간주되고, 그렇지 않은 경우 토큰이 지워지고 사용자가 로그인 화면으로 경로 재 지정됩니다.

이 접근법의 문제점. 공유 브라우저는 무단 액세스가 가능하다는 것을 의미합니다.

또한 사이트의 취약성, 브라우저 문제 또는 컴퓨터에 설치된 맬웨어를 통해 쿠키에 액세스 할 수있는 사람은 누구나 사이트에 무단으로 액세스 할 수 있습니다. 이를 완화하기위한 한 가지 일반적인 제안은 쿠키를 사용자가 쿠키를 제시 할 때 확인되는 소스 IP 주소 (물론 암호화되거나 서버에 저장 됨)에 쿠키를 연결하려고 시도하는 것입니다. 여러 IP 주소에서 비롯 될 수 있으며 스푸핑에 취약 할 수 있습니다.

5
Rory McCune

쿠키를 삭제하기 위해 브라우저에 의존 할 필요는 없으며, 사이트에서 쿠키의 만료 날짜를 확인해야합니다.

사실, 이것이 안전하기 위해서는 쿠키 날짜의 일부로 만료 날짜를 설정하고 쿠키 값을 사용하지 않고 암호화하기를 원하기 때문에 어쨌든 할 것입니다. 쿠키 자체의 일반 텍스트 만료 속성.

쿠키를 안전한 것으로 표시하고 개별 세션 동안 보조 쿠키를 사용하거나 SSL로 쿠키를 도난 당하지 않도록 전체 세션 (로그인 프로세스뿐만 아니라)을 보호하려고합니다. 승인되지 않은 당사자가 사용합니다.

4
Xander

이 기사 쿠키 절도 및 세션 ID 추측을 방지하는 방법을 설명합니다.

  • "기억하십시오"쿠키는 사용자 ID, 토큰 (큰 난수) 및 시퀀스 토큰 (또 다른 큰 난수)으로 구성됩니다.
  • 사용자가 쿠키를 제시하면이 세 가지 정보를 데이터베이스에서 검색합니다.
    • 발견되면 시퀀스 토큰이 재생성되고 데이터베이스에 저장되어 사용자에게 전송됩니다.
    • 사용자 이름과 토큰 만 발견되면 시퀀스 토큰이 이미 사용 되었기 때문에 다른 사람이 쿠키를 도용 한 것으로 간주됩니다. 그러면 시스템은 사용자에게 경고하거나 데이터베이스에서이 사용자로부터 저장된 모든 토큰을 삭제할 수 있습니다.

추가 보안 조치로, 사용자가 "내 정보 기억"쿠키로만 인증 된 경우 로그인 데이터 변경 또는 사물 지불과 같은 중요한 조치로 비밀번호를 요청하는 것이 좋습니다.

사용자 ID 및 토큰을 포함하는 데이터베이스 테이블에는 토큰의 만료 날짜도 포함됩니다. 또한 사용자 에이전트 및 IP 주소도 포함 할 수 있으므로 공격자가이 에이전트도 복제해야합니다. 모든 토큰은 기본적으로 암호처럼 작동하고 데이터베이스를 얻은 공격자가 로그인 할 수 있도록 해시로만 저장해야합니다.

PHP를 위해 샘플 구현 을 만들었습니다.

0
chiborg