Статьи

Топ-10 уязвимостей веб-безопасности номер 2: недостатки при внедрении

Номер 2 в Топ-10 самых критических уязвимостей безопасности веб-приложений, выявленных в рамках проекта Open Web Application Security Project (OWASP), — это недостатки инъекции. Инъекция происходит всякий раз, когда данные злоумышленника могут изменить запрос или команду, отправленные в базу данных, сервер LDAP, операционную систему или другой интерпретатор. Типы внедрения — это команды SQL, LDAP, XPath, XSLT, HTML, XML, OS … Внедрение SQL и межсайтовый скриптинг составляют более 80% обнаруженных уязвимостей в веб-приложениях ( SANS Top Cyber ​​Security Risks ).

Пример SQL-инъекции

Использование конкатенации строк для построения запроса : SQL-инъекция может происходить с динамическими запросами к базе данных, конкатенированными с введенным пользователем вводом, например, со следующим запросом:

"select * from MYTABLE where name=" + parameter

если пользователь указывает в качестве параметра «name ‘OR’ a ‘=’ a ‘», это приводит к следующему:

"select * from MYTABLE where name= 'name' OR 'a'='a'; 

OR ‘a’ = ‘a’ заставляет условие where всегда быть истинным, что эквивалентно следующему:

"select * from MYTABLE; 

если пользователь указывает в качестве параметра «имя» ИЛИ «=» а «; удалить из MYTABLE», это приводит к следующему:

"select * from MYTABLE where name= 'name' OR 'a'='a'; delete from MYTABLE;

OR ‘a’ = ‘a’ заставляет условие where всегда быть истинным, что эквивалентно следующему:

"select * from MYTABLE; delete from MYTABLE;

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

SQL-инъекция может использоваться для:

  • создавать, читать, обновлять или удалять данные базы данных

Защита от SQL-инъекций

  • Не объединяйте введенные пользователем данные в запрос или команду!

    • Используйте привязку Query Parameter с типизированными параметрами, это гарантирует, что входные данные могут быть интерпретированы только как значение для предполагаемого параметра, поэтому злоумышленник не сможет изменить цель запроса .
  • Проверьте все входные данные в приложении, используя белый список (что разрешено) для типа, формата, длины, диапазона, отклоните, если он недействителен. (см. предыдущую запись в блоге )
  • не предоставляйте пользователю слишком много информации в сообщениях об ошибках (таких как информация об исключениях SQL, имена таблиц ..).

Специфичная для Java Защита от SQL-инъекций

Не объединяйте введенные пользователем данные в запрос или команду:

  • Не делайте этого с JDBC:
    String empId= req.getParameter("empId") // input parameter
    String query = "SELECT * FROM Employee WHERE
    id = '" + empId +"'";

  • Не делайте этого с JPA:
    q = entityManager.createQuery(“select e from Employee e WHERE ”
    + “e.id = '” + empId + “'”);

Использовать привязку параметра запроса с введенными параметрами

  • В JDBC вы должны использовать PreparedStatement и устанавливать значения, вызывая один из методов setXXX объекта PreparedStatement, например:
    String selectStatement = "SELECT * FROM Employee WHERE id = ? ";
    PreparedStatement pStmt = con.prepareStatement(selectStatement);
    pStmt.setString(1, empId);

    Это устанавливает в качестве первого заполнителя вопросительного знака значение входного параметра empId в команде SQL. Любые опасные символы, такие как точки с запятой, кавычки и т. Д., Должны автоматически экранироваться драйвером JDBC.

  • С JPA или Hibernate вы должны использовать именованные параметры. Именованные параметры — это параметры в запросе с префиксом двоеточия (:). Именованные параметры в запросе привязываются к аргументу методом javax.persistence.Query.setParameter (String name, Object value). Например:
    q = entityManager.createQuery(“select e from Employee e WHERE ”
    + “e.id = ':id'”);
    q.setParameter(“id”, empId);

    Это устанавливает на идентификатор в EmpId в команде SQL, снова какие — либо опасные символы должны быть автоматически сбежавшим драйвером JDBC.

  • С JPA 2.0 или Hibernate вы можете использовать Criteria API. API критериев JPA 2.0 обеспечивает типизированный объектный API запросов на основе метамодели классов Entity, а не API запросов на основе строк. Это позволяет вам разрабатывать запросы, которые компилятор Java может проверить на корректность во время компиляции. Ниже приведен пример использования Criteria API для того же запроса, что и раньше:
    QueryBuilder qb = em.getQueryBuilder();
    CriteriaQuery<Employee> q = qb.createQuery(Employee.class);
    Root<Employee> e = q.from(Employee.class);
    ParameterExpression<String> id = cb.parameter(String.class);

    TypedQuery<Employee> query = em.createQuery(
    q.select(e).where(cb.equal(e.get(Employee_.id), id) );
    query.setParameter(id, empId);

Ссылки и дополнительная информация: