漏洞标题 CodeIgniter框架内核设计缺陷可能导致任意代码执行 相关厂商 CodeIgniter框架 漏洞作者 phith0n 提交时间 2016-03-11 02:00 公开时间 2016-0…
漏洞标题
CodeIgniter框架内核设计缺陷可导致任意代码执行
相关制造商
CodeIgniter框架
漏洞作者
Phith0n
提交时间
2016-03-11 02: 00
公共时间
2016-06-13 17: 20
漏洞类型
文件包含
危险等级
高
自我评估等级
15
漏洞状态
已提交给第三方合作机构(cncert National Internet Emergency Center)
标签标签
Php源码评论,白盒测试
漏洞详细信息
当CI加载模板时,它将调用$ this-> load-> view('template_name',$ data);
在内核中,查看视图函数源代码:
/system/core/Loader.php
公共函数视图($ view,$ vars=array(),$ return=FALSE)
{
返回$ this-> _ci_load(array('_ ci_view'=> $ view,'_ ci_vars'=> $ this-> _ci_object_to_array($ vars),'_ ci_return'=> $ return));
}
.
受保护的函数_ci_load($ _ ci_data)
{
//设置默认数据变量
Foreach(数组('_ ci_view','_ ci_vars','_ ci_c','_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
{
$$ _ ci_val=isset($ _ ci_data [$ _ ci_val])? $ _ci_data [$ _ ci_val]: FALSE;
}
$ file_exists=FALSE;
//设置所请求文件的路径
if(is_string($ _ ci_path)&& $ _ci_path!=='')
{
$ _ci_x=explode('/',$ _ci_path);
$ _ci_file=end($ _ ci_x);
}
其他
{
$ _ci_ext=pathinfo($ _ ci_view,PATHINFO_EXTENSION);
$ _ci_file=($ _ci_ext==='')? $ _ci_view。'。php': $ _ci_view;
Foreach($ this-> _ci_view_paths as $ _ci_view_file=> $ cascade)
{
if(file_exists($ _ ci_view_file。$ _ ci_file))
{
$ _ci_path=$ _ci_view_file。$ _ ci_file;
$ file_exists=TRUE;
打破;
}
如果(!$ cascade)
{
打破;
}
}
}
如果(!$ file_exists&&!file_exists($ _ ci_path))
{
Show_error('无法加载请求的文件:'。$ _ ci_file);
}
//这允许使用$ this->加载(视图,文件等)加载的任何内容
//可以从Controller和Model函数中访问。
$ _ci_CI=& get_instance();
Foreach(get_object_vars($ _ ci_CI)as $ _ci_key=> $ _ci_var)
{
如果(!isset($ this-> $ _ ci_key))
{
$ this-> $ _ ci_key=& $ _ci_CI-> $ _ ci_key;
}
}
/*
*提取和缓存变量
*
*您可以使用专用的$ this-> load-> vars()设置变量
*功能或通过此功能的第二个参数。我们会合并
*这两种类型并缓存它们以便嵌入其中的视图
*其他视图可以访问这些变量。
* /
如果(is_array($ _ ci_vars))
{
$ this-> _ci_cached_vars=array_merge($ this-> _ci_cached_vars,$ _ci_vars);
}
提取物($这 - > _ci_cached_vars);
/*
*缓冲输出
*
*我们缓冲输出有两个原因:
* 1.速度。你获得了显着的速度提升。
* 2.这样最终渲染的模板可以进行后处理
*输出类。为什么我们需要后期处理?一方面,
*以显示已用完的页面加载时间。
*在发送到浏览器之前拦截内容
*然后停止计时器它将不准确。
* /
Ob_start();
//如果PHP安装不支持短标签,我们会
//做一个小字符串替换,更改短标签
//到标准的PHP echo语句。
如果(!is_php('5.4')&&!ini_get('short_open_tag')&& config_item('rewrite_short_tags')===TRUE)
{
Echo eval('?>'。preg_replace('/; * \ s * \?> /',';>',str_replace('<=','<php echo',file_get_contents ($ _ci_path))));
}
其他
{
包括:($ _ ci_path); //include()vs include_once()允许多个具有相同名称的视图
}
Log_message('info','File loaded:'。$ _ ci_path);
//如果请求,则返回文件数据
如果($ _ci_return===TRUE)
{
$ buffer=ob_get_contents();
[@ob_end_clean](/ob_end_clean)();
返回$ buffer;
}
/*
*冲洗缓冲液..或者冲洗冲洗器?
*
*为了允许嵌套视图
*其他观点,我们需要在任何时候将内容刷新
*我们超出了输出缓冲的第一级别
*首先包含它可以正确看到和包含
*模板和任何后续的模板。 Oy公司!
* /
如果(ob_get_level()> $ this-> _ci_ob_level + 1)
{
ob_end_flush()函数;
}
其他
{
$ _ci_CI->输出 - > append_output(ob_get_contents());
[@ob_end_clean](/ob_end_clean)();
}
返回$ this;
}
看看这一段:
如果(is_array($ _ ci_vars))
{
$ this-> _ci_cached_vars=array_merge($ this-> _ci_cached_vars,$ _ci_vars);
}
提取物($这 - > _ci_cached_vars);
此提取将导致变量覆盖漏洞。
$ this-> _ci_cached_vars来自$ _ci_vars,$ _ci_vars是传递给view方法的用户的第二个参数。 (通常是开发人员传递给模板的变量)
我们看到背后的摘录:
提取物($这 - > _ci_cached_vars);
Ob_start();
//如果PHP安装不支持短标签,我们会
//做一个小字符串替换,更改短标签
//到标准的PHP echo语句。
如果(!is_php('5.4')&&!ini_get('short_open_tag')&& config_item('rewrite_short_tags')===TRUE)
{
Echo eval('?>'。preg_replace('/; * \ s * \?> /',';>',str_replace('<=','<php echo',file_get_contents ($ _ci_path))));
}
其他
{
包括:($ _ ci_path); //include()vs include_once()允许多个具有相同名称的视图
}
包含($ _ ci_path),$ _ci_path是模板地址,因为先前的变量覆盖会导致任何文件包含漏洞,然后是gethell。
因此,只要我们可以控制视图的第二个参数的“键值”,就传递_ci_path=文件: ///etc/passwd并在提取后覆盖原始模板地址,其中包含/etc/passwd。
此漏洞类似于http://**。**。**。**/bugs/wooyun-2014-051906,称为assign(在CI中称为$ this-> load-> vars或$ this-> )加载 - >视图)是由传入数组引起的。
漏洞证明:
以下Controller将导致漏洞:
< PHP
定义('BASEPATH')或退出('不允许直接访问脚本');
欢迎类扩展CI_Controller {
公共职能指数()
{
$ data=$ this-> input-> post();
$ this-> load-> view('welcome_message',$ data);
}
}

这也类似:
公共职能指数()
{
$ data=$ this-> input-> post('info');
$这 - >负载>瓦尔($数据);
$这 - >负载>查看( 'WELCOME_MESSAGE');
}

当包含远程文件时,您还可以直接包含php: //输入

修理计划:
用。替换提取物
Foreach($ this-> _ci_cached_vars as $ key=> $ value){
if(strpos($ key,'_ ci))!==0){
$$ key=$ value;
}
}
版权声明:请注明出处phith0n @乌云