I have pages that only display data from DB tables, the php pages only display the information they don't have any buttons, links, drop down menus, or forms.
Im using the old mysql and not the mysqli or PDO for syntax
Can I still get a SQl injection hack?
In order for SQL Injection to work, they need a way to send SQL Code to your server, as there is no input, it is in theory impossible for them to Inject SQL. (Although I am not an expert in the subject)
I would still recommend you to use a framework like mysqli or PDO, you should familiarize yourself with such frameworks as they became the norm in website design.
SQL Injection works by injecting strings into the SQL you're executing.
This is easiest if the application presents you with a nice text box whose content it glues into a SQL query, but it's also possible through other means.
For instance, if your reporting application uses any kind of the HTTP request to show data, an attacker can use WGET to spoof the request and inject SQL. For instance, if your reports have a URL format of http://myserver/report.php?month=february and you use february to build a SQL query, you're vulnerable.
It all depends on the query source. If ANY part of your SQL query comes from a user input (in other words; if not your whole query string is a string constant) then you are not safe.
For example:
SELECT * FROM USERS ;
SELECT * FROM myTable WHERE id = 5;
is safe but
SELECT * FROM myTable WHERE id = (some variable derived from user input like querystring or post-form)
is DEFINETELY not.
You should use
SELECT * FROM myTable WHERE id = #0
syntax for maximum security. This is the only one proven way to keep safe from SQL injection.
If the query is independent of the request you are safe. Be warned that mean users are very creative. You might have some dependency on user data which you are not aware of. E.g. a script like this might be broken:
$locale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
$sql = "SELECT * FROM entities WHERE id = 7 and locale = '$locale'";
Disclaimer: I'm not aware if Locale::acceptFromHttp() does some validation. Let's just assume for the context of this post it doesn't.
I don't want to say it's not possible to write safe code without prepared statements. OTOH it really doesn't hurt using them.
SQL injection occurs if user-controllable data is used in an SQL statement without proper processing:
The software constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component.
Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
Note that user-controllable data include any data that can be influenced by the request of a user, directly or indirectly.
Conversely, this means if your SQL queries don’t contain any user-controllable data, i. e., the queries are fixed in code and are not influenced by any changeable input, it cannot vulnerable to SQL injections.
I have pages that only display data from DB tables, the php pages only display the information they don't have any buttons, links, drop down menus, or forms.
I would dare to say that such a setup is just impossible.
The very idea of having a dynamical web-page, served by a php script from database, is to use the same script to show different content from database.
So - either you indeed have only set of static pages (which I doubt) - you need no PHP/database for them then - just static HTML would be enough.
Or - most likely - you have dynamical pages showing content based on user input of some sort - and thus perfectly vulnerable.
Related
I understand that you should NEVER trust user input from a form, mainly due to the chance of SQL injection.
However, does this also apply to a form where the only input is from a dropdown(s) (see below)?
I'm saving the $_POST['size'] to a Session which is then used throughout the site to query the various databases (with a mysqli Select query) and any SQL injection would definitely harm (possibly drop) them.
There is no area for typed user input to query the databases, only dropdown(s).
<form action="welcome.php" method="post">
<select name="size">
<option value="All">Select Size</option>
<option value="Large">Large</option>
<option value="Medium">Medium</option>
<option value="Small">Small</option>
</select>
<input type="submit">
</form>
Yes you need to protect against this.
Let me show you why, using Firefox's developer console:
If you don't cleanse this data, your database will be destroyed. (This might not be a totally valid SQL statement, but I hope I've gotten my point across.)
Just because you've limited what options are available in your dropdown does not mean you've limited the data I can send your server.
If you tried to restrict this further using behaviour on your page, my options include disabling that behaviour, or just writing a custom HTTP request to your server which imitates this form submission anyway. There's a tool called curl used for exactly that, and I think the command to submit this SQL injection anyway would look something like this:
curl --data "size=%27%29%3B%20DROP%20TABLE%20*%3B%20--" http://www.example.com/profile/save
(This might not be a totally valid curl command, but again, I hope I've gotten my point across.)
So, I'll reiterate:
NEVER trust user input. ALWAYS protect yourself.
Don't assume any user input is ever safe. It's potentially unsafe even if it arrives through some means other than a form. None of it is ever trustworthy enough to forgo protecting yourself from SQL injection.
You could do something as simple as the following example to make sure the posted size is what you expect.
$possibleOptions = array('All', 'Large', 'Medium', 'Small');
if(in_array($_POST['size'], $possibleOptions)) {
// Expected
} else {
// Not Expected
}
Then use mysqli_* if you are using a version of php >= 5.3.0 which you should be, to save your result. If used correctly this will help with sql injection.
As this question was tagged with sql-injection, here is an answer regarding this particular kind of attack:
As you've been told in the comments, you have to use prepared statements for the every single query involving any variable data, with no exceptions.
Regardless of any HTML stuff!
It is essential to understand that SQL queries have to be formatted properly regardless of any external factors, be it HTML input or anything else.
Although you can use white-listing suggested in other answers for the input validation purpose, it shouldn't affect any SQL-related actions - they have to remain the same, no matter if you validated HTML input or not. It means you still have to use prepared statements when adding any variables into the query.
Here you may find a thorough explanation, why prepared statements is a must and how to properly use them and where they aren't applicable and what to do in such case: The Hitchhiker's Guide to SQL Injection protection
Also, this question was tagged with mysqli. Mostly by accident, I presume, but anyway, I have to warn you that raw mysqli is not an adequate substitution for the old mysq_* functions. Simply because if used in the old style, it will add no security at all. While it's support for the prepared statements is painful and troublesome, to the point that average PHP user is just unable to endeavor them at all. Thus, if no ORM or some sort of abstraction library is option, then PDO is your only choice.
Yes.
Anyone can spoof anything for the values that actually get sent --
SO, for validating dropdown menus, you can just check to make sure that the value that you're working with was in the dropdown - something like this would be the best(most sanely paranoid) way:
if(in_array($_POST['ddMenu'], $dropDownValues){
$valueYouUseLaterInPDO = $dropDownValues[array_search("two", $arr)];
} else {
die("effin h4x0rs! Keep off my LAMP!!");
}
One way of protecting against users changing your drop downs using the console is to only use integer values in them. Then you can validate that the POST value contains an integer, and use an array to convert that to text when needed. E.g:
<?php
// No, you don't need to specify the numbers in the array but as we're using them I always find having them visually there helpful.
$sizes = array(0 => 'All', 1 => 'Large', 2 => 'Medium', 3 => 'Small');
$size = filter_input(INPUT_POST, "size", FILTER_VALIDATE_INT);
echo '<select name="size">';
foreach($sizes as $i => $s) {
echo '<option value="' . $i . '"' . ($i == $size ? ' selected' : '') . '>' . $s . '</option>';
}
echo '</select>';
Then you can use $size in your query with knowledge that it will only ever contain FALSE or an integer.
The other answers already cover what you need to know. But maybe it helps to clarify some more:
There are TWO THINGS you need to do:
1. Validate form data.
As Jonathan Hobbs' answer shows very clearly, the choice of html element for the form input does not do any reliable filtering for you.
Validation is usually done in a way that does not alter the data, but that shows the form again, with the fields marked as "Please correct this".
Most frameworks and CMSes have form builders that help you with this task. And not just that, they also help against CSRF (or "XSRF"), which is another form of attack.
2. Sanitize/Escape variables in SQL statements..
.. or let prepared statements do the job for you.
If you build a (My)SQL statement with any variables, user-provided or not, you need to escape and quote these variables.
Generally, any such variable you insert into a MySQL statement should be either a string, or something that PHP can be reliably turn into a string that MySQL can digest. Such as, numbers.
For strings, you then need to choose one of several methods to escape the string, that means, replace any characters that would have side effects in MySQL.
In old-school MySQL + PHP, mysql_real_escape_string() does the job. The problem is that it is far too easy to forget, so you should absolutely use prepared statements or query builders.
In MySQLi, you can use prepared statements.
Most frameworks and CMSes provide query builders that help you with this task.
If you are dealing with a number, you could omit the escaping and the quotes (this is why the prepared statements allow to specify a type).
It is important to point out that you escape the variables for the SQL statement, and NOT for the database itself. The database will store the original string, but the statement needs an escaped version.
What happens if you omit one of these?
If you don't use form validation, but you do sanitize your SQL input, you might see all kinds of bad stuff happening, but you won't see SQL injection! (*)
First, it can take your application into a state you did not plan for. E.g. if you want to calculate the average age of all users, but one user gave "aljkdfaqer" for the age, your calculation will fail.
Secondly, there can be all kinds of other injection attacks you need to consider: E.g. the user input could contain javascript or other stuff.
There can still be problems with the database: E.g. if a field (database table column) is limited to 255 characters, and the string is longer than that. Or if the field only accepts numbers, and you attempt to save a non-numeric string instead. But this is not "injection", it is just "crashing the application".
But, even if you have a free text field where you allow any input with no validation at all, you could still save this to the database just like that, if you properly escape it when it goes to a database statement. The problem comes when you want to use this string somewhere.
(*) or this would be something really exotic.
If you don't escape variables for SQL statements, but you did validate form input, then you can still see bad stuff happening.
First, you risk that when you save data to the database and load it again, it won't be the same data anymore, "lost in translation".
Secondly, it can result in invalid SQL statements, and thus crash your application. E.g. if any variable contains a quote or double quote character, depending which type of quote you use, you will get invalid MySQL statement.
Thirdly, it can still cause SQL injection.
If your user input from forms is already filtered / validated, intentional SQl injection may become less likely, IF your input is reduced to a hardcoded list of options, or if it is restricted to numbers. But any free text input can be used for SQL injection, if you don't properly escape the variables in SQL statements.
And even if you have no form input at all, you could still have strings from all kinds of sources: Read from the filesystem, scraped from the internet, etc. Noone can guarantee that these strings are safe.
Your web browser does not "know" that it is receiving a page from php, all it sees is html. And the http layer knows even less than that. You need to be able to handle nearly any kind of input that can cross the http layer (luckily for most input php will already give an error).
If you are trying to prevent malicious requests from messing up your db, then you need to assume that the guy on the other end knows what he is doing, and that he is not limited to what you can see in your browser under normal circumstances (not to mention what you can fiddle with a browser's developer tools).
So yes, you need to cater for any input from your dropdown, but for most input you can give an error.
The fact that you have restricted the user to only using values from a certain drop-down list is irrelevant. A technical user can capture the http request sent to your server before it leaves their network, alter it using a tool such as a local proxy server, and then continue it on it's way. Using the altered request, they can send parameter values that are not ones that you have specified in the drop down list. Developers have to have the mindset that client restrictions are often meaningless, as anything on a client can be altered. Server validation is required at every single point that client data enters. Attackers rely on the naivety of developers in this sole aspect.
It's best to use a parameterized query in order to ensure against SQL injection. In that case the look of the query would be this:
SELECT * FROM table WHERE size = ?
When you supply a query like the above with text that is unverified for integrity (the input isn't validated on the server) and it contains SQL injection code it will be handled correctly. In other words, the request will result in something like this happening in the database layer:
SELECT * FROM table WHERE size = 'DROP table;'
This will simply select 0 results as it returns which will make the query ineffective in actually causing harm to the database without the need for a whitelist, a verification check or other techniques. Please note that a responsible programmer will do security in layers, and will often validate in addition to parameterizing queries. However, there is very little cause to not parameterize your queries from a performance perspective and the security added by this practice is a good reason to familiarize yourself with parameterized queries.
Whatever is submitted from your form comes to your server as text across the wires. There is nothing stopping anyone from creating a bot to mimic the client or type it in from a terminal if they wanted to. Never assume that because you programmed the client it will act like you think it will. This is really easy to spoof.
Example of what can and will happen when you trust the client.
A hacker can bypass the browser completely, including Javascript form checking, by sending a request using Telnet. Of course, he will look at the code of your html page to get the field names he has to use, but from then on it's 'everything goes' for him. So, you must check all values submitted on the server as if they did not originate from your html page.
I understand that you should NEVER trust user input from a form, mainly due to the chance of SQL injection.
However, does this also apply to a form where the only input is from a dropdown(s) (see below)?
I'm saving the $_POST['size'] to a Session which is then used throughout the site to query the various databases (with a mysqli Select query) and any SQL injection would definitely harm (possibly drop) them.
There is no area for typed user input to query the databases, only dropdown(s).
<form action="welcome.php" method="post">
<select name="size">
<option value="All">Select Size</option>
<option value="Large">Large</option>
<option value="Medium">Medium</option>
<option value="Small">Small</option>
</select>
<input type="submit">
</form>
Yes you need to protect against this.
Let me show you why, using Firefox's developer console:
If you don't cleanse this data, your database will be destroyed. (This might not be a totally valid SQL statement, but I hope I've gotten my point across.)
Just because you've limited what options are available in your dropdown does not mean you've limited the data I can send your server.
If you tried to restrict this further using behaviour on your page, my options include disabling that behaviour, or just writing a custom HTTP request to your server which imitates this form submission anyway. There's a tool called curl used for exactly that, and I think the command to submit this SQL injection anyway would look something like this:
curl --data "size=%27%29%3B%20DROP%20TABLE%20*%3B%20--" http://www.example.com/profile/save
(This might not be a totally valid curl command, but again, I hope I've gotten my point across.)
So, I'll reiterate:
NEVER trust user input. ALWAYS protect yourself.
Don't assume any user input is ever safe. It's potentially unsafe even if it arrives through some means other than a form. None of it is ever trustworthy enough to forgo protecting yourself from SQL injection.
You could do something as simple as the following example to make sure the posted size is what you expect.
$possibleOptions = array('All', 'Large', 'Medium', 'Small');
if(in_array($_POST['size'], $possibleOptions)) {
// Expected
} else {
// Not Expected
}
Then use mysqli_* if you are using a version of php >= 5.3.0 which you should be, to save your result. If used correctly this will help with sql injection.
As this question was tagged with sql-injection, here is an answer regarding this particular kind of attack:
As you've been told in the comments, you have to use prepared statements for the every single query involving any variable data, with no exceptions.
Regardless of any HTML stuff!
It is essential to understand that SQL queries have to be formatted properly regardless of any external factors, be it HTML input or anything else.
Although you can use white-listing suggested in other answers for the input validation purpose, it shouldn't affect any SQL-related actions - they have to remain the same, no matter if you validated HTML input or not. It means you still have to use prepared statements when adding any variables into the query.
Here you may find a thorough explanation, why prepared statements is a must and how to properly use them and where they aren't applicable and what to do in such case: The Hitchhiker's Guide to SQL Injection protection
Also, this question was tagged with mysqli. Mostly by accident, I presume, but anyway, I have to warn you that raw mysqli is not an adequate substitution for the old mysq_* functions. Simply because if used in the old style, it will add no security at all. While it's support for the prepared statements is painful and troublesome, to the point that average PHP user is just unable to endeavor them at all. Thus, if no ORM or some sort of abstraction library is option, then PDO is your only choice.
Yes.
Anyone can spoof anything for the values that actually get sent --
SO, for validating dropdown menus, you can just check to make sure that the value that you're working with was in the dropdown - something like this would be the best(most sanely paranoid) way:
if(in_array($_POST['ddMenu'], $dropDownValues){
$valueYouUseLaterInPDO = $dropDownValues[array_search("two", $arr)];
} else {
die("effin h4x0rs! Keep off my LAMP!!");
}
One way of protecting against users changing your drop downs using the console is to only use integer values in them. Then you can validate that the POST value contains an integer, and use an array to convert that to text when needed. E.g:
<?php
// No, you don't need to specify the numbers in the array but as we're using them I always find having them visually there helpful.
$sizes = array(0 => 'All', 1 => 'Large', 2 => 'Medium', 3 => 'Small');
$size = filter_input(INPUT_POST, "size", FILTER_VALIDATE_INT);
echo '<select name="size">';
foreach($sizes as $i => $s) {
echo '<option value="' . $i . '"' . ($i == $size ? ' selected' : '') . '>' . $s . '</option>';
}
echo '</select>';
Then you can use $size in your query with knowledge that it will only ever contain FALSE or an integer.
The other answers already cover what you need to know. But maybe it helps to clarify some more:
There are TWO THINGS you need to do:
1. Validate form data.
As Jonathan Hobbs' answer shows very clearly, the choice of html element for the form input does not do any reliable filtering for you.
Validation is usually done in a way that does not alter the data, but that shows the form again, with the fields marked as "Please correct this".
Most frameworks and CMSes have form builders that help you with this task. And not just that, they also help against CSRF (or "XSRF"), which is another form of attack.
2. Sanitize/Escape variables in SQL statements..
.. or let prepared statements do the job for you.
If you build a (My)SQL statement with any variables, user-provided or not, you need to escape and quote these variables.
Generally, any such variable you insert into a MySQL statement should be either a string, or something that PHP can be reliably turn into a string that MySQL can digest. Such as, numbers.
For strings, you then need to choose one of several methods to escape the string, that means, replace any characters that would have side effects in MySQL.
In old-school MySQL + PHP, mysql_real_escape_string() does the job. The problem is that it is far too easy to forget, so you should absolutely use prepared statements or query builders.
In MySQLi, you can use prepared statements.
Most frameworks and CMSes provide query builders that help you with this task.
If you are dealing with a number, you could omit the escaping and the quotes (this is why the prepared statements allow to specify a type).
It is important to point out that you escape the variables for the SQL statement, and NOT for the database itself. The database will store the original string, but the statement needs an escaped version.
What happens if you omit one of these?
If you don't use form validation, but you do sanitize your SQL input, you might see all kinds of bad stuff happening, but you won't see SQL injection! (*)
First, it can take your application into a state you did not plan for. E.g. if you want to calculate the average age of all users, but one user gave "aljkdfaqer" for the age, your calculation will fail.
Secondly, there can be all kinds of other injection attacks you need to consider: E.g. the user input could contain javascript or other stuff.
There can still be problems with the database: E.g. if a field (database table column) is limited to 255 characters, and the string is longer than that. Or if the field only accepts numbers, and you attempt to save a non-numeric string instead. But this is not "injection", it is just "crashing the application".
But, even if you have a free text field where you allow any input with no validation at all, you could still save this to the database just like that, if you properly escape it when it goes to a database statement. The problem comes when you want to use this string somewhere.
(*) or this would be something really exotic.
If you don't escape variables for SQL statements, but you did validate form input, then you can still see bad stuff happening.
First, you risk that when you save data to the database and load it again, it won't be the same data anymore, "lost in translation".
Secondly, it can result in invalid SQL statements, and thus crash your application. E.g. if any variable contains a quote or double quote character, depending which type of quote you use, you will get invalid MySQL statement.
Thirdly, it can still cause SQL injection.
If your user input from forms is already filtered / validated, intentional SQl injection may become less likely, IF your input is reduced to a hardcoded list of options, or if it is restricted to numbers. But any free text input can be used for SQL injection, if you don't properly escape the variables in SQL statements.
And even if you have no form input at all, you could still have strings from all kinds of sources: Read from the filesystem, scraped from the internet, etc. Noone can guarantee that these strings are safe.
Your web browser does not "know" that it is receiving a page from php, all it sees is html. And the http layer knows even less than that. You need to be able to handle nearly any kind of input that can cross the http layer (luckily for most input php will already give an error).
If you are trying to prevent malicious requests from messing up your db, then you need to assume that the guy on the other end knows what he is doing, and that he is not limited to what you can see in your browser under normal circumstances (not to mention what you can fiddle with a browser's developer tools).
So yes, you need to cater for any input from your dropdown, but for most input you can give an error.
The fact that you have restricted the user to only using values from a certain drop-down list is irrelevant. A technical user can capture the http request sent to your server before it leaves their network, alter it using a tool such as a local proxy server, and then continue it on it's way. Using the altered request, they can send parameter values that are not ones that you have specified in the drop down list. Developers have to have the mindset that client restrictions are often meaningless, as anything on a client can be altered. Server validation is required at every single point that client data enters. Attackers rely on the naivety of developers in this sole aspect.
It's best to use a parameterized query in order to ensure against SQL injection. In that case the look of the query would be this:
SELECT * FROM table WHERE size = ?
When you supply a query like the above with text that is unverified for integrity (the input isn't validated on the server) and it contains SQL injection code it will be handled correctly. In other words, the request will result in something like this happening in the database layer:
SELECT * FROM table WHERE size = 'DROP table;'
This will simply select 0 results as it returns which will make the query ineffective in actually causing harm to the database without the need for a whitelist, a verification check or other techniques. Please note that a responsible programmer will do security in layers, and will often validate in addition to parameterizing queries. However, there is very little cause to not parameterize your queries from a performance perspective and the security added by this practice is a good reason to familiarize yourself with parameterized queries.
Whatever is submitted from your form comes to your server as text across the wires. There is nothing stopping anyone from creating a bot to mimic the client or type it in from a terminal if they wanted to. Never assume that because you programmed the client it will act like you think it will. This is really easy to spoof.
Example of what can and will happen when you trust the client.
A hacker can bypass the browser completely, including Javascript form checking, by sending a request using Telnet. Of course, he will look at the code of your html page to get the field names he has to use, but from then on it's 'everything goes' for him. So, you must check all values submitted on the server as if they did not originate from your html page.
This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 3 years ago.
I'm working on a site that has been hacked through SQL Injection (at first glance only db entries are corrupted with cross-site scripting) the potential vulnerability I found after looking at the code is that there's a lot of mysql_query call whose inputs are not escaped at all.
The good old :
$query = "SELECT * FROM mytable where name LIKE '%".$_GET['name']."%'"; /*HACK HERE*/
mysql_query($query, $connection);
Nevertheless I can't find how can we do something cool from that injection vulnerability (by cool I mean something like an INSERT or an UPDATE). I've tried to build a statement like this one :
SELECT * FROM mytable where name LIKE '%' AND WHERE id IN (INSERT INTO secondtable (id,description) VALUES (15, 'Fifteenth description');--%'
No success. I guess that the INSERT has nothing to do here.
I'm escaping all user's inputs in the code right now but I've not really get how hackers have penetrated this site, then I'm not 100% sure that my fix will do the job. Any brilliant suggestions ?
Thanks
Depending upon the version of mysql you are using, and the setup of the connection, mysql_query may allow more than one statement.
You should look at how the connection is being created, and for any usage of mysql_set_server_option.
Because mysql_query is not supporting multiple queries, So any injection that is doing like '; DROP TABLE mytable; -- won't be successful.
However, the attacker can combine with other select statement to select the other info like password info.
Interesting that your question hasn't received many (correct) answers yet!
As you discovered, usual PHP MySQL APIs like mysql_query, mysqli::query etc. only execute the first SQL statement in case one passes several of them (separated by semicolons), as would an attacker using the most common class of SQL injections.
Defender tip: banish mysqli::multi_query and friends from your code; the minute performance improvements are not worth the risk.
Does this clever move by PHP-folk completely close all attack channels on some code that goes like "SELECT yadda yadda" . $_GET["untrusted"]? Not quite. As knittl remarks, even a pure-DQL SELECT can be used to escalate one's privileges by UNION ALL SELECT'ing from any nearby interesting table, including but not limited to the passwords table. There are cheat sheets out there giving enough tips and tricks to basically extract the entire database this way.
Defender tip: apply defense-in-depth with known-good techniques:
input validation
whitelist indirection in an associative array
prepared statements (if you can make sure that they are effective and not just string escaping in disguise!)
an ORM
protective encoding (e.g. Base64) when the untrusted input cannot be satisfactorily sanitized (e.g. a blog post that may legitimately contain SQL-sensitive punctuation)
or as a last resort only, string escaping
Next, one may observe that not all DQL is side-effect free, in particular when it ends with INTO DUMPFILE somethingsomething.
Defender tip: always configure secure_file_priv in your MySQL / MariaDB server.
Last but not least, even an attacker who is in a position to inject arbitrary SQL is limited by the authority granted to the Web app as a whole.
Defender tip: secure your app by applying POLA.
Only GRANT the Web app's MySQL user as much authority as it needs. It is not a bad idea to design your app so that it requires no DDL at all. If you must provide a “back up / restore DB” feature or some such from the Web UI, use a separate MySQL user for that.
Automate backups, even though they are useless — restores are what matters.
Possible scenario 1
Weak passwords/hashing will let an attacker to select administrator's password.
It would be wise to change all administrators passwords.
Now, it's been a while since did any php, but in general most data access libs have some sort of parameterized sql to reduce the risk. A quick google came up with this for php:
http://php.net/manual/en/pdo.prepared-statements.php
The other poster have already described how to do a sql injection so I won't get into that.
I'm pretty sure that a hacker would be able to modify the query easily. Even if mysql_query() doesn't support multiple queries, there are ways around that. you could just use a mysql IF statement added on to the end, and of course that will execute a completely new query.
$query = "SELECT * FROM mytable where name LIKE '%".$_GET['name']."%'";
$_GET['name']="'; DROP TABLE mytable; -- ";
so
$query = "SELECT * FROM mytable where name LIKE '%'; DROP TABLE mytable; -- %'";
I read a lot about filtering data which my web site get from user to make web site secure in sql injenction and xss . . .
but I saw a lot function in php so I can't make decide what to do . . .
please help me make it more secure
You're asking a couple questions here, so I'll try to break it down:
SQL Injection
Problem
This can occur when you pass user input directly to the database, something like this:
$query = "SELECT * FROM Table WHERE field = " . $_POST['field'];
$result = mysql_query($query);
The user can put whatever they want into the 'field' field on the form, and the database will execute it. This means a user could enter a malicious string which prematurely terminates your intended query and then runs a query of their own.
Solution
Don't directly construct your queries with user input. Instead, you should look into using prepared statements (This is typically handled with the PDO library). Prepared statements can take several forms, but they all involve using placeholders in the actual query string to tell the database where to stick other data you'll pass in later. That way the database can handle any appropriate escaping itself. The code would look a bit like this:
$statement = $db->prepare("SELECT * FROM Table WHERE field = :field");
$statement->bindValue(":field", $_GET['field']);
$statement->execute();
In this case, :field indicates the placeholder for the value later supplied by bindValue. PDO will take care of the escaping as needed.
That said, you should still sanitize any user data as needed.
XSS
Problem
Cross-Site Scripting, or XSS, occurs when unsanitized user input is passed directly back to the browser. If the user entered JavaScript commands, these commands could be executed in another users browser, possibly allowing the original hacker to gain access to that users credentials.
Solution
Rather than going into a lot of detail here, I'll simply say that this can be avoided by setting the HttpOnly flag on any cookies you set, so that they cannot be accessed in JavaScript (malicious or otherwise), and by never, ever echoing back unsanitized inputs to a user.
Sanitizing User Inputs
PHP has some nice features built in for sanitizing many forms of user input. I'll simply recommend that you check out the filter_var function and the various filters it can apply.
Never just echo user input back to the user. You should do your best to validate your inputs and reject anything that doesn't conform, but for inputs you need to display back to the user, always use something like htmlentities(). For a heavier but much more thorough option, you can take a look at the HTML Purifier library.
Hope that gets you started in the right direction.
Most SQL injections can be prevented with mysql_real_escape_string(), assuming you're running MySQL. Other database systems also have similar functions.
Protecting your site from XSS attacks is more complicated. The simplest way to prevent javascript code injection is stripping away all HTML tags with strip_tags(), but that will prevent using harmless tags like <b> as well, though they can be whitelisted if needed.
The only generic advice I can give you is to learn:
Prepared statements to avoid SQL injections
A custom markup languages like StackOverflow is using to avoid XSS attacks
I have a php file at my site, and I connect to db, get some records and list them in same file.
mysql_connect("localhost", "blabla", "blabla") or die(mysql_error());
mysql_select_db("blabla") or die(mysql_error());
$blabla1 = mysql_query("SELECT * FROM gallery WHERE id_cat=1");
$blabla2 = mysql_query("SELECT * FROM gallery WHERE id_cat=2");
$blabla3 = mysql_query("SELECT * FROM gallery WHERE id_cat=3");
So, is there anything I need to do for security? Like sql-injection or anything else. there is nothing going to url. It is just www.blabla.com/gallery.php.
This snippet is perfectly safe, because there are no variables put into the query string.
To work safely in case you have to deal with variables one day - be they directly coming in from the user, or from another data source - you may want to switch over to a mySQL library that supports parametrized queries, like PDO. Those eliminate the danger of injections completely, because they take care of escaping the incoming data automatically.
If you stick with the mysql_* functions, make sure you escape all incoming any data using mysql_real_escape_string() and ensure they are inserted within a pair of single quotes.
As long as your queries don't use parameters, SQL Injection is not a risk.
SQL Injection can only happen when the users (or other sources) can influence anything that is send to the database in SQL, for example searchwords
There are no security issues here. SQL injection might happen where you get input from the user and use it in your queries.
if gallery table contain some user input, then some XSS attack may be conducted. To prevent this, all untrusted user input must be prepared using htmlspecialchars() function before printing to the browser.
This snippet is safe, as there is no user provided input in the queries.
if you have userinput, for example by getting the category that should be displayed from the URL or from POST you should use prepared statements. this may you are safe even with user input. This is much safer than pure escaping because the sql is parsed and then the parameters are inserted. This is better for performance and the userinput can't change the structure of the sql query.
The only thing that you might want to consider, assuming that the connection code is in the web-accessible PHP script, is to either:
move the MySQL connection out of the
script and into a file outside of
the site's document root
or, use externally-sourced variables
(i.e. from a different file outside
of the document root) for the
username and password in place of
hard-coded details in the script
That way if, for whatever reason the server displays the code instead of rendering the PHP, then the details will remain safe from view