Apache APISIX, CSRF 플러그인을 통해 API 보안 강화

API7.ai

February 23, 2022

Products

CSRF(교차 사이트 요청 위조) 공격의 핵심은 대상 서버가 많은 요청의 출처가 실제 사용자인지 공격자인지 구분할 수 없도록 만드는 것입니다. 공격의 일반적인 흐름은 먼저 공격자가 사용자를 공격자가 제공한 웹 페이지로 유도하는 것입니다. 이 페이지는 대상 서버로 자동으로 전송되는 요청을 포함하고 있습니다. 페이지가 정상적으로 로드되면 요청이 자동으로 서버로 전송됩니다. 서버는 이 요청이 사용자가 정상적으로 보낸 요청과 동일하게 보이지만, 사용자의 지식 없이 공격자에 의해 시작된 것임을 알지 못합니다. 요청이 사용자의 일부 자격 증명을 포함하고 있기 때문에, 공격자는 이러한 자격 증명을 분석하여 사용자의 정보에 접근할 수 있으므로 보안 위험이 발생합니다.

이 글에서는 Apache APISIX의 CSRF 보안 플러그인 csrf를 소개하고, csrf 플러그인을 통해 Apache APISIX에서 API 정보를 보호하는 방법을 자세히 설명합니다.

플러그인 소개

csrf 플러그인은 Double Submit Cookie 방식을 기반으로 구현되었습니다. RFC 7231#section-4.2.1에 정의된 대로, GET, HEAD, OPTIONS 메소드를 안전한 메소드로 간주합니다. 이 관례에 따라 csrf 플러그인은 이 세 가지 메소드를 직접 통과시키지만, 다른 메소드는 검사하고 안전하지 않은 요청을 차단합니다.

CSRF 공격을 방어하기 위해, 우리는 위조할 수 없는 토큰이나 식별자를 생성하고 이것이 공격자의 요청과 함께 전송되지 않도록 해야 합니다. 사용자는 요청 헤더에 csrf 플러그인이 의존하는 토큰을 포함해야 하며, 이 토큰은 서명을 위한 키를 사용하여 계산됩니다. 이렇게 하면 토큰이 다른 사람에 의해 위조될 수 없으므로 API가 보호됩니다.

플러그인

csrf 플러그인이 라우트에서 활성화되면, 해당 라우트에 대한 모든 요청 응답은 csrf 토큰을 포함한 쿠키를 포함하게 됩니다.

사용자는 이 라우트에 대한 안전하지 않은 요청에서 이 쿠키를 포함하고, 요청 헤더에 추가 필드를 추가하여 쿠키의 내용을 포함해야 합니다. 이 필드는 플러그인 구성에서 name 값이므로 요청이 CSRF 플러그인의 검사를 통과할 수 있습니다.

사용자는 플러그인 구성에서 임의의 키를 제공하며, 이 키는 플러그인이 토큰 정보를 sha256 해시로 암호화하고 CSRF 토큰을 생성하는 데 사용됩니다. 이렇게 하면 토큰이 위조될 수 없으므로 API가 보호됩니다.

플러그인 사용 방법

라우트에서 CSRF 플러그인 활성화

Admin API를 사용하여 APISIX에서 라우트를 생성하고 csrf 플러그인을 활성화합니다.

curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
  "uri": "/hello",
  "plugins": {
    "csrf": {
      "key": "edd1c9f034335f136f87ad84b625c8f1"
    }
  },
  "upstream": {
    "type": "roundrobin",
    "nodes": {
      "127.0.0.1:9001": 1
    }
  }
}'

플러그인에는 세 가지 구성 매개변수가 있습니다.

  • key: 필수 필드, 임의의 비밀 키 값입니다. 사용자는 임의의 키를 제공해야 합니다.
  • expires: 선택 사항, 임의의 비밀 키의 만료 시간, 기본값은 7200초입니다. CSRF 토큰이 쿠키를 사용하여 클라이언트로 전송되므로 이 구성은 쿠키의 구성에 배치되어 쿠키의 만료 시간을 제어합니다. 또한 플러그인은 토큰이 만료되었는지 여부를 결정하기 위해 시간을 계산합니다.
  • name: 선택 사항, CSRF 토큰의 이름, 기본값은 apisix-csrf-token입니다.

요청 보내기

먼저 POST 요청을 사용하여 라우트에 접근합니다.

curl -i http://127.0.0.1:9080/hello -X POST

Apache APISIX는 요청을 차단하고 401 오류를 반환합니다. 반환된 헤더에서 설정된 쿠키를 찾을 수 있으며, 플러그인의 name 필드가 구성되지 않은 경우 쿠키 내부의 기본값은 apisix-csrf-token=....이어야 합니다. 이는 CSRF 플러그인에 의해 생성된 CSRF 토큰입니다. 요청에서 이 쿠키를 포함하고 토큰이 요청 헤더에 작성되었는지 확인해야 합니다.

HTTP/1.1 401 Unauthorized
Set-Cookie: apisix-csrf-token= ${apisix-csrf-token};path=/;Expires=Mon, 13-Dec-21 09:33:55 GMT
{"error_msg":"no csrf token in headers"}

클라이언트 측에서 JavaScript를 사용한 예: js-cookie를 사용하여 쿠키를 읽고 axios를 사용하여 요청을 보냅니다.

const token = Cookie.get('apisix-csrf-token');

const instance = axios.create({
  headers: {'apisix-csrf-token': token}
});

쿠키의 토큰이 요청 헤더의 토큰과 일치하지 않으면 요청이 csrf 플러그인에 의해 차단됩니다. 다음 예제와 같습니다.

curl -i http://127.0.0.1:9080/hello -X POST -H 'apisix-csrf-token: ${apisix-csrf-token}' -b 'apisix-csrf-token= ${apisix-csrf-token}'
HTTP/1.1 401 Unauthorized
Set-Cookie: apisix-csrf-token= ${apisix-csrf-token};path=/;Expires=Mon, 13-Dec-21 09:33:55 GMT
{"error_msg":"csrf token mismatch"}

마지막으로 curl을 사용하여 정상적인 접근을 확인합니다.

curl -i http://127.0.0.1:9080/hello -X POST -H 'apisix-csrf-token: ${apisix-csrf-token}' -b 'apisix-csrf-token= ${apisix-csrf-token}'
HTTP/1.1 200 OK

내부적으로 플러그인은 쿠키의 토큰이 요청 헤더에 포함된 토큰과 일치하는지 확인하고 서명을 다시 계산하여 토큰이 유효한지 확인합니다.

플러그인 비활성화

csrf 플러그인에 대한 관련 구성 정보를 제거한 후 라우트를 업데이트하여 플러그인을 비활성화합니다.

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
  "uri": "/hello",
  "upstream": {
    "type": "roundrobin",
    "nodes": {
      "127.0.0.1:1980": 1
    }
  }
}'

요약

이 글에서는 csrf 플러그인이 어떻게 작동하는지와 사용 방법을 자세히 설명했습니다. 이 글이 Apache APISIX에서 CSRF 공격을 차단하기 위해 플러그인을 사용하는 방법을 더 명확히 이해하고 실제 시나리오에서의 적용을 용이하게 하는 데 도움이 되길 바랍니다.

Apache APISIX는 현재 추가 플러그인을 개발 중이므로, 관심이 있다면 GitHub Discussion에서 논의를 시작하거나 메일링 리스트를 통해 소통할 수 있습니다.

Tags: