Security-Problem: Guess Attibutes And Post Them

Today I (beginner) found a security-problem - i hope experts have an easy solution for it:

In the MySQL-table "company" I have 20 fields.

I have two forms for changing values in the table:

  • one form for the users where he sees only 5 of the attributes (fields)

  • one form for the webmaster with all 20 attributes

If a user guesses other attributes he could post values for them to the application and thus change fields which he should not change.

Login seems to be no solution because after loging-in he also could guess attributes and post values for them.

What is the Yii-way to solve the problem?

Regards

Jannis

Rules and scenarios.

http://www.yiiframework.com/doc/guide/1.1/en/database.ar#data-validation

http://www.yiiframework.com/doc/guide/1.1/en/form.model#declaring-validation-rules

http://www.yiiframework.com/wiki/266/understanding-scenarios/

Thanx, ORey,

I just know rules ans scenarios - but maybe there is a trick I don’t see.

#model Company

class Company extends CActiveRecord{

public function rules() {

   return array(


       array('company_name', 'required'),


       array('user_name', 'required'),


   );

#CompanyController

public function actionUpdate_1($id) {

 $model = $this->loadModel($id);


 if (isset( $_POST['Company'])) {


    $model->save();


    $this->redirect(array('view', 'id' => $model->id));


 }


 $this->render('update_1', array('model') => $model);

public function actionUpdate_2($id) {

 $model = $this->loadModel($id);


 if (isset( $_POST['Company'])) {


    $model->save();


    $this->redirect(array('view', 'id' => $model->id));


 }


 $this->render('update_2', array('model') => $model);     // <- only different line

#view: update_1.php <- the user is only allowed to change the company_name

<?php echo $form->textField($model, ‘company_name’); ?>

#view: update_2.php <- the Webadmin is also allowed to change the user_name

<?php echo $form->textField($model, ‘company_name’); ?>

<?php echo $form->textField($model, ‘user_name’); ?>

If the user calls http://…r=company/update_1 and posts also the user_name … it will be updated in the database.

Also if he cals company/update_2

I don’t see, how rules with scenarios can stop this. But I think I don’t understand enough.

Hope of a littlebit more light in the night :slight_smile:

Jannis

Basically you need to create an ‘administration’ scenario, and declare validation rules for fields that should not be changed by user only for this scenario.

Something like




array('company_name', 'required'),

array('user_name', 'required', 'on' => 'administration'),



Then in admin controller: $model->scenario = ‘administration’;

By default, user cannot mass-assign fields that are not declared in rules (including ‘safe’ rule), so in case of form hacking the filed user_name will be just dropped.

NB: plz check this twice, I may have forgotten something.

Ok, I think I understand that mechanism.

With “Then in admin controller: $model->scenario = ‘administration’;”

I think you mean the CompanyController, or? And I create the scenario in an actionChangeUser()

(Or do you use a second Controler for the modell Company?)

And this will also create the scenario:


$model = new Company('administration');

And I need a login, otherwise Yii can’t know who the admin is. I don’t know jet how this works, but it’s weekend and I have some time :slight_smile:

Thanx and nice weekend

Jannis

Scenarios are defined in models.

By saying “Then in admin controller: $model->scenario = ‘administration’;” I meant the one where ‘secret’ fields must be available for update.

And yes, you’ll need a login (or some other way to tell users apart). There are some good docs for this (in your case auth will be pretty simple, just create another field ‘role’ in users table and check for it in beforefilter).

For example,


public function filters() {

    return array(

        'accessControl',

    );

}


public function accessRules() {

    return array(

        array('allow',

            'expression' => '$user->getState("isAdmin") == 1',

        ),

        array('deny',

            'users' => array('*'),

        ),

    );

}

(you’ll also need to create your own user identity, see how it’s done here: http://www.yiiframework.com/doc/guide/1.1/en/topics.auth)