How does a PreparedStatement avoid or prevent SQL

2018-12-31 08:37发布

I know that PreparedStatements avoid/prevent SQL Injection. How does it do that? Will the final form query that is constructed using PreparedStatements will be a string or otherwise?

9条回答
大哥的爱人
2楼-- · 2018-12-31 08:53

The problem with SQL injection is, that a user input is used as part of the SQL statement. By using prepared statements you can force the user input to be handled as the content of a parameter (and not as a part of the SQL command).

But if you don't use the user input as a parameter for your prepared statement but instead build your SQL command by joining strings together, you are still vulnerable to SQL injections even when using prepared statements.

查看更多
时光乱了年华
3楼-- · 2018-12-31 08:56

PreparedStatement:

1) Precompilation and DB-side caching of the SQL statement leads to overall faster execution and the ability to reuse the same SQL statement in batches.

2) Automatic prevention of SQL injection attacks by builtin escaping of quotes and other special characters. Note that this requires that you use any of the PreparedStatement setXxx() methods to set the value.

查看更多
余生无你
4楼-- · 2018-12-31 08:58

As explained in this post, the PreparedStatement alone does not help you if you are still concatenating Strings.

For instance, one rogue attacker can still do the following:

  • call a sleep function so that all your database connections will be busy, therefore making your application unavailable
  • extracting sensitive data from the DB
  • bypassing the user authentication

Not only SQL, but even JPQL or HQL can be compromised if you are not using bind parameters.

Bottom line, you should never use string concatenation when building SQL statements. Use a dedicated API for that purpose:

查看更多
临风纵饮
5楼-- · 2018-12-31 09:04

The SQL used in a PreparedStatement is precompiled on the driver. From that point on, the parameters are sent to the driver as literal values and not executable portions of SQL; thus no SQL can be injected using a parameter. Another beneficial side effect of PreparedStatements (precompilation + sending only parameters) is improved performance when running the statement multiple times even with different values for the parameters (assuming that the driver supports PreparedStatements) as the driver does not have to perform SQL parsing and compilation each time the parameters change.

查看更多
琉璃瓶的回忆
6楼-- · 2018-12-31 09:08

To understand how PreparedStatement prevents SQL Injection, we need to understand phases of SQL Query execution.

1. Compilation Phase. 2. Execution Phase.

Whenever SQL server engine receives a query, it has to pass through below phases,

Query Execution Phases

  1. Parsing and Normalization Phase: In this phase, Query is checked for syntax and semantics. It checks whether references table and columns used in query exist or not. It also has many other tasks to do, but let's not go in detail.

  2. Compilation Phase: In this phase, keywords used in query like select, from, where etc are converted into format understandable by machine. This is the phase where query is interpreted and corresponding action to be taken is decided. It also has many other tasks to do, but let's not go in detail.

  3. Query Optimization Plan: In this phase, Decision Tree is created for finding the ways in which query can be executed. It finds out the number of ways in which query can be executed and the cost associated with each way of executing Query. It chooses the best plan for executing a query.

  4. Cache: Best plan selected in Query optimization plan is stored in cache, so that whenever next time same query comes in, it doesn't have to pass through Phase 1, Phase 2 and Phase 3 again. When next time query come in, it will be checked directly in Cache and picked up from there to execute.

  5. Execution Phase: In this phase, supplied query gets executed and data is returned to user as ResultSet object.

Behaviour of PreparedStatement API on above steps

  1. PreparedStatements are not complete SQL queries and contain placeholder(s), which at run time are replaced by actual user-provided data.

  2. Whenever any PreparedStatment containing placeholders is passed in to SQL Server engine, It passes through below phases

    1. Parsing and Normalization Phase
    2. Compilation Phase
    3. Query Optimization Plan
    4. Cache (Compiled Query with placeholders are stored in Cache.)

UPDATE user set username=? and password=? WHERE id=?

  1. Above query will get parsed, compiled with placeholders as special treatment, optimized and get Cached. Query at this stage is already compiled and converted in machine understandable format. So we can say that Query stored in cache is Pre-Compiled and only placeholders need to be replaced with user-provided data.

  2. Now at run-time when user-provided data comes in, Pre-Compiled Query is picked up from Cache and placeholders are replaced with user-provided data.

PrepareStatementWorking

(Remember, after place holders are replaced with user data, final query is not compiled/interpreted again and SQL Server engine treats user data as pure data and not a SQL that needs to be parsed or compiled again; that is the beauty of PreparedStatement.)

If the query doesn't have to go through compilation phase again, then whatever data replaced on the placeholders are treated as pure data and has no meaning to SQL Server engine and it directly executes the query.

Note: It is the compilation phase after parsing phase, that understands/interprets the query structure and gives meaningful behavior to it. In case of PreparedStatement, query is compiled only once and cached compiled query is picked up all the time to replace user data and execute.

Due to one time compilation feature of PreparedStatement, it is free of SQL Injection attack.

You can get detailed explanation with example here: http://javabypatel.blogspot.in/2015/09/how-prepared-statement-in-java-prevents-sql-injection.html

查看更多
泪湿衣
7楼-- · 2018-12-31 09:08

Prepared statement is more secure. It will convert a parameter to the specified type.

For example stmt.setString(1, user); will convert the user parameter to a String.

Suppose that the parameter contains a SQL string containing an executable command: using a prepared statement will not allow that.

It adds metacharacter (a.k.a. auto conversion) to that.

This makes it is more safe.

查看更多
登录 后发表回答