신뢰할 수있는 모바일 애플리케이션에 대해서만 REST API를 보호하는 방법


96

REST API가 신뢰할 수있는 클라이언트, 내 경우에는 내 모바일 애플리케이션에서 생성 한 요청에만 응답하도록하려면 어떻게해야합니까? 원치 않는 요청이 다른 소스에서 오는 것을 방지하고 싶습니다. 사용자가 직렬 키 등을 채우지 않기를 원합니다. 설치 후, 사용자 상호 작용없이 장면 뒤에서 발생해야합니다.

내가 아는 한 HTTPS는 통신하는 서버의 유효성을 검사하는 것입니다. 물론 HTTPS를 사용하여 데이터를 암호화하려고합니다.

이것을 달성 할 수있는 방법이 있습니까?

업데이트 : 사용자는 사용자가 로그인하지 않아도되는 읽기 전용 작업을 수행 할 수 있지만 사용자가 로그인해야하는 쓰기 작업을 수행 할 수도 있습니다 (액세스 토큰에 의한 인증). 두 경우 모두 API가 신뢰할 수있는 모바일 응용 프로그램의 요청에만 응답하기를 원합니다.

API는 또한 모바일 애플리케이션을 통해 새 계정을 등록하는 데 사용됩니다.

업데이트 2 : 이것에 대한 여러 답변이있는 것처럼 보이지만 정직하게 대답 할 플래그를 모르겠습니다. 어떤 사람들은 할 수 있다고 말하고 어떤 사람들은 할 수 없다고 말합니다.


HTTPS는 SSL (및 TLS)을 사용합니다. SSL / TLS는 클라이언트 인증과 함께 사용할 수 있습니다.
atk

클라이언트 측 SSL 인증서를 의미합니까? 나는 그것이 모바일 응용 프로그램 (Android 및 iOS)에서도 가능하다는 것을 모른다는 것을 제외하고는 내가 찾고있는 것이라고 생각합니까? 클라이언트 인증서는 어디에 저장됩니까? 기기 저장 용량, 메모리?
Supercell

SSL은 모바일 애플리케이션이 아닌 모바일 장치 만 인증합니다.
Morons

@Supercell : 답을 추가하겠습니다
atk

답변:


48

당신은 할 수 없습니다.

당신은 엔티티, 확인 할 수 없다 실체를 그 사람, 하드웨어 클라이언트 소프트웨어 클라이언트가 될. 그들이 말한 내용 이 올바른지 확인한 다음 정직하다고 가정 할 수 있습니다 .

예를 들어, 어떻게 구글은 알고 않는 내가있어 내 Gmail 계정에 로그인? 그들은 단순히 사용자 이름과 암호를 물어 확인, 다음 정직을 가정 누가 그 정보를 것 때문에? 어떤 시점에서 구글이 충분하지이었다 (이상한 행동을 찾는) 행동 검증을 추가로 결정하지만 여전히에 의존 사람이 할 일 동작을 한 후 검증, 동작을 .

이것은 클라이언트를 확인하는 것과 똑같습니다. 고객 의 행동 만 검증 할 수 있지만 고객 자체는 검증 할 수 없습니다.

따라서 SSL을 사용하면 클라이언트에 유효한 인증서가 있는지 확인할 수 있으므로 간단히 앱을 설치하고 인증서를 얻은 다음 모든 새 코드를 실행할 수 있습니다.

질문은 : 왜 이것이 그렇게 중요한가? 이것이 진짜 관심사라면, 뚱뚱한 고객의 선택에 의문을 제기합니다. 아마도 당신은 웹 앱을 사용해야 할 것입니다 (따라서 API를 공개 할 필요가 없습니다).

Android 애플리케이션을위한 SSL 인증서 유효성 검증 참조

: : 모바일 앱에서 클라이언트 SSL 인증서는 얼마나 안전합니까?


1
OS에서 암호화 한 드라이브에 인증서가 저장된 하드웨어에서 클라이언트 인증서를 사용했습니다. 그러나 거기에서도 아무도 그것이 완전하다고 생각하지 않았습니다. 목표는 단지 ​​캐주얼 사용자를 어렵게 만드는 것입니다.
Steven Burnap

