복붙노트

PHP를 사용하여 CSRF 토큰을 올바르게 추가하는 방법

PHP

PHP를 사용하여 CSRF 토큰을 올바르게 추가하는 방법

내 웹 사이트의 양식에 보안을 추가하려고합니다. 양식 중 하나는 AJAX를 사용하고 다른 하나는 직접 "문의하기"양식입니다. CSRF 토큰을 추가하려고합니다. 내가 겪고있는 문제는 토큰이 HTML "값"중 일부에만 표시된다는 것입니다. 나머지 시간은 값이 비어 있습니다. 다음은 AJAX 양식에서 사용하는 코드입니다.

PHP :

if (!isset($_SESSION)) {
    session_start();
$_SESSION['formStarted'] = true;
}
if (!isset($_SESSION['token']))
{$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;

}

HTML

 <form>
//...
<input type="hidden" name="token" value="<?php echo $token; ?>" />
//...
</form>

어떤 제안?

해결법

  1. ==============================

    1.if와 함께 다른 사람이 필요한 것 같습니다.

    if와 함께 다른 사람이 필요한 것 같습니다.

    if (!isset($_SESSION['token'])) {
        $token = md5(uniqid(rand(), TRUE));
        $_SESSION['token'] = $token;
        $_SESSION['token_time'] = time();
    }
    else
    {
        $token = $_SESSION['token'];
    }
    
  2. ==============================

    2.보안 코드의 경우 다음과 같이 토큰을 생성하지 마십시오. $ token = md5 (uniqid (rand (), TRUE));

    보안 코드의 경우 다음과 같이 토큰을 생성하지 마십시오. $ token = md5 (uniqid (rand (), TRUE));

    이것을보십시오 :

    session_start();
    if (empty($_SESSION['token'])) {
        $_SESSION['token'] = bin2hex(random_bytes(32));
    }
    $token = $_SESSION['token'];
    

    Sidenote : 내 고용주의 오픈 소스 프로젝트 중 하나는 random_bytes () 및 random_int ()를 PHP 5 프로젝트로 백 포트하기위한 계획입니다. MIT의 라이선스가 있고 Github 및 Composer에서 paragonie / random_compat로 제공됩니다.

    session_start();
    if (empty($_SESSION['token'])) {
        if (function_exists('mcrypt_create_iv')) {
            $_SESSION['token'] = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
        } else {
            $_SESSION['token'] = bin2hex(openssl_random_pseudo_bytes(32));
        }
    }
    $token = $_SESSION['token'];
    

    == 또는 ===를 사용하지 말고, hash_equals ()를 사용하십시오 (PHP 5.6+ 만 사용할 수 있지만 hash-compat 라이브러리가있는 이전 버전에서는 사용할 수 있습니다).

    if (!empty($_POST['token'])) {
        if (hash_equals($_SESSION['token'], $_POST['token'])) {
             // Proceed to process the form data
        } else {
             // Log this as a warning and keep an eye on these attempts
        }
    }
    

    hash_hmac ()를 사용하여 특정 양식에만 사용할 수 있도록 토큰을 더 제한 할 수 있습니다. HMAC는 약한 해시 함수 (예 : MD5)에서도 안전하게 사용할 수있는 특수 키순 해시 함수입니다. 그러나 SHA-2 계열의 해시 함수를 대신 사용하는 것이 좋습니다.

    먼저 HMAC 키로 사용할 두 번째 토큰을 생성 한 다음이 논리를 사용하여이를 렌더링합니다.

    <input type="hidden" name="token" value="<?php
        echo hash_hmac('sha256', '/my_form.php', $_SESSION['second_token']);
    ?>" />
    

    그런 다음 토큰을 확인할 때 일치하는 연산을 사용합니다.

    $calc = hash_hmac('sha256', '/my_form.php', $_SESSION['second_token']);
    if (hash_equals($calc, $_POST['token'])) {
        // Continue...
    }
    

    하나의 양식에 대해 생성 된 토큰은 $ _SESSION [ 'second_token']을 모른 채 다른 컨텍스트에서 재사용 할 수 없습니다. HMAC 키로 별도의 토큰을 사용하는 것이 중요합니다.

    Twig 템플릿 엔진을 사용하는 사용자는이 필터를 Twig 환경에 추가하여 단순화 된 이중 전략의 이점을 누릴 수 있습니다.

    $twigEnv->addFunction(
        new \Twig_SimpleFunction(
            'form_token',
            function($lock_to = null) {
                if (empty($_SESSION['token'])) {
                    $_SESSION['token'] = bin2hex(random_bytes(32));
                }
                if (empty($_SESSION['token2'])) {
                    $_SESSION['token2'] = random_bytes(32);
                }
                if (empty($lock_to)) {
                    return $_SESSION['token'];
                }
                return hash_hmac('sha256', $lock_to, $_SESSION['token2']);
            }
        )
    );
    

    이 Twig 함수를 사용하면 두 가지 일반 용도 토큰을 다음과 같이 사용할 수 있습니다.

    <input type="hidden" name="token" value="{{ form_token() }}" />
    

    또는 잠긴 변형 :

    <input type="hidden" name="token" value="{{ form_token('/my_form.php') }}" />
    

    나뭇 가지는 템플릿 렌더링에만 관심이 있습니다. 여전히 토큰을 올바르게 검증해야합니다. 제 생각에, 나뭇 가지 전략은 최대의 보안 가능성을 유지하면서 더 큰 유연성과 단순성을 제공합니다.

    각 CSRF 토큰이 정확히 한 번 사용할 수 있도록 허용된다는 보안 요구 사항이있는 경우 가장 간단한 전략은 각각의 성공적인 유효성 검사 후 다시 생성합니다. 그러나 이렇게하면 여러 탭을 한 번에 탐색하는 사람들과 잘 어울리지 않는 이전의 모든 토큰이 무효화됩니다.

    Paragon Initiative Enterprises는 이러한 코너 케이스에 대한 Anti-CSRF 라이브러리를 유지 관리합니다. 독점적으로 양식 당 하나의 토큰으로 작동합니다. 세션 데이터 (기본 구성 : 65535)에 충분한 토큰이 저장되면 가장 먼저 사용되지 않은 토큰이 먼저 순환 처리됩니다.

  3. ==============================

    3.$ token 변수가 세션에있을 때 세션에서 검색되지 않습니다.

    $ token 변수가 세션에있을 때 세션에서 검색되지 않습니다.

  4. ==============================

    4.page.php에서

    page.php에서

    session_start();
        if (empty($_SESSION['token'])) {
            $_SESSION['token'] = bin2hex(random_bytes(32));
        }
        $token = $_SESSION['token'];
    

    verification.php에서

    session_start();
    if (empty($_SESSION['token'])) {
        $_SESSION['token'] = bin2hex(random_bytes(32));
    }
    if (!empty($_POST['token'])) {
        if (hash_equals($_SESSION['token'], $_POST['token'])) {
             // Proceed to process the form data
        } else {
             // Log this as a warning and keep an eye on these attempts
        }
    }
    
  5. from https://stackoverflow.com/questions/6287903/how-to-properly-add-csrf-token-using-php by cc-by-sa and MIT license