Безопасность программной платформы Java

Безопасность программной платформы Java (англ. Java platform security) — совокупность средств и механизмов, предназначенных для повышения безопасности приложений, работающих на программной платформе Java. В их числе — контроль выполнения программ с помощью виртуальной машины Java (JVM), менеджер безопасности для изоляции (сандбоксирования) недоверенного кода и набор стандартных средств разработки для работы с безопасностью. Несмотря на эти механизмы, платформа и компания Oracle подвергались критике из-за роста количества вредоносных программ, эксплуатирующих уязвимости в JVM, которые своевременно не устранялись компанией Oracle[1].

Механизмы безопасности

Виртуальная машина Java (JVM)

В бинарном виде программы платформы Java представляют собой не машинный код, а промежуточный байткод. JVM выполняет верификацию этого байткода перед запуском, предотвращая выполнение опасных операций, таких как переходы по неверным адресам, которые могут соответствовать данным, а не инструкциям. Это также позволяет JVM обеспечивать контроль границ массивов и другие ограничения времени исполнения. Благодаря этому программы на Java существенно менее подвержены ошибкам безопасности памяти (например, переполнение буфера), чем программы на языках, не гарантирующих безопасность памяти, например на C.

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

Менеджер безопасности

Платформа Java предоставляет менеджер безопасности, позволяющий запускать недоверенный байткод в сандбоксированной среде, защищая от вредоносного или ошибочного программного обеспечения за счёт ограничения доступа к ключевым функциям платформы и её API. Например, недоверенному коду может быть запрещено читать или изменять файлы на локальной файловой системе, выполнять произвольные команды с привилегиями пользователя, обращаться к сетевым ресурсам, получать доступ к приватному состоянию объектов через рефлексию или инициировать завершение работы JVM.

Менеджер безопасности также позволяет криптографически подписывать Java-программы. В таком случае пользователь может разрешить выполнение подписанного кода с полными привилегиями, если он подписан доверенным издателем.

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

API безопасности

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

Класс sun.misc.Unsafe

Класс sun.misc.Unsafe — это внутренняя утилита в языке Java, реализующая набор низкоуровневых небезопасных операций[1]. Он не входит в официальный набор классов Java, однако используется внутренними библиотеками Java. Класс подключается из неофициального модуля jdk.unsupported, а начиная с Java 11 — частично мигрировал в jdk.internal.misc.Unsafe (является частью модуля java.base)[1].

Главная особенность — возможность прямого управления памятью и адресацией, манипуляций с объектами и полями, управления потоками и реализация низкоуровневых механизмов конкурентности (сравнимых с управлением памятью на C).

Объявление класса: public final class Unsafe;. Это синглтон-класс с приватным конструктором[2].

Класс включает методы (многие объявлены как native и используют Java Native Interface), включая:

  • получение экземпляра Unsafe через sun.reflect.Reflection.
  • получение значения по смещению в объекте. Аналогичные методы — getBoolean(), getByte(), getShort(), getChar(), getLong(), getFloat(), getDouble().
  • запись значения по смещению в объекте. Аналогичные методы: putBoolean(), putByte(), putShort(), putChar(), putLong(), putFloat(), putDouble().
  • доступ к ссылочным полям.
  • методы чтения и записи значений по произвольному адресу или в выделенной памяти.
  • выделение блока нативной памяти (аналог malloc()).
  • изменение размера блока памяти (аналог realloc()).
  • инициализация памяти байтовым значением (аналог memset()).
  • копирование блоков памяти (аналог memcpy()).
  • освобождение памяти (аналог free()).
  • методы для работы со статическими и объектными полями, массивами, адресным пространством, инициирования классов, работы с блокировками, исключениями, атомарными операциями, межпоточной синхронизацией и др.

Среди констант определены значения смещений, размеров, индексов для разных типов массивов и вспомогательных структур.

Примеры

Пример использования:

package org.wikipedia.example;

import java.lang.reflect.Field;

import sun.misc.Unsafe;

public class Example {
    public static void main(String[] args) throws Exception {
        // Получение экземпляра Unsafe через рефлексию
        Field f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe unsafe = (Unsafe)f.get(null);

        // Выделение блока памяти на 8 байт
        long memoryAddress = unsafe.allocateMemory(8L);

        try {
            // Запись и чтение значения long
            unsafe.putLong(memoryAddress, 123456789L);
            long value = unsafe.getLong(memoryAddress);
            System.out.printf("Value from memory: %d%n", value); // Output: 123456789
        } finally {
            // Освобождение выделенной памяти
            unsafe.freeMemory(memoryAddress);
        }
    }
}

