Cách bảo vệ API REST chỉ cho các ứng dụng di động đáng tin cậy


96

Làm cách nào để đảm bảo API REST của tôi chỉ đáp ứng các yêu cầu được tạo bởi các khách hàng đáng tin cậy, trong trường hợp ứng dụng di động của riêng tôi? Tôi muốn ngăn chặn các yêu cầu không mong muốn đến từ các nguồn khác. Tôi không muốn người dùng điền vào một khóa nối tiếp hoặc bất cứ điều gì, nó sẽ xảy ra đằng sau hậu trường, khi cài đặt và không có bất kỳ tương tác người dùng nào cần thiết.

Theo như tôi biết, HTTPS chỉ để xác thực máy chủ mà bạn đang liên lạc là người mà nó nói. Tôi sẽ sử dụng HTTPS để mã hóa dữ liệu.

Có cách nào để hoàn thành việc này?

Cập nhật: Người dùng có thể thực hiện các hành động chỉ đọc, không yêu cầu người dùng đăng nhập, nhưng họ cũng có thể thực hiện các hành động ghi, yêu cầu người dùng phải đăng nhập (Xác thực bằng mã thông báo truy cập). Trong cả hai trường hợp, tôi muốn API đáp ứng các yêu cầu chỉ đến từ các ứng dụng di động đáng tin cậy.

API cũng sẽ được sử dụng để đăng ký tài khoản mới thông qua ứng dụng di động.

Cập nhật 2: Có vẻ như có nhiều câu trả lời cho điều này, nhưng thực lòng tôi không biết câu nào sẽ đánh dấu câu trả lời. Một số người nói nó có thể được thực hiện, một số người nói nó không thể.


HTTPS sử dụng SSL (và TLS). SSL / TLS có thể được sử dụng với xác thực ứng dụng khách.
ATK

Bạn có nghĩa là chứng chỉ SSL phía khách hàng? Tôi nghĩ đó là những gì tôi đang tìm kiếm, ngoại trừ tôi không biết liệu điều đó có khả thi trong các ứng dụng di động (Android và iOS) không? Chứng chỉ ứng dụng khách sẽ được lưu trữ ở đâu? Lưu trữ thiết bị, bộ nhớ?
Supercell

SSL sẽ chỉ xác nhận thiết bị Di động, KHÔNG phải ứng dụng di động.
Morons

@Supercell: Tôi sẽ thêm một câu trả lời
ATK

Câu trả lời:


48

Bạn không thể.

Bạn không bao giờ có thể xác minh một thực thể, bất kỳ thực thể nào , có thể là một người, khách hàng phần cứng hoặc khách hàng phần mềm. Bạn chỉ có thể xác minh rằng những gì họ nói với bạn là chính xác, sau đó giả sử trung thực .

Ví dụ: làm thế nào để Google biết rằng tôi đang đăng nhập vào tài khoản Gmail của mình? Họ chỉ cần hỏi tôi tên người dùng và mật khẩu, xác minh điều đó , sau đó giả sử trung thực vì ai khác sẽ có thông tin đó? Tại một số điểm, Google đã quyết định rằng điều này là không đủ và đã thêm xác minh hành vi (tìm kiếm hành vi kỳ quặc) nhưng điều đó vẫn dựa vào người thực hiện hành vi , sau đó xác thực hành vi .

Đây chính xác là điều tương tự với việc xác nhận Khách hàng. Bạn chỉ có thể xác thực hành vi của Khách hàng chứ không thể xác thực Khách hàng.

Vì vậy, với SSL, bạn có thể xác minh Khách hàng có chứng chỉ hợp lệ hay không, vì vậy người ta có thể chỉ cần cài đặt Ứng dụng của bạn, lấy Chứng chỉ, sau đó chạy tất cả mã mới.

Vì vậy, câu hỏi là: Tại sao điều này rất quan trọng? Nếu đây là một mối quan tâm thực sự, tôi sẽ đặt câu hỏi về sự lựa chọn của bạn về một khách hàng béo. Có lẽ bạn nên dùng Ứng dụng web (vì vậy bạn không cần phải tiết lộ API của mình).

