SQL Injection Protection - php

I thought I would get your opinion on an option I thought that would essentially eliminate the possibility of SQL injection (I think).
Currently, I have my admin account which obviously gives me full command of the database (alter, drop, etc). I than have an account that PHP uses which only has access to SELECT, UPDATE, DELETE, INSERT. What about setting up a user for each of those actions, and then just referencing the connect ID in the mysql_query statement - now obviously this would put a lot more strain on the server, having to make 4 connections perpage essentially, but if it security is important, it seems to me that this would be a valid option, by limiting the commands to EXACT function that you want performed in that case. Any thoughts on the viability of this option?
UPDATE: As I failed to mention earlier, this would NOT be the sole barrier of preventing SQL injection, mysql_real_escape_string(), prepared statements, etc. But I was just thinking maybe if by some how, ALL of these fail, wouldn't this at least limit the damage they could do? (e.g. on a registration form, they would be unable to SELECT hashes, or DELETE entries).

This is not what SQL Injection is all about. Any time you use parameters that haven't been sanitized in your SQL query you leave your database open to SQL injection, which might not necessarily have the goal of destroying data. It could also be to steal data or gain unauthorized access.
Consider a very restricted account where all it could do is SELECT. You write a query for authentication:
$sql = "SELECT COUNT(*) AS count
FROM users
WHERE user_id='{$_POST['user']}' AND pass='{$_POST['password'}'";
// check if returns a count of 1, if yes, log in
With normal input, you expect the query to look like:
SELECT COUNT(*) AS count
FROM users
WHERE user_id = 'username' AND pass='********'
Which should return 1 as the count if both username and pass match. Now an attacker tries to log in as admin. Since you haven't sanitized your inputs, they send $_POST['user'] as: admin'; --. The whole query becomes:
SELECT COUNT(*) AS count
FROM users
WHERE user_id = 'admin'; -- AND pass='********'
Everything after -- is a comment, so this ignores the other condition and returns 1 regardless. There you go, you've just granted a malicious user admin access. That is how some real attacks are carried out. You start with a low privileged account and through holes in security you try to gain access to more privileges.
Long story short, having an application-wide account with restricted privileges (eg: no DROP, ALTER, etc) is good. Never give anyone or any application more privileges than they need. But to prevent SQL injection, use prepared statements.

Having separate user with limited privileges is a common practice. But even if you will have such a user, it won't protect you from SQL injection attacks.
Consider the following example:
mysql_query('DELETE FROM posts WHERE user_id = '.$user_id
.' AND post_id = '.$_GET['post_id']);
Malicious user can trash all your posts with ease by setting post_id to 1 OR 1=1:
http://www.example.com/delete_post.php?post_id=1+OR+1%3D1
To get a valid protection you should always escape strings to be used in a query:
$_GET['post_id'] = mysql_real_escape_string($_GET['post_id']);
Or better use prepared statements.

This has very little to do with SQL Injection. You are talking about user permissions. Setting user permissions would have zero effect on protecting you from SQL Injections if you don't sanitize your user input and don't use prepared statements with PDO.
Read more about SQL Injections: SQL Injections and PDO