Возможна также упаковка работы с нативной памятью в отдельный класс, аналогично java.lang.foreign.MemorySegment:

package org.wikipedia.example;

import java.lang.reflect.Field;

import sun.misc.Unsafe;

public class NativeMemory implements AutoCloseable {
    private static final Unsafe unsafe;
    private final long address;
    private final long size;

    static {
        try {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            unsafe = (Unsafe)theUnsafe.get(null);
        } catch (Exception e) {
            throw new RuntimeException("Unable to access Unsafe", e);
        }
    }

    public NativeMemory(long size) {
        this.size = size;
        this.address = unsafe.allocateMemory(size);
    }

    public void putByte(long offset, byte value) {
        checkBounds(offset, 1);
        unsafe.putByte(address + offset, value);
    }

    public byte getByte(long offset) {
        checkBounds(offset, 1);
        return unsafe.getByte(address + offset);
    }

    private void checkBounds(long offset, long bytes) {
        if (offset < 0 || offset + bytes > size) {
            throw new IndexOutOfBoundsException(String.format("Offset out of bounds: %d", offset));
        }
    }

    @Override
    public void close() {
        unsafe.freeMemory(address);
    }
}

Использование:

package org.wikipedia.example;

public class Main {
    public static void main(String[] args) {
        try (NativeMemory mem = new NativeMemory(1024)) {
            mem.putByte(0, (byte)42);
            System.out.printf("Value: %s%n", mem.getByte(0));
        }
    }
}

Потенциальные источники уязвимостей в приложениях Java

Существует ряд возможных источников уязвимостей в приложениях на Java: часть их свойственна и не-Java-средам, другие — специфичны для платформы Java. К первому типу относятся:

  • Уязвимости механизмов защиты, предоставляемых оборудованием или операционной системой, на которые приложение полагается в вопросах безопасности.
  • Уязвимости в нативных библиотеках, таких как стандартная библиотека C, используемых для реализации приложения и/или виртуальной машины.
  • Уязвимости, вызванные ошибками в пользовательском коде (например, неправильная обработка SQL-запросов, приводящая к SQL-инъекциям).

Обсуждение безопасности Java, как правило, сосредоточено на "родных" источниках уязвимостей платформы. К ним, в частности, относятся:

  • Уязвимости в механизмах изоляции (sandbox), позволяющие недоверенному байткоду обходить ограничения менеджера безопасности.
  • Уязвимости в библиотеке классов Java, обеспечивающей безопасность приложения.

Уязвимость в платформе Java не обязательно ставит под угрозу все Java-приложения. Обычно при публикации информации о найденных уязвимостях и патчах (например, компанией Oracle) указывается разбивка по уязвимым типам приложений[3].

Например, гипотетическая уязвимость, затрагивающая только механизм изоляции в конкретной реализации JVM, угрожает лишь тем Java-программам, которые исполняют недоверенный байткод. Приложения, в которых все байткод-классы полностью контролируются пользователем, не подвержены данной угрозе. Так, браузерный плагин, построенный на такой JVM, будет потенциально уязвим к запуску вредоносных апплетов с публичных сайтов, а серверное веб-приложение — нет[4].

Как и в других средах, уязвимости могут появляться и в неочевидных частях платформы. Так, в 2011 году компания Oracle выпустила обновление для устранения ошибки в Double.parseDouble[5]. Эта ошибка приводила к бесконечному циклу при разборе специальной строки, что открывало путь для отказа в обслуживании web-сервера через передачу особого значения.

Критика менеджера безопасности

Менеджер безопасности платформы Java (разрешающий, как указано выше, запуск недоверенного байткода) в последние годы подвергался критике за то, что делал пользователей уязвимыми для вредоносных программ, особенно при использовании Java в браузере (например, через выполнение апплетов с публичных сайтов).

Ряд уязвимостей вынудил компанию Oracle задержать выпуск Java 8[6].

2012 год

В 2012 году троянец Flashback эксплуатировал уязвимость в Java, которая не была оперативно закрыта компанией Apple, несмотря на то, что Oracle выпустила патч[7]. Позже Apple выпустила инструмент для удаления вредоносной программы для пользователей Mac OS X Lion, не использующих Java[8]. Начиная с Java 7, обновление 4, Oracle стала самостоятельно выпускать дистрибутивы Java для Lion и более новых версий macOS[9].