Xem thêm: Đánh bại xác thực chứng chỉ SSL cho các ứng dụng Android

và: Chứng chỉ SSL của khách hàng an toàn như thế nào trong một ứng dụng di động?


1
Tôi đã sử dụng chứng chỉ ứng dụng khách trên phần cứng nơi chứng chỉ được lưu trữ trên ổ đĩa được hệ điều hành mã hóa. Nhưng ngay cả ở đó, không ai tin rằng nó là hoàn hảo. Mục đích là để làm khó người dùng thông thường.
Steven Burnap

1
@Morons: một ứng dụng web sẽ giải quyết vấn đề này, nhưng chúng tôi nghĩ rằng người dùng sẽ có khả năng sử dụng ứng dụng gốc hơn là một ứng dụng web (vui lòng sửa lại cho tôi nếu giả định của chúng tôi sai). Lý do tại sao điều này rất quan trọng là vì API cung cấp cho người dùng quyền truy cập vào các phần của cơ sở dữ liệu của chúng tôi, nơi chứa rất nhiều dữ liệu chúng tôi thu thập được qua nhiều tháng làm việc. Đó là dữ liệu mà các công ty hoặc người dùng khác có thể dễ dàng sử dụng cho mục đích riêng của họ. Không đảm bảo an toàn cho khách hàng, chúng tôi sẽ không biết ai đang sử dụng nó (chống lại chúng tôi).
Supercell

6
Một ứng dụng web không giải quyết được vấn đề. Việc thay đổi bất kỳ phía máy khách webapp nào cũng khá đơn giản và khiến nó làm bất cứ điều gì bạn muốn.
Steven Burnap

5
@Supercell Bạn không thể hiển thị dữ liệu cho ai đó và sau đó ngăn họ chia sẻ dữ liệu đó. Nếu bạn không muốn một số người có Dữ liệu, bạn không cung cấp cho họ (hiển thị nó) cho họ.
Morons

Tôi đồng ý nhưng vì lý do khác nhau. Bạn có thể nếu bạn có quyền kiểm soát các thiết bị, giống như en.wikipedia.org/wiki/SecurID . Nhưng điện thoại di động không phải là thứ có thể kiểm soát được (chúng có thể chấp nhận tệp đính kèm như khóa plugin hoặc thứ gì đó).
imel96

31

Tôi chắc chắn rằng bạn cảm thấy thoải mái khi xử lý thông tin đăng nhập của người dùng và với việc liên lạc qua SSL, vì vậy tôi sẽ tập trung vào những gì tôi nghĩ đó là phần thú vị hơn của câu hỏi: làm thế nào để đảm bảo rằng các hành động chỉ đọc của bạn - mà không yêu cầu người dùng phải được xác thực - chỉ được chấp nhận từ các ứng dụng khách của riêng bạn?

Trước bất cứ điều gì khác, có một nhược điểm mà fNek đã gợi ý trong một câu trả lời trước đó - ứng dụng khách của bạn nằm trong tay của những người dùng có khả năng thù địch. Họ có thể được kiểm tra, thông tin liên lạc của họ được kiểm tra, mã của họ bị tháo rời. Không có gì tôi sẽ đề xuất sẽ cho phép bạn đảm bảo rằng ai đó không thiết kế ngược lại ứng dụng khách của bạn và lạm dụng API REST của bạn. Nhưng nó nên đặt một rào cản trước bất kỳ nỗ lực thông thường nào.

Dù sao, một cách tiếp cận phổ biến là:

  • Khách hàng chứa một bí mật
  • Khi thực hiện một yêu cầu, nó sẽ nối các tham số yêu cầu với các bí mật và băm kết quả
  • Băm này được gửi với yêu cầu và được kiểm tra bởi máy chủ

ví dụ, hãy tưởng tượng một GETyêu cầu cho/products/widgets

Giả sử bí mật của máy khách là "OH_HAI_I_IZ_SECRET"

Ghép nối động từ HTTP và URL và bí mật:

GET/products/widgetsOH_HAI_I_IZ_SECRET

Và lấy một hàm băm SHA-1 về điều đó:

