세션 하이재킹을 방지하는 가장 좋은 방법은 무엇입니까?


124

특히 이것은 클라이언트 세션 쿠키를 사용하여 서버에서 세션을 식별 할 때 관련됩니다.

전체 웹 사이트에 SSL / HTTPS 암호화를 사용하는 가장 좋은 답변이며 중간 공격이 기존 클라이언트 세션 쿠키를 스니핑 할 수 없다는 것을 가장 잘 보장 할 수 있습니까?

그리고 세션 쿠키에 저장된 세션 값 자체에 일종의 암호화를 사용하는 것이 두 번째로 좋은 방법일까요?

악의적 인 사용자가 시스템에 물리적으로 액세스 할 수있는 경우에도 파일 시스템을 조사하여 유효한 세션 쿠키를 검색하고이를 사용하여 세션을 탈취 할 수 있습니까?

답변:


140

세션 값을 암호화하면 효과가 없습니다. 세션 쿠키는 이미 임의의 값이므로 암호화하면 스니핑 될 수있는 다른 임의 값이 생성됩니다.

유일한 실제 솔루션은 HTTPS입니다. 전체 사이트에서 SSL을 수행하고 싶지 않다면 (성능 문제가있을 수 있음) 민감한 영역을 보호하는 SSL만으로 벗어날 수 있습니다. 그렇게하려면 먼저 로그인 페이지가 HTTPS인지 확인하십시오. 사용자가 로그인 할 때 일반 세션 쿠키 외에 보안 쿠키 (브라우저가 SSL 링크를 통해서만 전송 함)를 설정합니다. 그런 다음 사용자가 "민감한"영역 중 하나를 방문하면 HTTPS로 리디렉션하고 보안 쿠키가 있는지 확인합니다. 실제 사용자는이를 갖고 세션 하이재커는 그렇지 않습니다.

편집 :이 답변은 원래 2008 년에 작성되었습니다. 현재 2016 년이며 전체 사이트에 SSL을 사용하지 않을 이유가 없습니다. 더 이상 일반 텍스트 HTTP가 아닙니다!


28
HTTPS는 스니핑 만 방지합니다. 그러나 XSS가 있거나 세션 ID를 쉽게 추측 할 수 있거나 세션 고정에 취약하거나 세션 ID 스토리지가 약한 경우 (SQL 주입?) SSL은 전혀 개선되지 않습니다.
Calimo

5
@Josh 악의적 인 사용자가 시스템에 물리적으로 액세스 할 수있는 경우에도 파일 시스템을 조사하여 유효한 세션 쿠키를 검색하고이를 사용하여 세션을 탈취 할 수 있습니까?
Pacerier 2012-06-14

72
악의적 인 사용자가 파일 시스템에 물리적으로 액세스 할 수있는 경우 세션을 탈취 할 필요가 없습니다.
조쉬 Hinman

25
@조롱. 사실이 아닙니다. 때로는 사용자가 파일 시스템에 제한된 시간 동안 물리적으로 액세스 할 수 있습니다. 동료가 화장실로 달려가는 노트북을 잠금 해제 한 상태로 두었다고 가정 해 보겠습니다. 이제 노트북으로 이동하여 EditThisCookie 플러그인을 설치하고, EditThisCookie 내보내기 기능을 사용하여 plus.google.com에서 쿠키를 가져 오면 이제 그의 계정이 생겼 습니다 . 소요 시간 : 18 초.
Pacerier

1
나는 구글이 빌드에서이 분명히 당신은 세션 하이재킹에 대해 이야기 할 때의 생각 첫 번째 일이 같은 보안 기능의 어떤 것 확신
xorinzor

42

SSL은 스니핑 공격에만 도움이됩니다. 공격자가 귀하의 컴퓨터에 액세스 할 수있는 경우 귀하의 보안 쿠키도 복사 할 수 있다고 가정합니다.

최소한 오래된 쿠키가 잠시 후에 가치를 잃도록하십시오. 쿠키가 작동을 멈 추면 성공적인 hijaking 공격도 차단됩니다. 사용자가 한 달 이상 전에 로그인 한 세션의 쿠키가있는 경우 비밀번호를 다시 입력하도록합니다. 사용자가 사이트의 "로그 아웃"링크를 클릭 할 때마다 이전 세션 UUID를 다시 사용할 수 없도록하십시오.