SQL injection and escaping sound magical to many people, something like shield against some mysterious danger, but: don't be scared of it - it is nothing magical. It is just the way to enable special characters being processed by the query.
So, don't invent new magial shields and ways how to protect the magical injection danger! Instead, try to understand how escaping of the input works.
The best would be just to have a look what escaping really does. Say the input string is:
');DROP TABLE table;--
after escaping:
\');DROP TABLE table;--
in fact it escaped only the single slash. That's the only thing you need to assure - that when you insert the string in the query, the syntax will be OK!
insert into posts set title = '\');DROP TABLE table;--'
It's nothing magical like danger shield or something, it is just to ensure that the resultant query has the right syntax! (of course if it doesn't, it can be exploited)
The query parser then looks at the \' sequence and knows that it is still the variable, not ending of its value. It will remove the backslash and the following will be stored in the database:
');DROP TABLE table;--
which is exactly the same value as user entered. And which is exactly what you wanted to have in the database!!
So this means that the if you fetch that string from the database and want to use it in the query again, you need to escape it again to be sure that the resultant query has the right syntax.
But, in your example, very important thing to mention is the magic_quotes_gpc directive!
This feature escapes all the user input automatically (gpc - _GET, _POST and _COOKIE). This is an evil feature made for people not aware of sql injection. It is evil for two reasons. First reason is that then you have to distinguish the case of your first and second query - in the first you don't escape and in the second you do. What most people do is to either switch the "feature" off (I prefer this solution) or unescape the user input at first and then escape it again when needed. The unescape code could look like:
function stripslashes_deep($value)
{
return is_array($value) ?
array_map('stripslashes_deep', $value) :
stripslashes($value);
}
if (get_magic_quotes_gpc()) {
$_POST = stripslashes_deep($_POST);
$_GET = stripslashes_deep($_GET);
$_COOKIE = stripslashes_deep($_COOKIE);
}
The second reason why this is evil is because there is nothing like "universal quoting".
When quoting, you always quote text for some particular output, like:
string value for mysql query
like expression for mysql query
html code
json
mysql regular expression
php regular expression
For each case, you need different quoting, because each usage is present within different syntax context. This also implies that the quoting shouldn't be made at the input into PHP, but at the particular output! Which is the reason why features like magic_quotes_gpc are broken (never forget to handle it, or better, assure it is switched off!!!).
So, what methods would one use for quoting in these particular cases? (Feel free to correct me, there might be more modern methods, but these are working for me)
mysql_real_escape_string($str)
mysql_real_escape_string(addcslashes($str, "%_"))
htmlspecialchars($str)
json_encode() - only for utf8! I use my function for iso-8859-2
mysql_real_escape_string(addcslashes($str, '^.[]$()|*+?{}')) - you cannot use preg_quote in this case because backslash would be escaped two times!
preg_quote()

Related

How to secure project against hacks and attacks?

