Cara melindungi API REST hanya untuk aplikasi seluler tepercaya

96

Bagaimana cara memastikan REST API saya hanya menanggapi permintaan yang dihasilkan oleh klien tepercaya, dalam kasus saya aplikasi seluler saya sendiri? Saya ingin mencegah permintaan yang tidak diinginkan datang dari sumber lain. Saya tidak ingin pengguna mengisi kunci serial atau apa pun, itu harus terjadi di belakang layar, pada saat pemasangan, dan tanpa interaksi pengguna apa pun.

Sejauh yang saya tahu, HTTPS hanya untuk memvalidasi server yang Anda ajak berkomunikasi adalah yang dikatakannya. Saya tentu saja akan menggunakan HTTPS untuk mengenkripsi data.

Apakah ada cara untuk menyelesaikan ini?

Pembaruan: Pengguna dapat melakukan tindakan hanya baca, yang tidak mengharuskan pengguna untuk login, tetapi mereka juga dapat melakukan tindakan menulis, yang memang mengharuskan pengguna untuk login (Otentikasi oleh Token Akses). Dalam kedua kasus ini saya ingin API menanggapi permintaan yang datang hanya dari aplikasi seluler tepercaya.

API juga akan digunakan untuk mendaftarkan akun baru melalui aplikasi seluler.

Pembaruan 2: Sepertinya ada beberapa jawaban untuk ini, tapi sejujurnya saya tidak tahu yang mana yang ditandai sebagai jawaban. Ada yang bilang itu bisa dilakukan, ada yang bilang tidak bisa.

Supercell
sumber
HTTPS menggunakan SSL (dan TLS). SSL / TLS dapat digunakan dengan otentikasi klien.
atk
Apakah maksud Anda sertifikat SSL sisi klien? Saya pikir itulah yang saya cari, kecuali saya tidak tahu apakah itu mungkin dalam aplikasi mobile (Android dan iOS)? Di mana sertifikat klien disimpan? Penyimpanan perangkat, memori?
Supercell
SSL hanya akan mengesahkan perangkat Seluler, BUKAN aplikasi seluler.
Moron
@Supercell: Saya akan menambahkan jawaban
atk

Jawaban:

48

Kamu tidak bisa

Anda tidak pernah dapat memverifikasi suatu entitas, entitas apa pun , baik itu orang, klien perangkat keras atau klien perangkat lunak. Anda hanya dapat memverifikasi bahwa apa yang mereka katakan adalah benar, lalu anggap jujur .

Misalnya, bagaimana Google tahu saya masuk ke akun Gmail saya? Mereka hanya meminta saya untuk nama pengguna dan kata sandi, memverifikasi itu , lalu menganggap kejujuran karena siapa lagi yang akan mendapatkan info itu? Pada titik tertentu Google memutuskan bahwa ini tidak cukup dan menambahkan verifikasi perilaku (mencari perilaku aneh) tetapi itu masih mengandalkan orang tersebut untuk melakukan perilaku tersebut , kemudian memvalidasi perilaku tersebut .

Ini persis sama dengan memvalidasi Klien. Anda hanya dapat memvalidasi perilaku Klien, tetapi bukan Klien itu sendiri.

Jadi dengan SSL, Anda dapat memverifikasi bahwa Klien memiliki sertifikat yang valid atau tidak, Jadi seseorang dapat menginstal Aplikasi Anda, mendapatkan Cert, lalu menjalankan semua kode baru.

Jadi pertanyaannya adalah: Mengapa ini begitu kritis? Jika ini merupakan masalah nyata, saya akan mempertanyakan pilihan Anda untuk klien yang gemuk. Mungkin Anda harus menggunakan Aplikasi web (jadi Anda tidak perlu membuka API Anda).

Lihat juga: Mengalahkan Validasi Sertifikat SSL untuk Aplikasi Android

dan: Seberapa amankah sertifikat SSL klien di aplikasi seluler?

