CSRF対çç¨ã³ã³ãã¼ãã³ãã¨ãã«ãã¼
CSRF対çã®ãã¼ã¯ã³ãã§ãã¯ã¯ãçµå±èªä½ã§å
¥ããäºã«ãã¦ã
Tokenä½æããã³ãã§ãã¯ã®ã³ã³ãã¼ãã³ãã¨ãã«ãã¼ãä½æãã¾ããã
ãã©ã°ã¤ã³ã«ã¾ã¨ãã¦ãè¯ããããªã®ã§ãããè¯ãå称ãæãæµ®ãã°ãªãã®ã§ä¿ç *1
(2011/2/10 ã³ã¡ã³ãææãåãã¦ä¿®æ£ãã¾ããï¼
ä½æããã³ã³ãã¼ãã³ãã¨ãã«ãã¼ã®ã½ã¼ã¹ã¯æ«å°¾ã
Tokenã³ã³ãã¼ãã³ã
Authã³ã³ãã¼ãã³ãã®$ActionMapãè¦ã¦ãæªè¨å®/read以å¤ï¼create, delete, updateï¼ã®ã¢ã¯ã·ã§ã³ã§ããã°ãPOSTãããå ´åTokenãã§ãã¯ãè¡ãªãã
Tokenããªãããããã¯æ£ãããªãå ´åãå¦çåæ¢ã
Tokenãã«ãã¼
value=ã»ãã·ã§ã³IDã®ããã·ã¥ ã§ããhiddenã¿ã°ãåºå
æå·åã¯ããã©ã«ãmd5
ã³ã³ããã¼ã©ã»ãã¥ã¼å´ã®å¯¾å¿
Tokenãã§ãã¯ã¯app_controllerã®beforeFilterã§å®æ½ã
// 対CSRF:Tokenãã§ã㯠$this->Token->checkToken();
Tokenãå¿
è¦ãªviewã«ã¯formã¿ã°å
ã«ä»¥ä¸ã®éã追è¨ã
echo $token->create();
create/delete/updateã®ããããã ãã©ãTokenãã§ãã¯ããããªãã¢ã¯ã·ã§ã³ãããå ´åã¯ãåã
ã®ã³ã³ããã¼ã©ã«ä»¥ä¸ã®å¤æ°ãè¨å®ã
var $disableTokenActions = array('add','mobile_add');
* ã§å ¨ã¢ã¯ã·ã§ã³ã§ä¸ä½¿ç¨ã
é·æéåãã»ãã·ã§ã³IDã ã¨ç¡ç¨å¿ãªã®ã§ãæå¹æéãã¡ãã£ã¨å¤ãã¾ãã*2
- Configure::write('Session.timeout', '3600'); + Configure::write('Session.timeout', '432');
èªåã®èªè¨¼ã³ã³ãã¼ãã³ãä»æ§ã«ãªã£ã¦ãã¾ãããAuthPlusãAuthã«ç½®æããã°CakePHPããã©ã«ãã®Authã³ã³ãã¼ãã³ã対å¿ã§ä½¿ç¨ã§ããã¯ãã§ãã
å ¨å·®å
Index: controllers/components/token.php =================================================================== --- controllers/components/token.php (revision 0) +++ controllers/components/token.php (revision 0) @@ -0,0 +1,111 @@ +<?php +/** + * CSRF対çç¨Tokenãã§ãã«ã¼ + * Security.level = medium ã¾ã㯠low ã®ã¿ + */ + +class TokenComponent extends Object +{ + +/** + * Components used by TokenHelper + * + * @var array + * @access public + */ + var $components = array('Session'); + + var $_modelClass; + var $_data = array(); + var $_action; + var $_actionMap = array(); + var $type; + var $useToken = false; + var $disableActions = array(); + + function initialize(&$controller) + { + $this->_modelClass = $controller->modelClass; + $this->_action = $controller->action; + if (isset($controller->params['data'])) { + $this->_data = $controller->params['data']; + } + + if (isset($controller->AuthPlus)) { + $this->_actionMap = $controller->AuthPlus->actionMap; + } else { + return ; + } + + if (isset($this->_actionMap[$this->_action])) { + $this->type = $this->_actionMap[$this->_action]; + } + + if (!isset($controller->disableTokenActions)) { + $this->useToken = false; + } else { + $this->useToken = $this->isUseToken($controller->disableTokenActions); + } + + $this->Session->startup($controller); + } + + /* true: Token OK */ + function checkToken($tag_name = '__Token', $hash_type = 'md5') + { + if ($this->useToken === false) { + return ; + } + $hashed_session_id = $this->get_hashed_session_id(); + + if ($this->_data) { + if (!isset($this->_data[$this->_modelClass][$tag_name])) { + $this->_blackHole(); + } + if ($this->_data[$this->_modelClass][$tag_name] != $hashed_session_id) { + $this->_blackHole(); + } + } else { + return ; + } + } + + /* true:Tokenä½¿ç¨ */ + function isUseToken($disableTokenActions) + { + if ($disableTokenActions == '*') { + return false; + } + if (!$this->type || $this->type == 'read') { + return false; + } + if (in_array($this->_action, (array)$disableTokenActions)) { + return false; + } + + return true; + } + + function _blackHole($msg='') + { + if (!$msg) { + $msg = _('ILLEGAL POST!'); + } + + die($msg); + } + + /* ç¾å¨ã®ã»ãã·ã§ã³IDãæå·åãã¦åå¾ */ + function get_hashed_session_id($hash_type = 'md5') + { + $session_id = $this->Session->id(null); + + if (!$session_id) { + $this->_blackHole('No Session.'); + } + + return Security::hash($session_id. Configure::read('Security.salt'), $hash_type); + } + +} + Index: views/helpers/token.php =================================================================== --- views/helpers/token.php (revision 0) +++ views/helpers/token.php (revision 0) @@ -0,0 +1,38 @@ +<?php +/** + * CSRF対çç¨Tokenåºåãã«ãã¼ + * è¦Formãã«ãã¼ + */ + +class TokenHelper extends AppHelper { +/** + * Other helpers used by TokenHelper + * + * @var array + * @access public + */ + var $helpers = array('Form', 'Session'); + + /* Tokenãã»ããããhiddenã¿ã°åºå */ + function create($tag_name = '__Token', $hash_type = 'md5') + { + $hashed_id = $this-> get_hashed_session_id($hash_type); + + return $this->Form->input($tag_name, array( + 'type' => 'hidden', + 'value' => $hashed_id, + ) + ); + } + + /* ç¾å¨ã®ã»ãã·ã§ã³IDãæå·åãã¦åå¾ */ + function get_hashed_session_id($hash_type = 'md5') + { + $session_id = $this->Session->id(); + + return Security::hash($session_id. Configure::read('Security.salt'), $hash_type); + } + +} + +
Index: controllers/app_controller.php =================================================================== --- controllers/app_controller.php (revision 196) +++ controllers/app_controller.php (working copy) @@ -21,17 +21,23 @@ var $isAdmin = false; var $isMobile = false; var $components = array( 'AuthPlus', 'Acl', + 'Token' ); /* ACL */ // 追å ã¢ã¯ã·ã§ã³ç¨ crudMap var $actionMapPlus = array(); + // POSTã®Tokenãã§ãã¯ãããªãã¢ã¯ã·ã§ã³ + var $disableTokenActions = array(); + function beforeFilter() { parent::beforeFilter(); @@ -46,6 +52,9 @@ $this->AuthPlus->actionPath = 'controllers/'; $this->AuthPlus->authorize = 'crud'; + // 対CSRF:Tokenãã§ã㯠+ $this->Token->checkToken(); + // èªè¨¼ã¢ã¯ã·ã§ã³è¨å® if (Configure::read('mobileUserAgent')) { $this->AuthPlus->loginAction = '/m/users/login'; Index: controllers/users_controller.php =================================================================== --- controllers/users_controller.php (revision 196) +++ controllers/users_controller.php (working copy) @@ -2,7 +2,11 @@ class UsersController extends ModuleController { var $name = 'Users'; var $helpers = array( 'Html', 'Form', + 'Token' ); /* ACL */ // 追å ã¢ã¯ã·ã§ã³ç¨ crudMap @@ -11,6 +15,8 @@ 'change_password' => 'update', ); + var $disableTokenActions = array('add','mobile_add'); + function beforeFilter() { parent::beforeFilter();
--- views/users/edit.ctp (revision 197) +++ views/users/edit.ctp (working copy) @@ -7,6 +7,7 @@ 'label' => __('YourName', true), ) ); + echo $token->create(); ?> </fieldset> <?php echo $form->end('Submit');?>
--- config/core.php.sample (revision 196) +++ config/core.php.sample (working copy) @@ -122,7 +122,7 @@ * Session time out time (in seconds). * Actual value depends on 'Security.level' setting. */ - Configure::write('Session.timeout', '3600'); + Configure::write('Session.timeout', '432'); // 60 * 60 * 12 / 100 /** * If set to false, sessions are not automatically started. */
*1:æ°æã¡ã¨ãã¦ã¯Tokenãã©ã°ã¤ã³ãªã®ã§ãããå¼ã³åºããToken.Tokenã«ãªãã®ãã©ãã«ã ^^;
*2:ããããã®å¤ãåæ¥ãããã§ãã©ã¦ã¶ä¸ã§æ稿æ¸ãã¨ç¡å¹ã«ãªãã¾ãã ã»ã»ã»ãããªåã®å ¥ã£ãé·æã¯ãããã¹ãã¨ãã£ã¿ã§éæä¿åãã¤ã¤æ¸ãã¦ã³ãããã¦ãã ãããã¨ç§ã¯è¨ãããã