Есть ли в Java переполнение буфера?


96

Есть ли в Java переполнение буфера? Если да, можете ли вы дать мне сценарии?


2
Известно, что некоторые библиотечные функции (реализованные в машинном коде) содержат ошибки. Особенно в области Java 5 известно множество эксплойтов в 2D, звуковых или цветовых профилях.
eckes

Ответы:


108

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

  1. Если вы вызываете собственный код через JNI
  2. В самой JVM (обычно написанной на C ++)
  3. Интерпретатор или JIT-компилятор работает некорректно (проверка границ обязательного байт-кода Java)

24

Управляемые языки, такие как Java и C #, не имеют этих проблем, но определенные виртуальные машины (JVM / CLR / и т. Д.), На которых фактически выполняется код, могут.


5
C # в небезопасном контексте может иметь переполнение буфера. Java как язык полностью запрещает это (вы должны менять языки через JNI, чтобы получить доступ к неманговому указателю)
ShuggyCoUk,

1
Хорошая точка зрения. С небезопасным C # вы, очевидно, больше не изолированы от удобного управляемого мира.
Брайан Расмуссен,

1
Верно, и даже если ВЫ не пишете небезопасных и не выполняете никаких взаимодействий, вы можете использовать библиотеку, которая это делает. Так что это то, чего нужно остерегаться.
BobbyShaftoe

13

Во всех смыслах и целях нет.

В Java есть проверка границ массива, которая проверяет, что к данным нельзя получить доступ из области за пределами выделенного массива. Когда кто-то пытается получить доступ к области, превышающей размер массива,ArrayOutOfBounds будет выброшено исключение.

Если происходит переполнение буфера, это, вероятно, связано с ошибкой в ​​виртуальной машине Java и, насколько мне известно, не является предполагаемым поведением, описанным в Спецификациях языка Java или Спецификациях виртуальной машины Java.


10

Да и нет. Нет, в том смысле, что вы действительно не можете создать ошибочно открытую уязвимость для переполнения буфера, потому что это модель управляемой памяти. Однако в JVM и JDK могут быть уязвимости переполнения буфера. См. Этот совет Secunia:

http://secunia.com/advisories/25295

Или посмотрите эти старые рекомендации по нескольким предыдущим уязвимостям JDK и JRE:

  • Уязвимости, связанные с целыми числами и переполнением буфера в среде выполнения Java (JRE) "unpack200" Утилита распаковки JAR-файлов может привести к повышению привилегий https://download.oracle.com/sunalerts/1020225.1.html

    Целочисленные уязвимости и уязвимости переполнения буфера в среде выполнения Java (JRE) с распаковкой апплетов и приложениями Java Web Start, использующими утилиту распаковки JAR "unpack200", могут позволить ненадежному апплету или приложению повысить привилегии. Например, ненадежный апплет может предоставить себе разрешения на чтение и запись локальных файлов или выполнение локальных приложений, доступных пользователю, запускающему ненадежный апплет.

    Sun благодарит "regenrecht" за работу с iDefense VCP ( http://labs.idefense.com/vcp/ ) и Криса Эванса из Google за то, что они обратили наше внимание на эти проблемы.

  • В Sun Java Development Kit (JDK) и Java Runtime Environment (JRE) обнаружено множество уязвимостей. https://security.gentoo.org/glsa/200705-23

    Группа безопасности Fujitsu сообщила о неуказанной уязвимости, связанной с «неправильным использованием системных классов». Кроме того, Крис Эванс из группы безопасности Google сообщил о целочисленном переполнении, которое привело к переполнению буфера в анализаторе ICC, используемом с файлами JPG или BMP, и неправильном вызове open () для / dev / tty при обработке определенных файлов BMP.


9

Переполнение буфера в строгом смысле перезаписи стека или самой кучи потребует либо:

  1. Ошибка в фреймворке (они существовали в прошлом и могут снова появиться)
  2. Использование JNI (по сути, больше не используется управляемый код)

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

Эта последняя форма менее вероятна, но плохо написанная широко распространенная функция очистки строк sql, у которой была такая проблема, как это, была бы привлекательной целью.


4

Виртуальные машины Java (и .Net) отлавливают код, который пытается писать вне зарезервированной памяти. Приложения, которые не справляются с этим правильно, по-прежнему могут вызывать проблемы с безопасностью. Если злоумышленники могут запускать исключения, вводя недопустимые данные, они могут, например, выполнить атаки отказа в обслуживании.


3

Как уже отмечалось, Java как язык имеет проверку границ при любом доступе к памяти, и если здесь есть ошибка, то виновата JVM, а не программа. Однако следует отметить, что это аналогичный аргумент утечкам памяти в Java; хотя невозможно разбить стек, исключение ArrayOutOfBoundsException в неправильном месте, которое не обрабатывается правильно, все же может в конечном итоге испортить вашу систему.


3

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


3

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

Например, для проверки границ недостаточно:

/* !! WRONG !! */ 0 <= off && 0 <= len && off+len <= buff.length /* !! WRONG !! */

У IIRC StringBufferкогда-то была такая ошибка, но с ней ничего интересного не было.


Что является достаточным для проверки границ?
Broam

1
@Broam: 0 <= off && 0 <= len && off <= buff.length-lenя думаю. Не цитируйте меня. Он выглядит так же, но нет возможности переполнения (в исходном off + len может стать отрицательным и, следовательно, явно меньше, чем длина массива). Убедитесь, что ни один программист обслуживания никогда не «приводит» его в очевидную форму. Я нахожу целочисленное переполнение очень запутанным. Придется подумать над этим какое-то время, а потом возникает мучительное подозрение, что я ошибся. Но, конечно, должен быть другой рецензент и оригинальный программист - вместе, конечно, ошибка не могла бы пройти! (не)
Том Хотин - tackline

Пришлось немного на это разглядеть, но вы правы. off + len может переполниться и обернуться ... в C. В Java , если я не ошибаюсь, вы получите исключение переполнения до того, как это произойдет, верно?
Broam

1
Нет. Целочисленная арифметика незаметно завершается. В C # есть «режим», в котором при переполнении выдается исключение, но я не думаю, что он часто используется (если вы думаете его использовать, вы, вероятно, все равно будете поступать правильно).
Tom Hawtin - tackline

1

Одна из ключевых особенностей JAVA - безопасность. Программы, написанные на интерпретируемых языках, не подвержены эксплойту переполнения буфера, но вы всегда можете вызвать переполнение буфера в самом Интерпретаторе. Хотя будет сложно. Точно так же Python также является интерпретируемым языком и защищен от переполнения буфера.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.