2012-02-08 4 views
1

내 사용자 인증 프로세스가 그렇게 보입니다.고유 토큰으로 보안 로그인

서명 프로세스 중에는 다음 코드가 실행됩니다.

$token = sha1(microtime(true) . mt_rand(10000, 90000)); 
setcookie('auth', $token, $timeout); 

그러면 사용자 ID 열 바로 뒤에 데이터베이스 테이블에 token이 추가됩니다. BTW, $_SESSION$_COOKIE에만 $token 값을 저장합니다.

쿠키가 존재하는 경우 모든 페이지 및 검사의 상단에 제공 protect라는 이름의 또 다른 기능이있다

:

  1. 를 먼저 확인의 DB 테이블에 $token 위해이 토큰에는 사용자가없는 경우는, 로그 아웃
  2. 그런 다음 $_SERVER['HTTP_USER_AGENT'], $_SERVER['REMOTE_ADDR']과 db 테이블에 저장된 값을 확인하십시오.

질문

내가 공격자가 동일한 PC와 같은 브라우저를 사용하는 경우, 단순히 "복사 - 붙여 넣기"쿠키에 의해 접근 할 수 있기 때문에이, 안전한 방법이 아니라고 생각합니다. 또한 $ _SERVER [ 'REMOTE_ADDR']은 항상 작동하지 않습니다.

어떻게하면 더 안전하게 로그인 할 수 있습니까? 여기

자세한

기능이

public function protect() { 
    if (!isset($_SESSION)) { 
     session_start(); 
    } 
    $data = array(); 

    if (isset($_SESSION['auth'])) { 
     $stmt = $this->db->prepare("SELECT l.browser, l.ip, u.ban from log AS l, users AS u WHERE l.token =? AND u.id=l.user_id LIMIT 1") or die($this->db->error); 
     $stmt->bind_param("i", $_SESSION['auth']) or die($stmt->error); 
     $stmt->execute() or die($stmt->error); 
     $stmt->store_result(); 
     if ($stmt->num_rows == 0) { 
      $this->signout(); 
     } 
     $stmt->bind_result($data['browser'], $data['ip'], $data['ban']); 
     $stmt->fetch() or die($stmt->error); 
     $stmt->close() or die($stmt->error); 
     $this->validation->check("protection", $data); 
    } else { 
     if (!isset($_COOKIE['auth'])) { 
      header('Location:' . wsurl); 
     } 
     $stmt = $this->db->prepare("SELECT l.browser, l.timeout, l.ip, u.ban from log AS l, users AS u where l.token =? AND u.id=l.user_id LIMIT 1") or die($this->db->error); 
     $stmt->bind_param("s", $_COOKIE['auth']) or die($stmt->error); 
     $stmt->execute() or die($stmt->error); 
     $stmt->store_result(); 
     if ($stmt->num_rows == 0) { 
      $this->signout(); 
     } 
     $stmt->bind_result($data['browser'], $data['timeout'], $data['ip'], $data['ban']) or die($stmt->error); 
     $stmt->fetch() or die($stmt->error); 
     $this->validation->check("protection", $data); 
     session_regenerate_id(); 
     $_SESSION['auth'] = $_COOKIE['auth']; 
     $stmt->close() or die($stmt->error); 
    } 
} 

을 보호되고 검증 훨씬 당신이 할 수있는 응용 프로그램의 가용성에 영향을주지 않고이 아니라이

if ($data['browser'] != md5($_SERVER['HTTP_USER_AGENT'])) { 
      $this->registration->signout(); 
     } 

     if ($data['ban'] == 1) { 
      $this->registration->signout(false); 
      header('Location:' . wsurl . "?page=msg&id=34"); 
     } 
     if ($data['ip'] != $this->common->getIP("long")) { 
      $this->registration->signout(); 
     } 

     if (isset($data['timeout']) && !empty($data['timeout'])) { 
      if (($data['timeout'] - $this->common->getTime()) < 0) { 
       $this->registration->signout(); 
      } 
     } 
+0

해결책은 조용하게 보입니다. '$ _SERVER [ 'HTTP_USER_AGENT']'와'$ _SERVER [ 'REMOTE_ADDR']'도 데이터베이스에 저장할 수 있습니다. 나중에이 값을 쿠키에 저장된 값 대신 실제 값과 대조하여 확인할 수 있습니다. – SecStone

+0

@SecStone 그래서 쿠키에 토큰 만 저장해야하고 다른 모든 매개 변수는 db로 저장해야합니다. –

+0