1
@Morons : 웹앱이이 문제를 해결하지만 사용자가 웹앱보다 기본 앱을 사용할 가능성이 더 높다고 생각합니다 (가정이 틀리면 수정 해주세요). 이것이 중요한 이유는 API가 사용자에게 데이터베이스의 일부에 대한 액세스 권한을 부여하기 때문입니다. 여기에는 몇 달 동안의 작업을 통해 수집 한 많은 데이터가 포함되어 있습니다. 다른 회사 나 사용자가 자신의 목적으로 쉽게 사용할 수있는 데이터입니다. 클라이언트를 보호하지 않으면 누가 우리를 사용하는지 알 수 없었습니다.
Supercell

6
웹앱으로 문제가 해결되지 않습니다. webapp 클라이언트 측을 수정하고 원하는대로 수행하는 것은 매우 사소한 일입니다.
Steven Burnap

5
@Supercell 다른 사람의 데이터를 표시 한 다음 공유하지 못하게 할 수 없습니다. 일부 사용자가 데이터를 갖기를 원하지 않으면 데이터를 제공하지 않습니다 (표시).
Morons

동의하지만 다른 이유가 있습니다. rsa는 en.wikipedia.org/wiki/SecurID 와 같이 장치를 제어 할 수 있다면 가능합니다 . 그러나 모바일은 제어 할 수있는 것이 아닙니다 (플러그인 키와 같은 첨부 파일을 수용 할 수 있음).
imel96 1

31

사용자 로그인 및 SSL을 통한 통신에 익숙해 져 있으므로 질문에서 더 흥미로운 부분에 대해 중점적으로 다룰 것입니다. 읽기 전용 작업을 보장하는 방법- 사용자 인증이 필요 하지 않은 사용자 는 자신의 클라이언트 앱에서만 허용됩니까?

다른 무엇보다도, fNek이 이전 답변에서 암시 한 단점이 있습니다. 클라이언트 앱은 잠재적으로 악의적 인 사용자가 사용합니다. 검사, 통신 검사, 코드 분해가 가능합니다. 내가 제안 할 것은 누군가가 클라이언트를 리버스 엔지니어링하지 않고 REST API를 남용하지 않도록 보장 할 수는 없습니다. 그러나 우발적 인 시도 앞에 장벽을 두어야합니다.

어쨌든 일반적인 접근 방식은 다음과 같습니다.

  • 클라이언트는 비밀을 포함
  • 요청시 요청 매개 변수를 비밀과 연결하고 결과를 해시합니다.
  • 이 해시는 요청과 함께 전송되고 서버에 의해 확인됩니다.

예는 상상 GET에 대한 요청을/products/widgets

클라이언트 시크릿이 "OH_HAI_I_IZ_SECRET"이라고 가정합니다.

HTTP 동사, URL 및 비밀을 연결하십시오.

GET/products/widgetsOH_HAI_I_IZ_SECRET

그리고 그 SHA-1 해시를 가져 가십시오 .

4156023ce06aff06777bef3ecaf6d7fdb6ca4e02

그런 다음 함께 보내십시오.

GET /products/widgets?hash=4156023ce06aff06777bef3ecaf6d7fdb6ca4e02

마지막으로, 누군가 개별 요청을 최소한 재생하지 못하게하려면 타임 스탬프도 가져 와서 매개 변수와 해시에 추가하십시오. 예를 들어, 현재 Unix 시간은 1384987891입니다. 연결에 추가하십시오.

GET/products/widgetsOH_HAI_I_IZ_SECRET1384987891

해시 :

2774561d4e9eb37994d6d71e4f396b85af6cacd1

그리고 보내기 :

GET /products/widgets?time=1384987891&hash=2774561d4e9eb37994d6d71e4f396b85af6cacd1

서버는 해시를 확인하고 타임 스탬프가 최신인지 확인합니다 (예 : 5 분 이내에 시계가 완벽하게 동기화되지 않도록 허용)

경고! 모바일 앱에 대해 이야기하고 있기 때문에 누군가의 휴대 전화에 시계가 잘못 연결될 위험이 있습니다. 또는 시간대가 잘못되었습니다. 또는 뭔가. 해시에 시간을 추가하면 일부 합법적 인 사용자가 중단 될 수 있으므로이 아이디어를주의해서 사용하십시오.


6
이 해싱 메커니즘은 프로그래머가 APK를 분해 할 때 이해할 수 있습니다.
Punith Raj

8
@PunithRaj 정확하게, 나는 두 번째 단락에서 그것을 다뤘습니다. "내가 제안하는 것은 클라이언트가 리버스 엔지니어링하지 않고 REST API를 악용하지 않도록 보장 할 수는 있지만 우발적 인 시도 앞에 장벽을 두어야한다."
Carson63000

