Panacea for SQL Injection - Queries with Parameters
Introduction
This topic is the beginning of a short cycle about panacea for various vulnerabilities in Web applications.
It just so happened that a large number of Web applications suffer from SQL injection. And how many do not write articles, how bug reports are not published - all the same, programmers
I suggest they, and indeed everyone use the so-called prepared-statements . They are also called parameterized queries .
The idea is simple, like all ingenious - to separate the request from user data.
You probably ask: what does it mean to "separate" ? This refers to: separate them from the compilation of the request.
After all, your site should process user data, and not make SQL queries based on them (although who knows?). The latter even sounds silly, but it is precisely because of this that we have a similar situation.
Implementation
Implementation is no more complicated than an idea. For example, let's take a request to get a blog entry: In PHP code, it will look something like this: The security problem is visible to the naked eye - the url_title parameter of the address bar is not filtered. This fact is usually revealed when one of the visitors has already found it. B then the code will be converted to a more terrible look: Some queries look especially terrible: I even made a mistake when I printed this safe example and made a syntax error somewhere around quotation marks and escape slashes. The larger the request, the greater the confusion. Ripples in the eyes and does not read at all. We now turn both queries into parameterized ones. In my opinion, very convenient. Instead of designs : N
SELECT `date`,`title`,`text`,`tags` FROM `posts` WHERE `url_title`='bla-bla-bla'
//...
$sql = 'SELECT `date`,`title`,`text`,`tags` FROM `posts` WHERE `url_title`=\''.$_GET['url_title'].'\'';
DB::exec($sql);
//...
//...
$sql = 'SELECT `date`,`title`,`text`,`tags` FROM `posts` WHERE `url_title`=\''.mysql_real_escape_string($_GET['url_title']).'\'';
DB::exec($sql);
//...
//...
$sql = 'SELECT `firstname`,`lastname`,`nickname`,`avatar` FROM `users` WHERE `login`=\''.mysql_real_escape_string($_GET['username']).'\' AND `password`=\''.mysql_real_escape_string($_GET['password']).'\'';
DB::exec($sql);
//...
//...
$sql = 'SELECT `date`,`title`,`text`,`tags` FROM `posts` WHERE `url_title`=:1';
DB::exec($sql, $_GET['url_title']);
//...
//...
$sql = 'SELECT `firstname`,`lastname`,`nickname`,`avatar` FROM `users` WHERE `login`=:1 AND `password`=:2';
DB::exec($sql, $_GET['username'], $_GET['password']);
//...
the corresponding argument is substituted. They, of course, can be duplicated and all that.
And what happens behind the scenes (the code is taken from one project
public static function exec($query) {
global $args;
if(func_num_args() > 1) {
$args = func_get_args();
$query = preg_replace_callback(
'/:([0-9]+)/',
create_function(
'$matches',
'global $args; return "\'".str_replace("\'", "\\\\\'", @$args[$matches[1]])."\'";'
),
$query
);
}
self::$result = sqlite_query($query, self::$handle);
return self::$result;
}
$username = mysql_real_escape_string($username);
$command->bindParam(":username",$username,PDO::PARAM_STR);
Advantages
- Readability Increases
- No separate filtering function required
- If you take such an appeal to the database as a style, then you can forget about SQL injections.
disadvantages
- In the beginning you will have to torment yourself in order to switch to the use of such queries.