PHP 세션 보안


125

PHP로 책임있는 세션 보안을 유지하기위한 지침은 무엇입니까? 웹 전체에 정보가 있으며 모든 정보가 한 곳에 도착한시기입니다.

답변:


88

세션을 안전하게 유지하기 위해 수행해야 할 몇 가지 작업이 있습니다.

  1. 사용자를 인증하거나 민감한 작업을 수행 할 때는 SSL을 사용하십시오.
  2. 보안 레벨이 변경 될 때마다 (예 : 로그인) 세션 ID를 재생성하십시오. 원하는 경우 요청마다 세션 ID를 다시 생성 할 수도 있습니다.
  3. 세션 시간 초과
  4. 레지스터 전역을 사용하지 마십시오
  5. 서버에 인증 세부 사항을 저장하십시오. 즉, 쿠키에 username과 같은 세부 정보를 보내지 마십시오.
  6. 를 확인하십시오 $_SERVER['HTTP_USER_AGENT']. 이것은 세션 하이재킹에 작은 장벽을 추가합니다. IP 주소를 확인할 수도 있습니다. 그러나 이것은 여러 인터넷 연결 등의 부하 분산으로 인해 IP 주소가 변경되는 사용자에게 문제를 일으 킵니다 (여기서는 우리 환경의 경우).
  7. 파일 시스템의 세션에 대한 액세스를 잠 그거나 사용자 정의 세션 처리를 사용하십시오.
  8. 민감한 작업의 경우 로그인 한 사용자에게 인증 세부 정보를 다시 제공하도록 요구하십시오.

15
암호화 된 트래픽과 암호화되지 않은 트래픽에 대해 별도의 세션이 없으면 일부 작업에만 SSL을 사용하는 것으로 충분하지 않습니다. HTTPS 및 HTTP를 통해 단일 세션을 사용하는 경우 공격자는 첫 번째 비 HTTPS 요청에서 세션을 훔칩니다.
Kornel

6
-1 사용자 에이전트가 스푸핑하기 쉽습니다. 당신이 설명하는 것은 코드를 낭비하고 보안 시스템이 아닙니다.
rook

24
@ 루크는 사소한 장애 (공격자가 자신의 사이트를 사용하여 피해자의 사용자 에이전트를 캡처 할 수 있음) 일 수 있으며 모호성을 통해 보안에 의존하지만 여전히 하나의 추가 장벽입니다. 세션 사용 중에 User-Agent HTTP가 변경되면 매우 의심스럽고 공격 가능성이 높습니다. 나는 당신이 그것을 혼자 사용할 수 있다고 말한 적이 없습니다. 다른 기술과 결합하면 훨씬 안전한 사이트가됩니다.
grom

5
@grom 나는 당신의 문을 가로 질러 스카치 테이프를 붙이고 사람들이 침입하는 것을 막을 것이라고 말하는 것처럼 생각합니다.
rook

8
사용자 에이전트를 확인하는 경우 호환성 모드를 전환 할 때 IE8 사용자의 모든 요청을 차단합니다. 내 코드 에서이 문제를 추적 한 재미를보십시오 : serverfault.com/questions/200018/http-302-problem-on-ie7 . 다른 사람들이 말했듯이 스푸핑하는 것은 사소한 일이므로 사용자 에이전트 체크 아웃을하고 있습니다.
bestattendance

15

한 가지 지침은 세션의 보안 수준이 변경 될 때마다 session_regenerate_id 를 호출 하는 것입니다. 세션 하이재킹을 방지하는 데 도움이됩니다.


11

내 두 개 이상의 센트 :

  • 아무도 믿지 마라
  • 필터 입력, 이스케이프 출력 (쿠키, 세션 데이터도 입력)
  • XSS를 피하십시오 (HTML을 잘 유지하고 PHPTAL 또는 HTMLPurifier를 살펴 보십시오 )
  • 심층 방어
  • 데이터를 노출시키지 마십시오

이 주제에 관한 작지만 좋은 책이 있습니다 : Chris Shiflett의 필수 PHP 보안 .

필수 PHP 보안 http://shiflett.org/images/essential-php-security-small.png

