В этой статье пойдет речь об атаке SQL-инъекцией. Читатели также узнают о том, как предотвратить подобное хакерское нападение и защитить свою систему.
Уязвимости для SQL-инъекций появляются при небезопасной отправке запросов к базе данных. Ненадежные данные интерпретируются как часть структуры SQL-запросов и представляют собой опасность для системы пользователя.
Как предотвратить появление уязвимостей для SQL-инъекций?
Лучший способ предотвратить появление уязвимостей для SQL-инъекций – это использовать фреймворк, который позволяет безопасно создавать и настраивать запросы. ORM (Object Relational Mapper) прекрасно подойдет в данных целях. Для получения дополнительных уровней безопасности следует проверить все входные данные и использовать инструменты WAF (Web Application Firewall).
Простой пример
Допустим, у пользователя есть Java-приложение, которое позволяет ему и другим доверенным лицам извлекать документы по идентификатору. Необходимо ввести следующую команду:
String query = "SELECT * FROM documents WHERE ownerId=" + authContext.getUserId() + " AND documentName = '" +
request.getParameter("docName") + "'";
executeQuery(query);
Итак, если идентификатор пользователя равен 25, а URL-адрес похож на этот «https://www.example.com/documents/?docName=ABC123» , то запрос будет примерно следующим:
SELECT * FROM documents WHERE ownerId=25 AND documentName='ABC123';
Пока все идет хорошо. Но что нужно предпринять, если URL-адрес другой? К примеру, этот — «https://www.example.com/documents/?docName=ABC123’OR’1’=’1 ».
Пользователь вводит запрос, с помощью которого можно вернуть все документы всем пользователям. Это становится возможным благодаря тому, что «1=1», а это выражение, которое всегда верно (или истинно).
SELECT * FROM documents WHERE ownerId=25 AND documentName='ABC123' OR '1'='1';
Ой, какая неловкость. Но как пользователь может этого избежать?
Object Relational Mappers
Используя Java в качестве примера, пользователь прибегает к применению ORM, такого как hibernate. Собственно говоря, он реализует JPA (Java Persistence API), что может выглядеть следующим образом.
Во-первых, следует определить модель.
@Entity
public class Document {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String documentName;
private Integer ownerId;
}
Во-вторых, пользователь выбирает класс репозитория.
@Repository
public interface DocumentRepository extends JpaRepository<Document, Long> {
List<Document> findByDocumentNameAndOwnerId(String documentName, Integer ownerId);
}
Наконец, он может использовать его.
Пользователь теперь может получить документы, если ввести данную команду:
List<Document> docs = documentRepository.findByDocumentNameAndOwnerId(request.getParameter("docName"), authContext.getUserId());
ORM (Object Relational Mappers) позаботится о безопасной обработке всех параметров. Теперь следует предположить, что человек хочет лучше контролировать свои запросы. В этом случае многие ORM могут предоставить составители («строители») запросов. Человек будет использовать любой из них, к примеру, Hibernate Criteries API .
Если человек использует Python, у Django есть отличный ORM. Если пользователь не применяет Django, то sqlalchemy станет отличным вариантом.
PHP имеет свою доктрину. Следует просто найти в Google ORM для выбранной технологии.
Предупреждение
Нужно быть аккуратным с фреймворками ORM по двум причинам.
Во-первых, у них все еще есть функциональность для поддержки необработанных SQL-запросов или частей запросов. Следует просто отключить данную опцию.
Во-вторых, фреймворки ORM время от времени склонны к появлению уязвимостей, как и любой другой программный пакет, поэтому необходимо выполнять различные дополнительные практики безопасности. Пользователи обычно проверяют все входные данные, используют инструменты WAF и поддерживают версии своих пакетов в актуальном состоянии, чтобы не попасть впросак.
Prepared statements
Prepared statements – это уже устаревшая функция. Следует избегать ее использования, поскольку по сравнению с ORM она включает в себя более высокий риск человеческих ошибок. Тем не менее, prepared statements все еще более надежна, чем обычная конкатенация строк. Ее реализация может выглядеть следующим образом:
String query = "SELECT * FROM documents WHERE ownerId=? AND documentName = ?";
PreparedStatement ps = conn.prepareStatement(query);
ps.setString(1, authContext.getUserId());
ps.setString(2, request.getParameter("docName"));
ResultSet rs = ps.executeQuery();
Теоретически это безопасно. Однако, по опыту многих специалистов, по мере того, как кодовая база будет расти, ошибки начнут появляться все чаще. Пользователю нужен только один промах, чтобы сделать свою систему полностью уязвимой. К примеру, те же массивы («foo, bar») — очень опасная зона, где могут возникнуть проблемы.
Поэтому, если человек решит использовать данный метод, то ему нужно быть очень осторожным при масштабировании.
Web Application Firewalls
Продукты WAF также имеют свои недостатки. Однако они предоставляют пользователю потрясающий дополнительный уровень безопасности и обычно довольно эффективны против атак SQL-инъекций.
Отличным решением с открытым исходным кодом является развертывание Apache с ModSecurity CRS для защиты своего веб-приложения.
Database Firewalls
В зависимости от используемой базы данных и имеющегося бюджета человек может попробовать применить различные межсетевые экраны баз данных.
Заключение
SQL-инъекция представляет собой одну из атак, выполняемых при наличии уязвимостей в системе. Пользователь может предотвратить атаку, используя соответствующую библиотеку или фреймворк для построения протокола.
ORM безопаснее, чем prepared statements. И если человеку нужен низкоуровневый контроль запросов, следует использовать ORM более низкого уровня, который еще называют «строителем» запросов. Продукты WAF помогут добавить дополнительный уровень безопасности, но не следует полностью полагаться только на возможности данных инструментов.
Автор переведенной статьи: Teo Selenius.
Важно! Информация исключительно в учебных целях. Пожалуйста, соблюдайте законодательство и не применяйте данную информацию в незаконных целях.
ЧИТАТЬ ВСЕ СТАТЬИ НА САЙТЕ | ПОДПИСЫВАЙТЕСЬ НА НАШ TELEGRAM КАНАЛ