원문출처 : http://www.microsoft.com/korea/technet

매일 매순간 누군가 어딘가에서 웹을 누비고 다니며 해킹할 사이트가 없을까 노리고 있다는 사실을 염두에 두도록 합시다. ASP.NET 개발자들은 어떤 해킹 시도도 성공하지 못하도록 항상 경계 태세를 늦추지 말아야 합니다. 다시 말해서 사용자의 입력 내용을 제약 및 검증하고, 데이터베이스를 안전하게 평가하고, 중요한 데이터를 안전하게 저장하고, 이처럼 악의적인 해커들이 발붙이지 못하게 쫓아낼 수 있는 보안 코드를 일상적으로 작성해야 합니다.


ASP.NET 사이트가 방어해야 하는 전형적인 해킹 공격의 형태는 세션 하이재킹(session hijacking)입니다. 간단히 설명해서, 세션 하이재킹이란 웹 사이트에 연결할 때 다른 사람의 세션 상태에 액세스하는 것을 말합니다. 이로 인해 초래되는 손상의 심각성은 세션 상태에 무엇이 저장되어 있느냐에 따라 달라집니다. 세션에 쇼핑 손수레 정보가 포함되어 있으나 사용자가 결제하기 전에 사용자의 신원을 확인하도록 되어 있는 경우에는 세션 하이재킹이 그리 위험하지 않을 수도 있습니다. 그러나 세션에 신용카드 번호나 이와 유사한 정도의 중요한 데이터가 포함되어 있고 이러한 정보가 사용자에게 다시 제시될 수 있는 경우라면 정말로 주의를 기울여야 합니다.


세션 하이재킹 공격은 일반적으로 세션 ID 추측 및 세션 ID 쿠키 도용이라는 두 가지 방법 중 하나를 통해 이루어집니다. 세션 ID 추측이란 세션 ID 샘플을 수집하여 다른 사람에게 할당된 유효한 세션 ID를 "추측"하는 방식을 말합니다. ASP.NET 응용 프로그램은 ASP.NET이 세션 ID에 대해 무작위의 120비트 숫자를 사용하기 때문에 이러한 형태의 세션 하이재킹에 대해서는 그다지 취약하지 않은 편입니다. ASP.NET 세션 ID를 사용자 자신의 ID로 교체하지만 않는다면(지난 여름에 바로 이러한 방식을 써서 순차적 세션 ID를 사용한 개발자를 만난 적이 있는데, 이것은 해커들에게 문을 활짝 열어주는 것이나 다름 없는 일입니다), 세션 ID 추측 방식에 대해서는 전혀 걱정하지 않아도 됩니다.


그러나 훔친 세션 쿠키는 또 다른 문제입니다. 연결된 세션 ID 쿠키를 보호하기 위해 SSL(Secure Sockets Layer)을 사용할 수 있으나 암호화된 연결에 대해 세션 ID 쿠키를 제한하는 사이트는 거의 없습니다. SSL을 사용하더라도 세션 ID 쿠키를 다른 방식으로 훔칠 수 있으며 이러한 방식 중 널리 알려진 것으로는 교차 사이트 스크립팅 공격, 중간에서 데이터를 가로채고 위조하는 man-in-the-middle 공격, 피해자 PC의 쿠키 저장소에 물리적으로 접근하는 방식 등이 있습니다. 더구나 공격자 측에서 거의 아무런 기술이 없어도, 훔친 세션 ID 쿠키를 이용하여 세션 하이재킹 공격을 성공적으로 수행할 수가 있습니다. 그 이유는 간단합니다. ASP.NET은 세션 ID 쿠키에 세션 ID 외에는 어떤 정보도 인코딩하지 않기 때문입니다. ASP.NET은 유효한 세션 ID가 포함된 쿠키를 받게 되면 아무런 질문도 하지 않고 해당 세션으로 연결합니다.


훔친 세션 ID 쿠키를 이용하는 공격에 대한 방어 체계를 아주 간단하게 구축한다는 것은 사실상 불가능한 일이지만 공격을 어렵게 만들기 위한 조치는 취할 수 있습니다. 예를 들어 일부 웹 사이트는 세션 ID에 IP 주소와 같은 추론적 정보를 인코딩합니다. 하지만 결국에는 몇몇 해커들이 IP 주소를 속이는 방법을 알아내므로, 이러한 방법으로 세션 하이재킹을 전적으로 예방할 수는 없습니다. 어쨌든 IP 주소는 호출자를 식별하기 위한 신뢰할 수 있는 방법은 아니지만 안전 기준을 높일 수는 있습니다. 보안이란 결국 안전 기준을 높이는 것을 뜻합니다. 해커가 공격을 수행하기 어렵게 만들수록 공격의 성공 가능성도 줄어들 것입니다.

SecureSessionModule 도입


