보안 가이드

이 가이드에서는 열린 웹을 구축할 때 염두해야 할 보안과 개인정보에 관련된 여러가지 가이드라인을 제시합니다.

웹 검색을 차단함으로 해결했다고 생각하지 않기

웹 검색을 통해 민감한 개인정보가 유출되는 사고를 겼었을 때, robots.txt등으로 검색을 차단하고나서 해당 정보가 검색 엔진에 드러나지 않았는 것을 확인하고 ‘이제는 안전하다’라고 착각할 수 있습니다. 이것이 착각인 이유는

  • 검색 엔진은 공개된 웹의 정보만을 보여줍니다. 거꾸로 생각하면 검색 엔진에 개인정보가 나왔다는 말은 그 개인정보가 공개되었다는(로그인 등을 통하지 않고도 누구나 볼 수 있게 된) 뜻입니다. 검색 엔진을 통하지 않고도 그 정보는 누구나 접근할 수 있는 상태인데, 검색 엔진을 막았다고 해결이 되었다고 생각하면 안 됩니다.
  • 그래도 대부분의 검색 엔진에 나오지 않으니 확산을 막았다고 생각할 수 있는데, 웹 상의 정보는 검색 엔진만이 접근하는 것이 아니며, 개인정보만을 노리는 악성 소프트웨어 로봇이 존재한다는 것을 알아야합니다. 이런 로봇들은 robots.txt도 무시하고 사이트에 접속하여 특정 패턴(주민등록번호 등)을 찾아 민감한 정보만을 빼내어 암시장 등으로 유포할 수 있는데, 검색 엔진을 막는 것과는 무관한 일입니다.

대문의 자물쇠가 고장이 나서 도둑이 들어왔다고 했을 때, 지도에서 우리집을 삭제한다고 해서 집이 안전해지지는 않습니다. 마찬가지로, 웹의 지도 역할을 하는 검색 엔진을 차단할 것이 아니라, 사이트 자체의 보안을 견고하게 하여 소중한 정보를 보호해야 합니다. 이를 위해서 지켜야 할 여러가지 팁을 아래에 소개합니다.

URL에 개인 식별 정보 넘기지 않기

URL을 통해서 보내는 파라미터는 검색 엔진에서 색인이 가능한 정보입니다. 따라서 URL에 사용자 ID나 비밀번호, 또는 세션 정보등의 개인 식별 정보(Personally Identifiable Information, 또는 PII)를 URL에 포함시키는 것은 결코 좋은 방법이 아닙니다. 개인 식별 정보를 HTTP의 GET 방식(URL을 사용하는 방법)이 아닌 POST 방식을 사용하여 웹 서버에 전달하면 이런 문제를 막을 수 있습니다. 아래는 실제 사례를 바탕으로 한 예입니다.

  • 사용자 아이디나 비밀번호가 URL에 들어간 좋지 않은 예: http://www.example.com/logic/login_post.php?job=join&subjob=write&id=홍길동&pw=1111
    • 게시판에 글을 올릴 때 사용자의 아이디(홍길동)과 암호(1111)가 URL에 포함이 되어버려 검색 엔진에 그대로 노출이 될 수 있는 경우입니다. 아이디와 암호와 같은 개인 식별 정보는 POST 방식을 사용하여 전달하는 것이 옳습니다. 로그인 정보와 같이 민감한 정보는 HTTPS를 사용하여 사용자와 웹 서버간의 통신을 암호화하는 것이 더 나은 보안을 위해서 좋습니다.
  • 글을 수정하는 페이지 URL가 노출된 나쁜 예: http://www.example.com/board/product/modify.html?board_act=edit&no=721&board_no=6
    • 게시판 등에서 특정 게시글을 수정하는 페이지가 URL로 되어있는 경우입니다. 이런 경우 자체가 문제는 아니지만, 만일 로그인하지 않고도 해당 URL만으로 수정할 수 있도록 되어 있으면 문제가 있습니다. 글을 수정하는 경우는 로그인을 요구하고, 게시판 번호(6)과 게시글 번호(721) 등의 정보를 POST 방식으로 웹 서버에 넘기는 게 좋습니다.
  • 적절한 정보만 들어간 좋은 URL의 예: http://www.example.com/bbs/board.php?bo_table=g4_qa&wr_id=229048
    • 이 경우 사용자 아이디와 암호가 POST 방식으로 전달되어 URL에 개인 식별 정보가 나타나지 않습니다. 그와 동시에 URL만으로 해당 콘텐츠에 접근할 수 있기 때문에 검색 친화적인 URL이라고 볼 수 있습니다. 게시판의 게시글 보기의 경우에 각 게시글을 URL만으로 접근할 수 있도록 해야 합니다.

