# SQL Injection (SQLi) SQL Injection is a vulnerability, where an attacker can inject sql code into a query. This happens when a user's input is not validated or sanitized and used in a sql query. ## Practical Example Imagine a website which offers user login. The user types in their username and password which are then sent to the applicaton. Now the application makes a very simple sql query to check if the user plus password exists: ```SELECT * FROM users WHERE user='$name' AND password='$password';``` A clever hacker could now type in any password and the username: ```admin'--``` As the code uses the user's input without controlling it, the query would look like: ```SELECT * FROM users WHERE user='admin'--' AND password='anything';``` Everything after the ```--``` is commented out. So this query would return everything for user admin without ever checking the password and consequently logging the attacker in as admin. (At least if a user named admin exists.) *Attention:* ```--```is used in Postgres, Mysql uses ```#```to comment out. ![](https://imgs.xkcd.com/comics/exploits_of_a_mom.png) > (Source: https://xkcd.com/327/) Depending on the vulnerable query the attacker finds, they can use a lot of other tricks to read information from the database. With clever statements or the use of unions the attacker could for example read out passwords (or password hashes) from a database. A very evil hacker-mom could drop entire database tables, or the complete database itself. ## Useful (My)SQL commands When you inside the database or can make otherwise full SQL requests to the database: ```sql -- Tell me which databases there are: SHOW DATABASES; -- Connect to a specific database with the name 'dvwa': USE dvwa; -- Tell me which tables there are in the current database: SHOW TABLES; -- Tell me what columns and types there are in a specific tables, here 'guestbook': DESCRIBE guestbook; -- return all columns from the table 'users' SELECT * FROM users; -- return only the colums 'first_name' and 'last_name' from the table 'users': SELECT first_name, last_name FROM users; -- return only the colums 'first_name' and 'last_name' from the table 'users', -- but only for those rows where the 'user_id' is equal to '1': SELECT first_name, last_name FROM users WHERE user_id = '1'; -- select two columns of another table SELECT name, comment FROM guestbook; -- now do a UNION between two result sets with two colums: -- (UNIONs only work on results with the same amount of columns) SELECT first_name, last_name FROM users UNION SELECT name, comment FROM guestbook; -- do the same with the first result set consisting only of one row where the user_id = 1 SELECT first_name, last_name FROM users WHERE user_id = '1' UNION SELECT user_id, user FROM users; ``` ## How to protect against SQLi As a user there is not much you can do to protect yourself against SQLi. The best advise is to use different passwords for every account you use! So if ever one of your passwords is leaked not all of your other accounts are compromised as well. The protection against SQLi is clearly the job of the web developer! Never trust a user or input that the client side can controll. Read the best practices for your programming language and database you use. All modern languages include save handling of query parameters. In PHP this could look something like this: ``` $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' ); $data->bindParam( ':id', $id, PDO::PARAM_INT ); $data->execute(); ``` In this example nothing but an integer is allowed as input. Also the use of string input is save, as it can not be stepped out of it with a ```'```.