В октябре Apple выпустила обновление, полностью удалившее плагин Java из всех браузеров[10]. Это было воспринято как сознательное дистанцирование Apple от Java[11].

2013 год

В январе была обнаружена уязвимость нулевого дня во всех версиях Java 7, использовавшаяся в сети с момента появления[12]. Причиной стала попытка исправить более раннюю брешь[13]. В ответ Apple добавила последний Java-плагин в "черный список"[14]. Oracle выпустила патч (обновление 11) через три дня[15]. Microsoft также выпустила заплатку для Internet Explorer 6—8[16].

Кибершпионское ПО Red October эксплуатировало уязвимость, исправленную ещё в октябре 2011 года[17]. Сайт Reporters Without Borders был скомпрометирован уязвимостью в Java до релиза Update 11[18].

Вскоре после выхода Update 11 была выявлена новая уязвимость[19], позднее подтверждённая[20]. Было также установлено, что защитный режим Java тоже подвержен реализации из-за ошибки[21]. Вслед за этим Mozilla по умолчанию отключила Java (а также Adobe Reader и Microsoft Silverlight) в Firefox[22], а Apple снова заблокировала самый свежий Java-плагин[23].

В феврале Twitter сообщил о предотвращённой атаке и порекомендовал пользователям отключить Java[24]. Позже в том же месяце о взломе через Java отчиталась Facebook[25], а также Apple[26]. Было обнаружено, что причиной стал взлом форума для разработчиков iPhone, использованного для атаки на Twitter, Facebook и Apple[27]. Сам форум не знал о наличии угрозы[28]. В дальнейшем аналогичные инциденты произошли с Microsoft[29].

Позже была обнаружена уязвимость, позволявшая полностью обходить песочницу Java в первоначальном релизе Java 7, а также в обновлениях 11 и 15[30]. В марте троянец McRat эксплуатировал ещё одну уязвимость нулевого дня в Java[31]. Oracle в скором времени выпустила очередной патч для устранения уязвимости[32].