이 아이디어가 효과가 있는지 확실하지 않지만 여기에 있습니다. 세션 쿠키에 일련 번호를 추가합니다. 아마도 다음과 같은 문자열 일 수 있습니다.

SessionUUID, 일련 번호, 현재 날짜 / 시간

이 문자열을 암호화하고 세션 쿠키로 사용하십시오. 일련 번호를 정기적으로 변경하십시오. 쿠키가 5 분 정도 지난 후 쿠키를 재발행하십시오. 원하는 경우 모든 페이지보기에서 재발행 할 수도 있습니다. 서버 측에서 해당 세션에 대해 발행 한 마지막 일련 번호를 기록해 둡니다. 누군가가 잘못된 일련 번호로 쿠키를 보낸 경우 공격자가 이전에 가로 챈 쿠키를 사용하고있을 수 있으므로 세션 UUID를 무효화하고 사용자에게 암호를 다시 입력 한 다음 새 쿠키를 다시 발급하도록 요청합니다.

사용자는 둘 이상의 컴퓨터를 가질 수 있으므로 둘 이상의 활성 세션을 가질 수 있습니다. 컴퓨터 사이를 전환 할 때마다 다시 로그인하도록 강요하는 작업을하지 마십시오.


나는 이것이 오래된 게시물이라는 것을 알고 있지만 공격자가 "일련 번호"에 의해 할당 된 창 내에서 세션을 가로채는 경우 그에게 영향을 미치지 않는다는 것을 포함하고 싶었습니다.
crush

@crush이지만 할당 된 창 이후에 공격자가 잠길 것입니다. 따라서 최소한 공격 창은 작습니다.
Johanneke 2013-07-11

2
유일한 문제는 사용자가 5 분 동안 당신의 웹 사이트를 떠나면, 그들은 다시 로그인해야합니다입니다
elipoultorak

21

PHP 보안에 관한 책을 읽어 보셨나요? 추천.

