REST API 호출을 어떻게 보호합니까?


92

백엔드에서 인기있는 웹 프레임 워크 (rails, sinatra, flask, express.js)를 사용하는 편안한 웹 앱을 개발 중입니다. 이상적으로는 Backbone.js로 클라이언트 측을 개발하고 싶습니다. 내 자바 스크립트 클라이언트 측만 해당 API 호출과 상호 작용하도록하려면 어떻게해야합니까? 이러한 API 호출이 공개 curl되어 브라우저에서 또는 단순히 링크를 입력하여 호출되는 것을 원하지 않습니다 .


모든 API 호출에 페이지가 제공 될 때 클라이언트에 전달되는 토큰이 필요합니까?
hajpoj

REST 인증 및 API 키 노출 도 참조하십시오 .
Arjan

Amazon AWS javascript SDK는 사전 서명 된 객체 URL을 사용합니다.- docs.aws.amazon.com
AmazonS3

답변:


91

첫 번째 원칙으로, API가 JS 클라이언트에서 사용되는 경우 공용이라고 가정해야합니다. 간단한 JS 디버거는 공격자를 위치에 배치하여 공격자가 바이트 단위로 동일한 요청을 보낼 수 있습니다. 그가 선택한 도구.

즉, 내가 귀하의 질문을 올바르게 읽었다면 이것은 당신이 피하고 싶은 것이 아닙니다. 정말로 일어나고 싶지 않은 것은 JS 클라이언트가 관여하지 않고 API가 (정기적으로) 소비된다는 것입니다. 다음은 시행하지 않는 방법에 대한 몇 가지 아이디어입니다. 적어도 클라이언트 사용을 권장합니다.

  • API에는 일종의 인증 필드 (예 : 클라이언트에서 계산 된 해시)가 있습니다. 그렇지 않다면 This SO question을 살펴보십시오 . 세션 별로 (하드 코딩 된) JS 클라이언트에 제공되는 솔트 (또는 API 키)를 사용해야합니다. 이렇게하면 API의 무단 소비자가 훨씬 더 많은 작업을하게됩니다.

  • JS 클라이언트를로드 할 때 일부 HTTP 헤더 (유저 에이전트가 떠오름)와 IP 주소를 기억하고 변경된 경우 재 인증을 요청하고 일반적인 용의자에 대한 블랙리스트를 사용합니다. 이로 인해 공격자는 숙제를 더 철저히하게됩니다.

  • 서버 측에서는 마지막 API 호출 몇 개를 기억하고 다른 API 호출을 허용하기 전에 비즈니스 로직이 지금 새로운 것을 허용하는지 확인하십시오. 이것은 공격자가 자신의 많은 세션을 서버와 함께 하나의 세션에 집중할 수있는 능력을 거부합니다. 다른 조치와 함께 사용하면 가해자를 쉽게 탐지 할 수 있습니다.

나는 가해자가 귀하의 서비스를 사용하는 것을 완전히 불가능하게 만드는 것이 불가능하다고 생각 하지만 그렇게 어렵게 만들 수 있으며 번거로울 가치가 없을 수도 있습니다.


이것은 유용한 정보이지만 내 백엔드 API에서 별도의 서버와 같은 다른 API 앱으로 인증을 만들고 싶다면 내 질문을 단순화하기 위해 내 백엔드 일명 node.js가 다른 백엔드로 가져 오기 요청을 보내길 원합니다. 내 자신의 최종 서버, 어떤 이유로 이것이 필요하지만 민감한 데이터에 액세스 할 수 있기 때문에 API 호출을 보호하고 싶습니다. 실제로 브라우저에 저장할 수 없기 때문에 세션 또는 jwt를 사용할 수 없습니다.
피라미드

@Thepyramid 서버 측에서 API 호출이 수행하는 작업은 중요하지 않습니다. 특히 서버 측이 또 다른 두 번째 → evel API 호출을 수행하는 경우 더욱 그렇습니다. 중요한 부분은 서버를 프록시가 아닌 응용 프로그램으로 취급하는 것입니다.
Eugen Rieck

당신은 더 많은 응용 프로그램으로 만드는 방법을 설명 할 수없는 프록시
피라미드

