Where to sanitize PHP $_POST[] input?
I am using codeigniter framework.
where s开发者_如何转开发hould i sanitize PHP input - controller or model ?
All of these answers relating to PHP methods in general but are irrelevant to CodeIgniter.
POST data
CodeIgniter automatically cleans your POST data when you use $this->input->post('item_name') if you have global_xss enabled in your config.php. If you only wish for specific items to be cleaned, you can use:
$this->input->post('item_name', TRUE);
Either way, you are safe from XSS attacks and other issues.
SQL injection
Anything being entered into the database is automatically escaped if you use ActiveRecord (insert(), update(), etc) or use the query() bindings.
$this->db->query('INSERT INTO bla (?, ?)', array($foo, $bar));
This is all escaped so no more faffing with what goes where. You can just code and leave security in the hands of the framework.
I used to be a friend of centralizing sanitation as much as possible, but extensive discussion on SO (for example here) has changed my mind. Definitely worth a read.
I submit to you the following practice:
In a central validation routine, do no sanitation, or just "rough" checks (say, for data type) and size ("$_POST["category_name"] should not be larger than 200 bytes.")
Mark incoming variables as unsafe (e.g. $unsafe_id = $_POST["category_name"];
). Store them in whatever controller / class / construct you have available for it.
Sanitize data where it is used. If incoming data is used in a exec
call for example, do the necessary sanitation directly in front of the call:
$safe_category_name = escapeshellargs($unsafe_category_name);
exec("external_binary -category_name '$safe_category_name'");
if the same data is then used in a, say, mySQL query, again sanitize it in front of the call:
$safe_category_name = mysql_real_escape_string ($unsafe_category_name);
mysql_query("SELECT * FROM items WHERE category_name = '$safe_category_name'");
(this is just an example. If starting a project from scratch, you will want to use PDO and prepared statements, which takes away the hassle of escaping incoming data in this context.)
if the same data is then output in a web page, again do the sanitation directly in front of the call:
$safe_category_name = htmlspecialchars($unsafe_category_name);
echo "<span>$safe_category_name</span>";
This practice
Establishes a workflow that assumes there are unsafe variables that need to be dealt with first, which leads to a safer programming style IMO.
Prevents unnecessary conversions.
Helps fight the illusion that there is a one-click method to make input "safe." There isn't. Sanitation depends 100% on context.
Sanitization depends on what the data is being sanitized for.
Usually there are two types of sanitization:
- database input
- front-end output
In the first case it's to prevent SQL injection attacks, and the second is to prevent Cross-site scripting attacks.
So to answer your question (with regards to the above mentioned attack vectors), your sanitization should be where vulnerabilities are present, and more specifically:
- where you write SQL queries with variables in them (the models)
- where you write any output (usually HTML) (the views)
I hope this helped.
Controllers should be thin.
PHP input should be sanitized in the model for anything to do with where the model keeps it. i.e. prevent SQL injection in the model.
It should be sanitized in the view for anything to do with the final output though. i.e. prevent XSS in the view.
Basically, all sensitization should be done just in time to prevent bad data doing any harm.
The controller is like the application gatekeeper, so it should be where you validate all inputs.
I would put it in the controller that handles the form submission. As Phil Sturgeon points out if you have the global_xss option enabled in your config CodeIgniter will handle a ceratin level of sanitizing anyway.
As an additional level of security I would use CodeIgniter's form_validation library. Here is a sample controller for you:
function processForm()
{
// fields will need to be validated so load library
$this->load->library('form_validation');
// field name, error message, validaiton rules
$this->form_validation->set_rules('first_name','Name','trim|required');
if($this->form_validation->run() == FALSE)
{
// load form again showing errors
} else {
// update database or proceed to stage 2
}
}
I hope this helps! Cheers
Your request goes to controller usually, you should do that in a controller, controller once gets this data and sanitized that can then interact with the model with safe data.
According to me, user input should be sanitized in the controller, since it represents a mandatory passage for the data between your View (the place where you show information to the user and you get user input) and your Model (where you store the data).
The model should always be considered as a pluggable component in your MVC structure, meaning that you might, for example, switch your model (the database implementation and/or the way you interact with it) at a certain point. For this reason, user data validation shouldn't be bound to the specific implementation of a DB. Just the part of sanitization that is DB-specific (if any) should be kept in the model.
Said this, the final decision is always up to you. Just keep in mind:
- Input must be always validated
- Design should be consistent. If you decide to sanitize user input in the controller, then try to aways do it there. This will bring to cleaner and easier to understand code
Hope this helps.
I would do it only in my view. There's no need to sanitize it for storing in the database. It's enough to just to ouput the clean data. You will also need to escape the data to prevent SQL injections.
精彩评论