Готовый оператор предотвращает SQL-инъекцию здесь? - PullRequest
7 голосов
/ 08 июля 2010

Код ниже взят из Справочный набор данных SAMATE .Я использовал его для тестирования инструмента статического анализа.Как видите, код должен предотвращать SQL-инъекцию как с помощью метода очистки, так и с использованием подготовленного оператора.

Поскольку инструменты SCA не могут знать пользовательские методы санации, они не обнаружат, что метод allowedиспользуется для предотвращения внедрения.

<code>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("<HTML><BODY><blockquote><pre>");
        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, ответ HttpServletResponse) выдает исключение ServletException, IOException {}}

Тем не менее, я думаю, что использование подготовленного утверждения должно в любом случае предотвратить инъекцию. Я ошибаюсь?

Ответы [ 4 ]

3 голосов
/ 08 января 2014

Да Подготовленный оператор здесь предотвратит внедрение SQL.Это потому, что вы используете заполнитель (?) В запросе.Это заполнитель, который важно отметить здесь.

Ниже приведены 2 примера подготовленных высказываний.Первый не помешает внедрению sql.

PreparedStatement ps = conn.prepareStatement ("SELECT * FROM users WHERE firstname LIKE" + name);

Вышеприведенный оператор, даже если он подготовленОператор не помешает SQL-инъекциям

Однако подготовленный ниже оператор хорош для предотвращения SQL-инъекций.

PreparedStatement ps = conn.prepareStatement («ВЫБРАТЬ * ОТ ПОЛЬЗОВАТЕЛЕЙ, ГДЕ ИМ НРАВИТСЯ?»);

Различие между первым и вторым утверждением заключается в том, что запрос в первом случае имеет виддинамически компилируется во время выполнения, но во втором случае он предварительно компилируется.

Это означает, что злонамеренный пользовательский ввод, такой как (a'or'1 '=' 1), может изменить запрос в первом операторе.Но второй запрос, поскольку он предварительно скомпилирован, будет обрабатывать злонамеренный пользовательский ввод как данные, а не как команду sql.

В выражениях Prehellred в словах можно предотвратить SQL-инъекцию тогда и только тогда, когда они используются с заполнителями и параметрами связывания.

3 голосов
/ 08 июля 2010

Вы правы.prepared statement позаботится о «недопустимом» вводе SQL.

Функция allowed(...) является своего рода проверкой ввода пользователя с точки зрения бизнес-правил, а не для предотвращения внедрения SQL.

1 голос
/ 08 июля 2010

Кажется, для предотвращения SQL-инъекций.Вы, конечно, правы, что функция allow () помогает, но это не совсем предпочтительный метод.Поскольку ваш код является просто примером, я бы предположил, что в реальном мире большинство программ допускают более 5 возможных вариантов.

1 голос
/ 08 июля 2010

Достаточно подготовленного оператора, чтобы предотвратить внедрение SQL ...

Однако, если вы намереваетесь записать пользовательские сообщения в параметр 'out' (например, out.printf( "Invalid username %s", name )), следите за внедрением JavaScript. Я мог бы ввести свое имя как <script>alert('hi')</script>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...