4156023ce06aff06777bef3ecaf6d7fdb6ca4e02

Sau đó gửi nó cùng, vì vậy yêu cầu sẽ là:

GET /products/widgets?hash=4156023ce06aff06777bef3ecaf6d7fdb6ca4e02

Cuối cùng, để ngăn người nào đó ít nhất phát lại các yêu cầu riêng lẻ, hãy lấy dấu thời gian và thêm nó vào các tham số và hàm băm. ví dụ: ngay bây giờ, trong thời gian Unix, là 1384987891. Thêm điều đó vào phần nối:

GET/products/widgetsOH_HAI_I_IZ_SECRET1384987891

Băm rằng:

2774561d4e9eb37994d6d71e4f396b85af6cacd1

Và gửi:

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

Máy chủ sẽ kiểm tra hàm băm và cũng xác minh rằng dấu thời gian là hiện tại (ví dụ trong vòng 5 phút để cho phép đồng hồ không được đồng bộ hóa hoàn hảo)

Cảnh báo! Vì bạn đang nói về các ứng dụng di động, có một rủi ro nhất định rằng điện thoại của ai đó sẽ có đồng hồ sai. Hoặc múi giờ sai. Hoặc một cái gì đó. Thêm thời gian vào hàm băm có thể sẽ phá vỡ một số người dùng hợp pháp, vì vậy hãy thận trọng khi sử dụng ý tưởng đó.


6
Cơ chế băm này có thể được hiểu bởi bất kỳ lập trình viên nào khi anh ta tháo lắp apk.
Punith Raj

8
@PunithRaj chính xác, tôi đã đề cập đến điều đó trong đoạn thứ hai. "Không có gì tôi sẽ đề xuất sẽ cho phép bạn đảm bảo rằng ai đó không thiết kế ngược lại ứng dụng khách của bạn và lạm dụng API REST của bạn. Nhưng nó sẽ đặt ra một rào cản trước mọi nỗ lực thông thường."
Carson63000

để cảnh báo, đang sử dụng UTC trên máy chủ và thiết bị di động, điều này giải quyết vấn đề, phải không?
chia sẻ

@ Carson63000 - vậy, có giải pháp cụ thể không? đặc biệt đối với API đăng ký người dùng, phải mở công khai (người dùng cần đăng ký trước khi đăng nhập, trên web hoặc trên ứng dụng di động) và có thể bị bot nhắm mục tiêu để tạo ra hàng ngàn người dùng giả mạo.
Tohid

17

Đối với bất kỳ ai quan tâm, trên Android bạn CÓ THỂ xác minh rằng yêu cầu bạn đã nhận được đã được gửi từ ứng dụng của bạn.

Nói tóm lại, khi bạn tải ứng dụng của mình lên google, bạn ký tên, với một khóa duy nhất chỉ có bạn biết (và google).

Quá trình xác minh diễn ra (ish) như thế này:

  1. ứng dụng của bạn truy cập google và yêu cầu mã thông báo xác thực
  2. ứng dụng của bạn sẽ gửi mã thông báo một cách an toàn đến mặt sau của bạn
    1. phần cuối của bạn vào google và kiểm tra mã thông báo xác thực mà nó nhận được từ ứng dụng của bạn.
    2. mặt sau của bạn sau đó kiểm tra xem khóa duy nhất mà ứng dụng của bạn đã ký trùng khớp chưa, nếu không nó có nghĩa là đó không phải là ứng dụng của bạn ...

toàn bộ blog giải thích về nó và cách triển khai nó có thể tìm thấy ở đây: http://android-developers.blogspot.co.il/2013/01/verifying-back-end-calls-from-android.html


1
Câu trả lời tốt, tuy nhiên người dùng độc hại vẫn có thể giả mạo một ứng dụng với đủ nỗ lực. nhưng không có gì là thực sự an toàn, đó không phải là vấn đề nếu, chỉ là vấn đề khi nào
mateos

1
Đối với iOS có tùy chọn này: link API DeviceCheck cũng cho phép bạn xác minh rằng mã thông báo bạn nhận được đến từ một thiết bị Apple xác thực mà ứng dụng của bạn đã được tải xuống
Iwaz

