Вопрос по android, http, hash, security – Защита доступа URL-адреса API через хеш в приложении Android

10

В моем приложении для Android пользователь может отправлять контент в базу данных, который затем могут видеть все остальные пользователи.

Этот новый контент отправляется на сервер с помощью запроса GET:

http://www.example.org/API.php?newContent=helloWorld

Проблема заключается в следующем: если пользователь узнает, как выглядит этот URL, он может легко отправлять вредоносные запросы в своем браузере и обходить приложение Android. Может быть, можно декомпилировать приложение и узнать об URL.

Как я могу защитить доступ к этому URL и запретить пользователям доступ к этому API напрямую?

Это хорошее решение для создания хэша в приложении и сравнения его с хэшем, сгенерированным в файле API.php на сервере?

Разве нельзя узнать, как создается хеш при декомпиляции приложения?

Заранее большое спасибо!

Ваш Ответ

4   ответа
17

единственный способ по-настоящему защитить этот URL-адрес, требуя проверки подлинности всех запросов к нему.

Один из способов сделать это - изменить запрос на POST-запрос и отправить вместе с запросом какой-нибудь токен аутентификации (простой хеш). Если токен отсутствует, просто не отвечайте на запрос. Хеш будет чем-то, что вы жестко закодируете как на клиенте, так и на сервере.

Теперь вопрос в том, как скрыть свой токен авторизации. До тех пор, пока вы не открыли исходный код, единственный способ получить доступ к нему - декомпилировать вашу программу, как вы упоминали. Чтобы избежать этого, вы можете использовать proguard (http://developer.android.com/guide/developing/tools/proguard.html).

Следует иметь в виду, что этот метод содержит одну точку отказа. Если ваш токен аутентификации когда-либо выставлен, вы готовы (например, разгром криптографического ключа HD DVD AACS).

Еще один способ аутентификации - для каждого пользователя. Пока действительный пользователь делает запрос, вас не должно волновать, поступает ли запрос из веб-браузера или из приложения для Android. Я думаю, что это намного лучший способ делать вещи. Делая это, вы можете регулировать запросы для каждого пользователя. Это, однако, требует от вас управления профилями пользователей и всей червей, которые идут вместе с ним.

Все это говорит о том, что в конце дня вас не должно волновать, знает ли кто-нибудь URL-адрес части вашего API. Я не знаю вашего конкретного случая использования, но должен быть способ спроектировать ваш API, чтобы вам было все равно, как вы получаете свои запросы. Кроме того, если вы делаете настоящий GET, то вы не должны ничего менять на сервере. Это означает, что все, что может сделать «злоумышленник», - это извлечь из него данные. Это серьезно ограничивает ущерб, который они могут нанести. На самом деле, если у вас нет конфиденциальных данных, которые вы не хотите, чтобы некоторые люди просматривали, у вас вообще не будет проблем. Если вы это сделаете, то вам стоит подумать о моем решении для аутентификации для каждого пользователя.

@MarcoW. Функции хеширования так же безопасны на Android, как и на любой другой платформе. Kurtis Nusbaum
Спасибо за этот подробный ответ :) Вы сказали, что я должен использовать POST только для вызовов API, которые изменяют данные на сервере. Но то, что я делаю, это: если пользователь хочет «поднять» пункт 123, я звоню:example.org/API.php?item=123&vote=up Это плохой подход? Меня беспокоит то, что можно легко найти функцию, которая генерирует токен аутентификации при декомпиляции приложения, не так ли? Таким образом, каждый «злоумышленник» может легко сгенерировать правильные значения хэша самостоятельно ?! caw
Две вещи. Во-первых, это не «правильный» подход. Как я уже сказал, вы должны использовать GET только для вещей, которые не вызывают изменений. Я должен быть в состоянии напечатать example.org/API.php?item=123&vote=up и получить согласованную веб-страницу. Во-вторых, если вы делаете это для пользователя, вам непременно следует использовать мой метод аутентификации для каждого пользователя. Таким образом, только действительные пользователи могут голосовать. Как я уже сказал в своем ответе, если вы действительно беспокоитесь о людях, которые смотрят на ваш код, вы можете использовать progaurd. Kurtis Nusbaum
Если вы действительно хотите узнать разницу POST и GET, вы можете погуглить. Я нашел эту статью, которая из моего скимминга, кажется, дает хорошее объяснение:cs.tut.fi/~jkorpela/forms/methods.html , Что касается Proguard, вы никогда не будете на 100% делать свой код запутанным. Я не знаю ни одного способа сделать Java полностью на 100% неразборчивой. Это логично, потому что в конце концов компьютер все еще должен декодировать и запускать его, поэтому код всегда будет иметь фиксированный порядок. Kurtis Nusbaum
Большое спасибо за ваш комментарий еще раз! Возможно, глупый вопрос, но: почему я должен использовать POST вместо GET для изменения действий? Я не вижу преимущества с точки зрения безопасности ... И: Proguard только затрудняет чтение вашего кода, но не делает его невозможным;) Как другие приложения обрабатывают генерацию хеша для Android? caw
2

