Илья Медведовский - Атака на Internet
/* Unplugged.java by Mark D. LaDue */
/* April 15, 1998 */
/* Copyright (c) 1998 Mark D. LaDue */
import netscape.applet.*;
import netscape.javascript.*;
public class Unplugged extends java.applet.Applet implements Runnable{
Thread controller = null;
JSObject jso = null;
int numplugs = 0;
String npname = null;
String[] plugs = null;
int histlen = 0;
public void init() {
jso = JSObject.getWindow(this);
}
public void start() {
if (controller == null) {
controller = new Thread(this);
controller.start();
}
}
public void stop() {}
public void run() {
Control.showConsole();
numplugs = (new Float((jso.eval("pcount()")).toString())).intValue();
System.out.println("nTotal number of plugins: " + numplugs + "n");
plugs = new String[numplugs];
for (int i = 0; i < numplugs; i++) {
plugs[i] = (String) jso.eval("nextPlug()");
System.out.println("Plugin " + (i+1) + ": " + plugs[i] + "n");
}
histlen = (new Float((jso.eval("hcount()")).toString())).intValue();
System.out.println("Total number of history entries: " + histlen);
}
}Для демонстрации нужно включить в html-файл следующий код:
<SCRIPT language="javascript">
navigator.plugins.refresh(true);
pcnt = 0;
hcnt = 0;
function pcount() {
var pc = navigator.plugins.length;
return pc;
}
function nextPlug() {
var np = navigator.plugins[pcnt].filename;
pcnt++;
return np;
}
function hcount() {
var hc = history.length;
return hc;
}
</SCRIPT>
<applet mayscript name="Unplugged" code="Unplugged.class" width=1 height=1>
Атака на святая святыхАтаки, подобные перечисленным ранее, используют вполне законопослушный код, не предпринимают никаких попыток взломать систему безопасности Java и пишутся очень легко. Теперь же настала очередь атак другого рода, использующих прорехи в реализации виртуальных машин. Они очень наглядно демонстрируют, как небольшая ошибка сводит на нет работу всей системы безопасности. Все эти ошибки уже благополучно исправлены, но каждая из них могла привести к очень серьезным последствиям:
1. Первая и едва ли не самая громкая ошибка в Java, даже удостоившаяся внимания некомпьютерной прессы, позволяла обойти ограничение на соединение с посторонними хостами. Не будь этого ограничения, Java бы превратилась в идеальный инструмент взломщика, позволяющий делать черную работу чужими руками. При загрузке апплета запоминалось имя хоста. Взломщик, имеющий доступ к DNS-серверу своего домена, вполне мог подставить вместо своего адреса адрес жертвы. С тех пор все реализации Java запоминают IP-адрес сервера, с которого они загружались, а не имя хоста.
2. Netscape Navigator 2.01 воспринимал имя класса, начинающееся с символа «», как вполне нормальное, что позволяло ссылаться практически на любой файл в системе, например лежащий в кэше браузера. Причем этот файл воспринимался уже как локальный и не попадал под ограничения для апплетов, загруженных из сети.
3. Ошибка, дающая возможность воспользоваться смешением типов.
4. Ошибки в верификаторе и механизме загрузки классов, позволяющие апплету создать свой ClassLoader. Это легко приводит к полному проникновению в систему. Защита строилась на том, что при создании нового ClassLoader вызывается конструктор предка, который возбуждает исключительную ситуацию. Был найден способ обойти вызов конструктора предка. Ошибка исправлена следующим образом: функция ClassLoader.defineClass, выполняющая ранее всю критичную работу, стала проверять флаг, устанавливаемый в конструкторе, и, только если он был установлен, вызывать private-функцию defineClass0.
5. Ошибка, связанная с приведением типов.
6. Проблема с пространствами имен. В двух разных апплетах могут быть описаны классы, имеющие одинаковые имена. Поскольку они выполняются в разных пространствах имен, проблема смешения типов не возникает. Но в Netscape Navigator 2.02 и первой бета-версии Internet Explorer типы исключений и интерфейсов сравнивались по именам, а не по парам (имя, пространство имен). И если один апплет передавал другому в качестве параметра объект такого класса, возникала стандартная ситуация смешения типов.
7. Незадолго до выхода Internet Explorer 3.0 в его последней бета-версии была обнаружена ошибка, связанная с именами пакетов (packages). Пакеты представляют собой группы классов, объединенных под одним именем. Их назначение двояко: во-первых, полное имя класса включает в себя имя пакета, которому он принадлежит; во-вторых, пакеты можно использовать для ограничения доступа – если не указан спецификатор доступа, считается, что переменная или функция доступна только классам этого пакета. Некоторые пакеты ограничивают свое членство лишь классами, входящими в стандартную поставку, за чем следит менеджер безопасности. Ошибка заключалась в следующем: менеджер безопасности учитывал только часть имени пакета при проверке контроля доступа, что не срабатывало для пакетов, чье имя начиналось с com.ms. В результате посторонний пакет мог получить доступ к внутренним переменным системных пакетов, в том числе к списку файлов, к которым апплет может получить доступ.
Остановимся чуть подробнее на некоторых из них.
Смешение типов может работать следующим образом. Предположим, что у нас есть два классаclass T
{
SecurityManager x;
}
class U
{
MyObject x;
}Далее заводим два указателя – t класса T и u класса U, каким-то образом заставляем их указывать на одну и ту же область памяти, после чего выполняем следующий код:
t.x = System.getSecurity(); // получаем SecurityManager MyObject m = u.x;
Теперь m указывает на ту же область памяти, где находится SecurityManager, и мы можем безболезненно менять его содержимое через поля объекта m. Подобная атака сработает при любом смешении типов, остается лишь найти ошибку, позволяющую проделать подобное совмещение указателей.
И такая ошибка была найдена в одной из бета-версий Netscape Navigator. При создании класса T неявно создается тип массив класса Т для внутреннего пользования. Его имя начинается с «[», и, поскольку нельзя создать класс, имя которого начинается с этого символа, все работает безошибочно. Но в той версии Netscape Navigator удавалось загрузить класс с таким именем. Точнее, при этом выдавалась ошибка, но виртуальная машина устанавливала имя в своей внутренней таблице. В результате Java считала объект массивом, хотя он принадлежал совсем другому типу. Итог – замена SecurityManager и потенциальный захват системы.
Ошибка, связанная с приведением типов:interface Inter
{
void f();
}
class Secure implements Inter
{
private void f();
}
class Dummy extends Secure implements Inter
{
public void f();
Dummy()
{
Secure s = new Secure();
Inter i = (Inter) s;
i.f();
}
}В этом коде вызов i.f() должен быть опознан как вызов защищенного метода класса Secure и запрещен. Неверное поведение Netscape Navigator 2.02 привело к возможности вызова закрытой функции defineClass0, призванной исправить ошибки в верификаторе и механизме загрузки классов. Небольшая модификация этой же ошибки:
interface Inter
{
void f();
}
class Secure implements Inter
{
private void f();
}
class Dummy implements Inter
{
public void f();
static void attack()
{
Inter inter[2] = {new Dummy(), new Secure() };
for(int j=0; j<2; ++j) inter[j].f();
}
}Выяснилось, что в целях оптимизации проверка на корректность вызова осуществлялась только при первом проходе цикла.
Ошибка в бета-версии Internet Explorer 3.0 была последней серьезной ошибкой, найденной в реализациях JDK 1.0.2. После ее обнаружения и до выхода JDK 1.1 прошло шесть спокойных месяцев.
Далее последовали ошибки, позволяющие определить реальный IP-адрес машины и список открытых портов, получить список авторов, подписям которых доверяют на этой машине, и сымитировать доверяемую подпись, отключить контроль за безопасностью в Netscape Navigator 4.0x, и еще 24 ошибки в верификаторе от JDK 1.0.2, 15 из которых перешли в 1.1.1, и 17 ошибок в верификаторе Internet Explorer.
Таким образом, несмотря на все заявления об окончательном решении проблемы безопасности в Java, нельзя не заметить, что до сих пор во всех ее реализациях были обнаружены серьезные ошибки, и нет оснований в ближайшее время рассчитывать на ее полную безопасность.
Не только JavaНе будем подробно останавливаться на каждой ошибке, обнаруженной в популярных браузерах, постараемся лишь выделить основные из них. Соответствующая информация регулярно появляется на сайтах производителей (для Internet Explorer – http://www.microsoft.com/windows/ie/security/, для Netscape Navigator – http://home.netscape.com/products/security/resources/notes.html), оттуда же можно скопировать последние обновления и исправления, что обязательно стоит сделать, если вы хотите чувствовать себя в относительной безопасности при работе в Сети.
Можно выделить две основные категории ошибок в браузерах, не связанных непосредственно с Java: ошибки, позволяющие передать по сети содержимое локальных файлов и другой информации о пользователе, и ошибки, приводящие к нарушению работоспособности браузера, а в отдельных случаях и всей системы.
Ошибки первого типа наиболее разнообразны по способу реализации. Большинство ошибок Netscape Navigator связано с JavaScript. Среди них можно выделить передачу файлов через форму без ведома пользователя, использование средств взаимодействия Java и JavaScript для отслеживания действий пользователя (посещаемые сайты, данные, отправляемые через формы), получение файла с пользовательскими настройками (к примеру, пароль для доступа к почтовому серверу), «подделка» сайтов – отображение в окне браузера информации, не соответствующей адресной строке.
Так, следующий код, работающий в Netscape Navigator 4.5, демонстрирует считывание файла с локального диска. В примере первые несколько строк файла c: test.txt выводятся в окне сообщения, этот же код можно использовать и для передачи содержимого на сервер через форму или каким-то другим способом.