Является ли Java ReDos уязвимым? - PullRequest
0 голосов
/ 29 октября 2018

Я пытался воссоздать атака типа "отказ в обслуживании" с регулярным выражением с использованием (a+)+ regexp и aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa! (с большим количеством a) ввода с использованием jshell:

Pattern.compile("(a+)+")
    .matcher("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!")
    .matches()

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

(Кстати. Я использую Java 11, если это актуально)

РЕДАКТИРОВАТЬ: Похоже, что это связано с версией Java, когда я попробовал его на Java 8, он зависает, но в Java 9 и 11 он работает сразу. Что изменилось между этими версиями, которые могли повлиять на это? Все ли регулярные выражения теперь безопасны в Java?

Существует ли конкретный Java JEP, который изменил реализацию регулярного выражения? Я хотел бы знать, какие регулярные выражения все еще являются проблемой для более новой Java.

1 Ответ

0 голосов
/ 29 октября 2018

В настоящее время я использую Java 8, и следующий код зависает:

Pattern.compile("(a|aa)+")
       .matcher("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab")
       .matches()

Видя, как вы используете Java 11 (а также тестировали его с Java 9/10) и видели, что для его завершения требуется небольшое количество времени, очевидно, между этими версиями произошли изменения.

Посмотрев на исходный код Matcher в Java 11, мы обнаружим следующее дополнение, которого нет в Java 8:

/**
 * Storage used by top greedy Loop node to store a specific hash set to
 * keep the beginning index of the failed repetition match. The nodes
 * themselves are stateless, so they rely on this field to hold state
 * during a match.
 */
IntHashSet[] localsPos;

Это локальное хранилище, наряду с большим количеством другого добавленного кода, кажется, является одной из основных причин, почему конечный автомат для регулярных выражений в Java 9+ выполняется намного быстрее, чем в Java 8 и ниже.

...