sql_injection:primary_defenses
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
sql_injection:primary_defenses [2016/10/13 10:43] – peter | sql_injection:primary_defenses [2020/04/16 20:53] (current) – removed peter | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== SQL Injection - Primary Defenses ====== | ||
- | |||
- | ===== Primary Defenses ===== | ||
- | |||
- | * Use Prepared Statements (Parameterized Queries) | ||
- | * Use Stored Procedures | ||
- | * Escape all User Supplied Input | ||
- | |||
- | |||
- | ===== Prepared Statements ===== | ||
- | |||
- | The use of prepared statements with variable binding (aka parameterized queries) is how all developers should first be taught how to write database queries. | ||
- | |||
- | Prepared statements ensure that an attacker is not able to change the intent of a query, even if SQL commands are inserted by an attacker. | ||
- | |||
- | |||
- | ==== PHP ==== | ||
- | |||
- | === Using mysqli === | ||
- | |||
- | The MySQL Improved extension handles bound parameters. | ||
- | |||
- | <code php> | ||
- | $stmt = $db-> | ||
- | $stmt-> | ||
- | $stmt-> | ||
- | </ | ||
- | |||
- | or | ||
- | |||
- | <code php> | ||
- | $stmt = $dbh-> | ||
- | $dbh-> | ||
- | </ | ||
- | |||
- | === Using ADODB === | ||
- | |||
- | ADODB provides a way to prepare, bind and execute all in the same method call. | ||
- | |||
- | <code php> | ||
- | $dbConnection = NewADOConnection($connectionString); | ||
- | $sqlResult = $dbConnection-> | ||
- | ' | ||
- | array($_REQUEST[' | ||
- | ); | ||
- | </ | ||
- | |||
- | |||
- | === Using the ODBC layer === | ||
- | |||
- | <code php> | ||
- | $stmt = odbc_prepare( $conn, ' | ||
- | $success = odbc_execute( $stmt, array($email) ); | ||
- | </ | ||
- | |||
- | or: | ||
- | |||
- | <code php> | ||
- | $res = odbc_exec($conn, | ||
- | $sth = $dbh-> | ||
- | $sth-> | ||
- | </ | ||
- | |||
- | === Using the PDO layer === | ||
- | |||
- | Here's the long way to do bind parameters. | ||
- | |||
- | <code php> | ||
- | $dbh = new PDO(' | ||
- | $stmt = $dbh-> | ||
- | $stmt-> | ||
- | $stmt-> | ||
- | |||
- | // insert one row | ||
- | $name = ' | ||
- | $value = 1; | ||
- | $stmt-> | ||
- | </ | ||
- | |||
- | And a shorter way to pass things in. | ||
- | |||
- | <code php> | ||
- | $dbh = new PDO(' | ||
- | $stmt = $dbh-> | ||
- | $stmt-> | ||
- | </ | ||
- | |||
- | |||
- | === Using PostgreSQL === | ||
- | |||
- | <code php> | ||
- | $result = pg_query_params( $dbh, ' | ||
- | </ | ||
- | |||
- | |||
- | === Alternative Method === | ||
- | |||
- | **TODO** : Check if this works? | ||
- | |||
- | < | ||
- | |||
- | For example, | ||
- | |||
- | <code mysql> | ||
- | $mysql[' | ||
- | |||
- | $mysql[' | ||
- | </ | ||
- | |||
- | will make the injection attempt successful, whereas | ||
- | |||
- | <code mysql> | ||
- | $mysql[' | ||
- | |||
- | $mysql[' | ||
- | </ | ||
- | |||
- | will make the injection attempt fail. | ||
- | |||
- | Isn't the latter method (str_replace(array(' | ||
- | |||
- | |||
- | |||
- | ==== Java ==== | ||
- | |||
- | === JDBC === | ||
- | |||
- | The JDBC API has a class called PreparedStatement which allows the programmer to safely insert user-supplied data into a SQL query. The location of each input value in the query string is marked with a question mark. The various set*() methods are then used to safely perform the insertion. | ||
- | |||
- | <code java> | ||
- | String name = //user input | ||
- | int age = //user input | ||
- | Connection connection = DriverManager.getConnection(...); | ||
- | PreparedStatement statement = connection.prepareStatement( | ||
- | " | ||
- | statement.setString(1, | ||
- | statement.setInt(2, | ||
- | ResultSet rs = statement.executeQuery(); | ||
- | while (rs.next()){ | ||
- | //... | ||
- | } | ||
- | </ | ||
- | |||
- | === Hibernate === | ||
- | |||
- | Hibernate uses named parameters to safely insert data into a query. A named parameter consists of a colon, followed by a unique name for the parameter. | ||
- | |||
- | <code java> | ||
- | String name = //user input | ||
- | int age = //user input | ||
- | Session session = //... | ||
- | Query query = session.createQuery(" | ||
- | query.setString(" | ||
- | query.setInteger(" | ||
- | Iterator people = query.iterate(); | ||
- | </ | ||
- | |||
- | |||
- | ==== Perl ==== | ||
- | |||
- | Perl's DBI, available on the CPAN, supports parameterized SQL calls. Both the do method and prepare method support parameters (" | ||
- | |||
- | <code perl> | ||
- | $sth = $dbh-> | ||
- | foreach my $email (@emails) { | ||
- | $sth-> | ||
- | $row = $sth-> | ||
- | [...] | ||
- | } | ||
- | </ | ||
- | |||
- | However, you can't use parameterization for identifiers (table names, column names) so you need to use DBI's quote_identifier() method for that: | ||
- | |||
- | <code perl> | ||
- | # Make sure a table name we want to use is safe: | ||
- | my $quoted_table_name = $dbh-> | ||
- | |||
- | # Assume @cols contains a list of column names you need to fetch: | ||
- | my $cols = join ',', | ||
- | |||
- | my $sth = $dbh-> | ||
- | </ | ||
- | |||
- | You could also avoid writing SQL by hand by using DBIx:: | ||
- | |||
- | |||
- | ==== SQLite ==== | ||
- | |||
- | Use **sqlite3_prepare()** to create a statement object. | ||
- | |||
- | |||
- | |||
- | ===== Escape all User Supplied Input ===== | ||
- | |||
- | **<color red> | ||
- | |||
- | See: https:// | ||
- | |||
- | |||
- | ===== References ===== | ||
- | |||
- | http:// | ||
- | https:// |
sql_injection/primary_defenses.1476355438.txt.gz · Last modified: 2020/07/15 09:30 (external edit)