필자는 ASP.NET에서 훔친 세션 ID 쿠키를 사용하는 것이 좀더 어려웠더라면 좋았을텐데라고 푸념하는 대신 뭔가 조치를 취하기로 결정하고, SecureSessionModule이라는 HTTP 모듈을 개발했습니다. 이 모듈은 ASP.NET HTTP 파이프라인에 위치하며 세션 ID 쿠키에 대한 들어오는 요청과 나가는 응답을 모니터합니다(그림1 참조). [편집자 업데이트 - 2004년 7월 20일:공격자에게 지나치게 많은 정보를 제공하지 않도록 그림 1을 업데이트하였음]


그림 2는 SecureSessionModule이 어떤 방식으로 작동되는지 보여줍니다. 먼저 이 모듈은 ASP.NET의 SessionStateModule에서 발급한 세션 ID 쿠키에 대한 모든 나가는 응답을 일일이 확인합니다. 이러한 쿠키가 발견되면 SecureSessionModule은 해시된 메시지 인증 코드(MAC)를 세션 ID에 부가하는 방식으로 이 쿠키를 수정합니다. 세션 ID, 요청자의 IP 주소에서 네트워크 주소 부분(예: 192.16.0.14의 192.16 부분), 요청 시 받은 사용자 에이전트(User-Agent) 헤더 및 서버에 저장된 비밀 키를 통해서 MAC가 생성됩니다. 이 프레임워크의 System.Security.Cryptography.HMACSHA1 클래스를 이용하면 MAC 생성 작업을 아주 손쉽게 할 수 있습니다. 그렇다면 전체 IP 주소를 사용하지 않고 네트워크 주소를 사용하는 이유는 무엇일까요? AOL과 같은 공용 프록시 서버를 통해 인터넷에 액세스하는 사용자의 노드 주소는 요청 시마다 달라질 수 있으나 네트워크 주소는 변하지 않기 때문입니다.


그림 2 SecureSessionModule

둘째, SecureSessionModule은 ASP.NET 세션 ID 쿠키에 대한 모든 들어오는 요청을 점검합니다. 세션 ID 쿠키가 포함된 요청에 대해 파이프라인 통과를 허용하기 전에 SecureSessionModule은 요청자의 IP 주소, 사용자 에이전트 헤더 및 비밀 키를 통해 MAC를 생성함으로써 쿠키를 검증합니다. 새로 계산된 MAC가 쿠키에 있는 MAC와 일치하면 이 MAC는 쿠키에서 삭제되고 요청이 진행될 수 있습니다. 만일 MAC가 일치하지 않으면 SecureSessionModule은 그림 3에 나타난 바와 같이 InvalidSessionException을 발생시킵니다.


그 결과 세션 ID 쿠키는 발급된 후에는 동일한 네트워크 주소에서 동일한 사용자 에이전트 헤더와 함께 제출되는 경우에만 유효한 것으로 인정됩니다. 세션 ID 쿠키를 훔친 공격자라도 IP 주소와 HTTP 헤더를 속일 수 있는 경우에만 이를 사용할 수 있습니다. 물론 두 가지 모두 가능하지만 이러한 종류의 속임수를 사용하려면 공격자가 상당한 수준의 기술을 가지고 있어야 합니다. 또한 위장한 IP 주소를 사용한 요청으로부터 응답을 받는 일은 처음부터 단순히 요청을 제출하는 방식보다 훨씬 더 어려우며 적절한 출력단 필터링(egress filtering)으로 차단될 수 있습니다. 공격자가 쿠키 안의 해시를 MAC 생성에 사용되는 비밀 키 없이 자신의 IP 주소와 사용자 에이전트 헤더로 생성한 해시로 간단히 바꾸기란 불가능합니다. 이 비밀 키만 제대로 보안이 유지되는 한 보통의 해커들은 훔친 세션 ID를 악의적인 목적에 사용하기가 실지로 힘든다는 사실을 알게 될 것입니다.

SecureSessionModule 배포


SecureSessionModule 배포는 간단히 SecureSessionModule.dll을 응용 프로그램 루트의 하위 디렉터리로 복사하고 다음과 같이 Web.config에 등록하기만 하면 됩니다.

<configuration>  <appSettings>    <add key="SessionValidationKey"      value="DAD4D476F80E0148BCD134D7AA5C61D7" />  </appSettings>  <system.web>    <httpModules>      <add name="SecureSession"        type="SecureSessionModule,           SecureSessionModule" />    </httpModules>  </system.web></configuration>



Web.config의 섹션에 SessionValidationKey 값이 필요합니다. 이것은 MAC 생성에 사용되는 "비밀 키"로서 SecureSessionModule는 로드 시 이 비밀 키를 찾으며 비밀 키가 없는 경우에는 예외를 발생시킵니다. 이 키는 모든 응용 프로그램에 대해 고유해야 하며 긴 임의의 수를 사용해야 합니다. 그림 3에서 비밀 키를 생성할 때 .NET Framework RNGCryptoServiceProvider 클래스로 구축된 간단한 도구를 사용했습니다. 임의성을 극대화하기 위해서는 이와 유사한 도구를 사용해야 합니다. 또한 웹 그룹에 배포할 경우 SessionValidationKey는 모든 서버에 동일해야 합니다. 물론 구성 파일에 일반 텍스트 보안 키를 저장하면 위험을 야기할 수 있습니다. 보안 기준을 좀더 강화하려면 비밀 키의 암호화를 고려해 보십시오. ASP.NET로부터 Windows DPAPI(Data Protection API)를 사용하는 방법은 안전한 ASP.NET 응용 프로그램 구축: 인증, 권한 부여 및 보안 통신 문서에 설명되어 있습니다. DPAPI는 키 관리 문제, 특히 암호 해독 키 저장 문제를 운영 체제 자체로 넘겨주므로 구성 파일에서 비밀 내용을 암호화하는 데 이상적인 도구입니다.


