预准备语句是否在此处阻止SQL注入

er4*_*z0r 7 java security static-analysis sql-injection prepared-statement

以下代码来自SAMATE Reference Dataset.我用它来测试静态分析工具.正如您所看到的,代码应该通过使用清理方法以及使用预准备语句来阻止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("<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( "</pre></blockquote></body></html>" );
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

尽管如此,我认为使用准备好的声明无论如何都应该阻止注入.我错了吗?

Mic*_*Sim 3

你是对的。将prepared statement处理“非法”SQL 输入。

allowed(...)功能是根据业务规则对用户输入进行验证,而不是防止 SQL 注入。