PHP 세션 수정 / 하이재킹


145

PHP 세션 수정 및 하이재킹과 이러한 문제를 방지하는 방법에 대해 더 많이 이해하려고합니다 . Chris Shiflett 웹 사이트에서 다음 두 기사를 읽었습니다.

그러나 제대로 이해하고 있는지 잘 모르겠습니다.

세션 수정을 방지하려면 session_regenerate_id (true)를 호출하는 것으로 충분합니다. 누군가를 성공적으로 로그인 한 후? 나는 그것을 올바르게 이해한다고 생각합니다.

또한 세션 하이재킹을 방지하기 위해 $ _GET을 통해 URL로 전달 된 토큰을 사용하는 방법에 대해서도 설명합니다. 이것이 정확히 어떻게 이루어 집니까? 누군가 로그인하면 토큰을 생성하고 세션 변수에 저장 한 다음 각 페이지에서 해당 세션 변수를 $ _GET 변수의 값과 비교할 것 같아요?

이 토큰은 세션 당 또는 페이지로드마다 한 번만 변경해야합니까?

또한 URL에 값을 전달하지 않고 도용을 방지하는 좋은 방법입니까? 이것은 훨씬 쉬울 것입니다.


이러한 권장 사항을 찾은 페이지에 링크를 추가 할 수 있습니다.
Gumbo

답변:


219

좋아, 별개의 두 가지 관련 문제가 있으며 각각 다르게 처리됩니다.

세션 고정

공격자가 사용자 세션의 세션 식별자를 명시 적으로 설정하는 곳입니다. 일반적으로 PHP에서는 URL과 같은 URL을 제공하여 수행됩니다 http://www.example.com/index...?session_name=sessionid. 공격자가 클라이언트에 URL을 제공하면 세션 하이재킹 공격과 동일합니다.

세션 고정을 방지하는 몇 가지 방법이 있습니다 (모두 수행).

  • 파일 session.use_trans_sid = 0에서 설정 php.ini하십시오. 이것은 PHP에게 URL에 식별자를 포함하지 말고 식별자에 대한 URL을 읽지 말라고 지시합니다.

  • 파일 session.use_only_cookies = 1에서 설정 php.ini하십시오. 이것은 세션 식별자와 함께 URL을 사용하지 않도록 PHP에 지시합니다.

  • 세션 상태가 변경 될 때마다 세션 ID를 재생성하십시오. 이는 다음 중 하나를 의미합니다.

    • 사용자 인증
    • 세션에 민감한 정보 저장
    • 세션에 대한 변경
    • 기타...

세션 도용

공격자가 세션 식별자를 보유하고 해당 사용자 인 것처럼 요청을 보낼 수 있습니다. 이는 공격자가 식별자를 가지고 있기 때문에 서버와 관련하여 유효한 사용자와 구분할 수는 없습니다.