Orang bodoh
sumber
1
Saya telah menggunakan sertifikat klien pada perangkat keras tempat sertifikat disimpan pada drive yang dienkripsi oleh OS. Tetapi bahkan di sana, tidak ada yang percaya itu sangat mudah. Tujuannya hanya untuk menyulitkan pengguna biasa.
Steven Burnap
1
@Morons: aplikasi web akan menyelesaikan ini, tapi kami pikir pengguna akan lebih cenderung menggunakan aplikasi asli daripada aplikasi web (tolong perbaiki saya jika asumsi kami salah). Alasan mengapa hal ini sangat penting adalah karena API memberi pengguna akses ke bagian-bagian dari basis data kami, yang berisi banyak data yang kami kumpulkan selama berbulan-bulan kerja. Ini adalah data yang dapat dengan mudah digunakan perusahaan atau pengguna untuk keperluan mereka sendiri. Tanpa mengamankan klien, kami tidak akan tahu siapa yang menggunakannya (melawan kami).
Supercell
6
Webapp tidak menyelesaikan masalah. Cukup sepele untuk memodifikasi sisi klien webapp apa pun dan membuatnya melakukan apa pun yang Anda inginkan.
Steven Burnap
5
@Supercell Anda tidak dapat menampilkan data seseorang dan kemudian menghentikan mereka untuk membagikannya. Jika Anda tidak ingin beberapa memiliki Data, Anda tidak memberikan (menunjukkannya) kepada mereka.
Moron
Saya setuju tetapi untuk alasan yang berbeda. Anda dapat melakukannya jika Anda memiliki kendali atas perangkat, seperti r.wikipedia.org/wiki/SecurID . Tetapi ponsel bukanlah sesuatu yang dapat dikontrol (mereka dapat menerima lampiran seperti kunci plugin atau sesuatu).
imel96
31

Saya yakin Anda merasa nyaman dengan berurusan dengan login pengguna, dan dengan komunikasi melalui SSL, jadi saya akan fokus pada apa yang saya pikir itu bagian yang lebih menarik dari pertanyaan: bagaimana memastikan bahwa tindakan read-only Anda - yang tidak mengharuskan pengguna untuk diautentikasi - hanya diterima dari aplikasi klien Anda sendiri?

Sebelum hal lain, ada kelemahan yang mengisyaratkan fNek dalam jawaban sebelumnya - aplikasi klien Anda ada di tangan pengguna yang berpotensi bermusuhan. Mereka dapat diperiksa, komunikasi mereka diinspeksi, kode mereka dibongkar. Tidak ada yang akan saya sarankan akan memungkinkan Anda untuk menjamin bahwa seseorang tidak merekayasa balik klien Anda dan menyalahgunakan REST API Anda. Tapi itu harus menempatkan penghalang di depan upaya kasual.

Bagaimanapun, pendekatan umum adalah:

  • Klien mengandung rahasia
  • Saat membuat permintaan, itu menggabungkan parameter permintaan dengan rahasia, dan hash hasilnya
  • Hash ini dikirim bersama permintaan, dan diperiksa oleh server

misalnya, bayangkan GETpermintaan/products/widgets

Katakanlah rahasia klien adalah "OH_HAI_I_IZ_SECRET"

Menggabungkan kata kerja HTTP, dan URL, dan rahasia:

GET/products/widgetsOH_HAI_I_IZ_SECRET

Dan ambil hash SHA-1 itu:

4156023ce06aff06777bef3ecaf6d7fdb6ca4e02

Kemudian kirimkan, jadi permintaannya adalah untuk:

GET /products/widgets?hash=4156023ce06aff06777bef3ecaf6d7fdb6ca4e02

Terakhir, untuk mencegah seseorang dari setidaknya mengulangi permintaan individual, ambil juga stempel waktu, dan tambahkan itu ke parameter dan hash. mis. saat ini, dalam waktu Unix, adalah 1384987891. Tambahkan itu ke rangkaian:

GET/products/widgetsOH_HAI_I_IZ_SECRET1384987891

Hash itu:

2774561d4e9eb37994d6d71e4f396b85af6cacd1

Dan kirim:

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

Server akan memeriksa hash dan juga memverifikasi bahwa cap waktu terkini (mis. Dalam waktu 5 menit untuk memungkinkan jam tidak sinkron dengan sempurna)

Peringatan! Karena Anda berbicara tentang aplikasi seluler, ada risiko pasti bahwa telepon seseorang akan salah jam. Atau zona waktu salah. Atau sesuatu. Menambahkan waktu ke hash mungkin akan merusak beberapa pengguna yang sah, jadi gunakan ide itu dengan hati-hati.

Carson63000
sumber
6
mekanisme hashing ini dapat dipahami oleh programmer mana pun ketika ia membongkar apk.
Punith Raj
8
@PunithRaj tepatnya, saya bahas di paragraf kedua. "Tidak ada yang akan saya sarankan akan memungkinkan Anda untuk menjamin bahwa seseorang tidak merekayasa balik klien Anda dan menyalahgunakan REST API Anda. Tetapi itu harus menempatkan penghalang di depan upaya kasual apa pun."
Carson63000
untuk peringatan, saya menggunakan UTC di server dan seluler, ini menyelesaikan masalah, bukan?
shareef
@ Carson63000 - jadi, apakah ada solusi konkret? terutama untuk API pendaftaran pengguna, yang harus dibuka untuk umum (pengguna harus mendaftar sebelum dapat masuk, baik di web atau di aplikasi seluler) dan dapat ditargetkan oleh bot untuk membuat ribuan pengguna palsu.
Tohid
17