1
내 말은 : 적절한 수준의 보안을 얻으려면 웹앱에있는 모든 도구를 사용해야합니다. 세션, 인증 데이터베이스, 비즈니스 로직. 그렇게하지 않고 서버를 다른 서버로 요청을 전달하는 방법으로 취급하면 다른 서버에 대한 프록시로 사용하고 다른 서버가 제공하는 보안에 의해 제한됩니다.
Eugen Rieck

1
@PirateApp 공격자는 CSRF 헤더를 쉽게 무시할 수 있습니다. 최종 장치가 패치되지 않은 브라우저 인 경우에만 작동합니다
Eugen Rieck

12

일종의 인증 시스템을 구현해야합니다. 이를 처리하는 한 가지 좋은 방법은 예상되는 헤더 변수를 정의하는 것입니다. 예를 들어 세션 토큰을 반환하는 인증 / 로그인 API 호출이있을 수 있습니다. API에 대한 후속 호출은 'your-api-token'과 같은 특정 이름을 사용하여 HTTP 헤더 변수에 세션 토큰이 설정 될 것으로 예상합니다.

또는 많은 시스템이 일종의 API 계정 시스템을 사용하여 예상되는 액세스 토큰 또는 키 (예 : youtube, facebook 또는 twitter)를 만듭니다. 이러한 경우 클라이언트는 클라이언트에 어떤 방식 으로든이를 저장해야합니다.

그런 다음 REST 프레임 워크에 세션에 대한 검사를 추가하고 예외를 던지기 만하면됩니다. 가능한 경우 상태 코드 (안정적)는 401 오류입니다.


8
헤더를보고 재생산하는 것을 막을 수는 없습니다.
cdmckay 2013-08-22

1
@cdmckay-토큰은 세션에 저장된 토큰과 일치해야합니다. 단순히 헤더를 재생산하면 다른 세션에서 오는 경우 "Unauthorized"응답이 발생합니다.
Andrei Volgin 2015

3
API로 전송되기 전에 여전히 동일한 세션을 사용하고 요청을 변경할 수 있습니다. 또는 런타임에 콘솔을 사용하여 필요한 부분 만 수정하는 일치하는 헤더 / 필드로 호출을 생성합니다 ...
Potter Rafed

2
@PotterRafed : 사용자가 자신의 유효한 세션에 액세스하면 공격이 아닌 앱을 사용하여 호출됩니다. 인증의 목적은 다른 사용자의 세션 / 데이터에 대한 액세스를 방지하는 것입니다 .
Andrei Volgin 17. 9.

@AndreiVolgin 예, 충분히 공평하지만 여전히 취약성입니다
Potter Rafed

9

이제 "JSON Web Token"이라는 개방형 표준이 있습니다.

참조 https://jwt.io/ & https://en.wikipedia.org/wiki/JSON_Web_Token을

JWT (JSON Web Token)는 일부 클레임 수를 주장하는 토큰을 만들기위한 JSON 기반 개방형 표준 (RFC 7519)입니다. 예를 들어 서버는 "admin으로 로그인"클레임을 가진 토큰을 생성하여 클라이언트에 제공 할 수 있습니다. 그런 다음 클라이언트는 해당 토큰을 사용하여 관리자로 로그인했음을 증명할 수 있습니다. 토큰은 서버의 키로 서명되므로 서버는 토큰이 합법적인지 확인할 수 있습니다. 토큰은 간결하고 URL에 안전하며 특히 웹 브라우저 SSO (Single Sign-On) 컨텍스트에서 사용할 수 있도록 설계되었습니다. JWT 클레임은 일반적으로 ID 공급자와 서비스 공급자간에 인증 된 사용자의 ID를 전달하거나 비즈니스 프로세스에서 요구하는 다른 유형의 클레임을 전달하는 데 사용할 수 있습니다. [1] [2] 토큰은 인증 및 암호화도 가능합니다. [3] [4]


사용자가 토큰을 복사하여 다른 응답에 사용하지 못하게하는 것은 무엇입니까?
Ulad Kasach

1
@UladKasach 솔직히 말해서 나는 그들에게 깊숙이 들어가 본 적이 없지만, 만료가 가능하고 사용자에게 고유하며 SSL로 암호화되어 있습니다 (물론 연습 중입니다). oauth afaik
bbozo

3

@MarkAmery와 Eugene을 실례합니다. 그러나 그것은 틀 렸습니다.

