문제

특히 이는 클라이언트 세션 쿠키를 사용하여 서버의 세션을 식별하는 경우에 관한 것입니다.

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

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

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

도움이 되었습니까?

해결책

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

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

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

다른 팁

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

최소한, 오래된 쿠키는 시간이 지나면 그 가치를 잃게 됩니다.성공적인 하이재킹 공격도 쿠키 작동이 중지되면 좌절됩니다.사용자가 한 달 이상 전에 로그인한 세션의 쿠키를 가지고 있는 경우 비밀번호를 다시 입력하도록 합니다.사용자가 사이트의 "로그아웃" 링크를 클릭할 때마다 이전 세션 UUID를 다시 사용할 수 없도록 하십시오.

이 아이디어가 효과가 있을지는 모르겠지만 다음은 이렇습니다.세션 쿠키에 일련 번호(예: 다음과 같은 문자열)를 추가하세요.

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

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

사용자가 두 대 이상의 컴퓨터를 보유할 수 있으므로 두 개 이상의 활성 세션이 있을 수 있다는 점을 기억하십시오.컴퓨터를 전환할 때마다 다시 로그인하도록 강요하는 작업을 수행하지 마세요.

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분마다 만료되도록 만들고, 해당 토큰을 다시 발급하고, 세션을 새 데이터와 다시 동기화합니다.데이터가 일치하지 않는 경우 사용자를 로그아웃하거나 세션을 다시 인증하도록 하세요.

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

// 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 주소가 갑자기 변경되어 세션 하이재킹 시도를 암시하는 경우 세션을 종료하고 사용자가 다시 인증하도록 하여 세션을 보호합니다.이는 해킹 시도를 방해하며 공격자는 세션에 액세스하는 대신 강제로 로그인해야 합니다.사용자에게 시도를 알리고(약간 위로), 약간 짜증이 나고 사용자에게 정보를 제공하면 해당 세션/정보가 보호됩니다.

프록시/네트워크 뒤에 있는 시스템에 대한 세션의 고유성을 캡처하기 위해 최선을 다하기 위해 사용자 에이전트 및 X-FORWARDED-FOR를 사용합니다.그러면 더 많은 정보를 사용할 수 있으므로 마음껏 창의력을 발휘해 보세요.

100%는 아니지만 꽤 효과가 좋습니다.

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

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

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

다음에 설명된 보안 쿠키 프로토콜을 사용해 보세요. 이것 Liu, Kovacs, Huang 및 Gouda의 논문:

문서에 명시된 대로:

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

배포 용이성에 관해서는 다음과 같습니다.

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

간단히 말해서:안전하고 가벼우며 저에게 딱 맞습니다.

세션 하이재킹을 100% 방지할 수 있는 방법은 없지만 일부 접근 방식을 사용하면 공격자가 세션을 하이재킹하는 데 걸리는 시간을 줄일 수 있습니다.

세션 하이재킹을 방지하는 방법:

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

2 - httponly가 true로 설정된 세션 쿠키만 보냅니다(자바스크립트가 세션 쿠키에 액세스하는 것을 방지).

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

내 접근 방식에서 실수를 발견하면 수정해 주세요.세션 하이재킹을 방지할 수 있는 다른 방법이 있으면 알려주세요.

세션 ID에 증분 정수를 사용하지 않는지 확인하세요.GUID나 무작위로 생성된 다른 긴 문자열을 사용하는 것이 훨씬 좋습니다.

세션 하이재킹을 방지하는 방법에는 여러 가지가 있지만 모두 사용자 만족도를 떨어뜨리거나 안전하지 않습니다.

  • IP 및/또는 X-FORWARDED-FOR 확인.이것들은 작동하고 꽤 안전합니다 ...하지만 사용자의 고통을 상상해보세요.그들은 WiFi를 사용하여 사무실에 와서 새로운 IP 주소를 얻고 세션을 잃습니다.다시 로그인을 하라고 하더군요.

  • 사용자 에이전트가 확인합니다.위와 마찬가지로 새 버전의 브라우저가 출시되고 세션이 손실됩니다.게다가 이것들은 "해킹"하기가 정말 쉽습니다.해커가 가짜 UA 문자열을 보내는 것은 쉬운 일이 아닙니다.

  • localStorage 토큰.로그온 시 토큰을 생성하여 브라우저 저장소에 저장하고 암호화된 쿠키(서버 측에서 암호화됨)에 저장합니다.이는 사용자에게 부작용이 없습니다(localStorage는 브라우저 업그레이드를 통해 지속됩니다).그것은 단지 모호함을 통한 보안이기 때문에 안전하지 않습니다.또한 JS에 일부 논리(암호화/암호 해독)를 추가하여 이를 더욱 모호하게 할 수 있습니다.

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

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

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");
}

SHA-2 알고리즘을 사용하여 다음에 제공된 예제를 사용하여 값을 해시했습니다. SHA-256 해싱 밸둥

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

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

리퍼러 헤더를 확인하는 것도 옵션이 될 수 있지만 더 쉽게 스푸핑될 수 있습니다.

보호 방법:

$ip=$_SERVER['REMOTE_ADDER'];
$_SESSEION['ip']=$ip;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top