Added KH 3.3.0
This commit is contained in:
3
includes/kohana/system/guide/kohana/security/cookies.md
Normal file
3
includes/kohana/system/guide/kohana/security/cookies.md
Normal file
@@ -0,0 +1,3 @@
|
||||
Discuss security of cookies, like changing the encryption key in the config.
|
||||
|
||||
Not sure why I'm linking to this: <http://kohanaframework.org/guide/security.cookies>
|
5
includes/kohana/system/guide/kohana/security/database.md
Normal file
5
includes/kohana/system/guide/kohana/security/database.md
Normal file
@@ -0,0 +1,5 @@
|
||||
Discuss database security.
|
||||
|
||||
How to avoid injection, etc.
|
||||
|
||||
Not sure why I'm linking to this: <http://kohanaframework.org/guide/security.database>
|
31
includes/kohana/system/guide/kohana/security/deploying.md
Normal file
31
includes/kohana/system/guide/kohana/security/deploying.md
Normal file
@@ -0,0 +1,31 @@
|
||||
Changes that should happen when you deploy. (Production)
|
||||
|
||||
Security settings from: <http://kohanaframework.org/guide/using.configuration>
|
||||
|
||||
<http://kerkness.ca/wiki/doku.php?id=setting_up_production_environment>
|
||||
|
||||
|
||||
## Setting up a production environment
|
||||
|
||||
There are a few things you'll want to do with your application before moving into production.
|
||||
|
||||
1. See the [Bootstrap page](bootstrap) in the docs.
|
||||
This covers most of the global settings that would change between environments.
|
||||
As a general rule, you should enable caching and disable profiling ([Kohana::init] settings) for production sites.
|
||||
[Route::cache] can also help if you have a lot of routes.
|
||||
2. Turn on APC or some kind of opcode caching.
|
||||
This is the single easiest performance boost you can make to PHP itself. The more complex your application, the bigger the benefit of using opcode caching.
|
||||
|
||||
/**
|
||||
* Set the environment string by the domain (defaults to Kohana::DEVELOPMENT).
|
||||
*/
|
||||
Kohana::$environment = ($_SERVER['SERVER_NAME'] !== 'localhost') ? Kohana::PRODUCTION : Kohana::DEVELOPMENT;
|
||||
/**
|
||||
* Initialise Kohana based on environment
|
||||
*/
|
||||
Kohana::init(array(
|
||||
'base_url' => '/',
|
||||
'index_file' => FALSE,
|
||||
'profile' => Kohana::$environment !== Kohana::PRODUCTION,
|
||||
'caching' => Kohana::$environment === Kohana::PRODUCTION,
|
||||
));
|
107
includes/kohana/system/guide/kohana/security/encryption.md
Normal file
107
includes/kohana/system/guide/kohana/security/encryption.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Encryption
|
||||
|
||||
Kohana supports built-in encryption and decryption via the [Encrypt] class, which is a convenient wrapper for the [Mcrypt library](http://www.php.net/mcrypt).
|
||||
|
||||
To use the class, first start by ensuring you have the Mcrypt extension loaded to your PHP config. See the [Mcrypt Installation page](http://www.php.net/manual/en/mcrypt.installation.php) on php.net. The Mcrypt extension requires [libmcrypt](http://sourceforge.net/projects/mcrypt/files/).
|
||||
|
||||
Next, copy the default config/encryption.php from system/config folder to your application/config folder.
|
||||
|
||||
The default Encryption config file that ships with Kohana 3.2.x looks like this:
|
||||
|
||||
<?php defined('SYSPATH') OR die('No direct script access.');
|
||||
|
||||
return array(
|
||||
|
||||
'default' => array(
|
||||
/**
|
||||
* The following options must be set:
|
||||
*
|
||||
* string key secret passphrase
|
||||
* integer mode encryption mode, one of MCRYPT_MODE_*
|
||||
* integer cipher encryption cipher, one of the Mcrpyt cipher constants
|
||||
*/
|
||||
'cipher' => MCRYPT_RIJNDAEL_128,
|
||||
'mode' => MCRYPT_MODE_NOFB,
|
||||
),
|
||||
|
||||
);
|
||||
|
||||
|
||||
A couple of notes about the config.
|
||||
First, you may have multiple first-level keys other than 'default' if you need to.
|
||||
In this respect, the config file is similar to having multiple databases defined in your config/database.php file.
|
||||
Second, notice there is no key provided. You need to add that.
|
||||
It is strongly recommended that you choose a high-strength random key using the [pwgen linux program](http://linux.die.net/man/1/pwgen)...
|
||||
|
||||
shell> pwgen 63 1
|
||||
trwQwVXX96TIJoKxyBHB9AJkwAOHixuV1ENZmIWyanI0j1zNgSVvqywy044Agaj
|
||||
|
||||
...or by going to [GRC.com/passwords.htm](https://www.grc.com/passwords.htm).
|
||||
|
||||
## Complete Config Example
|
||||
|
||||
Here's a sample encryption configuration with three types of encryption defined. **If you copy this example, please change your keys!**
|
||||
|
||||
<?php defined('SYSPATH') OR die('No direct script access.');
|
||||
// application/config/encrypt.php
|
||||
|
||||
return array(
|
||||
|
||||
'default' => array(
|
||||
'key' => 'trwQwVXX96TIJoKxyBHB9AJkwAOHixuV1ENZmIWyanI0j1zNgSVvqywy044Agaj',
|
||||
'cipher' => MCRYPT_RIJNDAEL_128,
|
||||
'mode' => MCRYPT_MODE_NOFB,
|
||||
),
|
||||
'blowfish' => array(
|
||||
'key' => '7bZJJkmNrelj5NaKoY6h6rMSRSmeUlJuTeOd5HHka5XknyMX4uGSfeVolTz4IYy',
|
||||
'cipher' => MCRYPT_BLOWFISH,
|
||||
'mode' => MCRYPT_MODE_ECB,
|
||||
),
|
||||
'tripledes' => array(
|
||||
'key' => 'a9hcSLRvA3LkFc7EJgxXIKQuz1ec91J7P6WNq1IaxMZp4CTj5m31gZLARLxI1jD',
|
||||
'cipher' => MCRYPT_3DES,
|
||||
'mode' => MCRYPT_MODE_CBC,
|
||||
),
|
||||
);
|
||||
|
||||
You can view the available encryption ciphers and modes on your system by running...
|
||||
|
||||
shell> php -r "print_r(get_defined_constants());" | grep MCRYPT
|
||||
|
||||
For more information on Mcrypt ciphers, visit [php.net/mcrypt.ciphers](http://us3.php.net/manual/en/mcrypt.ciphers.php).
|
||||
|
||||
## Basic Usage
|
||||
|
||||
### Create an instance
|
||||
|
||||
To use the Encryption class, obtain an instance of the Encrypt class by calling it's *instance* method,
|
||||
optionally passing the desired configuration group. If you do not pass a config group to the instance method,
|
||||
the default group will be used.
|
||||
|
||||
$encrypt = Encrypt::instance('tripledes');
|
||||
|
||||
### Encoding Data
|
||||
|
||||
Next, encode some data using the *encode* method:
|
||||
|
||||
$encrypt = Encrypt::instance('tripledes');
|
||||
$encrypted_data = $encrypt->encode('Data to Encode');
|
||||
// $encrypted_data now contains pCD5Z6oVdb9hbLxxV+FgGrhwVzZuhQoH
|
||||
|
||||
[!!] Raw encrypted strings usually won't print in a browser, and may not store properly in a VARCHAR or TEXT field. For this reason, Kohana's Encrypt class automatically calls base64_encode on encode, and base64_decode on decode, to prevent this problem.
|
||||
|
||||
[!!] One word of caution. The length of the encoded data expands quite a bit, so be sure your database column is long enough to store the encrypted data. If even one character is truncated, the data will not be recoverable.
|
||||
|
||||
### Decoding Data
|
||||
|
||||
To decode some data, load it from the place you stored it (most likely your database) then pass it to the *decode* method:
|
||||
|
||||
$encrypt = Encrypt::instance('tripledes');
|
||||
$decoded_string = $encrypt->decode($encrypted_data);
|
||||
echo $decoded_string;
|
||||
// prints 'Data to Encode'
|
||||
|
||||
You can't know in advance what the encoded string will be, and it's not reproducible, either.
|
||||
That is, you can encode the same value over and over, but you'll always obtain a different encoded version,
|
||||
even without changing your key, cipher and mode. This is because Kohana adds some random entropy before encoding it with your value.
|
||||
This ensures an attacker cannot easily discover your key and cipher, even given a collection of encoded values.
|
266
includes/kohana/system/guide/kohana/security/validation.md
Normal file
266
includes/kohana/system/guide/kohana/security/validation.md
Normal file
@@ -0,0 +1,266 @@
|
||||
# Validation
|
||||
|
||||
*This page needs to be reviewed for accuracy by the development team. Better examples would be helpful.*
|
||||
|
||||
Validation can be performed on any array using the [Validation] class. Labels and rules can be attached to a Validation object by the array key, called a "field name".
|
||||
|
||||
labels
|
||||
: A label is a human-readable version of the field name.
|
||||
|
||||
rules
|
||||
: A rule is a callback or closure used to decide whether or not to add an error to a field
|
||||
|
||||
[!!] Note that any valid [PHP callback](http://php.net/manual/language.pseudo-types.php#language.types.callback) can be used as a rule.
|
||||
|
||||
Using `TRUE` as the field name when adding a rule will be applied to all named fields.
|
||||
|
||||
Creating a validation object is done using the [Validation::factory] method:
|
||||
|
||||
$object = Validation::factory($array);
|
||||
|
||||
[!!] The `$object` object will be used for the rest of this tutorial. This tutorial will show you how to validate the registration of a new user.
|
||||
|
||||
## Provided Rules
|
||||
|
||||
Kohana provides a set of useful rules in the [Valid] class:
|
||||
|
||||
Rule name | Function
|
||||
------------------------- |-------------------------------------------------
|
||||
[Valid::not_empty] | Value must be a non-empty value
|
||||
[Valid::regex] | Match the value against a regular expression
|
||||
[Valid::min_length] | Minimum number of characters for value
|
||||
[Valid::max_length] | Maximum number of characters for value
|
||||
[Valid::exact_length] | Value must be an exact number of characters
|
||||
[Valid::email] | An email address is required
|
||||
[Valid::email_domain] | Check that the domain of the email exists
|
||||
[Valid::url] | Value must be a URL
|
||||
[Valid::ip] | Value must be an IP address
|
||||
[Valid::phone] | Value must be a phone number
|
||||
[Valid::credit_card] | Require a credit card number
|
||||
[Valid::date] | Value must be a date (and time)
|
||||
[Valid::alpha] | Only alpha characters allowed
|
||||
[Valid::alpha_dash] | Only alpha and hyphens allowed
|
||||
[Valid::alpha_numeric] | Only alpha and numbers allowed
|
||||
[Valid::digit] | Value must be an integer digit
|
||||
[Valid::decimal] | Value must be a decimal or float value
|
||||
[Valid::numeric] | Only numeric characters allowed
|
||||
[Valid::range] | Value must be within a range
|
||||
[Valid::color] | Value must be a valid HEX color
|
||||
[Valid::matches] | Value matches another field value
|
||||
|
||||
## Adding Rules
|
||||
|
||||
All validation rules are defined as a field name, a method, a function (using the [PHP callback](http://php.net/callback) syntax) or [closure](http://php.net/manual/functions.anonymous.php), and an array of parameters:
|
||||
|
||||
$object->rule($field, $callback, array($parameter1, $parameter2));
|
||||
|
||||
If no parameters are specified, the field value will be passed to the callback. The following two rules are equivalent:
|
||||
|
||||
$object->rule($field, 'not_empty');
|
||||
$object->rule($field, 'not_empty', array(':value'));
|
||||
|
||||
Rules defined in the [Valid] class can be added by using the method name alone. The following three rules are equivalent:
|
||||
|
||||
$object->rule('number', 'phone');
|
||||
$object->rule('number', array('Valid', 'phone'));
|
||||
$object->rule('number', 'Valid::phone');
|
||||
|
||||
### Adding Rules for multiple fields together
|
||||
|
||||
To validate multiple fields together, you can do something like this:
|
||||
|
||||
$object->rule('one', 'only_one', array(':validation', array('one', 'two')));
|
||||
$object->rule('two', 'only_one', array(':validation', array('one', 'two')));
|
||||
|
||||
public function only_one($validation, $fields)
|
||||
{
|
||||
// If more than 1 field is set, bail.
|
||||
$matched = 0;
|
||||
|
||||
foreach ($fields as $field)
|
||||
{
|
||||
if (isset($validation[$field]))
|
||||
{
|
||||
$matched++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($matched > 0)
|
||||
{
|
||||
// Add the error to all concerned fields
|
||||
foreach ($fields as $field)
|
||||
{
|
||||
$validation->error($field, 'only_one');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
## Binding Variables
|
||||
|
||||
The [Validation] class allows you to bind variables to certain strings so that they can be used when defining rules. Variables are bound by calling the [Validation::bind] method.
|
||||
|
||||
$object->bind(':model', $user_model);
|
||||
// Future code will be able to use :model to reference the object
|
||||
$object->rule('username', 'some_rule', array(':model'));
|
||||
|
||||
By default, the validation object will automatically bind the following values for you to use as rule parameters:
|
||||
|
||||
- `:validation` - references the validation object
|
||||
- `:field` - references the field name the rule is for
|
||||
- `:value` - references the value of the field the rule is for
|
||||
|
||||
## Adding Errors
|
||||
|
||||
The [Validation] class will add an error for a field if any of the rules associated to it return `FALSE`. This allows many built in PHP functions to be used as rules, like `in_array`.
|
||||
|
||||
$object->rule('color', 'in_array', array(':value', array('red', 'green', 'blue')));
|
||||
|
||||
Rules added to empty fields will run, but returning `FALSE` will not automatically add an error for the field. In order for a rule to affect empty fields, you must add the error manually by calling the [Validation::error] method. In order to do this, you must pass the validation object to the rule.
|
||||
|
||||
$object->rule($field, 'the_rule', array(':validation', ':field'));
|
||||
|
||||
public function the_rule($validation, $field)
|
||||
{
|
||||
if (something went wrong)
|
||||
{
|
||||
$validation->error($field, 'the_rule');
|
||||
}
|
||||
}
|
||||
|
||||
[!!] `not_empty` and `matches` are the only rules that will run on empty fields and add errors by returning `FALSE`.
|
||||
|
||||
## Example
|
||||
|
||||
To start our example, we will perform validation on the HTTP POST data of the current request that contains user registration information:
|
||||
|
||||
[!!] In Kohana controllers, we access `$this->request->post()` instead of `$_POST` for better request isolation.
|
||||
|
||||
$object = Validation::factory($this->request->post());
|
||||
|
||||
Next we need to process the POST'ed information using [Validation]. To start, we need to add some rules:
|
||||
|
||||
$object
|
||||
->rule('username', 'not_empty')
|
||||
->rule('username', 'regex', array(':value', '/^[a-z_.]++$/iD'))
|
||||
->rule('password', 'not_empty')
|
||||
->rule('password', 'min_length', array(':value', '6'))
|
||||
->rule('confirm', 'matches', array(':validation', 'confirm', 'password'))
|
||||
->rule('use_ssl', 'not_empty');
|
||||
|
||||
Any existing PHP function can also be used a rule. For instance, if we want to check if the user entered a proper value for the SSL question:
|
||||
|
||||
$object->rule('use_ssl', 'in_array', array(':value', array('yes', 'no')));
|
||||
|
||||
Note that all array parameters must still be wrapped in an array! Without the wrapping array, `in_array` would be called as `in_array($value, 'yes', 'no')`, which would result in a PHP error.
|
||||
|
||||
Any custom rules can be added using a [PHP callback](http://php.net/manual/language.pseudo-types.php#language.types.callback]:
|
||||
|
||||
$object->rule('username', 'User_Model::unique_username');
|
||||
|
||||
The method `User_Model::unique_username()` would be defined similar to:
|
||||
|
||||
public static function unique_username($username)
|
||||
{
|
||||
// Check if the username already exists in the database
|
||||
return ! DB::select(array(DB::expr('COUNT(username)'), 'total'))
|
||||
->from('users')
|
||||
->where('username', '=', $username)
|
||||
->execute()
|
||||
->get('total');
|
||||
}
|
||||
|
||||
[!!] Custom rules allow many additional checks to be reused for multiple purposes. These methods will almost always exist in a model, but may be defined in any class.
|
||||
|
||||
# A Complete Example
|
||||
|
||||
First, we need a [View] that contains the HTML form, which will be placed in `application/views/user/register.php`:
|
||||
|
||||
<?php echo Form::open() ?>
|
||||
<?php if ($errors): ?>
|
||||
<p class="message">Some errors were encountered, please check the details you entered.</p>
|
||||
<ul class="errors">
|
||||
<?php foreach ($errors as $message): ?>
|
||||
<li><?php echo $message ?></li>
|
||||
<?php endforeach ?>
|
||||
<?php endif ?>
|
||||
|
||||
<dl>
|
||||
<dt><?php echo Form::label('username', 'Username') ?></dt>
|
||||
<dd><?php echo Form::input('username', $post['username']) ?></dd>
|
||||
|
||||
<dt><?php echo Form::label('password', 'Password') ?></dt>
|
||||
<dd><?php echo Form::password('password') ?></dd>
|
||||
<dd class="help">Passwords must be at least 6 characters long.</dd>
|
||||
<dt><?php echo Form::label('confirm', 'Confirm Password') ?></dt>
|
||||
<dd><?php echo Form::password('confirm') ?></dd>
|
||||
|
||||
<dt><?php echo Form::label('use_ssl', 'Use extra security?') ?></dt>
|
||||
<dd><?php echo Form::select('use_ssl', array('yes' => 'Always', 'no' => 'Only when necessary'), $post['use_ssl']) ?></dd>
|
||||
<dd class="help">For security, SSL is always used when making payments.</dd>
|
||||
</dl>
|
||||
|
||||
<?php echo Form::submit(NULL, 'Sign Up') ?>
|
||||
<?php echo Form::close() ?>
|
||||
|
||||
[!!] This example uses the [Form] helper extensively. Using [Form] instead of writing HTML ensures that all of the form inputs will properly handle input that includes HTML characters. If you prefer to write the HTML yourself, be sure to use [HTML::chars] to escape user input.
|
||||
|
||||
Next, we need a controller and action to process the registration, which will be placed in `application/classes/Controller/User.php`:
|
||||
|
||||
class Controller_User extends Controller {
|
||||
|
||||
public function action_register()
|
||||
{
|
||||
$user = Model::factory('user');
|
||||
|
||||
$validation = Validation::factory($this->request->post())
|
||||
->rule('username', 'not_empty')
|
||||
->rule('username', 'regex', array(':value', '/^[a-z_.]++$/iD'))
|
||||
->rule('username', array($user, 'unique_username'))
|
||||
|
||||
->rule('password', 'not_empty')
|
||||
->rule('password', 'min_length', array(':value', 6))
|
||||
->rule('confirm', 'matches', array(':validation', ':field', 'password'))
|
||||
|
||||
->rule('use_ssl', 'not_empty')
|
||||
->rule('use_ssl', 'in_array', array(':value', array('yes', 'no')));
|
||||
|
||||
if ($validation->check())
|
||||
{
|
||||
// Data has been validated, register the user
|
||||
$user->register($this->request->post());
|
||||
|
||||
// Always redirect after a successful POST to prevent refresh warnings
|
||||
$this->redirect('user/profile', 302);
|
||||
}
|
||||
|
||||
// Validation failed, collect the errors
|
||||
$errors = $validation->errors('user');
|
||||
|
||||
// Display the registration form
|
||||
$this->response->body(View::factory('user/register'))
|
||||
->bind('post', $this->request->post())
|
||||
->bind('errors', $errors);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
We will also need a user model, which will be placed in `application/classes/Model/User.php`:
|
||||
|
||||
class Model_User extends Model {
|
||||
|
||||
public function register($array)
|
||||
{
|
||||
// Create a new user record in the database
|
||||
$id = DB::insert(array_keys($array))
|
||||
->values($array)
|
||||
->execute();
|
||||
|
||||
// Save the new user id to a cookie
|
||||
cookie::set('user', $id);
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
That is it, we have a complete user registration example that properly checks user input!
|
17
includes/kohana/system/guide/kohana/security/xss.md
Normal file
17
includes/kohana/system/guide/kohana/security/xss.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Cross-Site Scripting (XSS) Security
|
||||
|
||||
*This page is not comprehensive and should not be considered a complete guide to XSS prevention.*
|
||||
|
||||
The first step to preventing [XSS](http://wikipedia.org/wiki/Cross-Site_Scripting) attacks is knowing when you need to protect yourself. XSS can only be triggered when it is displayed within HTML content, sometimes via a form input or being displayed from database results. Any global variable that contains client information can be tainted. This includes `$_GET`, `$_POST`, and `$_COOKIE` data.
|
||||
|
||||
## Prevention
|
||||
|
||||
There are a few simple rules to follow to guard your application HTML against XSS. If you do not want HTML in a variable, use [strip_tags](http://php.net/strip_tags) to remove all unwanted HTML tags from a value.
|
||||
|
||||
[!!] If you allow users to submit HTML to your application, it is highly recommended to use an HTML cleaning tool such as [HTML Purifier](http://htmlpurifier.org/) or [HTML Tidy](http://php.net/tidy).
|
||||
|
||||
The second is to always escape data when inserting into HTML. The [HTML] class provides generators for many common tags, including script and stylesheet links, anchors, images, and email (mailto) links. Any untrusted content should be escaped using [HTML::chars].
|
||||
|
||||
## References
|
||||
|
||||
* [OWASP XSS Cheat Sheet](http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet)
|
Reference in New Issue
Block a user