Nó yêu cầu tài khoản (email)
user25

5

Ok, vì vậy nó đáng được đề cập trước khi tôi bắt đầu rằng đối với hầu hết các ứng dụng, điều này là quá mức cần thiết. Đối với hầu hết các trường hợp sử dụng, chỉ cần có một chứng chỉ hợp lệ và / hoặc mã thông báo là quá đủ. Nếu nó liên quan đến việc làm bất cứ điều gì khó khăn như dịch ngược ứng dụng của bạn thì thậm chí hầu hết các tin tặc sẽ không bận tâm trừ khi bạn cung cấp một số dữ liệu rất có giá trị. Nhưng này, niềm vui trong câu trả lời đó là gì?

Vì vậy, những gì bạn có thể làm là thiết lập mật mã bất đối xứng giống như chữ ký số được sử dụng để ký các chương trình. Mỗi ứng dụng sau đó có thể có một chứng chỉ riêng được cấp bởi một CA duy nhất và được xác minh khi người dùng của bạn kết nối. (khi đăng ký lần đầu hoặc khi cài đặt lần đầu) Khi chứng chỉ đó được xác thực, bạn có thể bảo mật ứng dụng của mình hơn nữa bằng cách đăng ký chứng chỉ đó là hợp lệ cho một số nhận dạng thiết bị cụ thể (chẳng hạn như ID Android )


5

Như @Morons đã đề cập trong câu trả lời của anh ấy, rất khó để xác minh thực thể ở đầu kia của kết nối.

Cách đơn giản nhất để cung cấp một số mức độ xác thực là yêu cầu máy chủ kiểm tra một số bí mật mà chỉ có thực thể thực sự mới biết. Đối với người dùng, đó có thể là tên người dùng và mật khẩu. Đối với một phần mềm không có người dùng, bạn có thể nhúng một bí mật.

Vấn đề với các phương pháp này là bạn phải đặt niềm tin vào khách hàng. Nếu ai đó đảo ngược kỹ sư ứng dụng của bạn hoặc đánh cắp mật khẩu của bạn, họ có thể giả vờ là bạn.

Bạn có thể thực hiện các bước để làm cho việc trích xuất thông tin bí mật trở nên khó khăn hơn bằng cách làm xáo trộn nó trong phần thực thi. Các công cụ như ProGuard là một obfuscator cho Java có thể giúp với điều này, tôi không biết nhiều về obfuscation trong các ngôn ngữ khác nhưng có khả năng là các công cụ tương tự. Sử dụng kết nối TLS giúp ngăn mọi người rình mò lưu lượng truy cập của bạn, nhưng không ngăn chặn cuộc tấn công MITM. Ghim có thể giúp giải quyết vấn đề đó.

Tôi làm việc cho một công ty tên là CriticalBlue (Công bố đầy đủ!), Người có một sản phẩm tên là Approov cố gắng giải quyết vấn đề về niềm tin này. Hiện tại, nó hoạt động cho Android / iOS và cung cấp cơ chế cho các máy chủ của chúng tôi kiểm tra tính toàn vẹn của ứng dụng khách. Nó thực hiện điều này bằng cách khiến khách hàng tính toán phản hồi cho một thử thách ngẫu nhiên. Khách hàng phải tính toán phản hồi bằng các thuộc tính của gói ứng dụng đã cài đặt khó giả mạo và nó bao gồm một số cơ chế chống giả mạo tinh vi.

Nó trả về một mã thông báo mà sau đó bạn có thể gửi làm bằng chứng xác thực cho API của mình.

Sự khác biệt quan trọng với phương pháp này là mặc dù có thể vô hiệu hóa kiểm tra tính xác thực trên máy khách, nếu bạn đã làm như vậy, bạn sẽ không nhận được mã thông báo xác thực mà bạn cần để xác minh ứng dụng của mình với máy chủ. Thư viện cũng được kết hợp chặt chẽ với các đặc điểm của tệp thực thi mà nó có trong đó, vì vậy sẽ rất khó để nhúng nó vào một ứng dụng giả mạo và khiến nó hoạt động.

