CodeIgniter框架内核设计缺陷可能导致任意代码执行

漏洞标题 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 @乌云