This article is called extended guide is because there is already a security guide in the Yii tutorial security section. but that guide is not complete in the sense that it does not rise the developers' attention to some other commonly happening attacks: SQL injection and magic URL, which can be major vulnerabilities in your application without much caring.
Warning: please do not consider this page as reference material. Its content is subject to caution. See comments at the bottom of the page.
SQL Injection
Sql injection is the most common attacks in the web application and has been ranked as the number 1 security issues by the OWASP. these attacks happen when you take input from users client side, and use it as a string in your raw SQL query. This attack can modify, delete data, and even exposes and manipulate all the sensitive data from the database.
One simple example could be:
"Select * from User where username=".$username;
This query is sinful because the attacker can easily inject query expression in the input $username which you take from client side. So imagin if user is capable of guessing your query and that user's input is "'john' or 1=1", then the whole query becomes:
"Select * from User where username='john' or 1=1";
and this query will return all the user data in your table, so attacker can do whatever they want with the data. This is a simple example, but it demonstrates very well of how the attack happens.
So the followings are some approachs to raise security guide:
- Input validation, do not trust any data from client side, always validate.
- Avoid write raw SQL statement in controller, if you have to, pay great attention to the input.
- Use prepared statment,in Yii, use methods in activeRecord or CDbCommand to pass $params.
Magic Urls
Another attack that you should pay attention to is the so called Magic Url. this attack happens when developers use parameters in the url as input and execute some operation on the server side. In particular, the architecture of Yii framework has opens the door to this attack. Without proper authentication guides and other countermeasures, attackers may be able to delete all the data you have in your database. so let's look at a concrete example:
Imagin you have a ImageController which contains common methods:
Class ImageController extends Controller{
public function accessRules(){
...
array('allow', 'actions'=>array('delete'),'users'=>array('*'),
...
}
public function actionCreate(){
....
}
...
public function actionDelete($id){
$this->loadModel($id)->delete();
}
}
If you look at the structure, you can see that this controller allows authenticated user to perform the action delete. So one scenario would be that users click on the delete button under a image on the interface then the image record will be removed from database table. But wait, is this that simple? If you have knowledge about the http url, then a url for this delete action would probably be
http://yourdomain.com/image/delete?id=3
or similar. It becomes clear now if your database design is just simply numerically increase the id for image records, then the obvious attack could happen just by simply changing the id value in the URL and remove the image record owned by another user, therefore this is a sinful code.
the followings are better some approachs to raise security guide:
- Authorized the operation by checking the role of the user, consider using Role-Based Access Control (RBAC).
- Avoid using get method when the result has side effect on the server side,use post instead and always check if it is a post request by checking: Yii::app()->request->isPostRequest
- Input validation if the parameter can be validate against the potential thread, do reluctance to trust user input.
- Raise the level of access rule, leave the least privilege to users.
Nice tips
Thanks for mentioning this. Am reality taking into account what you have mentioned here in my app am creating.
Be aware
Nice to see some efforts on security awareness. Also the first time i see OWASP being mentioned in conjunction with Yii.
However, there are some things that I'd like to point out (I'm not a security expert, I still consider myself a rookie on the subject), namely:
Under the 'Magic Url' paragraph above, you suggest using POST as a counter measure. While this certainly is better than using GET (since with GET, url parameters will easily be exposed in browser history, logs and referers), it is still just "security through obfuscation", which is not secure at all.
Using POST method, it is still possible for an attacker to send crafted HTTP requests to achieve the same result as with GET.
Using Yii's built in Authorization and accessControl is key here. Also, re-authorizing critical operations by forcing the user type the password again. I'd like to see built in support for this in the future.
nothing guarantees 100% secure
@donfuego: Maybe I should use suggestion than countermeasure. but notice nothing posted here will guarantee your system secure, it is just a suggestion to be more secure.
Please do not believe what is written in this page (as of 2011-11-20)
Sorry, but I think this article's value is very low. For instance, the recommendations on the first part, SQL Injection, are mostly useless:
$criteria->condition = "a=$userdata"
is not secure, even if it's a string.The most obvious solution is not even mentioned: when using SQL, use prepared queries whenever possible, like
Post::Model()->findBySql($sql, $parameters)
or$criteria->condition = "a > :first"
.The second part isn't better. "Magic Url" are in fact called "backdoors" and the advice are plain wrong. For instance, POST is not a security improvment because post requests can be easily forged.
I'm really sorry, but I believe the whole page should be deleted and written by someone more experienced in security. It's safer to say nothing rather than wrong advice.
See this forum post for an answer to bingjie2680.
reply to Francois
Hi Francois.Gannaz,
Thank you for your comment.
Sql injection:
Magic URl,
If you have any other thoughts or ideas, you are very welcome to update and improve this article to share your knowledge.
agree to Francois.Gannaz
Sql injection
the best solution is to use PDO methods (bindParams and bindValues), in Yii, You can use bindValue and bindParam
Magic Url
In fact, it is Cross-site Request Forgery...
You can read more about this CSRF Valition
多说一句,其实这些问题官方手册里都提到过。。。
people have problems with "Magic Urls"
if you have any doubt about the name "Magic Url", check out the book "24 deadly sins" chapter 4, this attack is diff from Cross-site Request Forgery, which is also presented in the book chapter 2
about Cross-site Request Forgery
Do you really know Cross-site Request Forgery? Do you really know csrf token?
no more comments...
well, I think I do, but Cross-site Request Forgery attack happens cross site as the name reads. the Magic Url I am talking about here is only applying to the same domain attack and does not necessarily have anything to do with cookies.
anyway, thanks for your comment. this tutorial has too many negitive comments, I would like to remove this if it is possible.
Thanks for sparking the discussion....
I'd rather see the discussion play out...IMO, developing best practices is what leads to long-term adoption of a framework...
I agree with the negative points
There is a lot of mis information here, for example magic URLs is not really a problem if you use bizrules (which you should) and so what if the user is able to manipulate a url to affect a row that they own? Other sites such as facebook etc actually allow this if you know what your doing, it is only when the user is allowed to effect rows not belonging to them you gotta start worrying. What you should of explained is how to prevent the problem of users effecting rows not related to themselves. I understand what you mean by this but you do not give a valid example really, nor do you explain the true problem which leads people to believe it only requires CSRF validation when in reality it is nothing to do with CSRF.
Not only that but GET is no more secure than POST (other than to hide plain text input from the user), the key is validation of the values and failure to instantly off the spot mass assign (like turning on the GLOBALS settings in PHP, it is never done now). POST does nothing more than change the method by which the data is transmitted so as to allow a much greater amount of data to be sent to the server since the browsers own address bar can only handle up to 4000 characters.
Also there is no difference to doing the SQL in the model than there is in the controller, that is a myth. The problem with injection comes from formation of the query string and the parameter sources you use, not where you place it. In fact I would consider putting all SQL into models bad practice because it does not really belong in the model, SQL really belongs on that page or to be more precise that controller action. That is where I would expect to find it.
Also find() and findby() are PDO accessible but they are also non-PDO accessible, you must use the $params param to actually get the PDO version of the command ( As I found out myself).
Also input validation should always be validated against a model, I am not sure what you mean by "the potential thread".
So your article is more badly explained than wrong but it is both at the same time.
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.