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 .