This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 3 years ago.
I asked this question earlier Preventing SQL Injection in dynamical SQL, but was not clear which resulted in the question being closed, and was later told in the comments that I should ask the question again.
A requirement of my PHP/MySQL application is to allow all users to create their own multiple "views" of the data. These views are not traditional SQL views, but performed by the application.
For instance, the user could create a view and provide the following criteria:
Name of the view.
Desired records per page.
Which columns to display by using a dropdown menu.
Any filters for the results. A first dropdown menu is used to select the column, a second dropdown menu is used to select the operator (equals, not equal, greater than, etc), and then either a third dropdown menu is used to select the value to be matched or the user directly enters the value to be matched.
Whether the records should be grouped on a given column.
Based on the user's selection, various tables might need to be joined to the query to support the select, where, and group by clauses, and the application is used to eliminate duplicate table joins should they exist.
After the user has finished configuring their views, there is a dropdown menu which allows them to select their desired view, and the appropriate results are displayed.
I have implemented this functionality by storing the user's selections in several tables, and also storing the resultant query (actually, I store individual sections of the query in various columns so I may count the total results in an initial query and return the correct number of results in a second query) in a SQL table. Note that I am storing the user's selections only so that I can allow them to edit their view requirements, and not to create the resultant query on the fly (more on this later).
I recognize that I have to be very careful as doing this can be prone to SQL injunction. For instance, I can't just escape the user's input using PDO and store it in the database, and then later retrieve the data and use it in a query since when it is retrieved, it is no longer escaped.
To combat this risk, I limit user input to integers wherever possible, and typecast them where possible. Where user inputs are percents and dollars, I multiply by 100, typecast the resultant as an integer, and then divide by 100 before storing it. A couple of the filters require text as the value in the WHERE clause, and as stated earlier, escaping the data is not enought, and instead I am using $user_input= preg_replace('/[^a-z0-9,]/i', '', $_POST['user_input']); to make safe.
Is this an accepted method to implement this functionality? Is there an easier way to ensure the user input is safe? My earlier post Preventing SQL Injection in dynamical SQL indicated that this type of practice should never be attempted, however, I don't know how else to do it. Are there any other steps I should take to prevent injection?
Or maybe I should not create a query and store it in a table when the user saves his view configuration, but create the query on the fly using the user's saved values each time the user selects a given view. This would have a negative performance impact and add complicity but I suppose I can do it. Would you recommend using this strategy?
Thank you
Hello I get you I think.
This is what you are looking for:
http://www.php.net/manual/en/function.addslashes.php
$safestring=mysql_real_escape_string($_POST['user_input']);
$safestring=addslashes($safestring);
If you want to make it even more safer, that is the user cannot input html in the input,
use this function after using the above one (i.e. mysql_real_escape_string)
$safestring=htmlspecialchars($safestring);
Now all your use input will stay as it is,
if string is "user's input" it will stay as "user's input" and not change to "users input", so nothing is being replaced, and its still safe.
Regards.
Related
I'm making a website for renting a car using PHP and MySQL .But I'm stuck, because I don't know how to combine car details and booking form details and show it in PHPMyAdmin when user submits the form.
Representation
You need to create relational representation in your MySQL database, like a table for cars, of the like of
cars(id, ...)
Where the ... represents whatever details you intend to store.
Storing a car
You need to create a PHP script that takes car details as input and stores cars as output. Since you already told us that you have a form, you will most likely use $_POST (an array with your named form elements for the form that you have submitted) as the input, but it is strongly recommended that you separate your functionality part from the definition of your input. So, you will most likely have a function/method (a standalone function or a method of a class) that will look something like this:
function storeCar($input) {
//...
}
where $input is an associative array and you actually store the values. Of course, pay attention to SQL injection and XSS injection as possibilities. These are possible vulnerabilities that infest the codes of most beginners. You can used parameterized queries to prevent SQL injection and htmlspecialchars to protect against XSS injection.
Your code will end up executing an insert into ... type of command once you POST your form.
Loading cars
You can execute select * from cars to see what your cars' details are (but it's better to list only the columns you are interested about) at any places that are connected to MySQL, including PHPMyAdmin. Or, in some UIs, such as PHPMyAdmin you can click on table names.
I have discovered that some old (2009) code that was written for a website, did, under certain circumstances on a search query save the SQL as a a $_GET variable!
When the search was carried out, the details are POSTED and then sanitized, and the results are paginated with the LIMIT clause in MySQL. If there is more than one page (ie +30 results) the pages are anchor links in the HTML with a GET var containing the SQL statement.
I know, this is absolutely not the way to do this. It's old code I've just seen it by chance. This needs to be fixed.
So I've fixed it, sanitized it and used an alternative method to reload the SQL, BUT:
My question is thus:
The page outputs the data relating to thumbnail images, all data is output as named array var (the original clause is a SELECT * clause), so if someone does abuse the GET variable, the page itself will only output the columns named,
I have managed to DELETE rows from the DB using the GET abuse, I would like to think the abuse is only effective if the result is not involving any returned output (such as DELETE) but I don't know; so given that the user can input anything into the GET clause but only get the displayed output of what's coded (ie named columns in a 30 row array) -- what other abuses can this gaping hole be open to?
Further details: The code is MySQLi
A tool like SQLMAP can probably take over the entire server and do with it whatever the user wants.
Having an unsanitized database input isn´t even hacking anymore, it´s waiting for someone to run a script on your machine and basically own it from that point on.
What the attacker can do depends on your database configuration and database user access. If you create a new user with a permission to only SELECT that one specified table, and use that user for that particular script, the harm it can do is reading data from that table.
Still this is bad practice. Never use it.
So, the context is: I have a site in which many pages may need the information about one table, say for instance, 'films'. This table has many fields, like title, language, year, description, director... And perhaps in one page I need only the title and the id of some rows and in another I also need the description.
So the question is: should I code a database manager (I am using MySQL) that retrieves all the fields of the rows that satisfy a condition (I guess the WHERE clause should be passed as a parameter)? Or should I be able to specify which fields are needed? I thinks this cannot be done easily with mysqli (because prepared statements require to specify beforehand the number of fetched fields), so for this to work I would need to use PDO instead, which I haven't used yet. Is it worth it this last approach? Or there is not really a big difference in performance if I retrieve the whole information about those rows?
Thank you in advance.
Based upon the comments above, My answer to your question(s) is
Retrieving some fields vs all fields isn't a real performance consideration until you are dealing with one or more CLOB/TEXT columns which have a lot of text in them. Good database practice indicates you should always specify which fields are returned from a query.
Any query against any table should have a where clause to restrict the number of rows returned. Especially if you are looking to query exactly one row.
Your question implies you are writing a wrapper layer around the queries to hide this complexity. Don't do this. Get an existing PHP library that does this work for you. See for example: Good PHP ORM Library? . There are a number of subtle issues, like security, which you will overlook.
I'm developing a basic php based function that executes MySQL queries in order to sort the data in the database and present it to the user. As a general statement, is it considered best practice to simply construct static queries and to execute them as needed, or simply piece together elements of a MySQL statement based on conditions?
To narrow the question, I have a specific example:
Say I have a few drop-down menus that define the search on the user's end. Let one drop-down simply contain a list of names, say Bob Smith, and the two others a date range. From there, I can easily create a search along the lines of SELECT item FROM checkOUT WHERE... I can definitely write a general query with parameters to be executed when ALL three of the parameters are present. Consider the case when only a date range is selected regardless of individuals - that would require only two parameters and a different general query. And what if the data is spread across multiple tables? That has to be taken into account. I should add as well that my function is based on drop-down menus - not original user input.
Basically, what would be the best method to create the MySQL Query - prepared statements or dynamically created statements? Obviously, the end result will rely on a hybrid of the two, but to which side it leans the farthest is the issue. I'm asking this question as I am not too familiar with this particular side of handling multiple queries from one source. Typically, I simply have to execute one query to get what I need and work with it - not sorting.
Any insight is appreciated.
I usually make a $where variable and an $order variable and then build them based on the filter input from the page. Then i just append that to the base $sql variable and run it. Seems to work great for me. Just don't forget to escape any nasty input from the user before running the query though.
I have the need to render a threaded view of a 2-levels hierarchical commenting system. The comments are stored in a database. The information about the hierarchy is given by field 'parent_id' (which is 0 for the top-level comments). I cannot change the structure of the database.
The present solution is by means of multiple SQL queries:
an SQL query is performed to fetch all top-level comments
the code loops through the top-level comments and for each of them performs an SQL query to fetch its children
Now I wonder if a solution with only one SQL query to fetch all the comments as they are followed by the code suggested here to sort them by threads could be more efficient.
Any reccomendation?
Thanks,
Luciano
I've done similar scripts and from my point of view it's better to do a first query to fetch all the 'parents' (parent_id==0) and then for each one of them do another query to get all its 'sons' information.
If you have to retrieve a HUGE ammount of threats using a single query you have to wait for the query to complete to work with the data. If you divide the search in different and smaller queries you can start formating and printing them before looking for the 'sons'. Also doing it in a single query could make the query slower since using more tables in the same query could make it halt due to a lock_table when someone is creating a new threat.
Another solution, which I would only recommend if the query is very slow due to being forced to use multiple JOINs or using WHERE with non-indexed fields (you should never do that, but if you can't change the database...), is to retrieve ALL the threats in a single query (both parents and sons, without any of those WHERE or JOIN that makes the query slower) and then organize them using PHP. This is by no means practical, and you should never use this method unless the time to complete the query is very long.