Bagi siapa pun yang tertarik, di Android Anda BISA memverifikasi bahwa permintaan yang Anda dapatkan telah dikirim dari aplikasi Anda.

Singkatnya, ketika Anda mengunggah aplikasi ke Google, Anda menandatanganinya, dengan kunci unik yang hanya diketahui oleh Anda (dan google).

Proses verifikasi berjalan (ish) seperti ini:

  1. aplikasi Anda masuk ke google dan meminta token auth
  2. aplikasi Anda mengirimkan token dengan aman ke ujung belakang Anda
    1. ujung belakang Anda pergi ke google dan memeriksa token auth yang didapatnya dari aplikasi Anda.
    2. bagian belakang Anda kemudian memeriksa apakah kunci unik aplikasi Anda telah menandatangani cocok, jika tidak itu berarti itu bukan aplikasi Anda ...

blog lengkap yang menjelaskannya dan cara menerapkannya dapat ditemukan di sini: http://android-developers.blogspot.co.il/2013/01/verifying-back-end-calls-from-android.html

ndori
sumber
1
Jawaban yang bagus, namun pengguna jahat masih bisa memalsukan aplikasi dengan upaya yang cukup. tapi tidak ada yang benar-benar aman, itu bukan masalah jika, hanya masalah kapan
mateos
1
Untuk iOS ada opsi ini: tautan API DeviceCheck juga memungkinkan Anda memverifikasi bahwa token yang Anda terima berasal dari perangkat Apple asli tempat aplikasi Anda telah diunduh
Iwaz
Itu membutuhkan akun (email)
user25
5

Ok, jadi nilainya menyebutkan sebelum saya memulai bahwa untuk sebagian besar aplikasi ini sangat berlebihan. Untuk sebagian besar kasus penggunaan, hanya memiliki satu sertifikat dan / atau token yang valid lebih dari cukup. Jika itu melibatkan melakukan sesuatu yang sulit seperti mendekompilasi aplikasi Anda, maka sebagian besar peretas tidak akan repot kecuali Anda memberikan beberapa data yang sangat berharga. Tapi hei, apakah kesenangan dalam jawaban itu?

Jadi yang dapat Anda lakukan adalah mengatur kriptografi asimetris seperti tanda tangan digital yang digunakan untuk menandatangani program. Setiap aplikasi kemudian dapat memiliki sertifikat individual yang dikeluarkan oleh CA tunggal dan diverifikasi ketika pengguna Anda terhubung. (baik saat pertama kali mendaftar atau saat pertama kali menginstal) Saat sertifikat itu diautentikasi, Anda kemudian dapat mengamankan aplikasi Anda dengan mendaftarkan sertifikat tersebut sebagai valid untuk satu pengenal perangkat yang diberikan (seperti Android ID )

Tom Squires
sumber
5

Seperti yang disebutkan @Morons dalam jawabannya, sangat sulit untuk memverifikasi entitas di ujung koneksi yang lain.

Cara paling sederhana untuk memberikan tingkat keaslian adalah dengan meminta server memeriksa beberapa rahasia yang hanya diketahui oleh entitas nyata. Untuk pengguna, itu bisa berupa nama pengguna dan kata sandi. Untuk perangkat lunak di mana tidak ada pengguna, Anda mungkin menanamkan rahasia.

Masalah dengan pendekatan ini adalah Anda harus menaruh kepercayaan pada klien. Jika seseorang membalikkan rekayasa aplikasi Anda atau mencuri kata sandi Anda, mereka dapat berpura-pura menjadi Anda.

Anda dapat mengambil langkah-langkah untuk membuatnya lebih sulit untuk mengekstrak informasi rahasia dengan mengaburkannya di executable. Alat seperti ProGuard yang merupakan obfuscator untuk Java dapat membantu dengan ini, saya tidak tahu banyak tentang kebingungan dalam bahasa lain tetapi ada kemungkinan alat serupa. Menggunakan koneksi TLS membantu mencegah orang mengintip lalu lintas Anda, tetapi tidak mencegah serangan MITM. Pinning dapat membantu mengatasi masalah itu.

