DB Security

by K. Yue

1. Database Security

Example:

CREATE USER 'temp'@'%' IDENTIFIED VIA mysql_native_password USING ....;
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES ON *.*
     TO 'temp'@'%' REQUIRE NONE WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;

2. SQL Injection (SQLI)

Example: adapted from the textbook and Wikipedia

Consider a Web form that accepts user names and passwords:

The back-end page may include unsafe code dynamically constructing a query.

query = "SELECT * FROM users WHERE name = '" + username + "' and password = '" + password + "';"

The variables username and password get their values from the users through the Web form through the CGI protocol.

Thus, if the user enters (not considering encryption issues here):

username = yue
password = 1Bkm*2ce

the variable query will have a value of

"SELECT * FROM users WHERE name = 'yue' and password = '1Bkm*2ce';"

The query can be executed to get information about the user 'yue' if the right password is provided.

If someone enters:

username = yue
password = 1Bkm*2'ce

query becomes:

"SELECT * FROM users WHERE name = 'yue' and password = '1Bkm*2'ce';"

Executing the SQL query statements will result in a SQL syntax error in the server-side program since the single quote character ' is an escape character in SQL with special meanings.

For SQL injection, attacker may enter:

username = yue
password = ' OR '1'='1

query becomes:

"SELECT * FROM users WHERE name = 'yue' and password = '' OR '1'='1';"

Note that the structure of the SQL statement has been changed. Since the and operator has a higher precedence than the or operator, this is equivalent to:

"SELECT * FROM users WHERE (name = 'yue' and password = '') OR '1'='1';"

The condition in the WHERE clause will always be evaluated to true. The query will bypass the password checking and return information about all users, not just the user 'yue'.

For input:

username = yue
password = ' OR '1'='1’; DELETE * FROM student; --

query becomes essentially:

"SELECT * FROM users
 WHERE name = 'yue' and password = '' OR '1'='1';
 DELETE * FROM student; --
'; "

For input:

username = yue
password = ' OR '1'='1’; DROP TABLE users; SELECT * FROM account; --

query becomes essentially:

"SELECT * FROM users
 WHERE name = 'yue' and password = '' OR '1'='1';
DROP TABLE users;
SELECT * FROM account; --
'; "

In all of these examples, the intended structures of the SQL statements are changed by the attackers.

2.1 SQLI Mitigation

[1] Input validation: validate input parameter values, properly escaping special characters.

In the minimum, replace one ' by two ':

username = username.replace("'", "''")
password = password.replace("'", "''")

For input parameters:

username = yue
password = ' OR '1'='1

after filtering query becomes:

"SELECT * FROM users WHERE name = 'yue' and password = ''' OR ''1''=''1';"

The condition of the Where clause will be false (unless the password is really "' OR '1'='1".

[2] Using parameterized queries:

query = "SELECT * FROM users WHERE name = %s and password = %s;"
cursor.execute(query,(username, password))

[3] Using intermediate mid-tiered objects instead of SQL for centralized checking.

[4] Use database security features and good practices