Код ниже от Ссылочного Набора данных SAMATE. Я использовал его для тестирования инструмента статического анализа. Поскольку Вы видите, что код должен предотвратить Внедрение SQL оба при помощи метода санитизации, а также использования подготовленного оператора.
Так как инструменты SCA не могут знать пользовательские santitzation методы, желание не обнаруживают что allowed
метод используется для предотвращения инжекции.
public class SQLInjection_good_089 extends HttpServlet
{
private static final long serialVersionUID = 1L;
public SQLInjection_good_089()
{
super();
}
// Table of allowed names to use
final String allowed_names[] = { "Mickael", "Mary",
"Peter", "Laura", "John"};
// Function to check if the current name takes part of the allowed ones
public boolean allowed( String in )
{
boolean bool = false;
for( int i = 0; i < 5; i++ )
{
if( in.equals( allowed_names[i] ) )
{
// the current name is allowed to use
bool = true;
break;
}
}
return bool;
}
// Method which will be called to handle HTTP GET requests
protected void doGet( HttpServletRequest req, HttpServletResponse resp )
throws ServletException, IOException
{
// Initialize the output stream
resp.setContentType("text/html");
ServletOutputStream out = resp.getOutputStream();
out.println("");
Connection conn = null;
// Get the parameter "name" from the data provided by the user
String name = req.getParameter( "name" );
if ( (name != null) && (allowed(name) == true) )
{
try
{
// Set the context factory to use to create the initial context
System.setProperty (Context.INITIAL_CONTEXT_FACTORY, "your.ContextFactory");
// Create the initial context and use it to lookup the data source
InitialContext ic = new InitialContext ();
DataSource dataSrc = (DataSource) ic.lookup ("java:comp/env/jdbc:/mydb");
// Create a connection to the SQL database from the data source
conn = dataSrc.getConnection();
// Send a SQL request to the database
PreparedStatement ps = conn.prepareStatement( "SELECT * FROM users WHERE firstname LIKE ?" );
// replace the first parameter by name
ps.setString(1, name);
ps.executeQuery();
}
catch( NamingException e )
{
out.println( "Naming exception");
}
catch( SQLException e )
{
out.println( "SQL exception");
}
finally
{
try
{
if (conn != null)
conn.close ();
}
catch (SQLException se)
{
out.println("SQL Exception");
}
}
}
else
return;
out.println( "
" );
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
}
}
Тем не менее, я думаю, что использование подготовленного оператора должно предотвратить инжекцию здесь так или иначе. Действительно ли я ошибаюсь?
Вы правы. подготовленный оператор
позаботится о "незаконном" вводе SQL.
Функция allowed(...)
является своего рода проверкой пользовательского ввода с точки зрения бизнес-правил, а не для предотвращения SQL-инъекций.
Просто подготовленного оператора должно быть достаточно для предотвращения SQL-инъекций...
Однако, если вы собираетесь писать сообщения пользователю в параметр 'out' (например, out.printf("Invalid username %s", name )
), опасайтесь инъекций javascript. Я могу ввести свое имя как
Это, похоже, предотвращает SQL Injection. Вы, конечно, правы, что функция allowed() помогает, но это не совсем предпочтительный метод. Поскольку ваш код - всего лишь пример, я бы предположил, что в реальном мире большинство программ допускают более 5 возможных вариантов.