세션 하이재킹을 직접 방지 할 수는 없습니다. 그러나 사용하기 매우 어렵고 어렵게하기위한 단계를 수행 할 수 있습니다.

  • 강력한 세션 해시 식별자를 사용 session.hash_function에서 php.ini. PHP <5.3 인 경우 session.hash_function = 1SHA1 에 대해 설정하십시오 . PHP> = 5.3 인 경우 session.hash_function = sha256또는로 설정하십시오 session.hash_function = sha512.

  • 강력한 해시 보내기 session.hash_bits_per_character에서 php.ini. 이것을로 설정하십시오 session.hash_bits_per_character = 5. 이것은 크랙 하기 어렵지 않지만 공격자가 세션 식별자를 추측하려고 할 때 차이를 만듭니다. ID는 짧지 만 더 많은 문자를 사용합니다.

  • 함께 추가 엔트로피를 설정 session.entropy_file하고 session.entropy_length당신의 php.ini파일. 전자를 session.entropy_file = /dev/urandom엔트로피 파일에서 읽을 바이트 수로 설정합니다 session.entropy_length = 256.

  • 기본 PHPSESSID에서 세션 이름을 변경하십시오. 이는 호출 session_name()하기 전에 첫 번째 매개 변수로 고유 한 식별자 이름으로 호출 하여 수행됩니다 session_start.

  • 당신이 경우 정말 너무 세션 이름을 회전하지만 (당신은 시간에 의존 할 경우, 예를 들어)이을 변경하면 모든 세션이 자동으로 무효화 될 것으로 조심 수 편집증. 그러나 사용 사례에 따라 옵션 일 수 있습니다 ...

  • 세션 식별자를 자주 회전하십시오. 모든 요청 ( 이러한 수준의 보안 이 실제로 필요한 경우가 아니라면 )을 수행하지는 않지만 임의의 간격으로 수행합니다. 공격자가 세션을 가로 채면 너무 오랫동안 세션을 사용할 수 없기 때문에 자주 변경하려고합니다.

  • 세션에 사용자 에이전트를$_SERVER['HTTP_USER_AGENT'] 포함시킵니다 . 기본적으로 세션이 시작되면 다음과 같은 곳에 저장하십시오 $_SESSION['user_agent']. 그런 다음 각 후속 요청에서 일치하는지 확인하십시오. 이것은 가짜 일 수 있으므로 100 % 신뢰할 수는 없지만 그렇지 않은 것이 좋습니다.

  • 세션 에서 사용자의 IP 주소를$_SERVER['REMOTE_ADDR'] 포함하십시오 . 기본적으로 세션이 시작되면 다음과 같은 곳에 저장하십시오 $_SESSION['remote_ip']. 사용자에 대해 여러 IP 주소를 사용하는 일부 ISP (예 : AOL에 사용 된)에서 문제가 될 수 있습니다. 그러나 사용하면 훨씬 더 안전합니다. 공격자가 IP 주소를 위조하는 유일한 방법은 실제 사용자와 사용자 사이의 어느 시점에서 네트워크를 손상시키는 것입니다. 또한 네트워크를 손상 시키면 하이재킹 (MITM 공격 등)보다 훨씬 나빠질 수 있습니다.

  • 자주 증가하고 비교하는 세션 및 브라우저 측에 토큰을 포함하십시오. 기본적으로 각 요청 $_SESSION['counter']++에 대해 서버 측에서 수행하십시오. 또한 브라우저 측의 JS에서 동일한 작업을 수행하기 위해 로컬 저장소를 사용하여 무언가를하십시오. 그런 다음 요청을 보낼 때 간단히 토큰을 가져 와서 서버에서 nonce가 동일한 지 확인하십시오. 이렇게하면 공격자가 정확한 카운터를 가지지 못하기 때문에 하이재킹 된 세션을 감지 할 수 있어야합니다. 그렇지 않은 경우 2 개의 시스템이 동일한 수를 전송하고 하나의 시스템이 위조되었음을 알 수 있습니다. 모든 응용 프로그램에서 작동하지는 않지만 문제를 해결하는 한 가지 방법입니다.

둘에 대한 메모

세션 고정과 하이재킹의 차이점은 세션 식별자가 어떻게 손상되는지에 대한 것입니다. 수정시 식별자는 공격자가 미리 알고있는 값으로 설정됩니다. 하이재킹에서는 사용자가 추측하거나 도난당했습니다. 그렇지 않으면 식별자가 손상되면 두 가지의 효과는 동일합니다.

세션 ID 재생성

session_regenerate_id이전 세션을 사용하여 세션 식별자를 재생성 할 때마다 삭제해야합니다. 이것은 코어 세션 핸들러에서 투명하게 발생합니다. 그러나 일부 사용자 지정 세션 처리기session_set_save_handler() 는이 작업 수행하지 않으며 이전 세션 식별자를 공격 할 수 있습니다. 사용자 정의 세션 핸들러를 사용중인 경우, 열린 식별자를 추적하고, 저장 한 식별자와 동일하지 않은 경우 이전 식별자를 명시 적으로 삭제 (또는 변경) 한 것을 확인하십시오.

