$_GET validation question

Hi,

Can someone please summarize on how I should treat $_GET paramaters in terms of security. I am creating some urls by assigning $_GET parameters directly in the CHtml::link and I am also executing some queries in widgets, which use GET parameters directly in the query and I am worried about the security side of all this. If someone can summarize how I should escape all GET values please.

Regards,

b.

Main rule - don’t believe anyone :)

Always escape user input or data user can change. In SQL queries always use parameters.

Show please example of "I am creating some urls by assigning $_GET parameters directly in the CHtml::link"

I have also with same question… :)

I found this $this->_GET…? what is this?

I’m interested!

Why the use of parameters in the method find help?

Does that mean "escape user input"? a example?

Here is something, but only upon showing, not validate GET parameters

http://www.yiiframework.com/doc/guide/topics.security

Hi iGrog,

thanks for assising. Here is an example:


<li><?php echo CHtml::link('Link Label',array('controller/list','id'=>$_GET['id'])); ?></li>

which creates a menu with the current id attribute.

Can you also show examples on how to escape characters and how to use parameters with sql queries in a secure way.

Thanks,

b

I found the following comment by qiang:

http://www.yiiframework.com/forum/index.php?/topic/697-search-form/page__p__3758&#entry3758

Basically in sql queries we should use bindValue or bindParam to avoid sql injection attack. This comment was posted a year ago. I would like to know if anything has changed since then. And also how to escape $_GET parameters if used directly in links or text.

Cheers,

b

No change. Yii’s DB layer was built around PDO. It takes care of correct escaping for you:

Quote from http://www.php.net/m...statements.php:

When using DAO, you need to use bindParam/bindValue in order to prevent SQL injections, as described here under “Binding Parameters”. When using ActiveRecords, you don’t have to care about SQL injections since Yii does all the param-binding internally.

When using $_GET parameters in html, you have to make sure the data does not contain malicious code like "<script>…". You can do it this way:


CHtml::encode($_GET['something']);

CHtml::encode() is a wrapper for the php function htmlspecialchars().

Read more about security here.

if you expect an integer, just turn it into one via (int) or intval($_GET[‘id’])

Thanks Y!!. So to summarize:

using bindParam is safe and creating links like below is safe?


<?php echo CHtml::link('Value',array('controller/action','id'=>CHtml::encode($_GET['id']))); ?>

Additionally, I would like to know when I should use the CHtmlPurifier. Is there a specific case where it should be used. I don’t remember qiang using it in the blog demo?

Thanks,

b

Using parameter binding is safe, yes. You don’t have to mess around with any additional function like addslashes() or mysql_real_escape_string(). Just make sure you really always bind the needed params and don’t write them directly into the sql query string. As I said that only counts for DAO, not for ActiveRecord.

The way you use the CHtml::link() is safe. What you also can do is this:


<?php echo CHtml::link('Value',array('controller/action','id'=>$_GET['id'],'encode' => true)); ?>

When encode is set to true, all values of the htmloptions you define (in this case the value of "id") will be auto-encoded. Means less writing when you assign many htmloptions.

With CHtmlPurifier you can basically auto-encode a whole page or only parts of a page (like a comments list). So there’s no need for CHtml::encode($comment->text); anymore. But it’s slower than encode(). The nice thing however is that you may allow defined htmltags when using the Purifier. I’ve never used that so I can’t give an example. You may look here under “options” and here for more info about the purifier.

nice… :)

Just for clarification, when you pass custom sql to an ActiveRecord, you have to bind params of course.

This is unsafe:


$user = User::model()->find("`name` = '{$_GET['name']}'");

This is safe:


$user = User::model()->find("`name` = :name", array(':name' => $_GET['name']));

This is safe since Yii does auto-bind the params:


$user = new User;

$user->name = $_GET['name'];

$user->save();

Thanks for your valuable input Y!!. How about when used with criteria

example:


$criteria->condition="value = '".$_GET['id']."'";

is this safe? Does Yii auto-bind the parameter in this case?

Thanks,

b

No, use the following syntax:




$criteria->condition = 'id = :id';

$user = User::model()->find($criteria, array(':id' => $_GET['id']))

// or ...

// $criteria->params = array(':id' => $_GET['id']);

// $user = User::model()->find($criteria)



thanks andy_s.

This:


// $criteria->params = array(':id' => $_GET['id']);

// $user = User::model()->find($criteria)

works as a charm but this


$criteria->condition = 'id = :id';

$user = User::model()->find($criteria, array(':id' => $_GET['id']))

does not work. It throws a syntax error which I am unable to identify.

Error:


CDbCommand failed to execute the SQL statement: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':id' at line 1

Sorry, my fault. A second parameter for the find() method is used only when a first paramter is a string (like ‘id = :id’).

excellent help. I will prepare a cookbook

very good help!

I hope this cookbook

thanks at all

What is wrong:

CDbCommand failed to execute the SQL statement: SQLSTATE[HY093]: Invalid parameter number: no parameters were bound




        echo $_GET['city']; //http://yii.dev/index/test/city/amsterdam.html prints amsterdam on the page

        $criteria = new CDbCriteria;

        $criteria->condition = 'City = :city';

        $city = City::model()->find($criteria, array(':city' => $_GET['city']));