경고로 서버와 모바일에서 UTC를 사용하고 있다면 문제가 해결됩니다.
shareef

@ Carson63000-구체적인 솔루션이 있습니까? 특히 공개적으로 열려 있어야하는 사용자 등록 API (웹 또는 모바일 앱에서 로그인하기 전에 사용자가 등록해야 함)의 경우, 봇이 대상을 지정하여 수천 명의 가짜 사용자를 만들 수 있습니다.
Tohid

17

관심있는 사람이라면 누구나 Android에서 수신 한 요청이 앱에서 전송되었는지 확인할 수 있습니다.

간단히 말해서 Google에 앱을 업로드 할 때 나에게만 알려진 고유 한 키로 서명합니다.

확인 과정은 다음과 같습니다.

  1. 앱이 Google에 가서 인증 토큰을 요청합니다.
  2. 앱이 토큰을 백엔드에 안전하게 보냅니다.
    1. 백엔드는 Google로 이동하여 앱에서 얻은 인증 토큰을 확인합니다.
    2. 그런 다음 백엔드는 앱이 서명 한 고유 키가 일치하지 않는지 확인합니다.

그것을 설명하는 전체 블로그와 그것을 구현하는 방법은 여기에서 찾을 수 있습니다 : http://android-developers.blogspot.co.il/2013/01/verifying-back-end-calls-from-android.html


1
좋은 대답이지만 악의적 인 사용자는 여전히 충분한 노력으로 앱을 속일 수 있습니다. 그러나 진정으로 안전한 것은 없습니다, 그것은 언제, 단지 문제 일뿐입니다
mateos

1
iOS의 경우 다음 옵션이 있습니다. link DeviceCheck API를 사용하면 수신 한 토큰이 앱이 다운로드 된 인증 된 Apple 장치에서 온 것인지 확인할 수 있습니다
Iwaz

계정 (이메일)이 필요합니다
user25

5

좋아, 시작하기 전에 언급 할 가치가있다. 대부분의 응용 프로그램에서 이것은 지나치게 과도합니다. 대부분의 유스 케이스에는 하나의 유효한 인증서 및 / 또는 토큰 만 있으면 충분합니다. 앱을 디 컴파일하는 것과 같은 어려운 일을하는 경우 매우 중요한 데이터를 제공하지 않으면 대부분의 해커조차 귀찮게하지 않습니다. 그러나 그 대답의 재미는 어디에 있습니까?

따라서 프로그램 서명에 사용되는 디지털 서명 과 같은 비대칭 암호화를 설정하면 됩니다. 그런 다음 각 앱은 단일 CA에서 발급하고 사용자가 연결될 때 확인되는 개별 인증서를 가질 수 있습니다. (처음 등록 할 때 또는 처음 설치할 때) 해당 인증서가 인증되면 지정된 장치 식별자 (예 : Android ID )에 대해 해당 인증서를 유효한 것으로 등록하여 애플리케이션을 더욱 안전하게 보호 할 수 있습니다.


5

@Morons가 그의 답변에서 언급했듯이 연결의 다른 쪽 끝에서 엔티티를 확인하는 것은 매우 어렵습니다.

어떤 수준의 신뢰성을 제공하는 가장 간단한 방법은 서버가 실제 실체 만이 알 수있는 비밀을 확인하도록하는 것입니다. 사용자의 경우 사용자 이름과 비밀번호 일 수 있습니다. 사용자가없는 소프트웨어의 경우 비밀을 포함시킬 수 있습니다.

이러한 접근 방식의 문제점은 클라이언트를 신뢰해야한다는 것입니다. 누군가가 앱을 리버스 엔지니어링하거나 비밀번호를 도용하는 경우 사용자 인 것처럼 가장 할 수 있습니다.

실행 파일에서 비밀 정보를 난독 처리하여 추출하기 어려운 단계를 수행 할 수 있습니다. Java의 난독 화기 인 ProGuard와 같은 도구가이를 도울 수 있습니다. 다른 언어의 난독 화에 대해서는 많이 알지 못하지만 비슷한 도구가있을 수 있습니다. TLS 연결을 사용하면 사람들이 트래픽을 스누핑하는 것을 방지 할 수 있지만 MITM 공격은 막을 수 없습니다. 고정 하면 해당 문제를 해결하는 데 도움이됩니다.