기본 세션 처리기를 사용하면을 호출하면 session_regenerate_id(true)됩니다. 이전 세션 정보가 제거됩니다. 이전 ID는 더 이상 유효하지 않으며 공격자 (또는 그 문제에 대한 다른 사람)가이를 사용하려고하면 새 세션이 생성됩니다. 그래도 사용자 정의 세션 처리기에주의하십시오 ....

세션 파괴

로그 아웃 등의 세션을 파괴하려는 경우 세션을 철저히 파괴해야합니다. 쿠키 설정 해제가 포함됩니다. 사용 session_destroy:

function destroySession() {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
    session_destroy();
}

4
문자 당 4 비트 대신 5를 사용해도 "강도"는 변경되지 않습니다 (이 경우 "강도"가 무엇이든 상관 없음). 그러나 요점은 일반적으로 권장되지만 중요한 세부 정보가 부족합니다. 예를 들어 이전 세션 ID와 연관된 세션에서 발생하는 상황 또는 이전 세션 ID를 가진 세션이 유효하지 않은 후에 처리되는 방법.
Gumbo

2
@ battal : 아니요, 그게 요점입니다. session_regenerate_id여전히 이전 ID와 연관된 세션을 무효화하지 않습니다. delete_old_session 매개 변수가 true로 설정된 경우에만 세션이 삭제됩니다. 그러나 침입자가이 ID 재생성을 시작하면 어떻게됩니까?
Gumbo

6
세션 변수를 변경할 때마다 세션 재생성에 동의하지 않으며 로그인 / 로그 아웃시에만 수행해야합니다. 또한 사용자 에이전트를 검사하는 것은 의미가 없으며 REMOTE_ADDR을 검사하는 것은 문제가 있습니다. 내가 추가하고 싶은 한 가지는입니다 session.entropy_file = /dev/urandom. PHP의 내부 엔트로피 생성은 매우 약한 것으로 입증되었으며 / dev / random 또는 / dev / uranom에서 제공하는 엔트로피 풀은 하드웨어 rng없이 웹 서버에서 얻을 수있는 최선입니다.
rook

4
또한 당신은 추가해야 session.cookie_httponly하고 session.cookie_secure. 첫 번째는 xss를 막는 데 도움이되지만 완벽하지는 않습니다. 두 번째는 OWASP A9를 막는 가장 좋은 방법입니다.
rook

4
그러한 훌륭한 대답을 이해하지 못하지만 가장 중요한 부분은 누락하십시오 : SSL / HTTPS를 사용하십시오. 카운터 증가는 여러 요청이 서로 빠르게 발생하는 문제의 원인입니다. 사용자가 페이지를 두 번 새로 고치거나 제출 버튼을 두 번 누르십시오. IP 주소 솔루션은 요즘 모든 모바일 사용자에게있어 항상 문제가되고 있습니다. 첫 번째 IP 세트를 볼 수는 있지만 여전히 문제가 있습니다. 가장 먼저 세션 ID를 발견하지 못하게하고 SSL / HTTPS를 사용하고 있습니다.
Sanne

37

두 세션 공격의 목표는 동일합니다. 다른 사용자의 합법적 인 세션에 액세스하십시오. 그러나 공격 벡터는 다릅니다.

  • A의 세션 고정의 공격 , 공격자는 이미 유효한 세션에 대한 액세스 권한을 가지고 있으며,이 특정 세션을 사용하는 피해자를 강제로 시도합니다.

  • A의 세션 하이재킹 공격 , 공격자는 그 / 그녀의 세션을 사용하여 피해자의 세션의 ID를 얻기 위해 시도합니다.

두 가지 공격 모두에서 세션 ID는 이러한 공격에 초점을 둔 민감한 데이터입니다. 따라서 읽기 액세스 (Session Hijacking)와 쓰기 액세스 (Session Fixation) 모두에 대해 보호되어야하는 세션 ID입니다.

이 경우 HTTPS를 사용하여 중요한 데이터를 보호하는 일반적인 규칙도 적용됩니다. 또한 다음을 수행해야합니다.

세션 수정 공격 을 방지하려면 다음 을 확인하십시오.

세션 하이재킹 공격 을 방지하려면 다음 을 확인하십시오.