정리하면 다음과 같습니다.

  • 안전한 개인정보 관리를 위해서 개인 식별 정보는 POST 방식을 사용하여 전달하고 그 외의 경우는 GET 방식을 사용하는 것이 좋습니다.
  • 게시물 검색, 목록보기, 내용보기 등은 GET 방식을 사용합니다.
  • 게시물 작성 페이지(보통 아이디/비밀번호 등을 넣게 되어있는), 로그인 페이지 등은 POST 방식을 사용합니다.

로그인 여부를 체크하는 일은 반드시 서버에서 하기

로그인 여부를 체크하고 로그인하지 않았으면 해당 페이지를 접근하지 못하도록 하는 일은 웹 서버에서 해야할 일입니다. 클라이언트(웹 브라우저)는 사용자가 페이지에 접근할 자격이 있는지, 서버가 판단한 결과만을 받아야 합니다. 이런 작업을 웹 페이지 상에서 자바 스크립트를 사용하여 처리하는 경우가 있는데, 이는 사용자 정보를 다른 이들이 볼 수 있게 노출하게 되는 결과를 낳을 수 있습니다. 이는 HTML 페이지의 자바 스크립트 코드가 클라이언트, 다시 말해 사용자의 웹 브라우저에서 실행되기 때문입니다. 예를 들어 보겠습니다.

[phone_numbers.html]

<html>
  <script>
  if (IsUserLoggedIn()) {
      alert("로그인하세요.");
      window.location = "/login.html";
  }
  </script>
  <body>
  회원 목록 및 전화번호
  ...
  </body>
</html>

이것은 phone_numbers.html라는, 한 동호회의 회원 목록과 전화번호를 볼 수 있는 HTML 페이지의 일부분입니다. 페이지가 열릴 때 IsUserLoggedIn()라는 함수를 통하여 사용자가 로그인하였는지 확인하고, 로그인하였으면 페이지의 내용를 보여주고, 그렇지 않으면 login.html로 바로 이동하여 사용자의 로그인을 유도하게 되어있습니다. 하지만 만약 웹 브라우저의 자바 스크립트를 끄고 보거나, phone_numbers.html의 소스를 본다면 어떨까요? 이 목록이 고스란히 드러날 것입니다. 검색 로봇 또한 자바 스크립트를 실행하지 않는 클라이언트이므로 마찬가지로 이 목록을 그대로 수집하고, 검색 가능케 합니다.

무척 단순한 예시이기는 하나, 사용자의 로그인 여부를 확인하는 일과 같이 서버가 해야할 작업은 반드시 서버에서 해야하는 이유를 극명하게 보여줍니다.

필요없는 개인정보 수집하지 않기

웹 서비스를 제공하기 위해 개인정보를 수집해야 하는 경우가 있긴 하지만, 서비스를 제공하는 데 필요가 없는 정보를 수집하는 것은 지양해야합니다. 회원가입에 필요한 기본 정보는 이메일, 아이디, 암호 정도입니다. 특별한 이유없이 주민등록번호*나 주소 등, 민감한 개인정보를 수집하고, 또 이를 제대로 관리하지 않아서 개인정보 유출 사고 등으로 이어지는 경우가 많습니다. 회원에게 정보를 수집하기 전에 서비스에 반드시 필요한 정보가 무엇인지 검토하고, 그런 정보가 어떻게 쓰이고 관리되는지 사용자에게 알리는 것만으로 큰 사고를 미연에 방지할 수 있습니다.