저는 이 신뢰 문제를 해결하려고 시도하는 Approov 라는 제품을 보유한 CriticalBlue (전체 공개!)라는 회사에서 일하고 있습니다. 현재 Android / iOS에서 작동하며 서버가 클라이언트 앱의 무결성을 검사 할 수있는 메커니즘을 제공합니다. 클라이언트가 임의의 챌린지에 대한 응답을 계산하도록하여이를 수행합니다. 클라이언트는 위조하기 어려운 설치된 앱 패키지의 속성을 사용하여 응답을 계산해야하며 정교한 안티 탬퍼 메커니즘이 포함되어 있습니다.

API에 진위 증명으로 보낼 수있는 토큰을 반환합니다.

이 방법과의 중요한 차이점은 클라이언트에서 진위 확인을 비활성화 할 수 있지만 인증 토큰을 얻지 못하면 서버에서 앱을 확인해야한다는 것입니다. 라이브러리는 실행 파일의 특성과 밀접하게 연결되어 있으므로 가짜 앱에 포함시키고 작동시키는 것은 매우 어렵습니다.

누군가 API를 해킹 할 가능성과 그 비용을 결정하기 위해 API 개발자가 수행해야하는 비용 / 이익 분석이 있습니다. 응용 프로그램의 간단한 비밀 검사는 사소한 공격을 방지하지만보다 결정적인 공격자로부터 자신을 보호하는 것은 아마도 훨씬 더 복잡하고 잠재적으로 비용이 많이 듭니다.


0

SSL은 통신 채널을 보호합니다.

로그인에 성공하면 암호화 된 연결을 통해 인증 토큰이 발급됩니다.

모든 후속 요청에서 인증 토큰이 REST API로 전달됩니다.


1
추가 정보를 추가했습니다. 액세스 토큰을 사용하여 언급 한 것과 같은 인증을 수행 할 계획이었습니다. REST API는 특정 작업에 대해서만 사용자가 로그인 할 필요가 없습니다. 두 경우 모두 클라이언트에 서명 / 신뢰해야합니다.
Supercell

기본 모바일 개발에 대해 잘 모르지만 모바일 애플리케이션이 모바일 API를 REST API에 제공 할 수 있습니까? 내 안드로이드 폰에 앱을 설치할 때 종종 앱에 특정 권한을 부여하라는 요청을받습니다. 보안 연결을 통해 모든 요청과 함께 휴대폰 번호를 보낼 수 있으면 알 수없는 휴대폰 번호로 모든 요청을 거부 할 수 있습니다. 여기서 큰소리로 생각하는 중…
CodeART

작동하지만 사용자가 로그인하고 사용자 계정에 바인딩 된 번호가 필요합니다. 그렇지 않으면 서버는 번호를 확인할 것이 없습니다.
Supercell

모바일 애플리케이션을 어떻게 설치 하시겠습니까?
CodeART

앱 스토어 (Google, Apple, Microsoft)를 통해 제공 될 예정입니다.
Supercell

0

너무 안전하지는 않지만 비밀 코드 또는 dgital 서명을 추가 할 수 있습니다. 단점 : 앱에 포함되어 있어야하므로 수행하는 작업을 알면 쉽게 얻을 수 있습니다.


0

내가 아는 한 HTTPS는 통신하는 서버의 유효성을 검사하는 것입니다.

실제로 SSL을 사용하여 클라이언트와 서버를 모두 인증 할 수 있습니다. 또는 "예, 클라이언트 인증서를 사용할 수 있습니다"라고 다르게 언급했습니다.

당신은 ...

  • 모바일 장치에서 클라이언트 인증서를 지정하는 방법을 결정하기 위해 사용중인 SSL 라이브러리를 확인하십시오.
  • 신뢰할 수 있고 등록 된 클라이언트의 연결 만 허용하도록 코드를 작성하거나 HTTPS 서버를 구성하십시오.
  • 신뢰할 수있는 클라이언트 인증서를 서버에 추가 할 수있는 메커니즘 제공
  • 더 이상 신뢰할 수없는 클라이언트 인증서를 서버에서 제거하는 메커니즘 제공

모바일 응용 프로그램에서 원하는 위치에 인증서를 저장할 수 있습니다. 응용 프로그램 별 인증을 원하기 때문에 인증서를 보호 된 디스크 위치에 저장하는 것을 고려해야합니다 (Android의 경우 SQLite 데이터베이스에 "구성"테이블, 인증서 행 및 개인 키 행)을 만들 수 있습니다) .

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