Ok,
So, i'm a little unsure on this.
I have a url parameter username.
and I have this statement
SELECT * FROM users WHERE user_hash = md5($_GET['username'])
Is this secure?
Upon account creation an md5 hashed version of the username and the password are stored.
I'm confused as this seems so simple, if md5 stops sql injection why isn't username and password always saved in hash form?
Yes, this will avoid SQL injection, because md5() always returns a string of hex code.
But it isn't a general solution to SQL-injection. You would have to encode almost all the data in your tables in MD5 format. For instance,
$sql = "UPDATE users SET fullname = '" . md5($_GET['fullname']) . "'
WHERE id = '" . md5($_GET['id']) . "'";
But MD5 is a one-way hash, so there would be no way of displaying the full name that was stored this way.
Short answer is no, MD5 does not prevent SQL injection. Proper coding is the best way to handle this.
Reason being in this case is that your query string parameter is allowing direct access to the sql. E.g. what if the user sends you:
?username=%27a%27);DROP%20TABLE%20users;%20--
That fakes the MD5 function out and drops the users table. Of course they have to know somethings about your database in order to do this. The correct way to handle it would be to MD5 the value before it went into the SQL. In PHP it would be something like this:
$username = $GET['username'];
$hashed_username = md5($username);
$sql = "SELECT * FROM users WHERE user_hash = '$hashed_username'"
Or the best solution would be to use bound variables in queries where you let the SQL libraries handle the translation. If you are using PHP, look into PDO bindParam, http://php.net/manual/en/pdostatement.bindparam.php
BTW, your SQL won't work because you would need to quote (') the get variable in the SQL.
I'm confused as this seems so simple, if md5 stops sql injection why isn't username and password always saved in hash form?
The reason is because simple operations like searching for a user with a particular name would be impossible.
SELECT * FROM users where user LIKE '%cat%'
Would find all users with the word cat within it.
Also simple administration would be impossible, you can't even view a roster of all users.
Related
Ok,
So, i'm a little unsure on this.
I have a url parameter username.
and I have this statement
SELECT * FROM users WHERE user_hash = md5($_GET['username'])
Is this secure?
Upon account creation an md5 hashed version of the username and the password are stored.
I'm confused as this seems so simple, if md5 stops sql injection why isn't username and password always saved in hash form?
Yes, this will avoid SQL injection, because md5() always returns a string of hex code.
But it isn't a general solution to SQL-injection. You would have to encode almost all the data in your tables in MD5 format. For instance,
$sql = "UPDATE users SET fullname = '" . md5($_GET['fullname']) . "'
WHERE id = '" . md5($_GET['id']) . "'";
But MD5 is a one-way hash, so there would be no way of displaying the full name that was stored this way.
Short answer is no, MD5 does not prevent SQL injection. Proper coding is the best way to handle this.
Reason being in this case is that your query string parameter is allowing direct access to the sql. E.g. what if the user sends you:
?username=%27a%27);DROP%20TABLE%20users;%20--
That fakes the MD5 function out and drops the users table. Of course they have to know somethings about your database in order to do this. The correct way to handle it would be to MD5 the value before it went into the SQL. In PHP it would be something like this:
$username = $GET['username'];
$hashed_username = md5($username);
$sql = "SELECT * FROM users WHERE user_hash = '$hashed_username'"
Or the best solution would be to use bound variables in queries where you let the SQL libraries handle the translation. If you are using PHP, look into PDO bindParam, http://php.net/manual/en/pdostatement.bindparam.php
BTW, your SQL won't work because you would need to quote (') the get variable in the SQL.
I'm confused as this seems so simple, if md5 stops sql injection why isn't username and password always saved in hash form?
The reason is because simple operations like searching for a user with a particular name would be impossible.
SELECT * FROM users where user LIKE '%cat%'
Would find all users with the word cat within it.
Also simple administration would be impossible, you can't even view a roster of all users.
In various mysql queries, the end part of the query string is:
" WHERE UserID = " . $AccID
where
$AccID = $_SESSION['UID'];
and UserID is the respecting bigint column in the specific table of the db.
So my question is : do I need to escape the $AccID like this GetSQLValueString($AccID, "text") just to be on the safe side, or there is no need to, since it's not taken from a user input ?
p.s. $_SESSION['UID'] is set during the login procedure, after a successful authentication
Yes, you should escape it. You should not database-escape it when you put it into $_SESSION (you might want to use it for other purposes), but before inserting into the query.
Your best bet would be though to use parameterized SQL instead of always escaping and building your queries through string concatenation. Get familiar with PDO. For a better world.
If I am running a query on a MySQL database using PHP as in the following:
$query="SELECT * FROM tablename";
What is the best way to secure this from things like SQL Injections? I've heard about some escape methods, but won't it leave slashes in the query?
The query you have shown in the question doesn't use user supplied values so there is no case of SQL Injection but in a general case:-
Firstly, you must validate all the user input(usernames,emails etc.) before using it in a query. For ex:- If you have allowed only alphanumeric characters in a username, then you must check whether the input is actually alphanumeric or not before proceeding to form a database query and you must also check the size of all the inputs.
After that, in my opinion Prepared Statements is the best choice for preventing SQL injection.
Problem with mysql_real_escape_string():-
As mysql_real_escape_string() escapes characters according to default charset, so it is better than addslashes() function and it properly sanitizes SQL injections arising out of abuse of multibyte character sets, but in another article here, a workaround-scenario is shown that explains that injection can still be done.
Solution:-
So the proper and better way of preventing SQL injection is to use prepared statements. It is a technique in which SQL statements are precompiled before the insertion of the user-input (parameters) and are treated as reusable SQL templates. So, it separates the user input from actual SQL-Code and the SQL-parser never parses the user input.
Apart from security, it also optimizes the SQL query for speed. It helps in cases where you need to run same query multiple times with different user inputs.
You can refer to PHP manual for implementation details.
You shouldn't be doing a select * and should only get the fields you need.
You need to escape text that can be inputted by the user really or using data that is derived from such.
You need to use the mysql_real_escape_string().
first advice, never select *, only select the fields that are necessary, and if all of them are necessary, select individually, so when the project is continued by other developers, they would know whats going on more quicker. secondly, to secure a query use mysql_real_escape_string(); function and if HTML is being passed use htmlentities(); function
SQL Injection can be done, when you make something like this
$query="SELECT * FROM tablename WHERE Name LIKE '" . $_GET["name"] . "'";
Attacker can simply put SQL Injection in get parameter name - eg something like "' OR 1 OR '' = '"
Make sure every get or post parameter is passed thru mysql_real_escape_string or at least addslashes + intval .
$query="SELECT * FROM tablename WHERE Name LIKE '" . mysql_real_escape_string( $_GET["name"] ) . "'";
from your query i see that there is not security issue.
but, lets say that you want to involve a GET parameter in your query.
the worng way
$query="SELECT * FROM tablename WHERE id = ".$_GET['id']
here, you have a chance that some one will change the query.
so what you can do is use mysql_real_escape_string
the right way
$query="SELECT * FROM tablename WHERE id = '".mysql_real_escape_string($_GET['id'])."'";
this way you are protecting the parameter that has being sent by the user.
BUT
you should always verify each parameter coming from the user, and on top of that you secure it by the common way as shown above
I have used this code kindly see is it the right code and not injection able now
As far as I came to know is : injection code can be injected if we run the insert query?
kindly correct me i am not much educated programmer
$rs=mysql_query("Select * from subcat where CATID='".mysql_real_escape_string($_GET['cat'])."' order by ID ASC");
while($row=mysql_fetch_array($rs))
{
echo '<td align="left" style="text-decoration:none;padding-left:1px; ">'.$row['HEADING'].'';
echo '<td align="CENTER" style="text-decoration:none;padding-left:1px">BUY NOW';
echo '<td align="CENTER" style="text-decoration:none;padding-left:50px">Rs.'.$row['PRICE'].'';
echo '<tr><td colspan=5 style="border-bottom:1px #232323 solid;">';
}
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What is SQL injection?
I see a lot of php code floating around on stackoverflow and (too) little escaping of strings.
Can anyone
Explain what SQL injection is;
Explain what it can do to your server, data and code;
Give an example how to perform an SQL-injection
Give php sample code how to protect against SQL-injection
An SQL injection is a maliciously formed SQL query used to "confuse" an SQL database into giving something it shouldn't. For instance, consider the following query
"SELECT * FROM `users` WHERE `username` = '$name'";
In a normal case, this will work. If we submit 'Jack' to this, it will return all users named Jack. However, if a user enters, say "' OR 1=1", the resulting query would be
"SELECT * FROM `users` WHERE `username` = '' OR 1=1";
Since 1 always equals 1, and the combinating clause is OR, this will return true on every row, which will in turn display EVERY row to the malicious user. Using this technique, someone can view your entire database. Also consider if someone submits something like "'; DROP TABLE users";--, which results in
"SELECT * FROM `users` WHERE `username` = ''; DROP TABLE `users`";--";
Which is two queries, one which will do nothing, the second which will delete the ENTIRE users database, resulting in the loss of your data.
The best method to prevent SQL injections is to use prepared statements. With these, you send a query to the SQL database that says something like
"SELECT * FROM `users` WHERE `username` = '?'";
This lets the database know the format of the query (WHERE username equals some value), so there is no confusion when given a plain text query. Then the database knows to expect one value, and where to put it. Then you pass that value to the database which it can use to search. This is also better as the database can optimize the query for faster searching.
Read up on prepared statements, which will explain this in more detail.
I cannot resist aswell.
SQL Injection is "a code injection technique that exploits a security vulnerability occurring in the database layer of an application". In other words it's SQL code injected in as user input inside a query.
SQL Injections can manipulate data (delete, update, add ecc...) and corrupt or delete tables of the database. I'm not aware of SQL Injections manipulating scripts though.
Let's say in your PHP script you are expecting (as user input) a username and a password from the login form that are later used inside a query such as:
SELECT Id FROM Users WHERE Name = $name AND Password = $password;
The user can insert inside $name and as $password whatever he likes (for example trough an <input>). Let's imagine he adds a name such as "1 OR 1 = 1; --", the query will now look like:
SELECT Id FROM Users WHERE Name = 1 OR 1 = 1; -- AND Password = $password;
and then, after the ; I could add another query or make the script think that the username and the password actually exists.
Notice that -- AND Password = $password; is a SQL comment and will therefore be ignored.
If you are using PHP < 5 then you should look for mysql_real_escape_string() and use it to escape user inputs before embedding it inside a query.
If you are using PHP5+ you should use PDO or the mysqli extension which can prevent this problem via prepared statements.
I cannot resist posting this.
1- Sql Injection is explained better in one cartoon, than most other documents.
2- Mostly it does not do much to the server, but only to the underlying data. Consequence include delete, insert , select records, drop, create tables. (based on permissions etc..)
3- Examples.
4- Sorry I do not know PHP. But as long as you can abstract your DB layer from your View, you should be fine.
There's a lot of information out there (and elsewhere in here) about this subject, so do not take this answer as a complete list by any means and continue to research on your own...
Explain what SQL injection is;
Explain what it can do to your server, data and code;
Give an example how to perform an SQL-injection
Give php sample code how to protect against SQL-injection
SQL injection is where an attacker discovers that an input value supplied to your application is being sent directly to a database and realizes that they can craft that input to be a custom SQL command. It could be something as simple as entering a special character (such as %) into a text field and receiving a strange response.
It can do anything your database allows that command to do. For example, if your web application has DB owner permissions for the application's database then an attack can potentially drop tables or even drop the whole database. Or, with even normal application permissions, the attack can over-write data or read sensitive data (such as plain text passwords if you have those).
For example, if an application has a text field where you enter a username. If that field is open to SQL injection, an attacker can enter something like: MyName';DROP TABLE Users;-- In this example, the attack manually finishes the query with the closing single quote and semi-colon, then adds another query, then comments out anything afterward. If not protected against this, the database may run both queries.
This one I don't know updated enough information, but there's lots out there :)
I am using a normal php/mysql insert query and use md5 to encrypt the password
This is the INSERT query:
$sql = mysql_query("INSERT INTO user (username, password, role, approved) values ('".$username."', '".md5($password)."', 'user', '0')");
And this is my SELECT query which I use for my login check:
$sql = "SELECT id, username, password, role, approved FROM user WHERE username = '".$username."' AND password = '".md5($password)."'";
$result = mysql_query($sql);
But when I check the inserted password and the login password, it returns 2 different values even though if I give same values.
Can anybody help me to fix this problem?
Many of the typical caveats here apply... it can't hurt to mention them.
First, vanilla md5 for your password hashing is certainly not the best way to secure your user password within the database. There are numerous questions on stackoverflow that document better approaches, and though there are differences of opinion, they are all more secure that a regular md5, unsalted hash.
Secure hash and salt for PHP passwords
Why not use AES for password encryption in PHP?
Also, you are doing no sanitization of your sql inputs, leaving your database open to sql injection attacks. A meddlesome user could manipulate your user insert to drop tables or modify your data structure. You need to escape these values using mysql_real_escape_string() or adopt a totally different database access system like PDO that has parameterized sql.
How can I prevent SQL injection in PHP?
That being said, your query should check for the existence of a User row that has the correct username and password, usually achieved by doing a COUNT query first and ensuring that the user is present in the database with valid login creds.
You should ensure that your database columns are proper length and datatype to store the hashes for passwords. Truncation of either could destroy the data.
I hope this helps - SQL injection can be especially nasty!
Assuming $username and $password are in fact the same... have you checked to make sure the on table users the password column character length is big enough to hold the whole MD5 hash?
Got an example of the calculated and store MD5 hashes?