비 SSL 인증 사이트에 대해 다음 방법으로 많은 성공을 거두었습니다.

  1. 동일한 계정에서 여러 세션을 허용하지 않고 IP 주소로만 확인하지 않도록합니다. 오히려 데이터베이스에 사용자 세션과 함께 저장되는 로그인시 생성 된 토큰과 IP 주소, HTTP_USER_AGENT 등으로 확인합니다.

  2. 관계 기반 하이퍼 링크 사용 링크 생성 (예 : http://example.com/secure.php?token=2349df98sdf98a9asdf8fas98df8 ) 링크는 페이지 리디렉션시 임의로 생성 된 x-BYTE (기본 크기) 임의 솔트 MD5 문자열과 함께 추가됩니다. 토큰은 요청 된 페이지에 해당합니다.

    • 다시로드하면 몇 가지 검사가 수행됩니다.
    • 원래 IP 주소
    • HTTP_USER_AGENT
    • 세션 토큰
    • 당신은 요점을 얻습니다.
  3. 짧은 수명 세션 인증 쿠키. 위에 게시 된 것처럼 세션 유효성에 대한 직접적인 참조 중 하나 인 보안 문자열을 포함하는 쿠키는 좋은 생각입니다. x 분마다 만료되도록 만들고 해당 토큰을 다시 발급하고 세션을 새 데이터와 다시 동기화합니다. 데이터가 일치하지 않는 경우 사용자를 로그 아웃하거나 세션을 다시 인증하도록합니다.

저는이 주제에 대한 전문가가 아닙니다. 저는이 특정 주제에 대해 약간의 경험을 가지고 있습니다.이 중 일부가 누구에게나 도움이되기를 바랍니다.


4
추천하고 싶은 책이 있습니까?
Rikki

1
특히 OP가 PHP에 대해 구체적으로 언급하지 않았다는 점을 감안할 때 일반 보안 책만 보는 것이 좋습니다 (특히 다른 언어 간의 보안은 구현 세부 사항 만 다르지만 개념은 동일하게 유지됨).
matts1 2014 년

2017 년에는 facebook / gmail 등도 사용자를 싫어하지 않는 한 동일한 계정 (특히 모바일 장치)으로 여러 세션을 허용합니다. # 1은 약간 구식입니다.
cowbert

20
// Collect this information on every request
$aip = $_SERVER['REMOTE_ADDR'];
$bip = $_SERVER['HTTP_X_FORWARDED_FOR'];
$agent = $_SERVER['HTTP_USER_AGENT'];
session_start();

// Do this each time the user successfully logs in.
$_SESSION['ident'] = hash("sha256", $aip . $bip . $agent);

// Do this every time the client makes a request to the server, after authenticating
$ident = hash("sha256", $aip . $bip . $agent);
if ($ident != $_SESSION['ident'])
{
    end_session();
    header("Location: login.php");
    // add some fancy pants GET/POST var headers for login.php, that lets you
    // know in the login page to notify the user of why they're being challenged
    // for login again, etc.
}

이것이하는 일은 사용자 세션에 대한 '문맥 적'정보, 단일 세션의 수명 동안 변경되지 않아야하는 정보를 캡처하는 것입니다. 사용자는 미국과 중국의 컴퓨터에 동시에 있지 않을 것입니다. 그렇죠? 따라서 세션 하이재킹 시도를 강하게 암시하는 동일한 세션 내에서 IP 주소가 갑자기 변경되면 세션을 종료하고 사용자가 다시 인증하도록하여 세션을 보호합니다. 이것은 해킹 시도를 방해하고 공격자는 세션에 대한 액세스 권한을 얻는 대신 강제로 로그인해야합니다. 사용자에게 시도를 알리고 (약간 ajax), vola, 약간 짜증이 나고 정보를 알고있는 사용자 및 세션 / 정보가 보호됩니다.

우리는 프록시 / 네트워크 뒤에있는 시스템에 대한 세션의 고유성을 캡처하기 위해 최선을 다하기 위해 User Agent 및 X-FORWARDED-FOR를 사용합니다. 그런 다음 더 많은 정보를 사용할 수있을 것입니다. 자유롭게 창의력을 발휘하십시오.

100 %는 아니지만 꽤 효과적입니다.

세션을 보호하고, 세션을 만료시키기 위해 할 수있는 일이 더 많습니다. 빈 HTTP_REFERER (도메인이 URL 표시 줄에 입력 됨)를 캡처하여 이탈하고 돌아 오는 사용자를 감지하거나 HTTP_REFERER의 값이 귀하의 도메인과 일치하는지 (사용자가 외부 / 제작 된 링크를 클릭하여 귀하의 대지).

세션을 만료하고 무기한 유효하게 유지하지 마십시오.

쿠키에 의존하지 마십시오. 쿠키는 도난 당할 수 있으며 세션 하이재킹을위한 공격 벡터 중 하나입니다.


3
특정 (상당히 크지 만 기술적으로는 역방향) ISP가 사용자의 연결 경로를 다시 지정하여 사용자 브라우저의 IP를 수시로 변경하는 상황에 직면했습니다. 이로 인해 REMOTE_ADDR 검사가 우리에게 거짓 부정을 반환했습니다.
goofballLogic 2015-08-20

왜 해시를 생성해야합니까? $_SESSION['ident'] = $aip . $bip . $agent;안전합니다.
Dan Bray

2
이동 중에 웹 사이트를 사용하고 한 액세스 포인트에서 다른 액세스 포인트로 이동하는 모바일 사용자가있는 경우 해당 IP는 계속 변경되고 계정에서 계속 로그 아웃됩니다.
Kareem

프록시와 VPN은 어떻습니까? TOR 프록시를 사용하는 사람은 실제로 몇 분마다 계정에서 지속적으로 로그 아웃됩니다.
Bradley

간과하더라도 IP 주소는 클라이언트에 의해 조작 될 수 있으므로 어쨌든 공격자를 설득하는 데 큰 도움이되지 않습니다.
Bradley

9

설명 안전한 쿠키 프로토콜보십시오 Liu, Kovacs, Huang 및 Gouda 백서 .

문서에 명시된대로 :

클라이언트와 서버간에 실행되는 보안 쿠키 프로토콜은 인증, 기밀성, 무결성 및 재생 방지라는 네 가지 서비스를 제공해야합니다.

배포의 용이성 :

효율성 측면에서 우리의 프로토콜은 데이터베이스 조회 또는 공개 키 암호화를 포함하지 않습니다. 배포 가능성 측면에서 당사의 프로토콜은 기존 웹 서버에 쉽게 배포 할 수 있으며 인터넷 쿠키 사양을 변경할 필요가 없습니다.

간단히 말해서 안전하고 가벼우 며 저에게 아주 좋습니다.


9
귀하의 링크는 프로토콜의 사양입니다. 구현에 대한 링크가 있습니까? 그것은 좋을 것입니다-감사합니다.
Adam

9

세션 hijaking을 100 % 방지 할 수있는 방법은 없지만 몇 가지 접근 방식을 사용하면 공격자가 세션을 hijaking하는 시간을 줄일 수 있습니다.

세션 hijaking 방지 방법 :

1-항상 SSL 인증서로 세션을 사용합니다.

2-httponly가 true로 설정된 경우에만 세션 쿠키 보내기 (JavaScript가 세션 쿠키에 액세스하지 못하도록 방지)

2-로그인 및 로그 아웃시 세션 재생성 ID 사용 (참고 : 연속적인 ajax 요청이있는 경우 여러 세션을 생성 할 수 있기 때문에 각 요청에서 세션 재생성을 사용하지 마십시오.)

3-세션 시간 제한 설정

4-브라우저 사용자 에이전트를 $ _SESSION 변수에 저장하고 각 요청에서 $ _SERVER [ 'HTTP_USER_AGENT']와 비교합니다.

5-토큰 쿠키를 설정하고 해당 쿠키의 만료 시간을 0으로 설정합니다 (브라우저가 닫힐 때까지). 각 요청에 대해 쿠키 값을 다시 생성합니다 (Ajax 요청의 경우 토큰 쿠키를 다시 생성하지 마십시오). 전의:

    //set a token cookie if one not exist
    if(!isset($_COOKIE['user_token'])){
                    //generate a random string for cookie value
        $cookie_token = bin2hex(mcrypt_create_iv('16' , MCRYPT_DEV_URANDOM));

        //set a session variable with that random string
        $_SESSION['user_token'] = $cookie_token;
        //set cookie with rand value
        setcookie('user_token', $cookie_token , 0 , '/' , 'donategame.com' , true , true);
    }

    //set a sesison variable with request of www.example.com
    if(!isset($_SESSION['request'])){
        $_SESSION['request'] = -1;
    }
    //increment $_SESSION['request'] with 1 for each request at www.example.com
    $_SESSION['request']++;

    //verify if $_SESSION['user_token'] it's equal with $_COOKIE['user_token'] only for $_SESSION['request'] > 0
    if($_SESSION['request'] > 0){

        // if it's equal then regenerete value of token cookie if not then destroy_session
        if($_SESSION['user_token'] === $_COOKIE['user_token']){
            $cookie_token = bin2hex(mcrypt_create_iv('16' , MCRYPT_DEV_URANDOM));

            $_SESSION['user_token'] = $cookie_token;

            setcookie('user_token', $cookie_token , 0 , '/' , 'donategame.com' , true , true);
        }else{
            //code for session_destroy
        }

    }

            //prevent session hijaking with browser user agent
    if(!isset($_SESSION['user_agent'])){
        $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
    }

    if($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']){
      die('session hijaking - user agent');
    }

참고 : ajax 요청으로 토큰 쿠키를 재생성하지 마십시오. 참고 : 위 코드는 예입니다. 참고 : 사용자가 로그 아웃하면 쿠키 토큰과 세션이 삭제되어야합니다.

6-일부 사용자의 IP는 각 요청에 따라 변경되기 때문에 세션 히잡을 방지하기 위해 사용자 IP를 사용하는 것은 좋은 방법이 아닙니다. 유효한 사용자에게 영향을 미치는

7-개인적으로 세션 데이터를 데이터베이스에 저장합니다. 어떤 방법을 채택할지는 귀하에게 달려 있습니다.

내 접근 방식에서 실수를 발견하면 나를 수정하십시오. 세션 hyjaking을 방지하는 더 많은 방법이 있으면 알려주세요.


안녕, 나는 (ASP.NET에서) 세션 하이재킹을 방지하려고 시도하고 위의 모든 단계를 제안했습니다. 대략적으로 작동하지만 브라우저의 InPrivateBrowsing / 시크릿 모드를 사용하면 세션이 하이재킹됩니다. sessionId 문자열에 추가 할 추가 사항을 제안 해 주시겠습니까?
Vishwanath Mishra

4

세션 ID에 증분 정수를 사용하지 마십시오. GUID 또는 임의의 긴 문자열을 사용하는 것이 훨씬 좋습니다.


3

세션 도용에 대한 보호를 만드는 방법에는 여러 가지가 있지만 모두 사용자 만족도를 낮추거나 안전하지 않습니다.

  • IP 및 / 또는 X-FORWARDED-FOR 검사. 이러한 작업은 매우 안전하지만 사용자의 고통을 상상해보십시오. 그들은 WiFi가있는 사무실에 와서 새로운 IP 주소를 얻고 세션을 잃습니다. 다시 로그인했습니다.

  • 사용자 에이전트 확인. 위와 마찬가지로 새 버전의 브라우저가 나오고 세션이 손실됩니다. 또한 이들은 "해킹"하기가 정말 쉽습니다. 해커가 가짜 UA 문자열을 보내는 것은 사소한 일입니다.

  • localStorage 토큰. 로그온시 토큰을 생성하여 브라우저 저장소에 저장하고 암호화 된 쿠키 (서버 측에서 암호화 됨)에 저장합니다. 이는 사용자에게 부작용이 없습니다 (localStorage는 브라우저 업그레이드를 통해 유지됨). 모호함을 통한 보안만큼 안전하지 않습니다. 또한 JS에 로직 (암호화 / 복호화)을 추가하여 더 모호하게 만들 수 있습니다.

  • 쿠키 재발행. 이것이 아마도 올바른 방법 일 것입니다. 트릭은 한 번에 한 클라이언트 만 쿠키를 사용하도록 허용하는 것입니다. 따라서 활성 사용자는 매시간마다 쿠키를 재발급하게됩니다. 새로운 쿠키가 발행되면 기존 쿠키는 무효화됩니다. 해킹은 여전히 ​​가능하지만 훨씬 더 어렵습니다. 해커 나 유효한 사용자 모두 액세스가 거부됩니다.


1

로그인 단계에서 클라이언트와 서버가 비밀 솔트 값에 동의 할 수 있다고 생각해 보겠습니다. 그 후 서버는 각 업데이트에 카운트 값을 제공하고 클라이언트가 (비밀 솔트 + 카운트)의 해시로 응답하기를 기대합니다. 잠재적 납치범은이 비밀 솔트 값을 얻을 수있는 방법이 없으므로 다음 해시를 생성 할 수 없습니다.


3
그러나 아무도 훔칠 수없는이 소금을 클라이언트 측에 어떻게 저장하고 싶습니까?
Dcortez

1

AFAIK 세션 개체는 웹 서버에 저장되므로 클라이언트에서 액세스 할 수 없습니다. 그러나 세션 ID는 쿠키로 저장되며 웹 서버가 사용자의 세션을 추적 할 수 있도록합니다.

세션 ID를 사용한 세션 하이재킹을 방지하기 위해 요청 개체 내부의 웹 서버에서 액세스 할 수있는 두 가지 속성, 원격 주소 및 원격 포트의 조합을 사용하여 만든 해시 된 문자열을 세션 개체 내부에 저장할 수 있습니다. 이러한 속성은 사용자 세션을 사용자가 로그인 한 브라우저에 연결합니다.

사용자가 동일한 시스템의 다른 브라우저 또는 시크릿 모드에서 로그인하면 IP 주소는 동일하게 유지되지만 포트는 다릅니다. 따라서 응용 프로그램에 액세스하면 웹 서버에 의해 사용자에게 다른 세션 ID가 할당됩니다.

다음은 한 세션에서 다른 세션으로 세션 ID를 복사하여 구현하고 테스트 한 코드입니다. 아주 잘 작동합니다. 허점이 있으면 어떻게 시뮬레이션했는지 알려주세요.

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    HttpSession session = request.getSession();
    String sessionKey = (String) session.getAttribute("sessionkey");
    String remoteAddr = request.getRemoteAddr();
    int remotePort = request.getRemotePort();
    String sha256Hex = DigestUtils.sha256Hex(remoteAddr + remotePort);
    if (sessionKey == null || sessionKey.isEmpty()) {
        session.setAttribute("sessionkey", sha256Hex);
        // save mapping to memory to track which user attempted
        Application.userSessionMap.put(sha256Hex, remoteAddr + remotePort);
    } else if (!sha256Hex.equals(sessionKey)) {
        session.invalidate();
        response.getWriter().append(Application.userSessionMap.get(sessionKey));
        response.getWriter().append(" attempted to hijack session id ").append(request.getRequestedSessionId()); 
        response.getWriter().append("of user ").append(Application.userSessionMap.get(sha256Hex));
        return;
    }
    response.getWriter().append("Valid Session\n");
}