* 주민등록번호는 2012년 8월 18일부로 수집이 금지되었습니다.

불필요한 파일을 웹에 올리지 않고 문서 파일 내의 내용에 주의하기

정상적인 검색 로봇은 사용자가 웹주소(URL)로 접근할 수 있는 웹 문서를 수집합니다. 그렇게 수집한 정보는 기본적으로 공개된 것이라 가정(인터넷 사용자 누구나 볼 수 있으므로)을 하고 검색 결과에 반영합니다. 하지만 개인 정보 등의 비공개 정보가 관리자 또는 사용자의 실수로 공개된 웹페이지에 게시되어, 검색 결과에 노출이 되는 경우가 종종 발생합니다. 웹 사이트를 더욱 견고하게 구성하고 개인 정보를 보다 안전하게 관리하는 것이 무엇보다 중요하지만, 애초에 불필요한 파일이나 정보를 웹에 올리지 않는다면 이런 사고가 발생해도 그 피해를 줄일 수 있습니다. 공개된 웹은 ‘백업’을 위한 공간이 아닙니다. 웹 사이트의 기능과 상관없는 정보를 무분별하게, 불필요하게 올리는 일은 지양해야합니다.

웹에 게시하는 문서파일의 내용에도 주의하여야합니다. HTML 페이지가 아니라고 해서 검색에 노출되지 않을 거라고 생각하면 오산입니다. 대부분의 검색 엔진은 .pdf, .xls (엑셀), .doc, .hwp등 바이너리 문서들을 마치 HTML를 보듯 내용을 수집하고 분석하여 검색 결과에 반영할 수 있습니다. 개인 정보를 포함하고 있는 문서들(이력서나 회원 목록, 연락처 등)은 첫째) 공개된 웹에 올리지 않고, 둘째) 필요한 경우는 문서 자체를 암호화하고, 셋째) 문서를 게시하는 곳이 안전한 로그인 절차 등을 거친 사용자만이 열람할 수 있는 곳인지 반드시 확인하여야 합니다. 하지만 가능하면 비공개 사항은 공개된 곳에 게시하지 않는 것이 좋습니다.

웹 서버의 Directory Listing 끄기

