Security module

Installation

Install the Ubiquity-security module from the command prompt or from the Webtools (Composer part).

composer require phpmv/ubiquity-security

Then activate the display of the Security part in the Webtools:

../_images/display-security.png

Session CSRF

The session is by default protected against CSRF attacks via the VerifyCsrfToken class (even without the Ubiquity-security module).
A token instance (CSRFToken) is generated at the session startup. The validity of the token is then checked via a cookie at each request.

../_images/security-part.png

This protection can be customized by creating a class implementing the VerifySessionCsrfInterface.

app/session/MyCsrfProtection.php
class MyCsrfProtection implements VerifySessionCsrfInterface {
   private AbstractSession $sessionInstance;

   public function __construct(AbstractSession $sessionInstance) {
      $this->sessionInstance = $sessionInstance;
   }

   public function init() {
      //TODO when the session starts
   }

   public function clear() {
      //TODO when the session ends
   }

   public function start() {
      //TODO When the session starts or is resumed
   }

   public static function getLevel() {
      return 1; //An integer to appreciate the level of security
   }
}

Starting the custom protection in services:

app/config/services.php
use Ubiquity\utils\http\session\PhpSession;
use Ubiquity\controllers\Startup;
use app\session\MyCsrfProtection;

Startup::setSessionInstance(new PhpSession(new MyCsrfProtection()));

Deactivating the protection

If you do not need to protect your session against Csrf attacks, start the session with the NoCsrfProtection class.

app/config/services.php
use Ubiquity\utils\http\session\PhpSession;
use Ubiquity\controllers\Startup;
use Ubiquity\utils\http\session\protection\NoCsrfProtection;

Startup::setSessionInstance(new PhpSession(new NoCsrfProtection()));

CSRF manager

The CsrfManager service can be started directly from the webtools interface.
Its role is to provide tools to protect sensitive routes from Csrf attacks (the ones that allow the validation of forms for example).

../_images/csrf-manager-started.png
  • The service is started in the services.php file.
app/config/services.php
 \Ubiquity\security\csrf\CsrfManager::start();

Example of form protection:

The form view:

<form id="frm-bar" action='/submit' method='post'>
   {{ csrf('frm-bar') }}
   <input type='text' id='sensitiveData' name='sensitiveData'>
</form>

The csrf method generates a token for the form (By adding a hidden field in the form corresponding to the token.).

The form submitting in a controller:

use Ubiquity\security\csrf\UCsrfHttp;

#[Post('/submit')]
public function submit(){
   if(UCsrfHttp::isValidPost('frm-bar')){
      //Token is valid! => do something with post datas
   }
}

Note

It is also possible to manage this protection via cookie.

Example of protection with ajax:

The meta field csrf-token is generated on all pages.

app/controllers/BaseController.php
abstract class ControllerBase extends Controller{
   protected $headerView = "@activeTheme/main/vHeader.html";
   protected $footerView = "@activeTheme/main/vFooter.html";

   public function initialize() {
      if (! URequest::isAjax ()) {
         $meta=UCsrfHttp::getTokenMeta('postAjax');
         $this->loadView ( $this->headerView,['meta'=>$meta] );
      }
   }
}

This field is added in the headerView:

app/views/main/vHeader.html
{% block header %}
   <base href="{{config["siteUrl"]}}">
   <meta charset="UTF-8">
   <link rel="icon" href="data:;base64,iVBORw0KGgo=">
   {{meta | raw}}
   <title>Tests</title>
{% endblock %}

Example with a button posting data via ajax. The parameter csrf is set to true. So when the request is posted, the csrf-token is sent in the request headers.

#[Get(path: "/ajax")]
public function ajax(){
   $this->jquery->postOnClick('#bt','/postAjax','{id:55}','#myResponse',['csrf'=>true]);
   $this->jquery->renderDefaultView();
}

The submitting route can check the presence and validity of the token:

#[Post(path: "postAjax")]
public function postAjax(){
   if(UCsrfHttp::isValidMeta('postAjax')){
      var_dump($_POST);
   }else{
      echo 'invalid or absent meta csrf-token';
   }
}

Encryption manager

The EncryptionManager service can be started directly from the webtools interface.

  • In this case, a key is generated in the configuration file app/config/config.php.
  • The service is started in the services.php file.
app/config/services.php
 \Ubiquity\security\data\EncryptionManager::start($config);

Note

By default, encryption is performed in AES-128.

../_images/encryption-manager-started.png

Changing the cipher:

Upgrade to AES-256:

app/config/services.php
\Ubiquity\security\data\EncryptionManager::startProd($config, Encryption::AES256);

Generate a new key:

Ubiquity new:key 256

The new key is generated in the app/config/config.php file.

Model data encryption

The Crypt transformer can also be used on the members of a model:

app/models/User.php
 class Foo{
     #[Transformer(name: "crypt")]
     private $secret;
     ...
 }

Usage:

$o=new Foo();
$o->setSecret('bar');
TransformersManager::transformInstance($o);// secret member is encrypted

Generic Data encryption

Strings encryption:

$encryptedBar=EncryptionManager::encryptString('bar');

To then decrypt it:

echo EncryptionManager::decryptString($encryptedBar);

It is possible to encrypt any type of data:

$encryptedUser=EncryptionManager::encrypt($user);

To then decrypt it, with possible serialisation/deserialisation if it is an object:

$user=EncryptionManager::decrypt($encryptedUser);

Password management

Users token