나는 baeldung의 SHA-256 Hashing에서 주어진 예제를 사용하여 값을 해싱하기 위해 SHA-2 알고리즘을 사용했습니다.

귀하의 의견을 기대합니다.


@zaph 미안하지만 rep을 얻기 위해 답변을 추가하지 않았습니다. 요점은 SHA-2 암호화도 아닙니다. 하지만 다른 사용자의 세션 ID 쿠키가 다른 사용자의 세션에 사용되는 것을 감지 할 수 있다는 사실, 즉 원래 질문에서와 같이 세션 하이재킹. 내 솔루션을 테스트 한 결과 작동하는 것으로 나타났습니다. 그러나 나는 이것에 대한 전문가가 아니므로 커뮤니티에서 내 대답이 충분한 지 확인하고 싶습니다. 내 코드 스 니펫이 무엇을하는지보고 질문에 대한 답을 결정할 수 있습니다. 감사!
Jzf

@zaph 실수를 지적 해 주셔서 감사합니다. 귀하의 제안에 따라 내 답변을 업데이트했습니다. 답변이 도움이되었다고 생각되면 반대표를 제거하십시오.
Jzf

0

위험을 줄이려면 원래 IP를 세션과 연결할 수도 있습니다. 이렇게하면 공격자가 세션을 사용할 수 있으려면 동일한 사설 네트워크 내에 있어야합니다.