Примечания

  1. 1 2 3 Ben Evans. The Unsafe Class: Unsafe at Any Speed (англ.). blogs.oracle.com. Oracle Corporation (4 мая 2020). Дата обращения: 10 октября 2025. Архивировано 26 сентября 2021 года.
  2. sun.misc: Unsafe.java (англ.). docjar.com. Дата обращения: 10 октября 2025. Архивировано 30 сентября 2016 года.
  3. April 2013 Critical Patch Update (англ.). Oracle Blogs. Дата обращения: 10 октября 2025. Архивировано 29 апреля 2013 года.
  4. Security Alert for CVE-2013-0422 Released (англ.). Oracle Corporation. Дата обращения: 10 октября 2025. Архивировано 15 января 2013 года.
  5. Oracle Releases Hotfix for the Double.parseDouble Bug in Record Time (англ.). InfoQ. Дата обращения: 10 октября 2025. Архивировано 5 декабря 2024 года.
  6. Secure The Train (англ.). Blog of Mark Reinhold, Chief Architect of Oracle's Java Platform Group (18 апреля 2013). Дата обращения: 10 октября 2025. Архивировано 18 сентября 2025 года.
  7. Goodin, Dan Mac Flashback trojan exploits unpatched Java vulnerability, no password needed (англ.). Ars Technica (2 апреля 2012). Дата обращения: 18 февраля 2014. Архивировано 11 мая 2012 года.
  8. Geuss, Megan Flashback malware removal tool arrives for Java-less Mac users (англ.). Ars Technica (14 апреля 2012). Дата обращения: 18 февраля 2014. Архивировано 17 мая 2012 года.
  9. Foresman, Chris Forget Apple: Oracle to bring Java security fixes directly to Mac users (англ.). Ars Technica (27 апреля 2012). Дата обращения: 18 февраля 2014. Архивировано 27 мая 2012 года.
  10. Goodin, Dan Apple removes Java from all OS X web browsers (англ.). Ars Technica (18 октября 2012). Дата обращения: 18 февраля 2014. Архивировано 18 октября 2012 года.
  11. Cheng, Jacqui Where OS X security stands after a volatile 2012 (англ.). Ars Technica (23 декабря 2012). Дата обращения: 18 февраля 2014. Архивировано 24 декабря 2012 года.
  12. Goodin, Dan Critical Java zero-day bug is being "massively exploited in the wild" (Updated) (англ.). Ars Technica (10 января 2013). Дата обращения: 18 февраля 2014. Архивировано 10 января 2013 года.
  13. Goodin, Dan Critical Java vulnerability made possible by earlier incomplete patch (Updated) (англ.). Ars Technica (11 января 2013). Дата обращения: 18 февраля 2014. Архивировано 12 января 2013 года.
  14. Foresman, Chris Apple blacklists Java on OS X to prevent latest "critical" exploits (англ.). Ars Technica (11 января 2013). Дата обращения: 18 февраля 2014. Архивировано 12 января 2013 года.
  15. Mattise, Nathan Oracle patches widespread Java zero-day bug in three days (Updated) (англ.). Ars Technica (14 января 2013). Дата обращения: 18 февраля 2014. Архивировано 14 января 2013 года.
  16. Goodin, Dan Microsoft releases emergency update to patch Internet Explorer bug (англ.). Ars Technica (14 января 2013). Дата обращения: 18 февраля 2014. Архивировано 15 января 2013 года.
  17. Goodin, Dan Red October relied on Java exploit to infect PCs (англ.). Ars Technica (15 января 2013). Дата обращения: 18 февраля 2014. Архивировано 15 января 2013 года.
  18. Goodin, Dan Just-patched Java, IE bugs used to snare human rights sites (англ.). Ars Technica (22 января 2013). Дата обращения: 18 февраля 2014. Архивировано 23 января 2013 года.
  19. Goodin, Dan $5,000 will buy you access to another, new critical Java vulnerability (Updated) (англ.). Ars Technica (16 января 2013). Дата обращения: 18 февраля 2014. Архивировано 17 января 2013 года.
  20. Goodin, Dan Critical Java vulnerabilities confirmed in latest version (англ.). Ars Technica (18 января 2013). Дата обращения: 18 февраля 2014. Архивировано 19 января 2013 года.
  21. Goodin, Dan Java's new "very high" security mode can't protect you from malware (англ.). Ars Technica (28 января 2013). Дата обращения: 18 февраля 2014. Архивировано 30 января 2013 года.
  22. Goodin, Dan Firefox to block content based on Java, Reader, and Silverlight (англ.). Ars Technica (31 января 2013). Дата обращения: 18 февраля 2014. Архивировано 2 февраля 2013 года.
  23. Foresman, Chris For second time in a month, Apple blacklists Java Web plugin (англ.). Ars Technica (31 января 2013). Дата обращения: 18 февраля 2014. Архивировано 1 февраля 2013 года.
  24. Goodin, Dan Twitter detects and shuts down password data hack in progress (англ.). Ars Technica (2 февраля 2013). Дата обращения: 18 февраля 2014. Архивировано 2 февраля 2013 года.
  25. Gallagher, Sean Facebook computers compromised by zero-day Java exploit (англ.). Ars Technica (15 февраля 2013). Дата обращения: 18 февраля 2014. Архивировано 15 февраля 2013 года.
  26. Cheng, Jacqui Apple HQ also targeted by hackers, will release tool to protect customers (англ.). Ars Technica (19 февраля 2013). Дата обращения: 18 февраля 2014. Архивировано 20 февраля 2013 года.
  27. Gallagher, Sean Facebook, Twitter, Apple hack sprung from iPhone developer forum (англ.). Ars Technica (19 февраля 2013). Дата обращения: 18 февраля 2014. Архивировано 20 февраля 2013 года.
  28. Cheng, Jacqui Dev site behind Apple, Facebook hacks didn't know it was booby-trapped (англ.). Ars Technica (20 февраля 2013). Дата обращения: 18 февраля 2014. Архивировано 20 февраля 2013 года.
  29. Bright, Peter Microsoft joins Apple, Facebook, and Twitter; comes out as hack victim (англ.). Ars Technica (22 февраля 2013). Дата обращения: 18 февраля 2014. Архивировано 23 февраля 2013 года.
  30. Brodkin, Jon Java's latest security problems: New flaw identified, old one attacked (англ.). Ars Technica (25 февраля 2013). Дата обращения: 18 февраля 2014. Архивировано 28 февраля 2013 года.
  31. Goodin, Dan Another Java zero-day exploit in the wild actively attacking targets (англ.). Ars Technica (1 марта 2013). Дата обращения: 18 февраля 2014. Архивировано 1 марта 2013 года.
  32. Mattise, Nathan Oracle releases new Java patch to address this week's McRat problem (англ.). Ars Technica (5 марта 2013). Дата обращения: 18 февраля 2014. Архивировано 6 марта 2013 года.

Категории