Перейти к основному содержимому

Подделка журнала JVM

· 4 мин. чтения

1. Обзор

В этой быстрой статье мы рассмотрим одну из самых распространенных проблем безопасности в мире JVM — подделку журналов. Мы также покажем пример техники, которая может защитить нас от этой проблемы безопасности.

2. Что такое подделка бревен?

Согласно OWASP , подделка логов — одна из самых распространенных техник атак.

Уязвимости подделки журнала возникают, когда данные поступают в приложение из ненадежного источника или данные записываются в файл журнала приложения/системы каким-либо внешним объектом.

В соответствии с рекомендациями OWASP подделка или внедрение журнала — это метод записи непроверенного пользовательского ввода в файлы журнала, который позволяет злоумышленнику подделывать записи журнала или внедрять в журналы вредоносное содержимое.

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

3. Пример

Рассмотрим пример, когда пользователь отправляет запрос на оплату из Интернета. На уровне приложения после обработки этого запроса будет зарегистрирована одна запись с суммой:

private final Logger logger 
= LoggerFactory.getLogger(LogForgingDemo.class);

public void addLog( String amount ) {
logger.info( "Amount credited = {}" , amount );
}

public static void main( String[] args ) {
LogForgingDemo demo = new LogForgingDemo();
demo.addLog( "300" );
}

Если мы посмотрим на консоль, то увидим что-то вроде этого:

web - 2017-04-12 17:45:29,978 [main] 
INFO com.foreach.logforging.LogForgingDemo - Amount credited = 300

Теперь предположим, что злоумышленник вводит данные в виде «\n\nweb — 2017-04-12 17:47:08,957 [main] INFO Сумма успешно отменена», тогда журнал будет выглядеть так:

web - 2017-04-12 17:52:14,124 [main] INFO  com.foreach.logforging.
LogForgingDemo - Amount credited = 300

web - 2017-04-12 17:47:08,957 [main] INFO Amount reversed successfully

Злоумышленник намеренно создал поддельную запись в журнале приложения, которая исказила значение журналов и запутала любые действия типа аудита в будущем. В этом суть ковки бревен.

4. Профилактика

Самое очевидное решение — не записывать пользовательский ввод в лог-файлы.

Но это может быть невозможно во всех обстоятельствах, поскольку данные, предоставляемые пользователем, необходимы для отладки или аудита активности приложения в будущем.

Мы должны использовать какую-то другую альтернативу для решения такого сценария.

4.1. Внедрить валидацию

Одно из самых простых решений — всегда проверять ввод перед записью в журнал. Одна из проблем с этим подходом заключается в том, что нам придется проверять множество данных во время выполнения, что повлияет на общую производительность системы.

Кроме того, если проверка не пройдена, данные не будут зарегистрированы и будут потеряны навсегда, что часто является неприемлемым сценарием.

4.2. Ведение журнала базы данных

Другой вариант — занести данные в базу данных. Это более безопасно, чем другой подход, поскольку '\n' или новая строка ничего не значат в этом контексте. Однако это вызовет еще одну проблему с производительностью, поскольку для регистрации пользовательских данных будет использоваться огромное количество подключений к базе данных.

Более того, этот метод представляет еще одну уязвимость в системе безопасности, а именно SQL-инъекцию . Чтобы справиться с этим, мы могли бы в конечном итоге написать много дополнительных строк кода.

4.3. ЕСАПИ

Использование ESAPI является наиболее распространенным и рекомендуемым методом в этом контексте. Здесь все пользовательские данные кодируются перед записью в журналы. ESAPI — это API с открытым исходным кодом, доступный в OWASP :

<dependency>
<groupId>org.owasp.esapi</groupId>
<artifactId>esapi</artifactId>
<version>2.2.2.0</version>
</dependency>

Он доступен в центральном репозитории Maven .

Мы можем кодировать данные, используя интерфейс ESAPI Encoder :

public String encode(String message) {
message = message.replace( '\n' , '_' ).replace( '\r' , '_' )
.replace( '\t' , '_' );
message = ESAPI.encoder().encodeForHTML( message );
return message;
}

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

В предыдущем примере, если мы кодируем сообщение с помощью этой функции-оболочки, журнал должен выглядеть примерно так:

web - 2017-04-12 18:15:58,528 [main] INFO  com.foreach.logforging.
LogForgingDemo - Amount credited = 300
__web - 2017-04-12 17:47:08,957 [main] INFO Amount reversed successfully

Здесь поврежденный фрагмент строки закодирован и может быть легко идентифицирован.

Важно отметить, что для использования ESAPI нам необходимо включить файл ESAPI.properties в путь к классам, иначе ESAPI API выдаст исключение во время выполнения. Он доступен здесь .

5. Вывод

В этом кратком руководстве мы узнали о подделке журналов и методах преодоления этой проблемы безопасности.

Как всегда, полный исходный код доступен на GitHub .