Security

This component aids the developer in common security tasks such as password hashing and Cross-Site Request Forgery protection (CSRF).

Password Hashing

Storing passwords in plain text is a bad security practice. Anyone with access to the database will immediately have access to all user accounts thus being able to engage in unauthorized activities. To combat that, many applications use the familiar one way hashing methods ‘md5’ and ‘sha1’. However, hardware evolves each day, and becomes faster, these algorithms are becoming vulnerable to brute force attacks. These attacks are also known as rainbow tables.

安全组件使用bcrypt作为散列算法。 通过“Eksblowfish”密钥设置算法,我们可以将密码加密为slow”。 慢算法最小化了布鲁斯力攻击的影响。

Bcrypt是一种基于Blowfish对称分组密码算法的自适应哈希函数。 它还引入了一个安全性或工作因素,它决定了哈希函数生成哈希的速度。 这有效地否定了FPGA或GPU哈希技术的使用。

如果将来硬件变得更快,我们可以增加工作因素来缓解这个问题。

这个组件提供了一个简单的界面来使用算法:

<?php

use Phalcon\Mvc\Controller;

class UsersController extends Controller
{
    public function registerAction()
    {
        $user = new Users();

        $login    = $this->request->getPost('login');
        $password = $this->request->getPost('password');

        $user->login = $login;

        // Store the password hashed
        $user->password = $this->security->hash($password);

        $user->save();
    }
}

We saved the password hashed with a default work factor. A higher work factor will make the password less vulnerable as its encryption will be slow. We can check if the password is correct as follows:

<?php

use Phalcon\Mvc\Controller;

class SessionController extends Controller
{
    public function loginAction()
    {
        $login    = $this->request->getPost('login');
        $password = $this->request->getPost('password');

        $user = Users::findFirstByLogin($login);
        if ($user) {
            if ($this->security->checkHash($password, $user->password)) {
                // The password is valid
            }
        } else {
            // To protect against timing attacks. Regardless of whether a user
            // exists or not, the script will take roughly the same amount as
            // it will always be computing a hash.
            $this->security->hash(rand());
        }

        // The validation has failed
    }
}

使用带有 PHP 函数 openssl_random_pseudo_bytes 的伪随机字节生成 salt, 因此需要加载 openssl 扩展。

Cross-Site Request Forgery (CSRF) protection

This is another common attack against web sites and applications. Forms designed to perform tasks such as user registration or adding comments are vulnerable to this attack.

其思想是防止表单值被发送到应用程序之外。 为了解决这个问题,我们在每个表单中生成一个random nonce (token),在会话中添加令牌,然后在表单将数据发送回应用程序时验证令牌,将会话中的存储令牌与表单提交的令牌进行比较:

<?php echo Tag::form('session/login') ?>

    <!-- Login and password inputs ... -->

    <input type='hidden' name='<?php echo $this->security->getTokenKey() ?>'
        value='<?php echo $this->security->getToken() ?>'/>

</form>

然后在控制器的操作中,您可以检查CSRF令牌是否有效:

<?php

use Phalcon\Mvc\Controller;

class SessionController extends Controller
{
    public function loginAction()
    {
        if ($this->request->isPost()) {
            if ($this->security->checkToken()) {
                // The token is OK
            }
        }
    }
}

记住要向依赖注入器添加会话适配器,否则令牌检查将不起作用:

<?php

$di->setShared(
    'session',
    function () {
        $session = new \Phalcon\Session\Adapter\Files();

        $session->start();

        return $session;
    }
);

还建议在表单中添加captcha,以完全避免这种攻击的风险。

Setting up the component

此组件在服务容器中自动注册为security,您可以重新注册它来设置它的选项:

<?php

use Phalcon\Security;

$di->set(
    'security',
    function () {
        $security = new Security();

        // Set the password hashing factor to 12 rounds
        $security->setWorkFactor(12);

        return $security;
    },
    true
);

Random

The Phalcon\Security\Random class makes it really easy to generate lots of types of random data.

<?php

use Phalcon\Security\Random;

$random = new Random();

// ...
$bytes      = $random->bytes();

// Generate a random hex string of length $len.
$hex        = $random->hex($len);

// Generate a random base64 string of length $len.
$base64     = $random->base64($len);

// Generate a random URL-safe base64 string of length $len.
$base64Safe = $random->base64Safe($len);

// Generate a UUID (version 4).
// See https://en.wikipedia.org/wiki/Universally_unique_identifier
$uuid       = $random->uuid();

// Generate a random integer between 0 and $n.
$number     = $random->number($n);

External Resources

  • Vökuró, is a sample application that uses the Security component for avoid CSRF and password hashing, Github