브라우저에서 실행되는 js + html (클라이언트) 앱 은 다음과 같이 API에 대한 무단 직접 호출을 제외하도록 설정할 수 있습니다 .

  1. 첫 번째 단계 : 인증을 요구하도록 API를 설정합니다. 클라이언트는 먼저 서버 (또는 다른 보안 서버)를 통해 자신을 인증해야 올바른 암호를 제공하기 위해 인간 사용자를 묻는 예를 들어.

인증 전에는 API 호출이 허용되지 않습니다.

인증 중에 "토큰"이 반환됩니다.

인증 후에는 인증 "토큰"이있는 API 호출 만 허용됩니다.

물론이 단계에서는 암호가있는 권한이있는 사용자 만 API에 액세스 할 수 있지만, 앱을 디버깅하는 프로그래머 인 경우 테스트 목적으로 직접 액세스 할 수 있습니다.

  1. 두 번째 단계 : 이제 클라이언트 js + html 앱이 서버에서 처음 요청 된 후 짧은 시간 내에 호출되는 추가 보안 API를 설정합니다. 이 "콜백"은 클라이언트가 성공적으로 다운로드되었음을 서버에 알립니다. 클라이언트가 최근에 성공적으로 요청 된 경우에만 REST API 호출이 작동하도록 제한하십시오.

이제 API를 사용하려면 먼저 클라이언트를 다운로드하고 실제로 브라우저에서 실행해야합니다. 콜백을 성공적으로 수신 한 후 짧은 시간 내에 사용자가 입력 한 후에 만 ​​API가 호출을 수락합니다.

따라서이 사용자가 자격 증명이없는 권한없는 사용자 일 수 있다는 점에 대해 걱정할 필요가 없습니다.

( '어떻게 REST API 호출을 보호합니까'라는 질문의 제목은 대부분의 말에서 API가 어떻게 호출되는지에 대한 문자적인 질문이 아니라 WHOM에 의한 질문입니다. 맞습니까? )


5
두 번째 요점은 의미가 없습니다. 공격자가 앱을로드해야하는 경우이를 수행합니다 (콜백이 표시됨). 그리고 공격합니다.
Andrei Volgin 2015

포인트 2는 포인트 1에 추가됩니다. 공격자는 여전히 인증이 필요합니다. 포인트 2는 인증을 받기 위해 실제로 html 앱을 다운로드해야한다는 점만 추가합니다. 따라서 앱없이 API에 대한 직접 호출 (아마도 인증 후에 만 ​​액세스 및 다운로드 됨)은 불가능합니다. 이 질문에서 요청한 것입니다.
pashute

도메인의 요청 만 허용 할 수 있습니다.
Andrei Volgin 2015

이는 도메인 내부에 대한 호출 만 제한하므로 이제 자바 스크립트 브라우저 앱 사용자는 도메인 내부에 있어야하며 (아마도 원하는 것이 아님) 해당 사용자는 여전히 curl을 통해 API를 직접 호출 할 수 있습니다.
pashute

2
간과하는 것처럼 보이는 것은 사용자의 브라우저에 요청하는 모든 작업이 공격자에 의해 복제 될 수 있다는 것입니다. 브라우저가이를 수행하려면 읽을 수 있어야합니다.
Eugen Rieck

1
  1. 서버에 세션 VAR을 설정하면 클라이언트가 처음로드하여 index.html(또는 backbone.js등)

  2. 모든 API 호출에 대해 서버 측에서이 변수를 확인하십시오.

추신 이것은 "보안"솔루션이 아닙니다 !!! 이는 사람들이 다른 웹 사이트 및 앱에서 API를 남용하거나 API를 "핫 링크"하지 않도록 서버의 부하를 줄이기위한 것입니다.


0

내가하는 일은 다음과 같습니다.

  1. X-APITOKEN과 같은 호출로 HTTP 헤더로 API 보안 :

  2. PHP에서 세션 변수를 사용하십시오. 로그인 시스템을 준비하고 세션 변수에 사용자 토큰을 저장하십시오.

  3. Ajax에서 PHP로 JS 코드를 호출하고 curl과 함께 세션 변수를 사용하여 API를 호출합니다. 이렇게하면 세션 변수가 설정되지 않은 경우 호출되지 않고 PHP 코드에 API에 대한 액세스 토큰이 포함됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.