사건 개요
- 사건 번호 : KB831678
- 범인/가해자 : 마이크로소프트 IE 6.0 (SP1) , showModalDialog 메쏘드 및 showModelessDialog 메쏘드.
- 피해자 : 쿠키 분실로 인한 프로그램 오작동으로 인해 밤새도록 고민하고 삽질한 다수의 선량한 불특정 개발자들.
- 피해내용 :
-. window.open 메쏘드 호출 시 나타나는 팝업에서 쿠키가 사라지는 현상이 종종 발생함.
-. 쿠키가 사라짐에 따라 쿠키를 기반으로 하는 ASP.NET, ASP 세션 기능이나 쿠키 기반의 인증이 모두 작동하지 않음.
- 범행동기 : By Design.
- 범죄예방 방법 : window.open 호출 코드 수정 필요.
사건 줄거리
웹 어플리케이션에서 window.open 호출을 통해 팝업 윈도우를 띄울 때, 쿠키가 없어지는 현상이 종종 발생한다는 개발자들의 신고가 112 버그 신고 센터에 접수되어 수사에 착수. 사건 현장을 곧바로 봉쇄하고 테스트에 들어갔으나 쿠키가 없어지는 현상 발생하지 않음. 주변에 잠복근무를 수행하면서 동일 범행이 발생하길 기다렸으나 사건은 발생하지 않음. 사건은 미궁에 빠지고 잠시 잊혀지는 듯 했음. 하지만 지속적으로 개발자들의 쿠키 분실 신고가 들어옴. 탐문 수사에 들어간 수사팀은 modal 다이얼로그에서 window.open 으로 열리는 경우에만 쿠키가 사라지는 현상이 발생한다는 제보를 접수했지만, 항상 쿠키가 사라지는 것은 아니였음.
동일 범죄의 유무를 MS 범죄 데이터베이스에서 검색 도중 동일 범죄에 관련된 KB 자료 발견. 이 자료에 의하면 showModalDialog 혹은 showModelessDialog에 의해 생성된 다이얼로그 윈도우 내에서 window.open 이 호출되면 메모리 기반 쿠키(세션 쿠키, 메모리 쿠키라고도 함)가 사라지는 현상이 발생된다는 것임. 이 자료에 의해 범죄를 시스템상에서 재연하는데 성공하였고 범인을 찾아냄. 해결 방법은 단순히 window.open을 사용하는 것이 아닌 showXXXDialog 를 호출한 window 객체를 통해서 open 메쏘드를 호출하는 것임. 이를 위해 showXXXDialog를 호출하는 스크립트에서 window 객체를 매개변수를 통해 다이얼로그 윈도우에 넘겨줄 필요가 있음. (다이얼로그 윈도우에서 window.parent, window.opener 등은 모두 null 을 반환함) 상세한 방법은 KB 자료를 참고하기 바람.
사건의 원인 분석
사건 이해를 위한 기본 지식은 다음과 같음.
- 메모리 기반의 쿠키는 IEXPLORE.EXE 프로세스의 메모리에 기록됨.
- window.open 호출로 인해 나타나는 팝업 윈도우는 호출자 프로세스와 동일한 프로세스 내에서 작동하는 윈도우를 생성함. (파일 메뉴의 새로 만들기 | 창 메뉴로 수행하는 것과 동일)
- window.showXXXDialog 메쏘드에 의해 나타나는 다이얼로그 윈도우 역시 호출자 프로세스와 동일한 프로세스 사용함.
위 기본 지식에 의하면 showXXXDialog 호출에 의해 나타나는 윈도우에서 다시 window.open 호출을 통해 팝업을 띄우더라도 동일 프로세스를 사용해야 할 것임. 하지만, showXXXDialog 내에서 window.open 호출은 COM 자동화(automation)에 의해서 팝업 창을 생성함. COM 자동화는 이미 다른 IEXPLORE.EXE가 수행중이라면 이 프로세스 내에서 윈도우를 생성하여 버림. 따라서 두 번째로 수행된 IEXPLORE.EXE 프로세스 상에서 showXXXDialog가 수행되고 이 다이얼로그에서 window.open을 호출하면 첫번째 프로세스에서 팝업 윈도우를 생성함. 첫번째 프로세스의 메모리 쿠키 내용과 두번째 프로세스의 메모리 쿠키 내용은 동일하지 않음. 이 때문에 쿠키가 사라지는 듯한 현상을 느끼게 됨.
쿠키가 사라지는 현상이 매번 나타나지 않은 이유는 첫 번째 프로세스 상에서 showXXXDialog 가 호출되고 이 다이얼로그에서 다시 window.open 이 호출되면 동일 프로세스상에서 팝업 윈도우가 수행되므로 쿠키가 유지되기 때문임.
현장 검증
이 현상을 정확하게 reproduce 하기 위해서 KB 자료 의 내용을 그대로 따라서 수행하면 됨. parent.asp를 표시했을 때의 세션 ID 값을 잘 기억하기 바람. Modal 다이얼로그가 나타난 후 problem 버튼을 누르면 parent.asp가 표시하는 세션 ID와 다른 세션 ID가 나타남. (세션은 쿠키 기반이고 서로 다른 쿠키 값을 사용함으로써 서로 다른 세션 처럼 보이게 되는 것임)
주) Windows 2003 사용자는 ASP 테스트를 위해 웹 서비스 확장 에서 ASP ISAPI Extension을 '사용함'으로 설정할 것.
사건 예방
동일 피해를 당하지 않기 위해서는 다이얼로그 웹 페이지에서 단순히 window.open을 호출해서는 안됨. KB 자료 에서 권장한 방법대로 showXXXDialog를 호출한 페이지에서 다이얼로그에 window 객체를 매개변수로 넘겨주고 이 window 객체에 대해서 open 메쏘드를 호출해야 함.
사건에 대한 의견
당황스럽게도 범행 동기가 By Design 임. 선량한 대다수의 개발자는 이러한 사실을 모르고 있으며 원인을 모르는 쿠키 / 세션 분실로 고통 받고 있음. 이 사건의 직접적인 범인은 IE 6.0 (SP1 포함)과 showXXXDialog 메쏘드 이지만, 이 배후에는 마이크로소프트의 모종의 음모가 있을 것으로 추측됨. 아직 수사 결과로서 정확히 알아내지 못했지만 보안이나 기타 등등의 이유로 다이얼로그에서 window.open이 호출되면 COM 자동화를 사용하는 것 같음.
이상. 사건 보고서 끝.