세션 공격 을 방지하려면 다음 을 확인하십시오.

  • 응용 프로그램이 시작한 세션 만 수락합니다. 클라이언트 특정 정보로 시작시 세션을 지문으로 표시하여이를 수행 할 수 있습니다. User-Agent ID 는 사용할 수 있지만 원격 IP 주소 나 요청간에 변경 될 수있는 다른 정보는 사용하지 마십시오.
  • session_regenerate_id(true)인증 시도 후 ( true성공한 경우에만) 또는 권한 변경 후 사용하여 세션 ID를 변경하고 이전 세션을 삭제합니다. ( 이전 ID와 연관된 세션을 유지하려면 ID 재생성 하기 전에$_SESSION 사용 변경 사항을 저장하십시오 . 그렇지 않으면 새 ID를 가진 세션 만 해당 변경 사항의 영향을받습니다.)session_write_close
  • 올바른 세션 만료 구현을 사용하려면 ( 30 분 후에 PHP 세션을 만료 하려면 어떻게합니까? 참조 )

멋진 게시물, 특히 마지막 섹션.
Mattis

6

언급 한 토큰은 "nonce"-한 번 사용 된 숫자입니다. 반드시 한 번만 사용해야하는 것은 아니지만 사용 시간이 길수록 nonce를 캡처하여 세션을 가로 챌 수있는 가능성이 높아집니다.

nonces의 또 다른 단점은 그것들을 사용하고 동일한 형태로 여러 개의 병렬 창을 허용하는 시스템을 구축하는 것이 매우 어렵다는 것입니다. 예를 들어, 사용자는 포럼에서 두 개의 창을 열고 두 개의 게시물에서 작업을 시작합니다.

window 'A' loads first and gets nonce 'P'
window 'B' loads second and gets nonce 'Q'

여러 개의 창을 추적 할 방법이 없으면 창 B / Q에 대한 하나의 nonce 만 저장합니다. 그런 다음 사용자가 창 A에서 게시물을 제출하고 nonce 'P'를 전달하면 시스템은 게시물을로 거부합니다 P != Q.


세션 고정과는 어떤 관계가 있습니까?
rook

2
그는 많은 AJAX 요청을 동시에 사용하는 영역에서 특히 타당합니다.
DanielG

2

나는 Shiflett의 기사를 읽지 않았지만 당신이 무언가를 잘못 이해했다고 생각합니다.

기본적으로 PHP는 클라이언트가 쿠키를 허용하지 않을 때마다 URL에서 세션 토큰을 전달합니다. 가장 일반적인 경우 세션 토큰은 쿠키로 저장됩니다.

이것은 당신이 URL에 세션 토큰을 넣으면 PHP가 그것을 인식하고 그 이후에 사용하려고 시도한다는 것을 의미합니다. 세션 고정은 누군가 세션을 만든 다음 세션 토큰이 포함 된 URL을 열어 다른 사용자가 동일한 세션을 공유하도록 속일 때 발생합니다. 사용자가 어떤 방식으로 인증하면 악의적 인 사용자가 다른 권한을 가진 인증 된 세션 토큰을 알게됩니다.

Shiflett이 설명하는 것처럼 일반적인 방법은 사용자의 권한이 변경 될 때마다 다른 토큰을 재생성하는 것입니다.


여기에 추가하려면 기존에 열린 세션이 기존 사용자 권한으로 계속 유효하므로 이전에 열린 세션을 모두 삭제하십시오.
corrodedmonkee

0

예, 로그인시 세션 ID를 한 번 재생성하여 세션 수정을 방지 할 수 있습니다. 공격자가 새로 인증 된 세션의 쿠키 값을 알 수없는 경우이 방법입니다. 문제를 완전히 막는 또 다른 접근 방식은 session.use_only_cookies=True런타임 구성에서 설정됩니다. 공격자는 다른 도메인의 컨텍스트에서 쿠키 값을 설정할 수 없습니다. 세션 수정은 쿠키 값을 GET 또는 POST로 전송하는 데 의존합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.