Це досить стара тема, але все ще актуальна і напрочуд приносить більший вплив у наш час. Як зазначав Джон, це може бути просто помилкою, яку зробили дизайнери Java на самому початку. Але я не уявляю, що це може вплинути на безпеку.
Багато кодерів знають Apache Velocity, гнучкий і потужний механізм шаблонів. Він настільки потужний, що дозволяє подавати шаблон із набором іменованих об'єктів - суворо розглядається як об'єкти з мови програмування (спочатку Java). До цих об’єктів можна отримати доступ із шаблону, як у мові програмування, тому, наприклад, екземпляр Java String може використовуватися з усіма його загальнодоступними полями, властивостями та методами
$input.isEmpty()
де введенням є рядок , проходить безпосередньо через JVM і повертає true або false у вихідні дані синтаксичного аналізатора Velocity). Все йде нормально.
Але в Java всі об'єкти успадковуються від Object, тому наші кінцеві користувачі також можуть помістити це в шаблон
$input.getClass()
отримати екземпляр String Class.
І за допомогою цього посилання вони також можуть викликати статичний метод forName (String) щодо цього
$input.getClass().forName("java.io.FileDescriptor")
використовуйте будь-яке ім'я класу та використовуйте його для будь-якого облікового запису веб-сервера (деформувати, красти вміст БД, перевіряти конфігураційні файли, ...)
Цей подвиг якимось чином (у конкретному контексті) описаний тут: https://github.com/veracode-research/solr-injection#7-cve-2019-17558-rce-via-velocity-template-by-_s00py
Це було б неможливо, якби заборонялося викликати статичні методи з посилання на екземпляр класу.
Я не кажу, що певна програма програмування є кращою за іншу або близько того, але я просто хочу порівняти. Існує порт Apache Velocity для .NET. У C # неможливо викликати статичні методи лише з посилання на екземпляр, що робить експлойт таким чином марним:
$input.GetType().GetType("System.IO.FileStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
String hello = null; hello.valueOf(123);
працює!