이 책의 홈 페이지에는 흥미로운 코드 예제와 샘플 장이 있습니다.

여기에 설명 된 위에서 설명한 기술 (IP 및 UserAgent)을 사용할 수 있습니다. 신원 도용 방지 방법


XSS 방지의 경우 +1 그렇지 않으면 CSRF로부터 보호하는 것이 불가능하므로 누군가 세션 ID를 얻지 않고도 세션을 "대체"할 수 있습니다.
Kornel

11

필자는 PHP 6에서 해결되는 주요 문제 중 하나가 register_globals라고 생각합니다. 현재 피하는 데 사용되는 표준 방법 중 하나 register_globals$_REQUEST, $_GET또는 $_POST배열 을 사용하는 것 입니다.

이를 수행하는 "올바른"방법 (5.2에서는 현재 약간 버그가 있지만 조만간 6에서는 안정적 임)은 필터를 통하는 것 입니다.

따라서 대신 :

$username = $_POST["username"];

당신은 할 것입니다 :

$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);

또는 심지어 :

$username = filter_input(INPUT_POST, 'username');

2
이것은 질문과 전혀 관련이 없습니다.
픽셀 개발자

5
정말? 그렇다면 허용되는 답변에서 레지스터 전역을 사용하지 않는 이유는 무엇입니까? 대부분의 방대한 개발자들이 우려하는 한, 전역을 등록하고 변수 세션이 기술적으로 "세션"객체의 일부가 아니더라도 "세션"의 우산 아래에 떨어질까요?
cmcculloh

9
나는 이것이 질문에 완전히 대답 하지는 않지만 질문에 대한 답의 일부 라는 데 동의합니다 . 다시 말하지만, 이것은 "등록 전역을 사용하지 마십시오"라는 인정 된 답변의 요점을 드러냅니다. 이것은 대신 무엇을해야하는지 알려줍니다.
cmcculloh


5

내 경험상 IP 주소를 사용하는 것이 가장 좋은 아이디어는 아닙니다. 예를 들어; 내 사무실에는 부하에 따라 사용되는 두 개의 IP 주소가 있으며 IP 주소를 사용하여 계속 문제가 발생합니다.

대신 서버의 도메인에 대한 별도의 데이터베이스에 세션을 저장하기로 선택했습니다. 이렇게하면 파일 시스템의 어느 누구도 해당 세션 정보에 액세스 할 수 없습니다. 이것은 3.0 이전의 phpBB에서 실제로 도움이되었지만 (이를 수정 한 이후) 여전히 좋은 생각입니다.


3

이것은 매우 사소하고 명백하지만 모든 사용 후에 는 session_destroy 해야 합니다. 사용자가 명시 적으로 로그 아웃하지 않으면 구현하기 어려울 수 있으므로이를 수행하도록 타이머를 설정할 수 있습니다.

다음은 setTimer () 및 clearTimer ()에 대한 유용한 자습서 입니다.


3

PHP 세션 및 보안 (세션 하이재킹 제외)의 주요 문제는 현재 환경에 있습니다. 기본적으로 PHP는 세션 데이터를 OS의 temp 디렉토리에 파일로 저장합니다. 특별한 생각이나 계획이 없다면 이것은 세계적으로 읽을 수있는 디렉토리이므로 모든 세션 정보는 서버에 액세스 할 수있는 모든 사람에게 공개됩니다.

여러 서버에서 세션을 유지 관리하는 경우 이 시점에서 제공된 함수를 호출하여 세션 데이터를 CRUD (생성, 읽기, 업데이트, 삭제)하는 사용자 처리 세션으로 PHP를 전환하는 것이 좋습니다. 이 시점에서 모든 응용 프로그램 서버가 데이터에 액세스 할 수 있도록 세션 정보를 데이터베이스 나 memcache 솔루션에 저장할 수 있습니다.

공유 서버에있는 경우 자신의 세션을 저장하면 파일 시스템보다 자주 제어 할 수있는 데이터베이스에 세션을 저장할 수 있기 때문에 유리할 수도 있습니다.


3

