В этой статье представлены
4 основных
метода кодирования, которые следует избегать при программировании на
языке Java . Недавно я наткнулся на несколько проектов Java, в которых были найдены эти экземпляры. Пожалуйста, не стесняйтесь комментировать / предлагать, если я пропустил упоминание одного или нескольких важных моментов. Кроме того, извините за опечатки.
Ниже приведены ключевые моменты, описанные далее в этой статье:
- Выполнение динамически сгенерированного оператора SQL
- Непосредственная запись параметра Http на выход сервлета
- Создание SQL PreparedStatement из динамической строки
- Массив хранится напрямую
Выполнение динамически сгенерированного оператора SQL
Это самое распространенное из всех. Можно упомянуть об этой уязвимости в нескольких местах. На самом деле, многие разработчики также знают об этой уязвимости, хотя это другая вещь, в которой они время от времени совершают ошибки. В нескольких классах DAO были найдены экземпляры, такие как следующий код, которые могли привести к атакам с использованием SQL-инъекций .
StringBuilder query = new StringBuilder(); query.append( "select * from user u where u.name in (" + namesString + ")" ); try { Connection connection = getConnection(); Statement statement = connection.createStatement(); resultSet = statement.executeQuery(query.toString()); }
Вместо приведенного выше запроса можно также использовать подготовленное утверждение, подобное тому, которое продемонстрировано в приведенном ниже коде. Это не только делает код менее уязвимым для атак с использованием SQL-инъекций, но и делает его более эффективным .
StringBuilder query = new StringBuilder(); query.append( "select * from user u where u.name in (?)" ); try { Connection connection = getConnection(); PreparedStatement statement = connection.prepareCall(query.toString()); statement.setString( 1, namesString ); resultSet = statement.execute(); }
Непосредственная запись параметра Http в вывод сервлета
В классах сервлетов я обнаружил случаи, когда параметр запроса Http записывался как есть в поток вывода без каких-либо проверок проверки. Следующий код демонстрирует то же самое:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String content = request.getParameter("some_param"); // // .... some code goes here // response.getWriter().print(content); }
Обратите внимание, что приведенный выше код не сохраняется ничего. Подобный выше код может привести к так называемой отраженной (или непостоянной) уязвимости межсайтового скриптинга (XSS) . Отраженный XSS возникает, когда злоумышленник внедряет исполняемый код браузера в один HTTP-ответ. Поскольку это происходит по определению (будучи непостоянным), внедренная атака не сохраняется в приложении; это проявляется только в тех пользователях, которые открывают злонамеренно созданную ссылку или стороннюю веб-страницу. Строка атаки включается как часть созданных параметров URI или HTTP, неправильно обрабатывается приложением и возвращается жертве. Вы можете прочитать более подробную информацию на следующей странице OWASP по отражению XSS
Создание SQL PreparedStatement из строки динамического запроса
По сути это означает, что хотя PreparedStatement использовался, но запрос был сгенерирован как строковый буфер, а не так, как рекомендовано для подготовленного оператора (параметризовано). Если не проверять, испорченные данные пользователя будут создавать строку, в которой SQL-инъекция может вести себя непредсказуемым и нежелательным образом. Скорее следует сделать параметризацию оператора запроса и правильно использовать PreparedStatement. Посмотрите на следующий код, чтобы определить уязвимый код.
StringBuilder query = new StringBuilder(); query.append( "select * from user u where u.name in (" + namesString + ")" ); try { Connection connection = getConnection(); PreparedStatement statement = connection.prepareStatement(query.toString()); resultSet = statement.executeQuery(); }
Массив хранится напрямую
В случаях этой уязвимости, массив хранится напрямую, может помочь злоумышленнику изменить объекты, хранящиеся в массиве вне программы, и программа ведет себя непоследовательно, так как ссылка на массив, передаваемый методу, сохраняется вызывающей стороной / вызывающей стороной. Решение состоит в том, чтобы сделать копию внутри объекта, когда он будет передан. Таким образом, последующее изменение коллекции не повлияет на массив, хранящийся в объекте. Вы можете прочитать подробности на следующей странице stackoverflow . Следующий код представляет уязвимость:
// Note that values is a String array in the code below. // public void setValues(String[] somevalues) { this.values = somevalues; }