Yii 静态缓存varyByExpression 命令行注入排查

        根据leader要求,web版页面打开时间需要在1s内,对于目前项目依赖api的设计方案是一大考验。结合项目的实际情况以及YII的特性,考虑产品详情的基础数据做静态缓存,其它动态数据异步调用,根据方案进行设计,一个同事设计缓存key依赖时使用了varyByExpression,造成了命令行注入。具体排查过程如下:

 

1、注入表现:

http://xxx.xxxxxx.xxx/xxx/hotelPhoto?hotelid=%24%7b%40print(md5(acunetix_wvs_security_test))%7d

Yii 静态缓存varyByExpression 命令行注入排查_第1张图片

 

2、问题定位:

 Yii 静态缓存varyByExpression 命令行注入排查_第2张图片

是在页面渲染前输出内容,考虑基类或者初始化没有做参数过滤。


3、代码追踪:

A、检查基类(父类),没有发现echoprint等输出。

B、继续检查代码,在过滤器发现如下语句:

public function filters() {

        if(Yii::app()->params['allowCache']=='Y' || $_GET['nocache'] == 1){

            $index_exp = $this->_gets->getParam('hotelid', 0, true);

            $ycf_product_detail = Yii::app()->cache->get('2016_Product_detail');//缓存key后缀

            return array (

                array(

                    'YcfCOutputCache + hotelPhoto,navigation',

                    'duration' => Yii::app()->params['cacheTimeSet'],

                    'varyByExpression' => $index_exp,

                    'keySuffix' => $ycf_product_detail

                ),

            );

        }

    }

$index_exp = $this->_gets->getParam('hotelid', 0, true);这里获取参数没有过滤。

C、继续查看框架缓存的代码COutputCache.php

getCacheKey()函数有如下代码:

if($this->varyByExpression!==null)

     $key.=$this->evaluateExpression($this->varyByExpression);


查看父类CComponent.php evaluateExpression函数

public function evaluateExpression($_expression_,$_data_=array())

{

if(is_string($_expression_)){

extract($_data_);

return eval('return '.$_expression_.';');

}else{

$_data_[]=$this;

return call_user_func_array($_expression_, $_data_);

}

}

发现会直接执行输入命令,eval() 函数把字符串按照PHP 代码来计算。

 

4、解决方法:对获取的参数进行过滤$index_exp = (int)$this->_gets->getParam('hotelid', 0, true);


 

 

你可能感兴趣的:(Yii)