Read My Blog With JavaScript

Michael Lynch

JavaScript로 내 블로그 읽기

원문은 Michael Lynch님이 에 게재했습니다. 이 블로그 구독하기

이제 클라이언트 측 JavaScript로 내 블로그를 읽을 수 있습니다. 굳이 왜 그렇게 하고 싶을지는 모르겠지만, 어쨌든 가능합니다.

예를 들어 좋아하는 블로그들의 최근 글 목록을 모아 사이트에 블로그롤을 추가하고 싶은데, 서버 측에서 직접 가져오고 싶지 않을 수도 있습니다. JavaScript로 내 블로그의 최신 글 5개 제목을 표시하고 싶다면, 다음과 같은 코드를 작성하면 됩니다:

fetch("https://mtlynch.io/index.xml")
  .then((response) => response.text())
  .then((str) => new DOMParser().parseFromString(str, "application/xml"))
  .then((data) => {
    const articles = [...data.querySelectorAll("item")].map((item) => ({
      title: item.querySelector("title").textContent,
      date: new Date(item.querySelector("pubDate").textContent),
    }));

    // Sort articles by date, newest to oldest.
    articles.sort((a, b) => b.date - a.date);

    // Print the titles of the 5 most recent articles.
    articles.slice(0, 5).forEach((article) => console.log(article.title));
  });

위 코드는 다음과 같은 출력을 만듭니다:

Refactoring English: Month 10
Get xkcd Cartoons at 2x Resolution
List of 2x-resolution xkcd Cartoons
I Once Appeared in The Old New Thing
Refactoring English: Month 9

최근 Lobsters에 Simon Willison이 남긴 댓글에서 아이디어를 얻었습니다.

JavaScript가 내 사이트를 읽게 하려면 어떻게 해야 할까?

JavaScript 접근을 허용하기 위해 바꾼 것은 RSS 피드에 Cross-Origin Resource Sharing(CORS) HTTP 헤더를 설정한 것뿐입니다. 보통 클라이언트 측 JavaScript로 다른 사이트가 서로의 콘텐츠를 읽는 것을 막는 것은 동일 출처 정책입니다.

동일 출처 정책에 따르면 각 사이트(오리진)는 자신의 도메인과 연결된 리소스만 읽을 수 있습니다. 그래서 mtlynch.io에 있는 내 블로그를 방문했을 때, 내 페이지의 JavaScript가 chase.com에서 당신의 은행 잔액을 읽으려 하면 동일 출처 정책이 그 접근을 차단합니다.

다른 웹사이트가 JavaScript를 통해 내 블로그를 읽을 수 있게 하려면 블로그의 RSS 피드에 CORS 헤더를 설정해야 했습니다. 이 블로그는 정적 사이트이며 현재 Netlify에서 호스팅하고 있어, Netlify 설정 파일을 수정해 RSS 피드 URL에 CORS 헤더를 지정했습니다:

[[headers]]
  for = "/index.xml"
  [headers.values]
    Access-Control-Allow-Origin = "*"
    Access-Control-Allow-Methods = "GET, HEAD, OPTIONS"
    Access-Control-Allow-Headers = "Content-Type"

무슨 문제가 생길 수 있을까?

CORS는 보안 메커니즘이며, 인터넷에 공개된 사이트의 보안 제한을 완화하는 일에는 항상 마땅히 신중해야 합니다. 하지만 한동안 위험을 고민해 본 결과, 내 상황에서는 의미 있는 위험이 없다고 판단했습니다.

공격자가 비밀 데이터를 빼낼 수 있을까?

동일 출처 정책의 목적은 사용자가 사이트 A에 민감한 데이터를 가지고 있을 때, 사이트 A가 명시적으로 허용하지 않는 한 사이트 B가 그 어떤 데이터에도 접근하지 못하도록 하는 것입니다.

내 블로그는 비밀 정보가 없는 정적 사이트입니다. 내가 mtlynch.io를 방문할 때 보는 것은 다른 모든 사람이 보는 것과 정확히 같습니다. 따라서 공격자가 나를 속여 타사 사이트에서 악성 JavaScript를 실행하게 하더라도, 이 블로그에는 내가 가진 특별한 권한 자체가 없으므로 그 코드가 내 권한을 악용할 수 없습니다.

댓글 기능을 위해 TalkYard를 사용하고 있고 거기서는 관리자 권한이 있지만, RSS 피드에 대한 CORS 설정은 TalkYard에 영향을 주지 않습니다.

공격자가 나를 DDoS 할 수 있을까?

처음에는 공격자가 CORS 설정을 악용해 내 사이트에 DDoS 공격을 가할 수도 있겠다고 생각했습니다. 만약 공격자가 수백만 명을 어떤 페이지로 유도해 백그라운드의 JavaScript가 내 RSS 피드를 계속 요청하게 만든다면 어떻게 될까?

그러다 이런 DDoS 공격은 이미 가능하다는 것을 깨달았습니다. CORS는 제3자 도메인이 요청 결과를 읽을 수 있는지 여부만 제어할 뿐, 애초에 요청 자체를 차단하지는 않습니다. CORS 설정과 관계없이 어떤 도메인이든 다른 도메인에 GET 및 POST 요청을 보낼 수 있습니다.

공격자가 내 사이트를 사칭할 수 있을까?

내가 고려한 또 다른 공격은 사칭입니다. 방문자가 evil.example.com에 접속하면, 주소 표시줄에는 여전히 evil.example.com이 표시된 채로 내 블로그를 방문자의 브라우저 안에 그대로 재구성하는 JavaScript를 서버가 반환할 수 있습니다.

이 공격도 통할 수는 있지만, 내 CORS 설정과 관계없이 내 블로그를 사칭하는 더 간단한 방법이 있습니다. 사칭하는 사람은 내 블로그로 요청을 전달하는 HTTP 프록시를 운영하면 더 간단하게 사칭할 수 있습니다. 혹은 그냥 내 사이트를 스크레이핑해서 다른 곳에 호스팅하면 됩니다.

왜 내 블로그를 JavaScript가 읽을 수 있게 했을까?

아무도 내게 RSS 피드에 CORS를 활성화해 달라고 요청한 적은 없어서, 이게 실제로 누군가에게 도움이 될지는 모르겠습니다. 하지만 나는 열린 웹을 좋아하고, 다른 사이트가 내 사이트와 상호 운용될 수 있게 하는 흥미로운 방법이기도 해서 그냥 해보기로 했습니다.

이번 변경으로 내 RSS 피드를 활용해 뭔가 흥미로운 것을 만들게 되었다면, 알려 주세요.

이 글은 muse-spark-1.2-contributor 모델을 사용해 번역했습니다.

댓글