포럼
세션보안 애드온 광범위한 테스트를 부탁드립니다.
2015.02.13 16:08
(공모전 때문인가요? 모듈이나 애드온을 만들면 자료실에 올리기만 하지 않고 포럼에 소개글을 쓰는 게 유행이 된 것 같네요.)
XSS 공격의 피해를 줄이기 위해서는 세션 쿠키에 httpOnly 속성을 주어야 하고, SSL 사용시에는 세션 탈취를 막기 위해 secure 속성도 주어야 하고, 세션 고정(session fixation) 공격을 피하려면 세션 식별자를 정기적으로 ( + 로그인/로그아웃 시점에) 갱신해 주어야 합니다.
이 3가지는 세션 보안의 기초 중에서도 가장 기초가 되는 원칙들입니다.
그러나 XE는 SSO 및 가상사이트 등 기존 기능과의 호환성 문제, 안 그래도 탈이 많은 업로더 세션 유지 문제, 그리고 그 밖에도 몇 가지 어려움이 있어서 세션 보안을 강화하지 못하고 있는 실정입니다.
그래서 PHPSESSID는 전혀 건드리지 않고, 세션과 연동되는 별도의 쿠키에 httpOnly, secure 속성을 적용하고 그것들을 정기적으로 교체해 주는 방식으로 애드온을 만들어 보았습니다. 이름하여 세션 쉴드!
그러나 사실 이런 게 언제까지나 애드온으로 돌아다녀서는 안됩니다. 세션을 안전하게 처리해 주는 것은 제3자가 만들어 뿌리는 일개 애드온이 아니라 XE 코어에서 공식적으로 해줘야 할 일이라고 생각하거든요.
안 그래도 로그인이 안 된다, 로그인이 풀린다는 버그 신고가 잦은 상황에서 코어를 잘못 건드리면 골치아파지니까 일단 애드온으로 만들어 본 것 뿐입니다. 안정성이 검증되면 곧바로 해당기능을 코어로 옮겨달라고 PR을 넣을 예정입니다.
그러려면 특수한(?) 환경을 포함하여, 광범위한 상황에서 테스트를 해봐야 합니다.
보안에 관심 있으신 분, 모험심이 강하신 분, SSO와 가상사이트 등 특수한 환경을 운영하고 계신 분, SSL을 절반쯤 적용하다 마신 분, IE8 방문자 비율이 비정상적으로 높은 사이트를 운영하시는 분, 그냥 어벤져(S.H.I.E.L.D.)를 좋아하시는 분 모두 환영합니다. 운영하시는 사이트에 가차없이 적용하고, 문제가 생기면 사정없이 투덜거려 주세요.
※ 곧 자료실에 게시될 v1.2 이상 버전을 사용하신다면 REFRESH_TIMEOUT = 0 으로 설정하여 세션 식별자의 정기적인 갱신을 막을 수 있습니다. (로그인/로그아웃시에는 여전히 갱신됩니다.) 로그인이 풀리는 문제가 여전히 발생한다면 이 설정을 변경해서 사용해 주세요.
※ 기술적 참고내용
※ git 사용이 가능하신 분은 테스트 기간 동안 자료실보다는 github에서 clone하여 사용하시고, github에 새 커밋이 등록되면 그때그때 pull해서 쓰시기를 권합니다. 자료실은 업데이트가 하루 정도 늦어지는 경우가 많아서요.
https://github.com/kijin/xe-session-shield
- [2014/09/17] 묻고답하기 xe첨부이미지파일 접속경로 (디도스방안 급함) *3
- [2012/02/01] 묻고답하기 XE 1.4.5.10에서 1.5.1.4로 업데이트 후 관리자 로그인 안됌.ㅜㅜ해결책?? *2
- [2011/10/06] 웹마스터 팁 로그인이 안되는 문제를 겪고 계시면 참고해볼만 합니다. *2
- [2011/01/25] 묻고답하기 (기초) 세션 아이디를 알려주세요 HELP!! *1
- [2009/06/18] 묻고답하기 외부 페이지와 레이아웃 사이에 변수 값 전달...
댓글 10
-
도라미
2015.02.13 16:11
-
이즈야
2015.02.13 16:52
기술적으로는 문제가 없어보이는데 적용했던 커뮤니티 사이트에서 간헐적으로 로그인 해제 증상이 보이고 있습니다.
자동로그인까지 풀린다는 회원이 여러 명인 것을 보면 세션 쉴드 애드온에 어떠한 결함이 있는 게 아닌가 싶습니다.
혹여나 짐작되는 기술적 문제가 있는지 여쭤보고 싶습니다. -
기진곰
2015.02.13 19:38
아래에서 AJKJ님이 지적하신 문제(race condition)가 아닐까 생각되네요.
고쳐보도록 하겠습니다.
-
AJKJ
2015.02.13 17:30
쿠키 재생성 부분에서 문제가 있을것 같습니다
다음과 같은 문제가 있지 않을까요?
1. 통신이 불안정한 상태에서 파일업로드 요청 시작 or 페이지 로딩 요청. session_id=aaaaaaaaaaaa (0초 : request A)
2. 사용자가 다른 페이지를 더 빠르게 불러드리면서 기막힌 타이밍에 session_id 변경 session_id=bbbbbbbbbb (1초 : request B 1.5초 : resposne B)
3. request A가 서버에 도착할때쯤(2초) 이면 이미 무효된 세션을 가지게 됨.
4. 사용자가 response A(3초)를 받으면 로그아웃 된 페이지 처럼 보이게 됨. or 파일업로드 실퍠 (다른 페이지를 누리면 정상 로그인이 유지되나, 일반 이용자는 눈치채지 못함)
그리고 다음 링크에서 일부 서버환경에서 세션을 놓치는 문제가 있다고 하는데 참고하시면 좋을듯해요.
https://www.xpressengine.com/forum/22847766#comment_22848339
-
기진곰
2015.02.13 20:55
네, 항상 경쟁상태(race condition)가 문제죠. 두 가지 종류가 발생할 수 있겠는데요...
첫째는 AJKJ님이 말씀하신 것처럼 네트워크 환경 때문에 요청 순서가 뒤바뀌는 경우입니다. 일단, 쿠키 갱신 후에도 30초간 예전의 쿠키를 계속 사용할 수 있도록 변경해 보았습니다. 제가 만들어본 다른 프로그램에서는 이 정도만 해줘도 웬만한 경쟁상태는 피할 수 있더군요. 아무리 통신이 불안정하더라도 30초 이상 걸리면 연결을 끊어버리는 것이 보통이니까요. (더 길게 허용할 수도 있지만, 너무 봐주면 오히려 보안이 나빠집니다.)
둘째는 서버단에서 세션을 불러와 사용하고 저장하는 과정에서 발생하는 경쟁상태입니다. PHP에서 세션을 파일로 사용할 경우에는 자동으로 lock이 걸려서 순차적으로 접근하기 때문에 문제가 없지만, DB나 Memcached 등으로 사용하면 lock이 없기 때문에 두 페이지가 동시에 세션을 갱신해버리는 수가 있지요. 다음 버전에서는 여기에 뭔가 mutex를 걸어버리는 방법을 연구해 봐야겠습니다.
업로더는 PHPSESSID를 사용하도록 되어 있는데, PHPSESSID는 전혀 건드리지 않으므로 업로더와는 상관없을 거라고 생각합니다. procFileUpload act 사용시에는 애드온 작동을 일시 중지하도록 조치하기도 했고요.
-
기진곰
2015.02.13 22:14
DB, Memcached 등을 사용해도 세션이 동시에 여러 군데에서 수정될 가능성을 최소화하기 위해, 갱신 직전과 직후에 각각 session_write_close() && session_start() 해주고, 그 사이에 세션이 변경될 경우 갱신을 포기하는 (즉, 지금은 위험하니 다음으로 미루는) 코드를 추가해 보았습니다. 일종의 mutex를 동기화해 주는 거죠.
사실 XE는 그 묵직함-_- 때문에 처음 세션을 시작할 때(Context::init)와 마지막에 세션을 닫을 때(Context::close) 사이의 시간차가 상당히 나는 편입니다. 시간차가 많이 날수록 경쟁 상황이 발생할 가능성도 기하급수적으로 증가하죠. 방금 말씀드린 방법으로 시간차를 확 줄여버리면 문제가 발생할 여지도 확 줄어들 것 같습니다.
-
misol
2015.02.14 12:08
SSL 항상 사용일 경우, 세션 키를 secure 속성으로 굽는 것은 어떤가요?? -
기진곰
2015.02.14 22:32
단 한 페이지라도 SSL을 사용할 경우 xe_secure_ssl이라는 별도의 쿠키를 secure 속성으로 구워주고 있습니다.
혹시 "세션 키"가 PHPSESSID를 의미하는 거라면 그건 어렵습니다. PHPSESSID는 업로더 등 여러가지 문제가 걸려 있어서 건드리기 힘들 뿐더러, 세션 쿠키의 속성을 바꾸려면 세션을 시작하기 전에 미리 session_set_cookie_params() 함수를 써줘야 하는데 그 시점에서는 애드온이 끼어들 수가 없습니다. 별도의 쿠키로 구현한 것도 그 때문이고요.
-
AJKJ
2015.02.14 21:51
5분 간격으로 session regeneration을 하면 어떠한 보안상의 잇점이 있는지 알려주실 수 있을까요?
제가 생각하는 부분은 통신망을 감청(WiFi 스니핑 등등) 가능한 상황에서 여러개의 세션쿠키를 수집하고, 5분 이후에 사용하려고 할때, 만료된 세션이라서 계정에 접속하지 못하는 것 정도만 생각이 나네요.
만약 위 경우만이 문제가 된다면 FULL SSL 환경에서는 session regeneration을 로그인 또는 로그아웃에 한정시키는건 어떨가 싶어요.
-
기진곰
2015.02.14 22:46
네, 훔친 세션에 유통기간이 있다는 의미죠. 워낙 오래 전부터 당연히 해야 하는 것으로 받아들여져 오긴 했는데, 보안 기술과 해킹 기술 모두 엄청나게 발달해버린 2015년 현재 현실적으로 얼마나 도움이 될지는 저도 의심이 됩니다. 옆집 중딩이 훔친 세션으로 이리저리 기웃거리는 것을 막을 수는 있겠지만, 전문적인 해커라면 불과 몇 초 사이에 자기 목적을 이루고 사라져 버리겠죠.
일단 경쟁상태가 발생할 여지를 최소화해 놓고 좀더 테스트해 보고, 계속 문제가 발생한다면 세션 식별자 재생성 기능 사용 여부를 사용자가 선택할 수 있도록 하는 방법도 생각중입니다. 물론 로그인시에는 당연히 해줘야 하고요. 로그아웃시에는 따로 뭘 재생성할 필요도 없이 XE 코어 자체에서 세션을 완전 파괴해 버리더군요 ㅋㅋ
EDIT: 일단 POST 요청, AJAX 요청, 플래시를 사용한 요청에서는 세션 식별자를 재생성하지 않고 "예약"만 하도록 조치했습니다. 예약된 재생성은 나중에 평범한 (페이지 전체를 새로 로딩하는) GET 요청을 할 때에 이루어집니다.
XE 보안을 위해 많은 노력을 해주셔서 감사합니다.