정확히,이 값들은 쉽게 조작 될 수 있기 때문입니다. 그러나 더 많은 보안을 원한다면 유일한 해결책은 SSL을 사용하여 트래픽 캡처를 피하는 것입니다 (예 : 공용 WiFi 네트워크에서 서핑을하고 누군가가 요청할 때마다 전송되는 쿠키를 복사하는 경우). – SecStone

답변

4

를 확인합니다. 예를 들어, 사용자 IP, 사용자 에이전트 또는 사용자 제공 환경 변수의 혼합을 토큰의 소금으로 사용할 수 있지만 사용자 IP가 변경되거나 환경 변수가 정적 일 필요가없는 경우에는 그렇지 않습니다. 다시 로그인하십시오.

정식으로는 보안상의 문제는 아니지만 사용자의 책임입니다. 누군가 컴퓨터에 접속하여 쿠키를 복사 할 수 있다면 암호를 직접 추출 할 수 있습니다 (Firefox를 사용하는 경우 쉽게).

+0

So 내 방법에 대해 어떻게 생각하니? 충분히 안전합니까? –

+1

제 생각에는 사용자 에이전트와 IP 주소를 제거 할 수 있습니다. 최종 사용자에게는 인증이 더 까다로워서 앱과 아무 관련이없는 유스 케이스 시나리오 만 해결할 수 있습니다. 시스템이 매우 엄격한 보안을 필요로하지 않는 한, 인증 된 세션을 쿠키에 저장해서는 안됩니다. – Naatan

+0

그러나 쿠키에 일부 매개 변수를 저장하지 않으면 Rememmber가 어떻게 작동합니까? db 테이블에서 시간 초과를 설정하면? –

1

나는 오해했을 수도 있지만 쿠키를 훔칠 수있는 공격자는 쿠키를 생성하고 도난당한 토큰에 HTTP_USER_AGENT, REMOTE_ADDR 요소를 추가하여 세션을 도용 할 수 있습니다.

나는 토큰을 설정하고

TOKEN REMOTE_ADDR HTTP_USER_AGENT 
------------------------------------ 

열이있는 데이터베이스 테이블을 가질 것이다. protect() 메소드는 토큰을 확인한 다음 현재 사용자의 원격 주소와 사용자 에이전트를 데이터베이스와 비교해야합니다.

그런 식으로, 쿠키를 훔칠 수있는 침입자는 브라우저 (간단하지 않음)와 IP 주소 (매우 어렵지만 여전히 할 수있는 능력)를 모방 할 수 있어야합니다.

또한 this question을 확인하십시오.

+0

"서버에 인증 정보를 저장하십시오. 즉, 쿠키에 사용자 이름과 같은 세부 정보를 보내지 마십시오."라는 질문을 보았습니다. 하지만 쿠키에 일부 매개 변수를 저장하지 않으면 Rememmber가 어떻게 작동합니까? 'timeout' 컬럼을 db 테이블의 값으로 설정하면? 또한 "IP 주소를 확인할 수도 있지만 여러 개의 인터넷 연결에서로드 균형 조정으로 인해 IP 주소가 변경되는 사용자에게는 문제가 발생합니다 (여기의 환경에서 그렇습니다)." 나는 저장하는 ip 또는 가게하지 않기 위해 약간 혼란 스럽다? –

+0

쿠키에 토큰을 유지하고 데이터베이스 또는 서버의 무언가에 동일한 토큰을 유지합니다. 토큰을 사용하여 인증하십시오. IP 주소가 신뢰할 수 없습니다. 한 주소에서 다른 주소로 전환 한 사람이 세션을 잃을 수 있습니다. 반면에이 구성표에서 IP 주소를 사용하지 않으면 쿠키를 훔칠 수있는 모든 사람이 세션을 도용 할 수 있습니다. 또한 기본 PHP 세션 프레임 워크에서 읽을 가치가 있습니다. 상자 밖에서 필요한 모든 것을 잘 수행 할 수 있습니다. –

+0

세션에서 $ token을 저장한다고합시다 : $ _SESSION [ 'auth']. 쿠키는 사용하지 않습니다. 로그인하는 동안 사용자가 "Rememmber me"를 누를 지 확인합니다. '예'인 경우 : '시간 초과'열에 레코드를 추가합니다. 예를 들어 time() + 60 * 60 * 24 * 7 (1 주일). 그런 다음 protect() 함수가 매 시간 초과 값을 검사 할 때마다. 시간 초과가 만료되면 스크립트가 직접 사용자를 로그 아웃하고 (모든 세션 변수를 삭제합니다. 등) 세션 ID와 $ _SESSION [ 'auth']을 다시 생성합니다. 이 솔루션에 대해 어떻게 생각하십니까? –