Saya bekerja untuk perusahaan bernama CriticalBlue (Pengungkapan penuh!) Yang memiliki produk bernama Approov yang mencoba mengatasi masalah kepercayaan ini. Ini berfungsi untuk Android / iOS saat ini dan menyediakan mekanisme bagi server kami untuk memeriksa integritas aplikasi klien. Ini dilakukan dengan meminta klien menghitung respons terhadap tantangan acak. Klien harus menghitung respons menggunakan atribut dari paket aplikasi yang diinstal yang sulit dipalsukan dan itu mencakup beberapa mekanisme anti-tamper canggih.

Ini mengembalikan token yang kemudian dapat Anda kirim sebagai bukti keaslian ke API Anda.

Perbedaan penting dengan pendekatan ini adalah bahwa meskipun mungkin untuk menonaktifkan pemeriksaan keaslian pada klien, jika Anda melakukannya Anda tidak akan mendapatkan token otentikasi Anda perlu memverifikasi aplikasi Anda dengan server. Pustaka juga sangat erat dengan karakteristik executable yang ada di dalamnya, sehingga akan sangat sulit untuk menanamkannya di aplikasi palsu dan membuatnya bekerja.

Ada analisis biaya / manfaat yang harus dibuat oleh pengembang API untuk memutuskan seberapa besar kemungkinan seseorang akan mencoba meretas API mereka dan seberapa mahal harganya. Pemeriksaan rahasia sederhana dalam aplikasi mencegah serangan sepele, tetapi untuk melindungi diri Anda dari penyerang yang lebih gigih mungkin jauh lebih rumit dan berpotensi mahal.

ThePragmatist
sumber
0

SSL akan mengamankan saluran komunikasi.

Login yang berhasil akan mengeluarkan token otentikasi melalui koneksi terenkripsi.

Token otentikasi akan diteruskan ke API REST Anda di semua permintaan berikutnya.

CodeART
sumber
1
Saya telah menambahkan beberapa informasi tambahan. Saya berencana untuk melakukan otentikasi seperti yang Anda sebutkan, dengan token akses. API REST tidak mengharuskan pengguna untuk login, hanya untuk tindakan tertentu. Dalam kedua kasus, klien harus ditandatangani / dipercaya.
Supercell
Saya tidak tahu banyak tentang pengembangan ponsel asli, tetapi bisakah aplikasi seluler Anda memberikan nomor ponsel ke REST API? Ketika saya menginstal aplikasi di ponsel android saya, saya sering diminta untuk memberikan izin tertentu ke aplikasi tersebut. Jika Anda dapat mengirim nomor ponsel dengan setiap permintaan melalui koneksi aman, maka Anda dapat menolak semua permintaan dengan nomor ponsel yang tidak dikenal. Hanya berpikir keras di sini ...
CodeART
Itu bisa bekerja, tetapi itu akan mengharuskan pengguna untuk login dan nomor terikat ke akun pengguna. Kalau tidak, server tidak akan memiliki apa pun untuk memverifikasi nomor terhadap.
Supercell
Bagaimana Anda akan menginstal aplikasi seluler Anda?
CodeART
Mereka akan tersedia melalui app store (Google, Apple, Microsoft)
Supercell
0

Itu tidak akan terlalu aman, tetapi Anda dapat menambahkan semacam kode rahasia atau bahkan tanda tangan dgital. Kelemahan: Ini harus dimasukkan dalam aplikasi, yang membuatnya mudah untuk mendapatkannya jika Anda tahu apa yang Anda lakukan.

fek
sumber
0

Sejauh yang saya tahu, HTTPS hanya untuk memvalidasi server yang Anda ajak berkomunikasi adalah yang dikatakannya.

Bahkan, Anda dapat menggunakan SSL untuk mengotentikasi klien dan server. Atau, dengan kata lain, "Ya, Anda dapat menggunakan sertifikat klien".

Anda harus ...

  • lihat perpustakaan SSL yang Anda gunakan untuk menentukan cara menentukan sertifikat klien di perangkat seluler,
  • tulis kode atau konfigurasikan server HTTPS Anda sehingga hanya menerima koneksi dari klien tepercaya dan terdaftar.
  • datang dengan mekanisme untuk menambahkan sertifikat klien tepercaya ke server Anda
  • datang dengan mekanisme untuk menghapus sertifikat klien yang tidak lagi dipercaya dari server Anda

Anda dapat meminta aplikasi seluler menyimpan sertifikat di mana pun Anda inginkan. Karena Anda menginginkannya otentikasi khusus aplikasi, Anda harus mempertimbangkan untuk menyimpan sertifikat di lokasi disk yang dilindungi (di Android, Anda dapat membuat tabel "config" dalam database SQLite Anda, dan satu baris untuk sertifikat Anda dan satu lagi untuk kunci pribadi Anda) .

atk
sumber