내 웹 응용 프로그램은 세션을 사용하여 로그인 한 사용자에 대한 정보를 저장하고 응용 프로그램 내에서 페이지를 이동할 때 해당 정보를 유지 관리합니다. 이 특정 응용 프로그램에서, 나는를 저장하고있어 user_id
, first_name
그리고 last_name
사람의.
로그인시 “Keep Me Logged In (로그인 유지)”옵션을 제공하여 쿠키를 2 주 동안 사용자 컴퓨터에 저장하고 앱으로 돌아올 때 동일한 세부 정보로 세션을 다시 시작합니다.
이 작업을 수행하는 가장 좋은 방법은 무엇입니까? user_id
쿠키에 쿠키 를 저장하고 싶지 않습니다 . 쿠키를 사용하면 한 사용자가 다른 사용자의 신원을 쉽게 만들고 위조 할 수있는 것처럼 보입니다.
답변
자, 이것을 무뚝뚝하게하겠습니다 : 만약 사용자 데이터 또는이 목적을 위해 사용자 데이터에서 파생 된 것을 쿠키에 넣는다면, 당신은 뭔가 잘못하고있는 것입니다.
그곳에. 내가 말했어. 이제 실제 답변으로 넘어갈 수 있습니다.
사용자 데이터 해싱의 문제점은 무엇입니까? 글쎄, 그것은 모호함을 통해 노출 표면과 보안으로 귀착됩니다.
당신이 공격 자라고 잠시 상상해보십시오. 세션에서 remember-me에 대한 암호화 쿠키 세트가 표시됩니다. 32 자입니다. 사람. MD5 일 수도 있습니다.
또한 사용자가 사용한 알고리즘을 알고 있다고 잠시 상상해 봅시다. 예를 들면 다음과 같습니다.
md5(salt+username+ip+salt)
이제 공격자가해야 할 일은 “소금”(실제로 소금은 아니지만 나중에 더 자세히 설명)을 무차별 처리하는 것입니다. 이제 IP 주소의 모든 사용자 이름으로 원하는 모든 가짜 토큰을 생성 할 수 있습니다! 그러나 소금을 강제로 강제하는 것은 어렵습니다. 물론. 그러나 현대의 GPU는 그것을 능가합니다. 그리고 당신이 그것에 충분한 임의성을 사용하지 않으면 (충분히 크게 만드십시오), 그것은 빨리 떨어지고 성의 열쇠와 함께 떨어질 것입니다.
요컨대, 당신을 보호하는 유일한 것은 소금입니다. 생각만큼 많이 보호하지는 않습니다.
하지만 기다려!
이 모든 것이 공격자가 알고리즘을 알고 있다고 가정했습니다! 비밀스럽고 혼란 스러우면 안전합니까? 잘못되었습니다 . 그 사고 방식은 ‘ 불안을 통한 보안’ 이라는 이름을 가지 는데, 절대로 의존 해서는 안됩니다 .
더 나은 방법
더 좋은 방법은 ID를 제외하고 사용자 정보가 서버를 떠나지 않도록하는 것입니다.
사용자가 로그인하면 큰 (128-256 비트) 임의 토큰을 생성하십시오. 토큰을 사용자 ID에 맵핑하는 데이터베이스 테이블에 추가 한 후 쿠키의 클라이언트로 전송하십시오.
침입자가 다른 사용자의 임의 토큰을 추측하면 어떻게됩니까?
자, 여기서 수학을하자. 128 비트 랜덤 토큰을 생성 중입니다. 즉, 다음이 있음을 의미합니다.
possibilities = 2^128
possibilities = 3.4 * 10^38
이제 그 숫자가 얼마나 터무니 없는지 보여주기 위해 인터넷상의 모든 서버 (오늘 5 만, 000이라고하자)가 초당 1,000,000,000의 속도로 그 숫자를 무차별 적으로 시도한다고 가정 해 봅시다. 실제로 서버는 이러한 부하로 인해 녹아 버릴 것입니다.
guesses_per_second = servers * guesses
guesses_per_second = 50,000,000 * 1,000,000,000
guesses_per_second = 50,000,000,000,000,000
따라서 초당 50 조의 추측. 빠릅니다! 권리?
time_to_guess = possibilities / guesses_per_second
time_to_guess = 3.4e38 / 50,000,000,000,000,000
time_to_guess = 6,800,000,000,000,000,000,000
그래서 6.8 sextillion 초 …
좀 더 친근한 숫자로 가져 오도록합시다.
215,626,585,489,599 years
또는 더 나은 :
47917 times the age of the universe
예, 그것은 우주의 나이 47917 배입니다 …
기본적으로 금이 간 것은 아닙니다.
요약하자면 다음과 같습니다.
내가 권장하는 더 좋은 방법은 쿠키를 세 부분으로 저장하는 것입니다.
function onLogin($user) {
$token = GenerateRandomToken(); // generate a token, should be 128 - 256 bit
storeTokenForUser($user, $token);
$cookie = $user . ':' . $token;
$mac = hash_hmac('sha256', $cookie, SECRET_KEY);
$cookie .= ':' . $mac;
setcookie('rememberme', $cookie);
}
그런 다음 유효성을 검사하십시오.
function rememberMe() {
$cookie = isset($_COOKIE['rememberme']) ? $_COOKIE['rememberme'] : '';
if ($cookie) {
list ($user, $token, $mac) = explode(':', $cookie);
if (!hash_equals(hash_hmac('sha256', $user . ':' . $token, SECRET_KEY), $mac)) {
return false;
}
$usertoken = fetchTokenByUserName($user);
if (hash_equals($usertoken, $token)) {
logUserIn($user);
}
}
}
참고 : 데이터베이스에서 레코드를 조회하기 위해 토큰 또는 사용자와 토큰 조합을 사용하지 마십시오. 항상 사용자를 기준으로 레코드를 가져오고 타이밍 안전 비교 기능을 사용하여 나중에 가져온 토큰을 비교하십시오. 타이밍 공격에 대해 자세히 알아보십시오 .
이제 암호화 비밀이되는 것이 매우 중요합니다 SECRET_KEY
( /dev/urandom
높은 엔트로피 입력에서 생성 및 / 또는 파생 된 것). 또한, GenerateRandomToken()
(강한 임의의 원천이 될 필요가 mt_rand()
거의 강한 것만으로는 충분하지 않습니다. 같은 도서관, 사용 RandomLib 또는 random_compat , 또는 mcrypt_create_iv()
과를 DEV_URANDOM
) …
을 hash_equals()
방지하는 것입니다 타이밍 공격을 . PHP 5.6 이하의 PHP 버전을 사용하는 경우 기능 hash_equals()
이 지원되지 않습니다. 이 경우 hash_equals()
timingSafeCompare 기능으로 교체 할 수 있습니다 .
/**
* A timing safe equals comparison
*
* To prevent leaking length information, it is important
* that user input is always used as the second parameter.
*
* @param string $safe The internal (safe) value to be checked
* @param string $user The user submitted (unsafe) value
*
* @return boolean True if the two strings are identical.
*/
function timingSafeCompare($safe, $user) {
if (function_exists('hash_equals')) {
return hash_equals($safe, $user); // PHP 5.6
}
// Prevent issues if string length is 0
$safe .= chr(0);
$user .= chr(0);
// mbstring.func_overload can make strlen() return invalid numbers
// when operating on raw binary strings; force an 8bit charset here:
if (function_exists('mb_strlen')) {
$safeLen = mb_strlen($safe, '8bit');
$userLen = mb_strlen($user, '8bit');
} else {
$safeLen = strlen($safe);
$userLen = strlen($user);
}
// Set the result to the difference between the lengths
$result = $safeLen - $userLen;
// Note that we ALWAYS iterate over the user-supplied length
// This is to prevent leaking length information
for ($i = 0; $i < $userLen; $i++) {
// Using % here is a trick to prevent notices
// It's safe, since if the lengths are different
// $result is already non-0
$result |= (ord($safe[$i % $safeLen]) ^ ord($user[$i]));
}
// They are only identical strings if $result is exactly 0...
return $result === 0;
}
답변
보안 공지 : 결정적 데이터의 MD5 해시에서 쿠키를 만드는 것은 나쁜 생각입니다. CSPRNG에서 파생 된 임의 토큰을 사용하는 것이 좋습니다. 보다 안전한 접근 방법은이 질문에 대한 ircmaxell의 답변 을 참조하십시오 .
일반적으로 나는 다음과 같이합니다 :
- ‘로그인 상태 유지’로 사용자 로그인
- 세션 생성
- md5 (salt + username + ip + salt)를 포함하는 SOMETHING이라는 쿠키와 id를 포함하는 somethingElse라는 쿠키를 만듭니다.
- 데이터베이스에 쿠키 저장
- 사용자는 물건과 잎을한다 —-
- 사용자가 반환하고 다른 쿠키가 있는지 확인합니다. 쿠키가 존재하는 경우 해당 사용자의 데이터베이스에서 오래된 해시를 가져오고 쿠키의 내용을 확인합니다. 데이터베이스의 해시와 일치하는 항목이 있고 새로 계산 된 해시와 일치해야합니다. ip) 따라서 : cookieHash == databaseHash == md5 (salt + username + ip + salt), 만약 그렇다면, 2로 가십시오.
물론 다른 쿠키 이름 등을 사용할 수도 있습니다. 쿠키의 내용을 약간 변경할 수도 있습니다. 쿠키가 쉽게 만들어지지 않도록하십시오. 예를 들어 사용자를 만들 때 user_salt를 만들어 쿠키에 넣을 수도 있습니다.
또한 md5 (또는 거의 모든 알고리즘) 대신 sha1을 사용할 수 있습니다
답변
소개
제목 “Keep Me Logged In”-최상의 접근 방식을 사용하는 경우 다음을 고려해야하므로 가장 좋은 접근 방식으로 시작 위치를 알기가 어렵습니다.
- 신분증
- 보안
쿠키
쿠키는 취약합니다. 일반적인 브라우저 쿠키 도난 취약점과 사이트 간 스크립팅 공격간에 쿠키가 안전하지 않다는 사실을 인정해야합니다. 보안을 향상 시키려면 다음 php
setcookies
과 같은 추가 기능이 있음에 유의해야합니다.
bool setcookie (string $ name [, string $ value [, int $ expire = 0 [, string $ path [, string $ domain [, bool $ secure = false [, bool $ httponly = false]]]]]])
- 보안 (HTTPS 연결 사용)
- httponly (XSS 공격을 통한 신원 도용 감소)
정의
- 토큰 (예 : n 길이의 예상 할 수없는 임의 문자열 (예 : / dev / urandom))
- 참조 (예를 들어, n 길이의 예측할 수없는 임의 문자열 (예 : / dev / urandom))
- 서명 (HMAC 방법을 사용하여 키 해시 값 생성)
간단한 접근
간단한 해결책은 다음과 같습니다.
- 사용자가 Remember Me로 로그온했습니다
- 토큰 및 서명으로 발행 된 로그인 쿠키
- 돌아올 때 서명이 확인됩니다
- 서명이 정상이면 데이터베이스에서 사용자 이름 및 토큰을 찾습니다.
- 유효하지 않은 경우 .. 로그인 페이지로 돌아 가기
- 유효한 자동 로그인
위의 사례 연구는이 페이지에 제공된 모든 예제를 요약하지만 단점은
- 쿠키를 도난당한 경우 알 수있는 방법이 없습니다
- 공격자는 암호 변경 또는 개인 정보 및 베이킹 정보 등과 같은 데이터와 같은 민감한 작업에 액세스 할 수 있습니다.
- 손상된 쿠키는 여전히 쿠키 수명 동안 유효합니다.
더 나은 솔루션
더 나은 해결책은
- 사용자가 로그인했으며 내가 선택되었음을 기억하십시오
- 토큰 생성 및 서명 및 쿠키 저장
- 토큰은 무작위이며 단일 인증에만 유효합니다.
- 사이트를 방문 할 때마다 토큰이 교체됩니다.
- 로그인하지 않은 사용자가 사이트를 방문하면 서명, 토큰 및 사용자 이름이 확인됩니다.
- 로그인은 액세스가 제한되어 있어야하며 비밀번호, 개인 정보 등을 수정해서는 안됩니다.
예제 코드
// Set privateKey
// This should be saved securely
$key = 'fc4d57ed55a78de1a7b31e711866ef5a2848442349f52cd470008f6d30d47282';
$key = pack("H*", $key); // They key is used in binary form
// Am Using Memecahe as Sample Database
$db = new Memcache();
$db->addserver("127.0.0.1");
try {
// Start Remember Me
$rememberMe = new RememberMe($key);
$rememberMe->setDB($db); // set example database
// Check if remember me is present
if ($data = $rememberMe->auth()) {
printf("Returning User %s\n", $data['user']);
// Limit Acces Level
// Disable Change of password and private information etc
} else {
// Sample user
$user = "baba";
// Do normal login
$rememberMe->remember($user);
printf("New Account %s\n", $user);
}
} catch (Exception $e) {
printf("#Error %s\n", $e->getMessage());
}
사용 된 클래스
class RememberMe {
private $key = null;
private $db;
function __construct($privatekey) {
$this->key = $privatekey;
}
public function setDB($db) {
$this->db = $db;
}
public function auth() {
// Check if remeber me cookie is present
if (! isset($_COOKIE["auto"]) || empty($_COOKIE["auto"])) {
return false;
}
// Decode cookie value
if (! $cookie = @json_decode($_COOKIE["auto"], true)) {
return false;
}
// Check all parameters
if (! (isset($cookie['user']) || isset($cookie['token']) || isset($cookie['signature']))) {
return false;
}
$var = $cookie['user'] . $cookie['token'];
// Check Signature
if (! $this->verify($var, $cookie['signature'])) {
throw new Exception("Cokies has been tampared with");
}
// Check Database
$info = $this->db->get($cookie['user']);
if (! $info) {
return false; // User must have deleted accout
}
// Check User Data
if (! $info = json_decode($info, true)) {
throw new Exception("User Data corrupted");
}
// Verify Token
if ($info['token'] !== $cookie['token']) {
throw new Exception("System Hijacked or User use another browser");
}
/**
* Important
* To make sure the cookie is always change
* reset the Token information
*/
$this->remember($info['user']);
return $info;
}
public function remember($user) {
$cookie = [
"user" => $user,
"token" => $this->getRand(64),
"signature" => null
];
$cookie['signature'] = $this->hash($cookie['user'] . $cookie['token']);
$encoded = json_encode($cookie);
// Add User to database
$this->db->set($user, $encoded);
/**
* Set Cookies
* In production enviroment Use
* setcookie("auto", $encoded, time() + $expiration, "/~root/",
* "example.com", 1, 1);
*/
setcookie("auto", $encoded); // Sample
}
public function verify($data, $hash) {
$rand = substr($hash, 0, 4);
return $this->hash($data, $rand) === $hash;
}
private function hash($value, $rand = null) {
$rand = $rand === null ? $this->getRand(4) : $rand;
return $rand . bin2hex(hash_hmac('sha256', $value . $rand, $this->key, true));
}
private function getRand($length) {
switch (true) {
case function_exists("mcrypt_create_iv") :
$r = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
break;
case function_exists("openssl_random_pseudo_bytes") :
$r = openssl_random_pseudo_bytes($length);
break;
case is_readable('/dev/urandom') : // deceze
$r = file_get_contents('/dev/urandom', false, null, 0, $length);
break;
default :
$i = 0;
$r = "";
while($i ++ < $length) {
$r .= chr(mt_rand(0, 255));
}
break;
}
return substr(bin2hex($r), 0, $length);
}
}
Firefox 및 Chrome에서 테스트
이점
- 더 나은 보안
- 공격자에 대한 제한된 액세스
- 쿠키가 도난 당할 때 단일 액세스에만 유효합니다
- 다음에 원래 사용자가 사이트에 액세스하면 도난을 자동으로 감지하여 사용자에게 알릴 수 있습니다
불리
- 여러 브라우저 (모바일 및 웹)를 통한 지속적인 연결을 지원하지 않습니다
- 사용자는 다음 로그인 후에 만 알림을 받기 때문에 쿠키를 도난 당할 수 있습니다.
빠른 수정
- 지속적인 연결이 필요한 각 시스템에 대한 승인 시스템 도입
- 인증을 위해 여러 쿠키 사용
여러 쿠키 접근
공격자가 쿠키를 훔치려 고 할 때 쿠키는 특정 웹 사이트 나 도메인에만 집중합니다. example.com
그러나 실제로 두 개의 다른 도메인 ( example.com & fakeaddsite.com ) 에서 사용자를 인증하여 “광고 쿠키”처럼 보이게 할 수 있습니다
- 사용자 나를 기억 하여 example.com 에 로그온
- 쿠키에 사용자 이름, 토큰, 참조 저장
- 데이터베이스에 사용자 이름, 토큰, 참조를 저장하십시오. Memcache
- get 및 iframe을 통해 refrence ID를 fakeaddsite.com 으로 보냅니다.
- fakeaddsite.com은이 참조를 사용하여 데이터베이스에서 사용자 및 토큰을 가져옵니다.
- fakeaddsite.com은 서명을 저장합니다
- 사용자가 fakeaddsite.com에서 iframe으로 가져 오기 서명 정보를 반환하는 경우
- 데이터를 결합하고 유효성 검사를 수행하십시오.
- ….. 당신은 나머지를 알고
어떤 사람들은 두 가지 다른 쿠키를 어떻게 사용할 수 있는지 궁금 할 것입니다. 가능은 잘 상상 example.com = localhost
하고 fakeaddsite.com = 192.168.1.120
. 쿠키를 검사하면 다음과 같습니다
위 이미지에서
- 현재 방문한 사이트는 localhost입니다
- 192.168.1.120에서 설정된 쿠키도 포함합니다.
192.168.1.120
- 정의 된 내용 만 수락
HTTP_REFERER
- 지정된 연결 만 허용
REMOTE_ADDR
- 자바 스크립트 없음, 콘텐츠 없음
이점
- 공격자를 속인 시간의 99 %
- 공격자가 처음 시도 할 때 계정을 쉽게 잠글 수 있습니다
- 다른 방법과 마찬가지로 다음 로그인 전에 공격을 방지 할 수 있습니다
불리
- 단일 로그인만으로 서버에 여러 요청
개량
- iframe 사용 완료
ajax
답변
이 질문의 하나의 각도를 요청 여기 , 그리고 대답은 모두 당신이 필요로하는 토큰 기반 타이밍 쿠키 링크를 당신을 이끌 것입니다.
기본적으로 쿠키에는 userId를 저장하지 않습니다. 사용자가 이전 로그인 세션을 픽업하는 데 사용하는 일회성 토큰 (거대한 문자열)을 저장합니다. 그런 다음 실제로 보안을 유지하려면 암호 자체 변경과 같이 많은 작업에 필요한 암호를 요청하십시오.
답변
오래된 스레드이지만 여전히 유효한 관심사입니다. 보안에 대해 좋은 반응을 보였고 ‘불분명을 통한 보안’사용을 피했지만 실제 기술 방법으로는 충분하지 않았습니다. 내 방법에 기여하기 전에 말해야 할 사항 :
- 비밀번호를 일반 텍스트로 저장하지 마십시오 .
- 못사용자의 해시 비밀번호를 데이터베이스의 둘 이상의 위치에 저장하지 . 서버 백엔드는 항상 users 테이블에서 해시 된 비밀번호를 가져올 수 있습니다. 추가 DB 트랜잭션 대신 중복 데이터를 저장하는 것이 더 효율적이지 않습니다. 그 반대의 경우도 마찬가지입니다.
- 두 개의 사용자 수 있도록 세션 ID의는 고유해야 지금 , 아이디의 따라서 목적 (운전 면허증 ID 번호 이제까지 다른 사람과 일치 수 있을까? 호)이 2에 따라, 두 조각 고유 한 조합을 생성을 ID를 공유하지 고유 한 문자열. 세션 테이블은 ID를 PK로 사용해야합니다. 자동 로그인을 위해 여러 장치를 신뢰할 수있게하려면 모든 검증 된 장치 목록이 포함 된 신뢰할 수있는 장치에 대해 다른 테이블을 사용하십시오 (아래 예 참조).
- 알려진 데이터를 쿠키에 해시하려는 목적이 없으며 쿠키를 복사 할 수 있습니다. 우리가 찾고있는 것은 공격자가 사용자의 컴퓨터를 손상시키지 않고 얻을 수없는 확실한 정보를 제공하는 준수하는 사용자 장치입니다 (다시, 내 예 참조). 그러나 이는 자신의 컴퓨터의 정적 정보 (예 : MAC 주소, 장치 호스트 이름, 브라우저에 의해 제한되는 경우 useragent 등)를 일관되게 유지하지 못하도록 (또는 우선 스푸핑) 합법적 인 사용자가 할 수 없음을 의미합니다. 이 기능을 사용하십시오. 그러나 이것이 우려되는 경우 사용자에게 자동 로그인을 제공한다는 사실을 고려하십시오. 자신을 고유하게 식별하는따라서 MAC 스푸핑, 사용자 에이전트 스푸핑, 호스트 이름 스푸핑 / 변경, 프록시 뒤에 숨어 등으로 알려지기를 거부하는 경우 식별 할 수 없으며 자동 서비스에 대해 인증되지 않아야합니다. 원하는 경우 사용중인 장치의 ID를 설정하는 클라이언트 측 소프트웨어와 함께 제공되는 스마트 카드 액세스를 조사해야합니다.
모두 말하지만, 시스템에 자동 로그인하는 두 가지 좋은 방법이 있습니다.
첫째, 저렴하고 쉬운 방법으로 다른 모든 사람에게 적용 할 수 있습니다. 예를 들어 Google+ 계정으로 로그인하여 사이트를 지원하는 경우 사용자가 이미 Google에 로그인 한 경우 사용자를 로그인하는 간소화 된 Google+ 버튼이있을 것입니다. Google에 로그인). 사용자가 이미 신뢰할 수 있고 지원되는 인증 자로 로그인 한 상태에서 자동으로 로그인하고 확인란을 선택한 경우 클라이언트 측 스크립트가로드하기 전에 해당 ‘로그인 대상’버튼 뒤에서 코드를 수행하도록하십시오 사용자 이름, 세션 ID 및 인증자가 사용 된 자동 로그인 테이블에 서버가 고유 ID를 저장하도록하십시오. 이 로그인 방법은 AJAX를 사용하므로 어쨌든 응답을 기다리고 있습니다. 그 응답은 검증 된 응답 또는 거부입니다. 검증 된 응답을 받으면 정상적으로 사용하고 로그인 한 사용자를 정상적으로로드하십시오. 그렇지 않으면 로그인에 실패했지만 사용자에게 알리지 않고 로그인하지 않은 채 계속 진행하면 알 수 있습니다. 이는 쿠키를 훔친 (또는 권한 상승 시도로 쿠키를 위조 한) 공격자가 사용자가 사이트에 자동 로그인한다는 사실을 배우지 못하게하기위한 것입니다.
저렴하고 일부 사용자에게는 말하지 않아도 이미 Google 및 Facebook과 같은 장소에서 이미 로그인 한 상태를 확인하려고하기 때문에 더러워 질 수 있습니다. 그러나 사이트 자동 로그인을 요청하지 않은 사용자에게는 사용해서는 안되며이 특정 방법은 Google+ 또는 FB와 같은 외부 인증에만 사용됩니다.
외부 인증자가 사용자의 유효성을 검사했는지 여부를 서버 뒤에 알려주기 때문에 공격자는 고유 한 ID 이외의 다른 정보를 얻을 수 없습니다. 내가 자세히 설명하겠습니다.
- 사용자 ‘joe’가 처음으로 사이트를 방문하고 쿠키 ‘session’에 세션 ID가 배치되었습니다.
- 사용자 ‘joe’로그인하여 권한을 에스컬레이션하고 새 세션 ID를 가져오고 쿠키 ‘세션’을 갱신합니다.
- 사용자 ‘joe’는 Google+를 사용하여 자동 로그인하도록 선택하고 쿠키 ‘keepmesignedin’에 고유 ID를 가져옵니다.
- 사용자 ‘joe’는 Google에 로그인 상태를 유지하므로 백엔드에서 Google을 사용하여 사이트에서 사용자를 자동 로그인 할 수 있습니다.
- 공격자는 체계적으로 ‘keepmesignedin’에 대한 고유 ID를 시도하며 (모든 사용자에게 공개 된 지식) 다른 곳에서는 로그인하지 않습니다. ‘joe’에게 부여 된 고유 ID를 시도합니다.
- 서버는 ‘joe’에 대한 고유 ID를 받고 Google+ 계정에 대해 DB에서 일치 항목을 가져옵니다.
- 서버는 AJAX 요청을 실행하는 로그인 페이지로 공격자를 Google에 로그인하여 보냅니다.
- Google 서버는 요청을 받고 API를 사용하여 공격자가 현재 로그인하지 않은 것을 확인합니다.
- Google은이 연결을 통해 현재 로그인 한 사용자가 없다는 응답을 보냅니다.
- 공격자의 페이지가 응답을 받으면 스크립트가 URL에 인코딩 된 POST 값을 사용하여 로그인 페이지로 자동 리디렉션합니다.
- 로그인 페이지는 POST 값을 가져 와서 ‘keepmesignedin’쿠키를 빈 값으로 전송하고 날짜 1-1-1970까지 유효하여 자동 시도를 막아 공격자의 브라우저가 쿠키를 간단히 삭제하도록합니다.
- 공격자에게는 일반적인 최초 로그인 페이지가 제공됩니다.
공격자가 존재하지 않는 ID를 사용하더라도 검증 된 응답을받는 경우를 제외하고 모든 시도에서 시도가 실패합니다.
이 방법은 외부 인증자를 사용하여 사이트에 로그인하는 사람들을 위해 내부 인증 자와 함께 사용할 수 있으며 사용해야합니다.
=========
사용자를 자동 로그인 할 수있는 인증 시스템의 경우 다음과 같습니다.
DB에는 몇 가지 테이블이 있습니다.
TABLE users:
UID - auto increment, PK
username - varchar(255), unique, indexed, NOT NULL
password_hash - varchar(255), NOT NULL
...
사용자 이름의 길이는 255 자입니다. 내 서버 프로그램에서 시스템의 사용자 이름을 32 자로 제한하지만 외부 인증자는 @ domain.tld의 사용자 이름이 그보다 클 수 있으므로 최대 호환성을 위해 전자 메일 주소의 최대 길이 만 지원합니다.
TABLE sessions:
session_id - varchar(?), PK
session_token - varchar(?), NOT NULL
session_data - MediumText, NOT NULL
로그인 할 때 사용자 이름이 세션 데이터에 있고 프로그램이 널 데이터를 허용하지 않기 때문에이 테이블에는 사용자 필드가 없습니다. session_id 및 session_token은 임의의 md5 해시, sha1 / 128 / 256 해시, 임의의 문자열이 추가 된 날짜 시간 스탬프 또는 해시 또는 원하는 것을 사용하여 생성 할 수 있지만 출력의 엔트로피는 허용 가능한 한 높게 유지되어야합니다 무차별 대입 공격을 완전히 차단하여 세션 클래스에서 생성 된 모든 해시를 추가하기 전에 세션 테이블에서 일치하는지 확인해야합니다.
TABLE autologin:
UID - auto increment, PK
username - varchar(255), NOT NULL, allow duplicates
hostname - varchar(255), NOT NULL, allow duplicates
mac_address - char(23), NOT NULL, unique
token - varchar(?), NOT NULL, allow duplicates
expires - datetime code
MAC 주소는 본질적으로 고유해야하므로 각 항목마다 고유 한 값이 있습니다. 반면에 호스트 이름은 별도의 네트워크에서 합법적으로 복제 될 수 있습니다. “Home-PC”를 컴퓨터 이름 중 하나로 사용하는 사람은 몇 명입니까? 사용자 이름은 서버 백엔드에 의해 세션 데이터에서 가져 오므로 조작 할 수 없습니다. 토큰의 경우, 페이지의 세션 토큰을 생성하는 동일한 방법을 사용하여 사용자 자동 로그인을위한 쿠키로 토큰을 생성해야합니다. 마지막으로 날짜 시간 코드는 사용자가 자격 증명을 다시 확인해야 할 때 추가됩니다. 며칠 내에 사용자 로그인을 유지하면서이 날짜 / 시간을 업데이트하거나, 마지막 로그인에 관계없이 한 달 정도만 유지하도록 (디자인에 따라) 만료되도록 강제하십시오.
이를 통해 누군가 자동 로그인 한 사용자의 MAC 및 호스트 이름을 체계적으로 스푸핑하지 못하게됩니다. NEVER사용자가 비밀번호, 일반 텍스트 또는 기타 방식으로 쿠키를 유지하도록합니다. 세션 토큰과 마찬가지로 각 페이지 탐색에서 토큰을 재생성하십시오. 이는 공격자가 유효한 토큰 쿠키를 얻어이를 사용하여 로그인 할 가능성을 크게 줄입니다. 어떤 사람들은 공격자가 피해자로부터 쿠키를 훔치고 로그인을 위해 세션 재생 공격을 할 수 있다고 말합니다. 공격자가 쿠키를 훔칠 수 있다면 (가능한 경우), 전체 장치를 손상했을 수 있습니다. 즉, 장치를 사용하여 로그인 만하면 쿠키를 완전히 훔치려는 목적을 상실 할 수 있습니다. 사이트가 HTTPS (비밀번호, CC 번호 또는 기타 로그인 시스템을 처리 할 때)를 통해 실행되는 경우 브라우저 내에서 가능한 모든 사용자를 보호 할 수 있습니다.
명심해야 할 사항 : 자동 로그인을 사용하는 경우 세션 데이터가 만료되지 않아야합니다. 세션을 거짓으로 계속하는 기능을 만료 할 수 있지만 시스템간에 유효성 검사를 수행하면 세션간에 계속 지속될 것으로 예상되는 영구 데이터 인 경우 세션 데이터를 다시 시작해야합니다. 영구 및 비 영구 세션 데이터를 모두 원한다면 사용자 이름을 PK로 사용하여 영구 세션 데이터에 다른 테이블을 사용하고 서버에서 일반 세션 데이터처럼 검색하도록 다른 변수를 사용하십시오.
이러한 방식으로 로그인이 이루어지면 서버는 여전히 세션의 유효성을 검사해야합니다. 여기에서 도난 당하거나 손상된 시스템에 대한 기대치를 코딩 할 수 있습니다. 세션 데이터 로그인 패턴 및 기타 예상 결과는 종종 액세스하기 위해 시스템이 하이재킹되었거나 쿠키가 위조되었다는 결론을 초래할 수 있습니다. 여기에서 ISS Tech는 자동 로그인 시스템에서 사용자의 계정 잠금 또는 자동 제거를 트리거하는 규칙을 설정하여 공격자가 사용자의 공격 방식 및 차단 방법을 결정할 수있을 정도로 오랫동안 사용자를 차단합니다.
마지막으로, 임계 값을 초과 한 복구 시도, 비밀번호 변경 또는 로그인 실패로 인해 사용자가 올바르게 유효성 검증하고이를 확인한 후에 자동 로그인이 사용 불가능하게됩니다.
내 대답에 코드가 제공 될 것으로 예상되는 사람에게는 사과드립니다. 여기서는 그런 일이 일어나지 않을 것입니다. 필자는 PHP, jQuery 및 AJAX를 사용하여 사이트를 운영하고 Windows를 서버로 사용하지 않는다고 말할 것입니다.
답변
Stefan이 언급 한 접근 방식을 권장하고 (즉, Enhanced Persistent Login Cookie Best Practice 의 지침을 따르십시오 ) 쿠키가 HttpOnly 쿠키 인지 확인하여 잠재적으로 악의적 인 JavaScript에 액세스 할 수 없도록 하는 것이 좋습니다 .
답변
알고있는 비밀만으로 해시를 생성 한 다음 사용자와 연결할 수 있도록 DB에 저장하십시오. 잘 작동합니다.