SecureSessionModule가 ASP.NET가 해시에 사용하는 것과 동일한 비밀 키, 즉 Machine.config의 요소에서 validationKey 속성 값을 사용하는 것이 이상적입니다. 하지만 이러한 키를 검색하는 공용 API가 없을 뿐더러, 프레임워크가 validationKey를 검색하는 방식을 살펴본 후 .NET의 향후 버전과의 비호환 가능성을 피하기 위해 프레임워크의 논리를 복제하지 않기로 결정했습니다. .NET Framework의 2.0 버전에서 제공될 새로운 구성 API는 이러한 누락을 시정하고 ASP.NET 유효성 검사 키를 읽을 수 있는 문서화된 수단을 제공해줄 것이기 때문입니다.


일단 배포가 완료되면 SecureSessionModule은 수동적으로 작동하므로 중간 개입이 필요 없습니다. 원한다면 Global.asax에 Application_Error 메서드를 삽입하여 Windows 이벤트 로그나 다른 어떤 곳에 InvalidSessionExceptions를 기록하게 할 수 있습니다. 이런 방식을 이용하면 매일 아침 커피를 마시면서 로그를 점검하여 누군가가 흠친 세션 ID로 서버를 속이려고 시도했는지 여부를 확인할 수 있습니다. 이러한 메서드는 다음과 같습니다.


<%@ Import Namespace="System.Diagnostics" %>
<script language="C#" runat="server">
void Application_Error(Object sender, EventArgs e)
{
// Write an entry to the event log
EventLog log = new EventLog ();
log.Source = "My ASP.NET Application";
log.WriteEntry (Server.GetLastError().ToString(), EventLogEntryType.Error);
}
</script>

경고

생산 웹 서버에 SecureSessionModule를 배포하기 전에 다음과 같은 여러 잠재적인 문제를 고려해야 합니다.


첫째, SecureSessionModule은 불법 세션 ID 쿠키를 모두 완벽하게 발견할 수는 없습니다. 공격자가 피해자와 동일한 네트워크 주소를 가지고 있거나(예를 들어, 둘 다 동일한 프록시 서버을 사용할 경우) 또는 피해자의 네트워크 주소를 속일 수 있다면 사용자 에이전트 헤더만으로는 방어를 기대하기 어렵습니다. 사용자 에이전트 헤더가 세션 ID의 유효성을 확인하는 데 사용되고 있다는 것을 알기만 하면 누구든 사용자 에이전트 헤더를 쉽게 속일 수 있기 때문입니다.

둘째, 어떤 이유로든 사용자의 네트워크 주소나 사용자 에이전트 헤더가 요청별로 달라지는 경우 이 사용자는 자신의 세션 상태에 대한 액세스 권한을 잃게 됩니다. 셋째, SecureSessionModule은 쿠키가 없는 세션 상태에서는 사용할 수 없습니다. 이 모듈은 세션 ID가 URL이 아닌 쿠키로 통과된다는 것을 전제로 하기 때문입니다.

마지막으로 SecureSessionModule은 아직 생산 환경에서 테스트되지 않았습니다. 사용하시다가 혹시 결함이 발생할 경우 저에게 연락해 주시기 바랍니다. Microsoft는 ASP.NET에 이와 유사한 보안 장치 구축을 항상 고려해 왔으나 이로 인한 이전 버전과의 호환성의 문제 때문에 아직 추진하지 못하고 있습니다.

결론

세션 하이재킹(Session hijacking)은 보안에 심각한 위협을 미치는 존재로 남아 있습니다. SecureSessionModule은 세션 ID 쿠키에 세션 소유자에 대한 증거를 요소로 포함시킴으로써 훔친 세션 ID를 사용하여 세션을 강탈하려는 해커에 대항하여 보안 기준을 높일 수 있습니다. 네트워크 주소 또는 사용자 에이전트 헤더 모두 사용자를 구별하기 위해 확실하게 믿고 사용할 수 있는 방법은 아니기 때문에 이러한 증거가 결정적이라고 할 수 없지만, 그렇다고 하더라도 다른 사용자의 세션에 연결하여 데이터를 가로채어 웹 서버를 손상하려고 호시탐탐 기회를 노리는 해커들의 진로에 이러한 증거가 추가적인 장애물의 역할을 할 수 있을 것입니다.

출처 : [기타] 블로그 집필 - 간지코드 원문출처 : http://www.microsoft.com/korea/technet

Posted by 퓨전마법사
,