I have started in web development not long time ago. I know some stuff now, but I'm really concerned about security issues that may arise. I know simple security solutions like preg_replace , but I'm not confident with that.
So I would like to ask you for any sort of speaking "universal" security standards that can be applied in the following cases. As I mentioned, I'm not pro so it would be great if you can start with something simple, yet useful. If possible could you provide examples please?
I did have a look at php manual, although I would like to know additional info from person.
Here are some typical MySQL / PHP things I use in my projects. Could you suggest any improvements to make them more secure?
$sql = mysql_query("SELECT * FROM stories WHERE showing = 1 ORDER BY cr_date DESC LIMIT 5") or die (mysql_error("There was an error in connection"));
while($row = mysql_fetch_assoc($sql)){
$story_id = $row["id"];
// etc...
}
$username = $_POST['username'];
$sql = mysql_query("INSERT INTO myMembers (username, //etc... )
VALUES('$username' //etc.. ")or die (mysql_error());
$username = $_GET['username'];
//gets username from url like http://myweb.com/profile.php?username=blabla
First of all, thank you for caring about web security. Many PHP developers don't know anything about it, and don't care to learn. They are the ones who are exposing our passwords and bank accounts to hackers. Be part of the solution! :-)
1. Treat the mysql extension as if it is deprecated.
Use the PDO or mysqli extensions instead. The plain mysql extension does not support prepared statements, and some other features, such as transaction control. No one should be using mysql if they have PDO_mysql or mysqli available to them.
2. Do not interpolate external data into SQL.
Anytime you get a value from $_GET or $_POST, you should consider it to be unsafe to use in any SQL statement, or shell_exec(), or other instance where you execute the string as some kind of code.
3. Use prepared query parameters instead of interpolation.
It's really easy. In fact, it's easier to use query parameters than it is to interpolate variables into SQL strings. You don't need to worry about escaping, or long complex string-concatenation.
See example code here: http://us.php.net/manual/en/pdo.prepare.php
4. For corner cases, use careful filtering.
A query parameter takes the place for one literal value in an SQL expression. Not table names, not column names, not SQL keywords, not lists of values or full expressions. For those, you do need to use string interpolation, but see my presentation SQL Injection Myths and Fallacies for examples of how you can "whitelist" values to interpolate.
Also check out the PHP filter extension, which offers a flexible way of validating inputs or stripping off invalid characters to make sure only the valid part of the input is used.
Looking at your examples, the SELECT query has no dynamic values interpolated from external sources like $_GET. So that one is safe.
The INSERT query takes a value from the request, which could contain malicious content that changes the way your query runs. This one is a good candidate for using query parameters.
Also consider that SQL injection is one of the two most prevalent security issues with PHP. The other one is Cross-Site Scripting (XSS). This is not directly related to SQL, but you should learn about it too.
Here's a good resource for learning more about web programming security: OWASP.org cheat sheets.
Many frameworks have a good set of security measures already in place that will do a great deal in preventing things like SQL injections. Yii, CakePhP, CodeIgnitre all may be of some use.
Although it's almost impossible to beat Bill, I feel I must clarify answers stating that "you have to trust no user input".
In fact, quite contrary - SQL injection protection will do any good only if it would be totally ignorant of the data source. And treat ALL the data as potentially malicious. And process it accordingly.
Thus, to summarize all the advises:
Prepared statements is a good approach but not a complete one.
It has a brilliant idea of using some placeholder, a proxy to represent the actual value in the query. Thus this value can be properly sanitized.
But these placeholders, as Bill said, are limited to the strings and numbers only. So, it would be a good idea to add another placeholder of your own - for identifiers. But you still have to watch out SQL syntax keywords manually.
So, instead of "Do not interpolate external data into SQL." statement one have to use
"2. Do not interpolate values into query directly but only by some proxy, performing necessary precautions"
The most important thing to remember is never trust anything from an external source (eg user input, responses from other web services etc). Always sanitise all input and where possible use code from your database provider to do so.
In the case of MySQL parameterising all queries is essential, so use a prepared statement, eg
$statement = $db->prepare('SELECT * FROM stories WHERE title = :title');
$statement->execute(array(':title' => $title));
$rows = $statement->fetchAll();
Your current insert statement is vulnerable to an SQL injection attack, modify it to be closer to:
$username = $_POST['username'];
$statement = $db.prepare("INSERT INTO myMembers (username) VALUES(':username');
$statement->execute(array(':username' => $username));
You should also ensure that you never store any passwords in plain text, always store a hashed version of a password (along with a salt) and check that the hash matches rather than the actual string. This means that should your database become compromised, figuring out your user's credentials becomes a non-trivial task.
These are only a couple of ways of making your app more secure, I'd highly recommend reading OWASPs top 10 site vulnerabilities and researching these individually as each one in itself is quite a big topic!

How To Determine Whether A User Attempted A SQL Injection Attack

I'm familiar with using mysql_real_escape_string() and the PHP FILTER_SANITIZE function to prevent sql injections.
However, I'm curious as to how I would determine within a PHP script whether or not user input was a likely sql injection attempt? That would be useful for tracking potentially malicious IPs.
If the output of mysql_real_escape_string is different to the input, then the input contained unsafe characters. You could infer that the user might have been attempting an attack, especially if the field in question is one where you'd normally expect a low number of unsafe characters (e.g. a zip code).
But it might also be because their name happened to be Robert'); DROP TABLE Students; --.
So in general, there is no way to do this that's even close to reliable.
Simple answer is you cannot. Just write code that assumes that the serve is going to receive a pounding then you cannot go wrong.
This is a very hard problem to solve, automatically detecting which SQL queries are attacks (or simple mistakes).
There are companies who make products that attempt to do this, like GreenSQL and DB Networks ADF-4200, by applying heuristic tests to see if queries look "suspicious."
But even they rely more on whitelisting the queries that your application runs. The heuristics are known to have both false positives and false negatives. And there are whole categories of queries that neither whitelisting nor heuristics can catch, like calls to stored procedures.
Someone mentioned mod_security too, but this requires a lot of configuration, and then you're back to hand-coding rules for whitelisting your application's legitimate queries.
Just follow good practices like parameterizing and whitelisting, so that user input (or any untrusted content) is never evaluated as code.
Actually there is no certain way !
but it is possible to guess attacks !
simply check for most common usefull sql injection structures
for example scan this words (in case insensitive) in your inputs :
union
select
drop
--
;
if you know how to stop sql injection , you shouldn't be worried and you can run the query safely. but as I understood you want to detect injections , so i prefer you just log suspicious inputs and then decide manually ! in most cases logged queries are real injections.
Test for '--' and ';' strings ... maybe also OR, AND, (, etc. But you can never be 100% sure it WAS an attack.
I would say it's safer to assume that ALL user input is an attack when you write your code and make your program secure enough to mitigate the attack rather than trying to retroactively fix something that may or may not have been an attack.
You can try the following:
If there are no characters to be escaped in the input string, then
it's not an attack attempt.
Put the user input in the query without quoting.
Try to check the query syntax without running it (e.g. make mysql do it for you somehow (?)).
If there is no syntax error, then it was an attack attempt.
But this way you can only detect potentially successful attack attempts, not those which give parse error.
You may search for certain keys (union,delete,drop, ...) and so on. Search for --, \n (new lines) if you are sure that original query would never ever have it. Create a query that always returns some value - if with user malicious input it doesn't that may indicate an attack.
But because users tend to ALWAYS make mistakes or attack servers (number, i will write letters to check how much mess it will make...) all user inputs should be filtered before used.
(joke deleted)
EDIT: You can try the following:
If there are no characters to be escaped in the input string, then
it's not an attack attempt.
Put the user input in the query without quoting.
Try to check the query syntax without running it (e.g. make mysql do it for you somehow (?)).
If there is no syntax error, then it was an attack attempt.
But this way you can only detect potentially successful attack attempts, not those which give parse error.

What's the best, Escape then store Or store then escape the output?

After doing a long search on stackoverflow i didn't find any one talked about this even if it's a big choice, the Question is what's the best in order to prevent both of XSS and SQL injection, Escaping the data then store it in the DB or Store it as it is and escape when output it?
Note: it is better if you give some examples of practics if possible.
Thanks
The data must be properly SQL-escaped (or sent separately from the SQL, as others suggest) for storage, and HTML-escaped for display.
In order, you should do the following -
Validate the input to see if it meets your expectation. If it doesn't, reject the input and stop. If it meets, continue to next step without altering the input.
Bind the input to a parameterized query, or escape the input as you are forming the query. Note that escaping the input does not alter the input. The database will always contain the exact string the user entered.
When displaying to the user, you have to escape it according to the context. There are around 5 distinct ways in which the same string can be escaped - depending on whether you are displaying it in HTML element, HTML attribute, Javascript, CSS, or as a URL. See http://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet. Again, remember that escaping doesn't alter the string. The user must always see the exact string he had entered.
You may be tempted to store a modified string in the database - but please don't do so. If you escape it for HTML, you can never use the string in javascript. If you have to do back-end processing, you'd have to de-escape the string. You will soon reach a stage where you can't do the right thing anymore.
Remember that escaping is just a way to transport data from one layer to another. At rest (database or screen), the data should look exactly the way the user entered it.
Your question doesn't make much sense, because the very act of trying to store data containing an SQL injection is what causes the SQL injection.
Either way, you should be using Parameterized queries to prevent SQL injection.
For XSS/HTML escaping, I'd personally rather do it at insertion-time, because then you only have to do that processing once, instead of every time it's displayed. A small optimization, but an easy one.
Escape input, store, then escape output.
If you store without escaping, you're vulnerable to SQL injection.
Example: You have a query:
mysql_query("SELECT * FROM `table` WHERE `abc`= '{$_POST['def']}';
Let's say that $_POST['def'] is equal to
blah'; DROP TABLE `table`; SELECT * FROM `table` WHERE 'abc' = '123
That will cause your table to be dropped if it's not escaped.
If you output without escaping, you're vulnerable to XSS.
Otherwise, users can inject harmful Javascript into pages other users can view.

Is using a database-level MD5 function a bigger security risk than an application level function?

I've got a chunk of code that validates a user's username and password, which goes something like this:
$sql = "SELECT *
FROM user
WHERE
username='{$_POST['username']}' AND
password=MD5('{SALT}{$_POST['password']}')";
Is this any more/less secure than doing it like this?
$sql = "SELECT *
FROM user
WHERE
username='{$_POST['username']}' AND
password='".md5(SALT.$_POST['password'])."'";
Regardless of where/if escaping is done, is the first method vulnerable to sql injection attacks? Would the answer be the same for other database engines besides MySQL?
You should use prepared statements instead and have a look at this question.
Speaking about injection, both ways are secure, if you properly escape variables.
The first case will be more vulnerable, if you use complete query logging, and so the password will appear as plain text.
Besides, if your system is affected by some virus that works as proxy between your script and database, it'll be able to catch your password.
One last problem that you may encounter (quite rarely, in fact), is when the system is inflicted with a virus, that reads sensible data from memory.
I hope this makes sense.
Oh god, please tell me you're doing some type of mysql_escape_string or mysql_real_escape_string or AT LEAST addslashes or addcslashes to any $_POST variables before you insert them into a raw MySQL statement?
I think the most secure way to do this is to:
a) use filter_var or preg_replace to get rid of extraneous characters from the $_POST['username']
b) SELECT the row by the username from MySQL (also grabbing the digested password)
c) compare the message digested version of the password from the $_POST to that of the retrieved row (assuming you don't leave your password cleartext) in your application code, not in the SQL statement
If you do it this way, there's only 1 possible place for injection (username), and it's pretty impossible when you're doing a preg_replace( '/\W/', '', $_POST['username'] ) which removes anything not A-Za-z0-9_- (or change to your username whitelist of characters).
However, if you're doing rock-solid proper sanitization, it really doesn't matter where you do your comparison. Theoretically, though, I'd allow for the least possible interaction with user input and raw SQL statements (i.e. only SELECTing by username and comparing outside of your DB).
To start off with MD5 is prevent to be an insecure algorithm and should never be used for passwords. You should use a staled sha256 and most databases do not have this function call. But even if the database did I think its a bad idea. Not a very bad idea, but its best to keep as few copies of your password around. Often the database can be on a completely different machine, and if that machine where compromised then the attacker could obtain clear text passwords by looking at the quires. In terms of SQL Injection, there is no difference in security and judging by your queries you should be more worried about SQL injection.
Regardless of where/if escaping is done, is the first method vulnerable to sql injection attacks?
SQL injection will not occur if proper escaping and sanitizing takes place
Would the answer be the same for other database engines besides MySQL?
I think you should look more at the expense taken to perform one action over another. The first method would take less time to execute than the second method, ceteris paribus.

Is SQL injection a risk today?

I've been reading about SQL injection attacks and how to avoid them, although I can never seem to make the "awful" examples given work, e.g. see this post.
I created a PHP file and a table in the database, had a value passed through $_GET and tried to delete the table by doing bob'); drop table students; -- and it didn't work. PHP automatically escapes the \' and the query has an error, no harm done. Same issue when trying to replicate login "attacks" like AND WHERE 1=1 etc.
example code:
<?php
$id = $_GET['id'];
$sql = "INSERT INTO Users (Username) VALUES ($id)";
echo $sql;
mysql_query($sql) or die(mysql_error());
And I'd pass sql.php?id=1); delete from Users; --
So is this some dated thing that used to apply in the days of PHP3 or something, and nowadays even novices are protected from things like magic quotes?
I'm using PHP5 on Ubuntu.
Quite the contrary. Magic quotes are deprecated in PHP5 and will be completely removed in PHP 5.4, as they brought more confusion to the programming world than they did good. Checking whether magic quotes are active, and escaping any SQL input scrupulously if necessary, is still very, very important... No reason to feel bad though, we've all been there, and my unknowing ass has been saved by magic quotes countless times :)
The PHP manual on magic quotes explains everything.
No this is still very relevant.
As are XSS and CSRF. Never underestimate the importance of proper input filtering.
Heh, you're saved in this case by having magic_quotes_gpc set to "on".
You'll be screwed soon.
The largest identity-theft in history was achieved in 2007 by exploiting an SQL injection vulnerability: see "SQL injection attacks led to Heartland, Hannaford breaches" (ComputerWorld, 8/18/2009).
OWASP reported in 2007 that injection attacks (of which SQL injection is one example) continue to be one of the most common software security problems.
You can also search for recent SQL injection News and find many cases reported every month.
However, the example in the XKCD cartoon isn't necessarily the most common type of exploit. Dropping a table by executing a second SQL statement in one request probably wouldn't gain the attacker much in the way of valuable data, it would just be vandalism.
Also, some query interfaces disallow multi-query by default anyway. That is, the database client API executes only a single statement given the SQL string, regardless of semicolons. This defeats the example shown in the cartoon.
note: PDO's query() method is known to support multi-query by default. So it is susceptible to the XKCD-style attack.
As other folks have pointed out, the more likely risk is that an SQL injection will alter the logic of SQL expressions, and apply your query to extra rows besides those you intended.
For example:
$sql = "UPDATE Users SET PASSWORD = MD5('" . $_POST["password"] . "'||salt) " .
"WHERE user_id = " . $_POST["userid"];
What happens when I send a request with parameter userid set to the string 123 OR userid=456? I would reset my own password (userid 123) as well as the password of userid 456. Even hashing the password with a per-user salt wouldn't protect against this. Now I can log into either account.
There are lots of ways SQL injection can be perpetrated.
Magic quotes don't take character encoding into account, and thus are vulnerable to attacks based on multi-byte characters.
As for it being a risk today, Google searches turn up countless vulnerable sites. An SQL Injection vulnerability was reported for Bugzilla around September 10. So, yes, sites are still at risk. Should they be? The tools are there to prevent injection, so no.
That particular attack doesn't work, as mysql_query will only execute a single statement.
I can still abuse your code though, e.g. if I arranged for id to be SELECT password FROM Users WHERE Username='admin' I might have a fighting chance of being able to get your system to expose some internal information.
Basically, if you allow unfiltered input into your SQL, there will be some very creative ways of both creating data you didn't expect, and exposing data you didn't intend!
Oh my.. SQL Injection is not a risk, it is a gaping security hole. It mainly exists in php because the API makes you want to interpolate any old data into your SQL queries.
When I see a site written in PHP or ASP, I can just smell the SQL injection vectors that they reek of. People try to secure their PHP apps with mysql_real_escape_string() and intval() and do similarly in other languages. This is a mistake. It's like coding in C instead of Java or Python, where in the former, you make one mistake and you're dead, but in the latter, only semantic flaws can exist.
I strongly urge people to use either mysqli with prepared statements, or anything else that is parameterized, substituting text into code and then interpreting it is just bad practice in the first place IMHO.
On another note, PHP's magic quotes is just silly, and thankfully, deprecated. It can only cause more harm than good. If you rely on magic quotes, it means your app will be owned when magic quotes is disabled. Similarly, it may break other apps that don't expect escaped strings in inputs.
This is very much an active risk, magic quotes tries to give you a solution but I prefer to always develop with magic quotes off. This way I have to make sure I actually escape the inputs myself. Who knows if magic quotes will be on or off on the server where the script is actually deployed.
This is still a big problem. You can't assume that magic_quotes is turned on in every PHP installation you might use.
To see if magic qotes is turned on and clear out the mess from magic quotes:
if ( get_magic_quotes_gpc() !== 0 ) { $foo = stripslashes( $foo ); }
Then cleaning your statements a little:
$foo = mysql_real_escape_string( $foo );
$sql = "select * from foo where bar='{$foo}'";
etc.
In fact, you're better off just strictly turning of magic_quotes if you have the ability to do so.
I hope that helps you.
The bobby tables example will not work with the mysql interface because it doesn't do multiple queries in one call. The mysqli interface is vulnerable to the multiple query attack. The mysql interface is more vulnerable to the privilege boost attack:
In your form I type account: admin password: ' or 1=1 -- so that your typical login sql: select * from users where user_name = '$admin' and password = '$password'. The or causes this to be true and let's you log in.
Can't PHP do query parameters? If it can (as I'd be surprised if it didn't), that is the one solution which mitigates ALL SQL injection attacks.
As I've mentioned several times on stackoverflow before, I am a strong supporter of PDO, just stop using the old fashioned mysql, do yourself and your clients a big favor and learn PDO (it's really easy) and take advantage of prepared statements and bound parameters. Even if you do not need prepared statements performance wise, you still get the security benefits.
Also, I will recommend crashing your entire app in the clients face if magic quotes is set to on. It's just a drain on resources designed to protect the dumb and annoy the smart. (it uses more cpu than escaping manually, because it encodes everything, even when you don't need it)
There are a lot of different ways to perform a SQL Injection and quite a lot of ways to bypass basic safety precautions.
Those attacks have been within the top 10 web application vulnerabilities (rank #2) according to OWASP.
For more information, please refer to Top 10 2007-Injection Flaws.
No, and the less you worry about SQL Injection, the more likely you are to get hit by it.
Parameters passed to sql queries from the web pages ofen tend to be numeric IDs. For example let's assume you have an url http://foo.com/page.php?section=34 from which the section ID is used in a query like this:
SELECT content FROM sections WHERE section_id=$section;
No quotes to escape like in your example and whatever you'll put after the number in the URL will be passed to the query... So thew risk is real.
The simplest rule of thumb is to assume that all user input can be tainted. Check that data types are what you expect, variables are in the length/size ranges you were expecting, files are of the size and types you allow, etc. Other checks on non-external data can be warranted - before you call some important admin-level function, do a check - ($userlevel != ADMIN)?die():important_function();
There's always a bigger fish, or somebody who's a bigger jerk than you. Avoid assumptions about data and you've got a head start.
Not today yet, but it's only 20:34 UTC
Guardian jobs database attack demonstrates difficulties of database security, 06 Nov 2009
Guardian Jobs website hack may have been an SQL injection and not a 'sophisticated' attack, 27 Oct 2009
Whenever building up SQL from strings, SQL injection is a real danger.
I have also discovered that trying to avoid building up SQL from strings is a pointless endeavor. Sooner or later the full form of your SQL (not just things that could be parameters) must be generated at runtime.
I've have to develop for a server which has no way for me to disable magic_quotes! I include this on every page to undo the effects of magic quotes, so I can do proper escaping myself without \'double escaping\'. Even though I can taste vomit just from reading this, I haven't found a better solution.
if (get_magic_quotes_gpc()) {
$process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
while (list($key, $val) = each($process)) {
foreach ($val as $k => $v) {
unset($process[$key][$k]);
if (is_array($v)) {
$process[$key][stripslashes($k)] = $v;
$process[] = &$process[$key][stripslashes($k)];
} else {
$process[$key][stripslashes($k)] = stripslashes($v);
}
}
}
unset($process);
}
As per OWASP 2017 Top 10, still Injection is the most happened and dangerous attack.
"SQL injection is always the number one risk. That is a reflection of just how many incidents are out there, as well as other factors that keep it very high up there" Troy Hunt - founder of breach site haveibeenpwned.com
Just to remember, using SQL injection we can dump entire database, controlling web server by uploading web shell, etc.

Categories