The script is in PHP and as DB I use MySQL. Here is the script itself.
$unsafe_variable = $_GET["user-input"];
$sql=sprintf("INSERT INTO table (column) VALUES('%s')",$unsafe_variable);
mysql_query($sql);
Some people say that if user assigns ;DROP TABLE blah; string to the variable $unsafe_variable it deletes the table.
But I tried this example,
http://localhost/test.php?user-input=DROP%20TABLE%20my_table
But it didn't delete the table but instead inserted a new row (;DROP TABLE blah;) in the table.
Could anybody explain me how it is possible to attack this script with sql injections?
That particular injection wouldn't work since PHP's mysql_query function only allows one query per call. However, the following may work if column has a primary or unique key:
$unsafe_variable = "admin') ON DUPLICATE KEY UPDATE password=MD5(CONCAT('knownsalt', 'newpassword'))#";
Better to use the long-winded mysql_real_escape_string function:
$sql=sprintf("INSERT INTO table (column) VALUES(%s)",
mysql_real_escape_string($unsafe_variable));
mysql_query($sql);
mysql_query() doesn't allow the execution of multiple queries in one function. So you can't INSERT and then DROP the table. But you shouldn't rely on this as 'security'. Use parametrized queries instead. Check out PHP's PDO library.
However, they could change just about anything else, like possibly SELECTing a password field from another table as a subquery to place into that table so they can view the hash.
While mysql_query only allows one query to execute, in general this query is not safe. An example of a dangerous input that would exploit your query is:
'); DROP TABLE my_table; --
The '); at the start will close your query and insert an empty value, but will allow for additional queries to be executed following the INSERT. Then after dropping a table, the -- at the end will mark everything else following (ie. the rest of your query) as a comment.
In order to safely prepare input for use in a query, use mysql_real_escape_string.
The ONLY way you should be handling unsafe variables is with bind parameters.
Please read this page on how to prevent SQL injection from bobby-tables.com.
Nope, sprintf doesn't escape the content use:
$unsafe_variable = mysql_real_escape_string($_GET["user-input"]);
$sql=sprintf("INSERT INTO table (column) VALUES('%s')",$unsafe_variable);
mysql_query($sql);
mysql_real_escape_string($unsafe_variable)
Some people say that if user assigns ;DROP TABLE blah; string to the variable $unsafe_variable it deletes the table.
Patently that's not the case - but if you don't understand why, then you can't tell if your code is safe. Are you going to post every line here to check if its safe?
Without going into a long explanation about what the code above is doing and how to compromise it (SQL injection is already very well documented elsewhere - try Google for a start) you should ALWAYS ensure that any data leaving your PHP code is in the correct representation for where it is going.
For a MySQL database that means either:
1) use the output of mysql_real_escape_string (and make sure you pass the right resource handle)
or
2) use parameter binding.
A proper discussion of code injection attacks could easily fill several hundred pages - a bit much to answer in a S.O. query.
C.
I think the example you would need to try is http://localhost/test.php?user-input=';DROP%20TABLE%20my_table'
the '); closes the values('%s segment, and then issues a new command, drop table...
Related
My question of to day is. Do i need to escape PDO in my script?
$columns = implode(", ",$column);
$query = ''.$query.' '.$columns.' FROM '.$table.'';
$dbh_query = $dbh->prepare($query);
$dbh_query->execute();
$dbh_querys = $dbh_query->fetchAll();
return $dbh_querys;
The whole script can be found at.
https://github.com/joshuahiwat/crud/blob/master/control/query_connector.class.php
Can someone explain why do i need a escape at this time or why not.
I like to hear from you, thanks a lot!
The parts of your query that are dynamic are the table name and column names. You can't use bind functions for these parts of the query. Bind functions can be used only for the parts of the query that would otherwise be a simple value in an SQL query. Like a numeric constant, or a quoted string or quoted date literal.
To avoid SQL injection from dynamic table names or column names, you have the following choices:
Use values that are predefined in your class, or otherwise certain to be safe. Don't use external content from users or any other source.
Use escaping. Note that the function PDO::quote() doesn't do the kind of escaping you need for table names or column names.
Create a "allowlist" of known table names and the column names for the respective table, and compare the dynamic input to the allowlist. If it doesn't match the allowlist, raise an error.
First of all you need to understand that the word you are using - "escape" - is meaningless.
What you probably mean is "to make your query safe from SQL injection". But, unfortunately, there is no such magic "escaping" that will make some abstract query safe.
The traditional query building assumes that all the query parts beside data values are hard-coded, while data values are bound via placeholders, like this:
$query = 'SELECT col1, col2 FROM some_table WHERE id = ?';
$stmt = $dbh->prepare($query);
$stmt->execute([$id]);
$row = $stmt->fetch();
This kind of a query considered safe.
In your case of a dynamically constructed query, every part is potentially vulnerable.
And here it is very important to understand that a burden of sanitizing all the query parts is entirely on this function. You cannot dismiss the danger simply claiming that your data is coming from the trusted source. That's a slippery ground because people often have no idea whether their source is trusted or not.
So, if take your question as "Do I have to protect this code from SQL injection", than the answer is - YES, YOU HAVE.
In the meantime you are protecting only a small part of your query - the data values. So you still have to protect (this term is much better than "escape") all other parts.
On a side note, your code is connecting to database every time it runs a query, which is highly inefficient and makes it impossible to use some database features.
I'm very new to PHP and programming in general. I've come across an article about security, although not an issue yet in my case, I'm sure it will come up in the future at some point.
The article in question was about database input.
I'm using PDO most of the time while dealing with databases, however I'm confused about some parts. Perhaps someone can shed some light on a few things.
As I understand it, prepared statements in PDO for example:
SELECT <column> FROM <table name> WHERE <something>
Doesn't get execute right away(well, obviously) but only when execute(); is called. And gets interpreted as is.
So having something like
"SELECT <column> FROM <table name> WHERE" . <userinput> OR 1=1;
Lets say userinput is the username
And
<userinput> OR 1=1
is a user input variable via a form or whatever, will get interpreted exactly like that, meaning the username will be
userinput OR 1=1
And obviously no username OR 1=1 will exist in the database so an error will be returned.
That this mean that PDO is safe(a strong word, I know) from things like SQL injection? Or other 'hacking' methods?
What can I use/do to sanitize user input in general?
Yes it is safe, you can look at it as sandbox, if you have SQL like SELECT FROM books, it guaranties that input from user will not get out of boundaries (like modifying sql query), so it is safe from 1st order injection, but not from 2nd.
What i mean? Well PDO PREPARED statements(because you can use pdo without preparing statements in php) guaranties that you sql query is safe, but it doesn't filters the actual value.
Consider example: suppose we get some value from the form, the value will be 1); DROP TABLE books and we will save it in our database using our prepared statement INSERT INTO books VALUES(<value1>, ...),so the query will be executed successfully, value 1); DROP TABLE books will be saved in our database, but evil code will no be executed, no drop value. But if you then use our stored value in standard query, not prepared one. You will get hurt. But if you everywhere use PDO prepared statement your are safe. But i advice to filter values anyway.
Make use of Prepared Statements on PDO and you can stop worrying about SQL Injection.
I am sorry as this is the simplest answer i could give for this question.
Source
EDIT :
Found this answer on SO
Statement stmt = conn.prepareStatement("INSERT INTO student VALUES(?)");
stmt.setString(1, user);
stmt.execute();
If "user" came from user input and the user input was
Robert'); DROP TABLE students; --
Then in the first instance, you'd be hosed. In the second, you'd be safe and Little Bobby Tables would be registered for your school.
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 :)
hi how can i insert the array of service id into table into a single field like 2,3,4 in database i am confuse please help followingis my code...i am using this but it is inserted only single id..
$service=implode(",",$_POST['service']);
$sqlQuery="INSERT INTO ".DBPROMOTION." SET
promotion_service_id='".$service."',
promotion_user_id='".$user."',
promotion_discount='".$_POST['discount'].$_POST['type']."',
promotion_title='".$_POST['title']."',
promotion_start_date='".$startDate."',
promotion_end_date='".$endDate."',
promotion_code='".$_POST['code']."',
promotion_description='".$_POST['desc']."'"
You should use two database tables with relation one-to-many to link more than one element with table columnt. That would be better design.
You may insert all id's into db in form of string, but I don't think, that is what you aiming for.
Also, you should sanitize your input from $_POST before entering int to db, to prevent sql injection.
you database-model seem to be not normalized - correct that first before programming an application that will cause some realy big problems in the future.
also, you should never insert posted data directly to avoid sql-injection. use mysql_real_escape_string or, better, PDO for prepared statements.
to your problem directly: i think 'promotion_service_id' is an integer-field - '2,3,4' is a string, so (fortunately) you have no chance to insert it.
somewhere while studying I juz found out something interesting.. It says something as follows:
$query = sprintf("SELECT firstname, lastname, address, age FROM friends
WHERE firstname='%s' AND lastname='%s'",mysql_real_escape_string($firstname),
mysql_real_escape_string($lastname));
using the query like this instead of
$query="select firstname, lastname, address, age FROM friends
WHERE firstname='".$_RETURN['name1']."', lastname='".$_RETURN['name2']."'";
does this seem reasonable.. have u tried this coding ever.. and how it helps prevent any malicious attacks..
First off, what this is about is called is SQL-Injection. It's basically just the possibility to alter queries against the database via user input.
Let's look at an example:
Query:
SELECT temp1 FROM temp WHERE temp2 = 'VAR1';
Now we'll assign VAR1 the value of: '; DROP TABLE *; --
And we'll get:
SELECT temp1 FROM temp WHERE temp2 = ''; DROP TABLE *; --';
With mysql_real_escape_string it would look like this:
SELECT temp1 FROM temp WHERE temp2 = '\'; DROP TABLE *; --'
mysql_real_escape_string 'secures' a string for usage within a query.
But in the end, you should stop using the mysql_* altogether. They're deprecated and considered as insecure when it comes to preventing SQL injection or other means of tempering with the queries.
You should simply stop concatenating queries together like this and start using prepared statements, which not only are easier to use, prevent SQL Injection by default but also can improve the speed of your application.
For PHP there are two extensions which are designed to close the whole mysql_* opened:
mysqli
PDO
And I say it again: Please stop using mysql_*!
As far as I'm aware, mysql_real_escape_string is one of the better ways to prevent SQL injection, short of using prepared statements with mysqli or PDO.
Using formatting functions like sprintf is purely a matter of taste; the big advantage in the first example is that the function mysql_real_escape_string prevents all SQL injections (explained in one of the other answers); unlike the somewhat iffy magic_quotes_gpc feature in PHP, which many people rely on instead.
magic_quotes_gpc automatically escapes things you receive in requests from clients... but it cannot detect so-called second-level injections:
You get a malicious query from a client and store its contents in the database. magic_quotes_gpc prevents SQL injection; the malicious string gets stored correctly.
Later on, you fetch this string from the database and include it in another query. Now the string didn't come out of a request, so magic_quotes_gpc doesn't escape the string. VoilĂ , SQL injection; your data is now probably gone.
Using some means of escaping yourself, either something like mysql_real_escape_string or a database abstraction layer with a query builder (e.g. Adodb), is definitely superior to just hoping for the best.