Có một phân tích chi phí / lợi ích mà bất kỳ nhà phát triển API nào cũng phải thực hiện để quyết định khả năng ai đó sẽ cố gắng hack API của họ và mức độ có thể tốn kém như thế nào. Một kiểm tra bí mật đơn giản trong ứng dụng ngăn chặn các cuộc tấn công tầm thường, nhưng để bảo vệ bản thân trước kẻ tấn công kiên quyết hơn có lẽ phức tạp hơn đáng kể và có khả năng tốn kém.


0

SSL sẽ bảo mật kênh liên lạc.

Đăng nhập thành công sẽ phát hành mã thông báo xác thực qua kết nối được mã hóa.

Mã thông báo xác thực sẽ được chuyển đến API REST của bạn trong tất cả các yêu cầu tiếp theo.


1
Tôi đã thêm một số thông tin bổ sung. Tôi đã lên kế hoạch thực hiện xác thực như bạn đã đề cập, với mã thông báo truy cập. API REST không yêu cầu người dùng phải đăng nhập, chỉ cho các hành động cụ thể. Trong cả hai trường hợp, khách hàng cần phải được ký / tin cậy.
Supercell

Tôi không biết nhiều về phát triển di động bản địa, nhưng ứng dụng di động của bạn có thể cung cấp số điện thoại di động cho API REST không? Khi tôi cài đặt ứng dụng trên điện thoại Android, tôi thường được yêu cầu cung cấp một số quyền nhất định cho ứng dụng. Nếu bạn có thể gửi một số điện thoại di động với mọi yêu cầu qua kết nối an toàn, thì bạn có thể từ chối tất cả các yêu cầu có số điện thoại di động không xác định. Chỉ cần suy nghĩ thành tiếng ở đây ...
CodeART 20/11/13

Điều đó có thể hoạt động, nhưng nó sẽ yêu cầu người dùng phải đăng nhập và số lượng ràng buộc với tài khoản người dùng. Nếu không, máy chủ sẽ không có bất cứ điều gì để xác minh số.
Supercell

Làm thế nào bạn sẽ cài đặt ứng dụng di động của bạn?
CodeART

Chúng sẽ có sẵn thông qua các cửa hàng ứng dụng (Google, Apple, Microsoft)
Supercell

0

Nó sẽ không quá an toàn, nhưng bạn có thể thêm một số loại mã bí mật hoặc thậm chí là một chữ ký dgital. Nhược điểm: Nó phải được bao gồm trong ứng dụng, giúp bạn dễ dàng lấy được nó nếu bạn biết bạn làm gì.


0

Theo như tôi biết, HTTPS chỉ để xác thực máy chủ mà bạn đang liên lạc là người mà nó nói.

Trên thực tế, bạn có thể sử dụng SSL để xác thực cả máy khách và máy chủ. Hoặc, được nêu khác nhau, "có, bạn có thể sử dụng chứng chỉ ứng dụng khách".

Bạn sẽ cần ...

  • nhìn vào thư viện SSL bạn đang sử dụng để xác định cách chỉ định chứng chỉ ứng dụng khách trong thiết bị di động,
  • viết mã hoặc cấu hình máy chủ HTTPS của bạn để nó chỉ chấp nhận các kết nối từ các máy khách đã đăng ký, đáng tin cậy.
  • đưa ra một cơ chế để thêm chứng chỉ ứng dụng khách đáng tin cậy vào máy chủ của bạn
  • đưa ra một cơ chế để loại bỏ chứng chỉ ứng dụng khách không còn tin cậy khỏi máy chủ của bạn

Bạn có thể có ứng dụng di động lưu trữ chứng chỉ bất cứ nơi nào bạn muốn. Vì bạn muốn xác thực dành riêng cho ứng dụng, bạn nên xem xét việc lưu chứng chỉ vào vị trí đĩa được bảo vệ (trên Android, bạn có thể tạo bảng "config" trong cơ sở dữ liệu SQLite của mình và một hàng cho chứng chỉ của bạn và một hàng khác cho khóa riêng của bạn) .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.