если его javascript в веб-браузере или даже какой-то заблокированной платформе, такой как Iphone.

Если приложение может выполнять вызовы API, то, очевидно, все, что нужно для этих вызовов, находится на телефоне (секрет, хэш-функция, ключ API и т. Д.), Тогда кто-то всегда может сбросить память телефона и получить все эти данные. Затем они могут сделать любой запрос, который они хотят.

Что вы хотите сделать, это аутентифицировать пользователя, а затем проверить входные данные на стороне сервера.

Спасибо за этот ответ :) Конечно, я не хочу проверять вызовы API на стороне клиента. Но остальная часть вашего ответа именно то, что меня беспокоит. Таким образом, по вашему мнению, аутентификация пользователей является единственным способом защиты доступа к API для приложений Android? caw
0

чтобы запутать каждую букву URL. Так что вроде создания собственного словаря таким образом, чтобы URL мог выглядеть как 123.3 * 15 * 13 или что-то в этом роде, если бы кто-то декомпилировал APK, они бы не знали. И на этой ноте вы бы в идеале использовали Proguard, чтобы запутать его, чтобы ваше запутывание не имело смысла для кого-то, пытающегося провести обратный инжиниринг.

Вы можете сделать короткий метод Java, как это:

public String confuseString() {
    Stringbuilder sb = new StringBuilder();
    //your real URL would be abc.com, but in the app you have myURL = 123.3*15*13
    //With what I'm saying the * would precede a 2 digit number that represents 1 letter
     for (int i = 0; i < stringLength; i++){
         String letter = myURL.charAt(i);
        if (letter.equals("1"){
            letter = a;
            sb.append(letter);
        } // you would go one to code each character into a letter
     }

}

Конечно, было бы еще несколько утверждений if, но это позволило бы вам запутать ваш URL без внесения каких-либо изменений на стороне сервера. И если вы используете Proguard, то весь этот метод, который вы создадите, не будет иметь никакого смысла для тех, кто пытается реинжинировать.

Конечно, вы могли бы сделать свое запутывание намного сложнее, чем я предлагал, но в любом случае это идея.

По сути, вы будете шифровать URL очень запутанным способом.

Вот ответ, который может быть лучшим методом шифрования или, по крайней мере, дать дополнительное шифрование:

Java - зашифровать / расшифровать имя пользователя и пароль из файла конфигурации

Несмотря на то, что это хорошо, чтобы запутать ваш код независимо от этого, все же было бы хорошей практикой управлять каким-либо видом входа пользователя с помощью пароля. Таким образом, только действительные пользователи могут голосовать или что-то еще. Reed
Спасибо за дополнительный комментарий, Джакар! Я действительно ценю вашу идею. Но я пока не понимаю, почему эта функция должна усложнить реверс-инжиниринг, чем это делает ProGuard !? Не могли бы вы объяснить это? caw
Большое спасибо за этот подробный ответ и интересный подход :) Но разве я не мог использовать вместо этого какой-либо алгоритм шифрования? И еще: когда кто-то попытается выполнить обратный инжиниринг кода, он также найдет эту функцию запутывания и поймет, как должна быть переведена запутанная строка обратно, верно? caw
Пожалуйста. :) Чем больше кода вы добавляете, тем больше он запутывает, тем больше запутывает код. И в моем примере я сделалletter.equals("1"), но если вы определите в теле классаfinal String xqt = "1"; тогда делайletter.equals(xqt)тогда я верю, что Proguard поместит xqt в другой класс и будет ссылаться на него неясным образом. Но, по сути, чем больше вы добавляете, тем больше это запутывает, поэтому труднее его реконструировать. Reed
Да, вы можете использовать любой алгоритм шифрования. Чем сложнее, тем лучше, конечно. И технически, кто-то может перепроектировать код, но это будет действительно сложно, потому что Proguard делает код очень трудным для чтения в большинстве случаев. Так что да, все еще можно было бы выполнить обратный инжиниринг, но это сделало бы его НАМНОГО сложнее, если бы вы правильно внедрили шифрование. Reed
2

ованном виде перед отправкой каких-либо данных, поэтому любой, кто прослушивает, не сможет увидеть ни URL, ни данные, отправленные на сервер. Чтобы убедиться в этом, установите Wireshark в своей системе разработки и загрузите URL-адрес в браузер. Вы не увидите никаких данных в открытом виде (ни URL, ни данные, которые отправляются через GET или POST).

Спасибо, HTTPS - это хорошая концепция, чтобы запретить другим прослушивать секретную информацию, отправляемую на сервер. Но это не решает проблему функций генерации хешей, которые могут быть перепроектированы. caw
Вы можете добавить аутентификацию, будь то хеш-аутентификация или HTTP-аутентификация, куки-файл, или oauth, или ... Но без шифрования это будет тривиально обойти. Slartibartfast
Когда вы просто отправляете хеш на сервер для проверки подлинности, как можно обойти эту аутентификацию? Из простого прослушивания токенов аутентификации, отправленных на сервер, вы не можете понять, как генерируются эти значения хеша (в следующий раз). caw

Похожие вопросы