0

Cakephp version I'm using is 3.4.x

I have more than a dozen forms in my cakephp 3 application. I wanna implement xss filtering for all forms. What's the easiest way to do this without making changes to all form functions.

I read in one answer that, to sanitize in a view, we should use the CakePHP convenience function h($string) which will render all attempts at XSS completely harmless.

I tried this but id did not work out.

enter image description here

\src\Template\Users\view.ctp

<p><span>Address</span>: <?= h($user->address) ?></p>

Is there a way to implement xss filtering before saving data to database?

My Controller function (which cakephp baked for me) for adding a new user and his info

\src\Controller\UsersController.php

public function add(){
    $this->viewBuilder()->setLayout('admin')  ;
    $user = $this->Users->newEntity();
    if ($this->request->is('post')) {
        $user = $this->Users->patchEntity($user, $this->request->getData());
        if ($this->Users->save($user)) {
            $this->Flash->success(__('The user has been saved.'));

            return $this->redirect(['action' => 'index']);
        }
        $this->Flash->error(__('The user could not be saved. Please, try again.'));
    }
    $groups = $this->Users->Groups->find('list', ['limit' => 200]);
    $this->set(compact('user', 'groups'));
    $this->set('_serialize', ['user']);
}

\src\Model\Table\UsersTable.php

public function beforeSave(Event $event)
{
    $entity = $event->getData('entity');

    if ($entity->isNew()) {
        $hasher = new DefaultPasswordHasher();

        // Generate an API 'token'
        $entity->api_key_plain = sha1(Text::uuid());

        // Bcrypt the token so BasicAuthenticate can check
        // it during login.
        $entity->api_key = $hasher->hash($entity->api_key_plain);
    }
    return true;
}

Thanks!

version 2
  • 1,049
  • 3
  • 15
  • 36
  • How did `h()` not work for you? From your screenshot it looks like it did as it appears to have encoded the harmful script markup so that it won't run. The convenience function doesn't strip content, just ensures it is encoded correctly to prevent user input injecting potentially harmful code. – drmonkeyninja Jun 29 '17 at 08:30
  • 1
    But script tags are getting saved in the db. That's what I wanna prevent. @drmonkeyninja – version 2 Jun 29 '17 at 08:35
  • I don't believe this is something you can directly do with CakePHP. You probably need to look at stripping the tags manually in the `beforeSave`, check out the accepted answer to this: https://stackoverflow.com/questions/7130867/remove-script-tag-from-html-content. – drmonkeyninja Jun 29 '17 at 09:09

2 Answers2

0

You can use mutator method in your User Entity class:

class User extends Entity
{    
    protected function _setAddress($value) {
        return strip_tags($value);
    }
}

Using this mutator, You can modify input data before saving to database everytime, when entity is updated or created. More about mutators: https://book.cakephp.org/3.0/en/orm/entities.html#accessors-mutators

You can also use other way, but I wrote this minute ago. You should test this code if You wanna use. Using $entity->getDirty() method we can get all modified fields, and change their values in Table::beforeSave() method:

public function beforeSave($event)
{
    $entity = $event->getData('entity');

    $modified = $entity->getDirty();
    foreach((array) $modified as $v) {
        if(isset($entity->{$v})) {
            $entity->{$v} = strip_tags($entity->{$v});
        }
    }

    return true;
}    
Dariusz Majchrzak
  • 1,227
  • 2
  • 12
  • 22
0

You need to remove tag from your entity.

please check the official solution for cakephp 3.X

You need to use this in model

use Cake\Event\Event;
use ArrayObject;


public function beforeMarshal(Event $event, ArrayObject $data, ArrayObject $options)
{
    foreach ($data as $key => $value) {
        if (is_string($value)) {
            $data[$key] = trim(strip_tags($value));
        }
    }
}
Soubhagya Kumar Barik
  • 1,979
  • 20
  • 26