mirror of
https://github.com/getgrav/grav.git
synced 2026-06-04 13:14:30 +02:00
Add nonce functionality
This commit is contained in:
@@ -94,14 +94,17 @@ class TwigExtension extends \Twig_Extension
|
||||
new \Twig_simpleFunction('authorize', [$this, 'authorize']),
|
||||
new \Twig_SimpleFunction('debug', [$this, 'dump'], ['needs_context' => true, 'needs_environment' => true]),
|
||||
new \Twig_SimpleFunction('dump', [$this, 'dump'], ['needs_context' => true, 'needs_environment' => true]),
|
||||
new \Twig_SimpleFunction('evaluate', [$this, 'evaluateFunc']),
|
||||
new \Twig_SimpleFunction('gist', [$this, 'gistFunc']),
|
||||
new \Twig_SimpleFunction('nonce_field', [$this, 'nonceFieldFunc']),
|
||||
new \Twig_simpleFunction('random_string', [$this, 'randomStringFunc']),
|
||||
new \Twig_SimpleFunction('repeat', [$this, 'repeatFunc']),
|
||||
new \Twig_SimpleFunction('string', [$this, 'stringFunc']),
|
||||
new \Twig_simpleFunction('t', [$this, 'translate']),
|
||||
new \Twig_simpleFunction('ta', [$this, 'translateArray']),
|
||||
new \Twig_SimpleFunction('url', [$this, 'urlFunc']),
|
||||
new \Twig_SimpleFunction('evaluate', [$this, 'evaluateFunc']),
|
||||
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
@@ -595,4 +598,24 @@ class TwigExtension extends \Twig_Extension
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to add a nonce to a form. Call {{ nonce_field('action') }} specifying a string representing the action.
|
||||
*
|
||||
* For maximum protection, ensure that the string representing the action is as specific as possible.
|
||||
*
|
||||
* @todo evaluate if adding referrer or not
|
||||
*
|
||||
* @param string action the action
|
||||
* @param string nonceParamName a custom nonce param name
|
||||
*
|
||||
* @return string the nonce input field
|
||||
*/
|
||||
public function nonceFieldFunc($action, $nonceParamName = 'nonce')
|
||||
{
|
||||
$string = '<input type="hidden" id="' . $nonceParamName . '" name="' . $nonceParamName . '" value="' . Utils::getNonce($action) .'" />';
|
||||
// $string += '<input type="hidden" name="_grav_http_referer" value="/admin/pages/test-page" />';
|
||||
return $string;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -572,4 +572,20 @@ class Uri
|
||||
return $normalized_url;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the nonce to a URL for a specific action
|
||||
*
|
||||
* @param string $url the url
|
||||
* @param string $action the action
|
||||
* @param string $nonceParamName the param name to use
|
||||
*
|
||||
* @return string the url with the nonce
|
||||
*/
|
||||
public static function addNonce($url, $action, $nonceParamName = 'nonce')
|
||||
{
|
||||
$nonce = Utils::getNonce($action);
|
||||
$urlWithNonce = $url . '/' . $nonceParamName . self::getGrav()['config']->get('system.param_sep', ':') . $nonce;
|
||||
return $urlWithNonce;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,7 +384,101 @@ abstract class Utils
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isPositive($value) {
|
||||
public static function isPositive($value)
|
||||
{
|
||||
return in_array($value, [true, 1, '1', 'yes', 'on', 'true'], true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a nonce string to be hashed. Called by self::getNonce()
|
||||
*
|
||||
* @param string $action
|
||||
* @param bool $plusOneTick if true, generates the token for the next tick (the next 12 hours)
|
||||
*
|
||||
* @return string the nonce string
|
||||
*/
|
||||
private static function generateNonceString($action, $plusOneTick)
|
||||
{
|
||||
$user = self::getGrav()['user'];
|
||||
$username = $user->username;
|
||||
|
||||
if ( ! $username ) {
|
||||
$username = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
|
||||
}
|
||||
|
||||
$token = session_id();
|
||||
$i = self::nonceTick();
|
||||
|
||||
if ($plusOneTick) {
|
||||
$i++;
|
||||
}
|
||||
|
||||
return ( $i . '|' . $action . '|' . $username . '|' . $token );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time-dependent variable for nonce creation.
|
||||
*
|
||||
* @todo now a tick lasts a day. Once the day is passed, the nonce is not valid any more. Find a better way
|
||||
* to ensure nonces issued near the end of the day do not expire in that small amount of time
|
||||
*
|
||||
* @return int the time part of the nonce. Changes once every 24 hours
|
||||
*/
|
||||
private static function nonceTick()
|
||||
{
|
||||
$secondsInHalfADay = 60 * 60 * 12;
|
||||
return (int)ceil(time() / ( $secondsInHalfADay ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hash of given string. Uses BCrypt. The salt is taken from system.security.default_hash
|
||||
*
|
||||
* @param string $data string to hash
|
||||
*
|
||||
* @return string hashed value of $data, cut to 10 characters
|
||||
*/
|
||||
private static function hash($data)
|
||||
{
|
||||
$hash = password_hash($data, PASSWORD_BCRYPT, ['salt' => self::getGrav()['config']->get('system.security.default_hash')]);
|
||||
$hash = substr($hash, -12, 10);
|
||||
return $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a hashed nonce tied to the passed action. Tied to the current user and time. The nonce for a given
|
||||
* action is the same for 12 hours.
|
||||
*
|
||||
* @param string $action the action the nonce is tied to (e.g. save-user-admin or move-page-homepage)
|
||||
* @param bool $plusOneTick if true, generates the token for the next tick (the next 12 hours)
|
||||
*
|
||||
* @return string the nonce, a 10 characters string
|
||||
*/
|
||||
public static function getNonce($action, $plusOneTick = false)
|
||||
{
|
||||
$nonce = self::hash(self::generateNonceString($action, $plusOneTick));
|
||||
return $nonce;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the passed nonce for the give action
|
||||
*
|
||||
* @param string $nonce the nonce to verify
|
||||
* @param string $action the action to verify the nonce to
|
||||
*
|
||||
* @return boolean verified or not
|
||||
*/
|
||||
public static function verifyNonce($nonce, $action)
|
||||
{
|
||||
if ($nonce == self::getNonce($action)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$plusOneTick = true;
|
||||
if ($nonce == self::getNonce($action, $plusOneTick)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user