웹 서버의 기능 중 웹 페이지가 아닌 어떠한 디렉토리를 접속했을 때 (예: http://www.example.com/documents/), 그 디렉토리의 파일 목록을 보여주는 기능(Directory Listing)이 있습니다. 이 기능을 사용할 경우 사용자가 웹 브라우저에 해당 디렉토리의 경로를 입력하는 것으로 디렉토리 내의 정보를 쉽게 열람할 수 있게 됩니다. 만약 이 디렉토리로의 링크가 공개될 경우, 검색 로봇 또한 링크를 따라가 디렉토리 정보를 수집하기 때문에 비공개 정보가 검색 결과에 포함되는 결과로도 이어질 수 있습니다.

디렉토리 안에 있는 파일의 접속이 제한되어있어도 디렉토리의 구조를 보여주는 것부터가 웹 사이트의 보안을 취약하게 만드는 이유가 됩니다. 웹 서버의 환경설정을 통해 이 기능을 404 페이지나 다른 기본 페이지로 리디렉트 하는 것으로 만일의 사태를 미연에 방지할 수 있습니다.

robots.txt로 공개/비공개를 정하지 않기

만약 로그인을 한 사용자만이 접속 가능한 디렉토리가 있다면, 아래와 같이 자연스럽게 그 디렉토리를 robots.txt에서 Disallow문을 사용하여 검색을 차단하여 비공개 처리하는 것이 좋다고 생각하실지도 모릅니다.

User-agent: *
Disallow: /admin/    # 관리자 도구
Disallow: /private/  # 개인 정보
Allow: /public/      # 공개 정보
...

이런 경우 검색이 되는 것은 차단이 가능하지만, 의도와는 달리 robots.txt를 통해 웹 사이트의 구조와 민감한 정보의 위치를 공개하여, 오히려 악의적인 해커들에게 힌트를 줄 수 있다는 우려가 있습니다. 이를 비켜갈 수 있는 여러가지 방법이 있는데, 두 가지만 소개합니다.

  • 모든 파일을 Disallow한 다음 공개할 디렉토리만 선택적으로 Allow합니다.
    User-agent: *
    Disallow: /
    Allow: /index.html
    Allow: /public
    
  • 디렉토리명의 일부만 사용합니다.
    User-agent: *
    Disallow: /ad
    Disallow: /pr
    Allow: /public

하나 명심해야할 것은, robots.txt에서 디렉토리 구조를 조금 감추는 것은 보안에 작은 도움이 되긴 하지만, 디렉토리의 구조가 노출되어 공격을 당할 정도의 웹 사이트라면 그보다 더 큰 보안 문제가 있다는 이야기이기 때문에 안심해서는 안 됩니다. 민감한 정보는 올바르게 설정된 로그인 장치 등, 안전한 방법으로 보호하여야합니다. robots.txt는 보안 도구가 아니기 때문입니다.

자세한 오류문 내보내지 않고, 임시 파일(.bak 등) 주의하기

자바스크립트 등을 이용하여 동적 웹 페이지를 만들때, 편의상 오류문을 웹 페이지에 나오게 할 때가 있습니다. 이러한 기능은 개발시에는 분명히 도움이 되겠지만, 공개된 웹 사이트에 그런 기능을 유지하게 되면 안전하지 않습니다. 예를 들어, 데이터베이스를 사용하는 서비스를 제공할 때, 데이터베이스에 무언가 문제가 있거나 하여 서비스가 제대로 작동하지 않는 경우, 데이터베이스에서 제공하는 자세한 오류문은 사용자나 검색 엔진에게는 필요없는 정보일 뿐더러, 악의적인 해커들에게 사이트의 데이터베이스가 어떻게 구성되어 있는지 힌트를 줄 수 있습니다. 그렇기 때문에 사용자에게는 자세한 오류문을 그대로 내보내지 않고, 왜 서비스가 원활하게 제공되지 않는지 간단한 이유만 설명해주는 것이 좋습니다.

마찬가지로 웹 사이트를 개발할 때 임시 파일을 주의깊게 관리해야합니다. 대부분의 텍스트 편집기가 혹시 모를 상황에 대비하여 임시파일을 만듭니다 (예를 들어, index.asp의 임시 파일로 index.asp.bak을 작성). 이는 혹시 편집기가 강제 종료 되었을 때, 작성하던 내용을 다시 복구할 수 있게 하는데, 이렇게 생성된 임시파일을 그대로 놔두면 개발 정보가 유출이 되는 빌미를 제공할 수 있습니다. 개발시 생기는 이러한 임시 파일을 반드시 삭제함으로써 이런 원하지 않는 노출을 미연에 방지할 수 있습니다.

검색 결과에서 URL 삭제하기

지금까지는 보안 사고를 예방하는 방법에 대해 다루었습니다. 하지만 개인 정보가 이미 검색 엔진에 노출되어버린 경우엔 어떻게 해야할까요? 우선 개인 정보를 사이트에서 삭제하거나 비공개 처리하여 이후 수집이 되지 않도록 조치해야 합니다. 허나 대부분의 검색 엔진은 캐시(cache)에 이미 삭제가 된 정보라도 일정 기간 보관하고 있으므로, 각각의 검색 사이트에 삭제를 직접 요청하여 민감한 정보가 검색이 되지 않도록 해야합니다. 다음은 주요 검색 사이트의 검색 결과 삭제 관련 링크들입니다.