참조 자 헤더를 확인하는 것도 옵션 일 수 있지만 더 쉽게 스푸핑됩니다.


7
아니요, 원래 IP는 동적 IP를 통해, 사용자가 일시적으로 연결이 끊어 질 때 변경되거나, 프록시 팜의 (암시 적 또는 명시 적) 사용을 통해 변경 될 수 있으므로 사용할 수 없습니다. 또한 동일한 ISP에서 오는 세션 하이재커는 합법적 인 사용자와 동일한 프록시 및 IP를 사용할 수 있습니다.
Olaf Kock

1
PHP-Nuke는 세션 접근 방식에 대한 좋은 페이지를 가지고 있으며 IP에 연결하는 것이 모든 ISP에서 작동하지 않는 방법에 대해 자세히 설명합니다. phpnuke.org/…
Sembiance

4
Ip를 변경하는 것은 모바일 인터넷 제공 업체에서 매우 일반적입니다. Vodafone을 사용하면 모든 요청에 ​​따라 내 IP가 변경됩니다.
Blaise 2011 년

1
다소 오래된 게시물이지만 더 나아 가기 위해. IP는 언급 된대로 나쁜 생각입니다. 언급했듯이 모바일 사용자는 IP를 로밍하는 경향이 있습니다. 과거의 일부 ISP에도 로밍 IP (예 : AOL)가 있었지만이 접근 방식은 현재 IPv4 IP가 부족하여 점점 더 대중화되고 있습니다. 이러한 ISP 년대에는 플러스 그물 BT
피터

-15

보호 :

$ip=$_SERVER['REMOTE_ADDER'];
$_SESSEION['ip']=$ip;

12
나는 당신이 여기서 무엇을하는지 보지 못합니다.
samayo jul.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.