안녕하세요...바로 밑에서 세션 공유에 대한 글을 올렸던 TarauS입니다. 제가 올렸던 글에 대해서 많은 분들이 좋은 의견들을 남겨 주셔서 그 글을 참고하여 보안부분을 조금 더 강화한 소스를 다시 올립니다.
달라진 점이라면 그전에는 세션키만을 전송하였기에 세션키만 알아내면 뚫을 수 있는 취약점이 있었으나 이번에는 세션키를 검증할 수 있는 암호화된 키를 함께 체크합니다. 암호화된 키는 사용자가 고유하게 가지는 값들을 암호화 한 값으로 따로 전송할 필요는 없습니다.(사용자의 환경값이나 아이피값을 가지고 만드는 것이기 때문에 한 사용자가 계속 사용중이라면 변하지 않을테니까요^^) 결론적으로 세션키는 예전처럼 iframe를 이용해서 전송하고 그 대신 DB와의 쿼리 부분에 사용자키도 함께 넣어 체크하도록 한 것입니다. 그리고 또한 레퍼러 및 세션키를 받아서 설정하는 파일명도 함께 체크하도록 하여 조금이라도 보안적으로 강력해지도록 노력하였습니다. 이번 수정된 소스를 보시고 또 여러 의견 남겨 주시기 바랍니다.
아~ 그리고...사용자키를 암호화하는 함수는 넣지 않았습니다... 이 부분은 여러분들이 찾아서 넣으시기 바랍니다.^^
설정에 관련된 것은 밑의 게시물을 열어서 보시기 바랍니다. 참고만 하시고 session.inc 파일의 소스는 지금 올린 것을 사용하세요. http://www.phpschool.com/bbs2/inc_view.html?id=8923&code=tnt2&start=0&mode=&field=&operator=&period=&category_id=&s_que=
############## session.inc 파일 ################################################### <? header('P3P: CP="NOI CURa ADMa DEVa TAIa OUR DELa BUS IND PHY ONL UNI COM NAV INT DEM PRE"'); /* ------------------------------------------------------------------------ Table Scheme
CREATE TABLE sessions ( session_key char(32) not null, session_expiry int(11) unsigned not null, session_value text not null, session_check varchar(250) not null, PRIMARY KEY (session_key) ); */
#### DB 관련설정 $Cfg_DB_Host = "db_host"; $Cfg_DB_User = "db_user"; $Cfg_DB_Pass = "db_pass"; $Cfg_DB_Name = "db_name";
#### 쿠키 관련 설정 $Cfg_Cookie_Domain = ".aaa.com";
#### 보안 관련 설정 ## 상대편 서버에서 현재 서버의 link.php 파일을 아이프레임으로 호출하는 파일 $Cfg_Http_Referer = "http://www.bbb.com/member/login_process.php"; ## 현재 서버에서 상대편 서버로부터 넘어오는 세션키를 받는 파일 $Cfg_Php_Self = "/member/link.php";
#### 세션 관련 기본 설정 $SESS_DBH = ""; $SESS_LIFE = get_cfg_var("session.gc_maxlifetime");
#### 세션키의 유효성을 체크하기 위한 사용자 키 #### 사용자 키는 사용자가 고유하게 가지는 값들을 이용하여 만들어주면 됨 ## 서버키를 설정 (이 값은 아무것이나 정하시면 됩니다.) $SERVER_KEY = "~1234567890"; ## 사용자의 접속 환경 $USER_AGENT = $_SERVER["HTTP_USER_AGENT"]; ## 사용자의 접속 아이피 $USER_ADDR = $_SERVER["REMOTE_ADDR"]; ## 사용자 키 (각각의 정보를 이용한 조합은 여러분들이 직접 정하세요. 여기서 보여드리는 것은 예시입니다.) $USER_KEY = $USER_AGENT."||".$USER_ADDR."||".$SERVER_KEY;
#### 암호화 함수(유일한 암호화 함수를 직접 제작함) function encrypt($key) { ## 이부분에 암호화 루틴을 넣으면 됨 ## }
#### 암호화 함수를 통해 인코딩된 사용자 키 값 $ENCODE_KEY = encrypt($USER_KEY);
function sess_open($save_path, $session_name){ global $SESS_DBH,$Cfg_DB_Host,$Cfg_DB_User,$Cfg_DB_Pass,$Cfg_DB_Name;
$SESS_DBH = mysql_pconnect($Cfg_DB_Host,$Cfg_DB_User,$Cfg_DB_Pass) or die("SQL 서버에 접속할 수 없습니다."); mysql_select_db($Cfg_DB_Name, $SESS_DBH) or die("SQL 서버에 접속할 수 없습니다.");
return true; }
function sess_close(){ return true; }
function sess_read($key){ global $SESS_DBH, $SESS_LIFE,$ENCODE_KEY;
$qry = "SELECT session_value FROM sessions WHERE session_key = '$key' AND session_check='$ENCODE_KEY' and session_expiry > " . time(); $qid = mysql_query($qry, $SESS_DBH);
if (list($value) = mysql_fetch_row($qid)) { return $value; }
return false; }
function sess_write($key, $val){ global $SESS_DBH, $SESS_LIFE, $ENCODE_KEY;
$expiry = time() + $SESS_LIFE; $value = addslashes($val);
$qry = "INSERT INTO sessions (session_key,session_expiry,session_value,session_check) VALUES ('$key', $expiry, '$value', '$ENCODE_KEY')"; $qid = mysql_query($qry, $SESS_DBH);
if (! $qid) { $qry = "UPDATE sessions SET session_expiry = $expiry, session_value = '$value' WHERE session_key = '$key' AND session_check='$ENCODE_KEY' AND session_expiry > " . time(); $qid = mysql_query($qry, $SESS_DBH); }
return $qid; }
function sess_destroy($key){ global $SESS_DBH,$USER_KEY;
$qry = "DELETE FROM sessions WHERE session_key = '$key' AND session_check='$ENCODE_KEY'"; $qid = mysql_query($qry, $SESS_DBH);
return $qid; }
function sess_gc($maxlifetime){ global $SESS_DBH;
$qry = "DELETE FROM sessions WHERE session_expiry < " . time(); $qid = mysql_query($qry, $SESS_DBH);
return mysql_affected_rows($SESS_DBH); }
#### 세션키를 설정하는 함수 function set_session_id($SESSID){ global $HTTP_REFERER, $PHP_SELF; ## 레퍼러 및 현재 파일명을 함께 체크해서 제대로 된 요청일 때만 세션키를 설정 if($SESSID&&$HTTP_REFERER==$Cfg_Http_Referer&&$PHP_SELF==$Cfg_Php_Self) @session_id($SESSID); }
set_session_id($SESSID); session_set_save_handler("sess_open", "sess_close", "sess_read", "sess_write", "sess_destroy", "sess_gc"); session_set_cookie_params(0, "/", $Cfg_Cookie_Domain); ini_set('session.cache_limiter' ,'nocache, must-revalidate-revalidate'); session_start(); ?>
|