사이트 간 요청 위조 (CSRF), Sea Surf, 또는 요약해서 XSRF는 웹 보안의 세계에서 잠자고 있는 거인으로 여겨지고 있습니다. 그 이유는, 적절하게 실행하면 몰래 잠입하는 강력한 공격인 것임을 증명해 보일 수 있음에도 불구하고, 그다지 심각하게 취급하고 있지 않기 때문입니다. 또한, 이는 정기적으로 활용되는 일반적인 공격입니다. 이것이 OWASP의 상위 10 목록에 여러 번 연달아 자리를 차지한 이유입니다. 그렇기는 해도, 이용 당한 크로스 사이트 스크립팅 (XSS) 취약성은 언제나 CSRF 취약성을 능가할 것입니다. CSRF 공격은 큰 제약이 있습니다. CSRF는 오직 상태 변경만을 일어나게 할 수 있으며, 그러므로 공격자가 HTTP 응답의 내용을 받아야 하는 공격을 가능하게 하지는 못합니다.
사이트 간 요청 위조 (CSRF)는 악성의 개체가 피해자를 속여서 공격자를 대신하여 동작을 수행하도록 하는 공격입니다. 공격의 영향은 이용 당하는 피해자가 갖고 있는 권한의 수준에 따라서 달라질 것입니다. 공격자가 저지르는 동작은 분명히 동작을 수행하는 피해자가 관리자 수준에 있을 경우, 권한이 덜한 단순 사용자일 때보다 훨씬 더 큰 영향력을 가질 것입니다. CSRF 공격은 웹 어플리케이션이 사용자가 실제로 자신이 말하는 그 사람이 맞는지를 확인할 수 있다면 그 사용자를 전적으로 신뢰한다는 사실을 이용합니다.
사이트 간 요청 위조 (CSRF) 공격을 실행하는 데 두 가지 주요 부분이 있습니다. 첫 번째 부분은 피해자를 속여서 링크를 클릭하거나 페이지를 불러오도록 하는 것입니다. 이는 보통 피해자의 호기심을 자극하여 악성 링크를 클릭하도록 하는 소셜 엔지니어링을 통해서 진행합니다. 두 번째 부분은 교묘하게 만든 요청을 피해자의 브라우저로 전송하는 것입니다. 이는 합법적인 것처럼 보이는 요청을 웹 어플리케이션으로 전송할 것입니다. 요청은 피해자가 해당 웹사이트에서 연관을 갖고 있는 쿠키를 포함하여, 공격자가 원하는 값을 가진 채 전송됩니다. 이렇게 하여, 웹 어플리케이션은 이 피해자가 웹사이트에서 특정한 동작을 수행할 수 있음을 알게 되며, 이러한 HTTP 자격 또는 쿠키와 함께 전송되는 요청을 합법적인 것으로 간주합니다. 피해자가 공격자의 명령에 따라 요청을 전송하는 것이어도 말입니다.
웹 어플리케이션에 요청을 하게 되면, 브라우저는 요청과 함께 전송할 필요가 있는 웹 어플리케이션의 근원과 연관된 쿠키를 보유하는지 확인합니다. 보유하고 있는 경우, 예를 들면 쿠키와 같은 인증 데이터를 이 웹 어플리케이션으로 전송하는 요청에 포함하게 됩니다. 이는 피해자에게 완벽한 경험을 제공하도록 진행되어, 방문하는 모든 페이지에서 재인증을 할 필요가 없습니다. 웹사이트가 전송되는 쿠키를 승인하고 세션이 아직 유효한 것으로 간주할 경우, 공격자는 CSRF를 사용하여 마치 피해자가 전송하고 있는 것처럼 요청을 전송할 수 있으며, 웹사이트는 공격자가 보내는 요청인지 피해자가 보내는 요청인지 구별할 수가 없습니다. 요청은 언제나 피해자의 쿠키와 함께 피해자가 전송하기 때문입니다.
CSRF 공격은 단순하게 브라우저는 각 요청, 그리고 모든 요청과 함께 자동으로 웹 어플리케이션에 쿠키를 전송한다는 사실을 이용합니다.
사이트 간 요청 위조 (CSRF)는 피해자가 인증되는 경우에만 유효합니다. 이는 공격을 성공하기 위해서는 피해자가 로그인을 할 필요가 있다는 뜻입니다. CSRF 공격을 사용하여 인증 프로세스를 우회하기 때문에, 공개적으로 접속 가능한 것과 같이, 공격으로부터 보호하지는 못할 지라도, CSRF 공격의 영향을 받지 않는 몇 가지 요소가 있을 수 있습니다. 이는 요청을 전송하기 위해서 피해자가 로그인을 하도록 요구하지 않습니다. 누구나 요청을 보낼 수 있기 때문입니다. 예를 들어, 방문자가 양식을 통해서 쿼리를 전송할 수 있는, 웹사이트의 연락처 양식을 살펴봅시다. 피해자가 양식을 제출하기 위해서 어떠한 권리를 보유할 필요가 없습니다. 즉, 관리자나 일반 사용자가 양식을 제출하든 중요하지 않다는 의미입니다. 추가적인 특권이 있는 피해자가 모든 이들에게 개방되지 않은 동작을 수행할 때 문제가 발생합니다. 이 순간이 CSRF 공격을 활용하는 순간입니다.
위이용할 웹 어플리케이션에 피해자가 로그인을 했는지 확인하기 위해서, 공격자들은 동일한 웹 어플리케이션의 특정 피해자를 대상으로 하여, CSRF 공격이 성공할 것인지 확인합니다.
이 부분에서 설명하는 예시는 다소 단순하며, 반드시 실제 세계의 예시를 반영하는 것은 아닙니다. 하지만, CSRF 공격이 어떻게 작용하는지를 보여주는 좋은 예시라고 할 수 있습니다.
GET 요청은 그 특성 상 멱등성입니다. 이는 상태 변경을 수행하는 데 사용할 수 없으므로, GET 요청을 전송하여 데이터를 변경할 수 없다는 뜻입니다. 물론, 일부 웹 어플리케이션은 여전히 더 적합한 POST 대신에 GET을 사용하여 비밀번호 변경이나 사용자 추가 등, 운영을 위한 상태 변경을 수행하고 있습니다.
앞서 얘기한 악성 링크를 클릭하면, 공격자는 피해자를 자신의 악성 웹 어플리케이션으로 보낼 수 있으며, 이 악성 웹 어플리케이션이 스크립트를 실행하면 피해자의 브라우저가 불법적인 요청을 전송하도록 촉발하게 됩니다. 이러한 요청을 불법적인 것으로 정의하는데, 그 이유는 그러한 요청이 마치 사용자가 전송한 것처럼 웹 서버에 나타난다 하더라도, 피해자가 요청을 전송하고 있음을 인지하지 못하기 때문입니다. 이러한 요청은 웹 서버가 피해자가 자신이 말하는 그 사람이 맞는지 확인하기 위해서 필요로 하는 필수 쿠키를 포함하고 있기 때문입니다.
www.example.com이 GET 요청을 통해서 자금 이체를 처리하고, 이러한 요청에는 두 가지 변수, 이체할 금액, 그리고 돈을 이체할 계좌의 식별자를 포함하고 있다고 상상해 봅시다. 아래 예시는 합법적인 URL을 보여주고 있습니다. 이는 웹 어플리케이션으로 하여금 적절한 화폐 100,000 단위를 Fred의 계좌로 전송하도록 요청합니다.
요청은 인증된 사용자에 대한 쿠키를 요청 안에 포함하고 있으므로, 어떤 계좌에서 돈을 이체할 것인지 정의할 필요가 없습니다. 이는 정상 사용자가 이 URL에 접속하게 되면, 인증을 해야 하므로, 웹 어플리케이션이 어떤 계좌에서 자금을 인출할 것인지 알게 된다는 의미입니다. 이제 우리는 이러한 요청을 합법적인 이유로 사용할 수 있는 방법을 알고 있기 때문에, 이제 피해자를 속여서 피해자로서 인증한 상태에서 공격자가 원하는 요청을 전송하도록 하는 방법을 알아낼 수 있습니다.
이용할 웹 어플리케이션이 GET 요청을 예상하고 있는 경우, 공격자는 자신의 웹사이트에 태그를 포함할 수 있습니다. 그러면 이미지로 연결하는 대신에, 은행의 웹 어플리케이션으로 요청을 전송하게 됩니다.
정상 상태의 브라우저가 자동으로 해당 웹 어플리케이션에 관계된 쿠키를 전송하며, 그러므로 피해자는 공격자를 대신하여 상태 변경을 수행할 수 있게 됩니다. 여기서 상태 변경이란 자금의 이체입니다.
이 공격은 GET 요청에 대해 상당히 쉽게 작용하기는 하지만, 공격자들은 또한 POST 방법을 사용하여 요청을 전송할 수 있습니다. 사실, 대부분의 상태 변경 요청은 POST 요청을 통해서 진행됩니다. 이 요청은 GET 요청에서처럼 URL 자체가 아니라 요청 본문에 변수와 값을 전송합니다. 이는 활용할 수 있는 웹 어플리케이션이 상태 변경이 관련될 때 GET 요청 대신에 POST를 수락할 가능성이 더 높다는 의미입니다.
피해자를 속여서 POST 요청을 전송하도록 하는 일은 GET 요청을 보내는 것보다 조금 더 까다로울 수 있습니다. GET 요청을 사용하면, 공격자는 단순히 피해자가 URL에 필요한 모든 정보를 가진 요청을 전송하도록 할 필요가 있는 반면, POST 요청은 요청에 요청 본문을 첨부할 필요가 있습니다. JavaScript로, 공격자는 피해자를 자신의 악성 웹 어플리케이션으로 유혹할 수 있으며, 웹 페이지를 불러 오자마자, 불법적인 POST 요청이 자동으로 전송됩니다.
온로드 기능을 사용하는 다음의 예시를 살펴봅시다. 페이지를 불러오자 마자 피해자의 브라우저에서 요청을 자동으로 전송합니다. 다음 예시를 살펴봅시다.
페이지를 불러오자 마자, 온로드 기능은 csrf 라는 이름의 양식을 제출하는지 확인합니다. 이는 POST 요청을 전송합니다. csrf 양식을 살펴보면, 우리는 이 양식이 공격자가 통계적으로 설정한 두 개의 변수와 그 값을 포함하고 있음을 알게 됩니다. 여기서 example.com은 요청이 합법적인 것으로 확인합니다. 피해자의 쿠키를 포함하고 있기 때문입니다.
이는 이 공격을 실행하는 유일한 방법이 아닙니다. 공격자는 또한 iframe을 사용할 수 있습니다. 이는 스스로를 보이지 않게 하기 위해서 설정하는 속성을 보유하고 있습니다. 동일한 온로드 기능을 사용하여, 공격자는 자신의 악성 웹 어플리케이션의 iframe을 불러오고, iframe을 불러오자 마자, 요청을 전송하게 됩니다.
다양한 CSRF 방지 매커니즘이 제안되어 왔지만, 이들 모두 모든 시나리오에서 효과적인 것은 아닙니다. 다음과 같은 실행이 다양한 웹 어플리케이션에 대해 효과적인 것으로 증명되었으며, CSRF 공격으로부터 보호 장치를 제공합니다.
사이트 간 요청 위조 (CSRF)를 방지하는 가장 대중적인 실행 방법은 도전 토큰을 사용하는 것입니다. 이 토큰은 특정 사용자와 연관이 있으며, 웹 어플리케이션에 제시되는 모든 상태 변경 양식에 숨겨진 값으로서 찾을 수 있습니다. CSRF 토큰 또는 동기화 장치 토큰이라고 부르는 이 토큰은 다음과 같이 작용합니다.
이는 사이트 간 요청 위조 (CSRF) 공격으로부터 양식을 보호하는데, 그 이유는 요청을 만들어 낸 공격자 또한 피해자가 유효한 요청을 전송하도록 성공적으로 속이기 위해서는 CSRF 방지 토큰을 추측할 필요가 있기 때문입니다. 게다가, 여러 번 시도하거나 사용자가 로그 아웃한 이후에는 이 토큰이 무효화됩니다.
CSRF 방지 매커니즘을 적절하게 실행하기 위해서는, 암호화를 통해 안전을 담보하여, 토큰 그 자체를 쉽게 추측할 수 없도록 할 필요가 있습니다. 예측 가능한 패턴에 기반하여 토큰을 생성할 가능성이 있습니다.
또한 여러분에 대한 CSRF 공격으로부터 방어할 대중적인 프레임워크에서 손쉽게 이용할 수 있는 옵션을 사용할 것을 권장합니다. 즉, 가능한 한, 여러분이 만든 CSRF 방지 매커니즘의 작동을 삼가야 합니다. 이렇게 하면 오류의 여지를 줄일 수 있으며, 실행을 더 빠르고 더 쉽게 할 수 있습니다.
CSRF 공격은 언제나 특정한 기원으로 전송되는 요청과 함께 쿠키를 전송한 이후에만 가능합니다. CSRF 공격의 특성 때문에, 쿠키에 대하여 플래그 (flag)를 설정할 수 있으며, 이를 동일 사이트 쿠키에 조정할 수 있습니다. 동일 사이트 쿠키는 전송하는 쿠키에 관련된 동일한 근원에서 요청을 만드는 경우에만 전송할 수 있는 쿠키입니다. 쿠키, 그리고 요청을 만드는 페이지 두 가지에 대한 프로토콜, 포트 (해당하는 경우), 그리고 호스트가 동일한 경우에 두 가지가 동일한 근원을 갖는 것으로 간주합니다.
현재 동일 사이트 쿠키의 한계점은, 현대적인 브라우저 모두가 이를 지원하지 않는다는 점이며, 더 이전의 브라우저들은 동일 사이트 쿠키를 사용하는 웹 어플리케이션에 부응하지 않습니다 (지원되는 브라우저 목록에 대해서는 이곳을 클릭하세요). 지금, 동일 사이트 쿠키는 이러한 한계점으로 인하여 추가적인 심층 방어 레이어로서 더 적합한 반면, 여전이 다른 CSRF 보호 매커니즘을 사용해야 합니다.
결론
쿠키는 본질적으로 취약합니다. 그 이유는 쿠키는 각 요청과 함께 자동으로 전송되어, 공격자들이 CSRF로 이어지는 악성 요청을 쉽게 만들어 내도록 합니다. 공격자들은 응답 본문 또는 쿠키 그 자체를 입수할 수는 없지만, 공격자는 피해자들의 상승된 권리에 따라 동작을 수행할 수 있습니다. CSRF 취약성의 영향은 또한 공격자의 요청과 함께 쿠키를 전송하는 피해자의 특권과 관련이 됩니다. 데이터 검색이 CSRF 공격의 주요 범위는 아니지만, 상태 변경은 분명히 이용하는 웹 어플리케이션에 부정적인 영향을 미칩니다.