세션을 다음과 같이 설정했습니다.

로그인 페이지에서 :

$_SESSION['fingerprint'] = md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR']);

(구성 페이지에 정의 된 문구)

그런 다음 나머지 사이트 전체에있는 헤더에서

session_start();
if ($_SESSION['fingerprint'] != md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR'])) {       
    session_destroy();
    header('Location: http://website login page/');
    exit();     
}

3

php.ini

session.cookie_httponly = 1
change session name from default PHPSESSID

EQ 아파치 추가 헤더 :

X-XSS-Protection    1

httpd.conf-> <FilesMatch "\. (php | phtml | aspx | htm | html) $"> 헤더 세트 X-XSS-Protection "1"</ FilesMatch>
user956584

그주의 X-XSS-Protection모든 정말 유용하지 않습니다. 실제로 보호 알고리즘 자체가 실제로 악용되어 이전보다 더 나빠질 수 있습니다.
Pacerier

2

IP와 사용자 에이전트가 모두 변경되는지 확인합니다.

if ($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']
    || $_SESSION['user_ip'] != $_SERVER['REMOTE_ADDR'])
{
    //Something fishy is going on here?
}

5
사용자가 부하 분산 프록시 팜을 사용하지 않는 경우 IP가 합법적으로 변경 될 수 있습니다.
Kornel

2
그리고 user_agent는 사용자가 브라우저를 업그레이드 할 때마다 변경할 수 있습니다.
scotts

3
@ scotts IP 부분에 동의하지만 브라우저 업그레이드의 경우 로그인 할 때 세션을 설정하여 다시 로그인하면 새 세션을 만들지 않고 브라우저를 업그레이드하는 방법을 알 수 없습니다.
JasonDavis

IE8에서 호환 모드 간을 전환 할 때 user_agent도 변경할 수 있다고 생각합니다. 가짜도 매우 쉽습니다.

그러나 고정 IP EQ GSM을 사용하고 30 분마다 변경되는 사용자는 어떻습니까? 따라서 세션 + 호스트 이름에 저장된 IP, WHEN IP! = REMOTE_ADDR 호스트를 확인하고 hostanmes eq를 비교하십시오. holand.nl == true 인 경우 12.12.12.holand.nl-> 그러나 일부 호스트는 IP 기반 호스트 이름을 가졌다면 마스크 88.99.XX.XX를 비교해야합니다.
user956584

2

session_set_save_handler () 를 사용하는 경우 고유 한 세션 처리기를 설정할 수 있습니다. 예를 들어, 세션을 데이터베이스에 저장할 수 있습니다. 데이터베이스 세션 핸들러의 예제는 php.net 주석을 참조하십시오.

서버가 여러 개인 경우 DB 세션도 좋습니다. 그렇지 않으면 파일 기반 세션을 사용하는 경우 각 웹 서버가 동일한 파일 시스템에 액세스하여 세션을 읽고 쓸 수 있는지 확인해야합니다.


2

세션 데이터가 안전한지 확인해야합니다. php.ini를 보거나 phpinfo ()를 사용하면 세션 설정을 찾을 수 있습니다. _session.save_path_는 저장 위치를 ​​알려줍니다.

폴더 및 상위 폴더의 권한을 확인하십시오. 공개 서버 (/ tmp)이거나 공유 서버의 다른 웹 사이트에서 액세스 할 수 없습니다.

여전히 PHP 세션을 사용한다고 가정하면 _session.save_path_를 변경하여 다른 폴더를 사용하거나 _session.save_handler_를 변경하여 데이터베이스에 데이터를 저장하도록 php를 설정할 수 있습니다.

php.ini (일부 공급자는 허용) 또는 apache + mod_php, 사이트 루트 폴더의 .htaccess 파일에서 _session.save_path_를 설정할 수 있습니다. php_value session.save_path "/home/example.com/html/session" . _session_save_path () _를 사용하여 런타임에 설정할 수도 있습니다.

Chris Shiflett의 자습서 또는 Zend_Session_SaveHandler_DbTable 을 확인 하여 대체 세션 핸들러를 설정하십시오.

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