Codeigniter始终未完全修复的文件包含漏洞
Codeigniter介绍
Codeigniter是一款非常流行的PHP框架。我也曾经用这个框架开发了不少项目,因为结构简单,没有Laravel等框架那么复杂,在PHP开发圈使用量也比较大。
目前最新稳定版本是3.1.10。
文件包含漏洞
偶然翻到2016年PHITHON牛发过的《codeigniter框架内核设计缺陷可能导致任意代码执行》文章:这是一个因为extract()
变量覆盖+include()
文件包含的文件包含漏洞(某些条件下可以升级为任意代码执行)。
这个漏洞的原理想了解的人可以看一下PHITHON这篇文章,这里简单说几句。
在Codeigniter当中,Controller向模板传递变量有三种方式:
1 | <?php |
这3种传参方式当中,任何一个数组的key可控,或者第一个参数可控,都可以读取任意文件:
1 | <?php |
问题就是如果用户能传入_ci_path
这个参数,那么在system/core/Loader.php的代码:
1 | protected function _ci_load($_ci_data) |
extract()
就会造成$_ci_path被覆盖,从而include($_ci_path)
变成任意文件包含漏洞。
这里重点看一下官方对这个问题的处理方式。
这个漏洞官方在版本3.0.5
进行了修复,修复方式如下(查看):1
2
3
4
5
6
7
8
9
10
11
12if (is_array($_ci_vars))
{
foreach (array_keys($_ci_vars) as $key)
{
if (strncmp($key, '_ci_', 4) === 0)
{
unset($_ci_vars[$key]);
}
}
$this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
}
extract($this->_ci_cached_vars);
添加了一个$_ci_vars
的检测逻辑,如果$_ci_vars
是数组,并且它的key开头为_ci_
,就unset
掉这个变量,这样我们提交的_ci_path=/etc/passwd
就不能用了,从而解决了漏洞。
但是这个函数只是用来处理上面三中传递模板的方式的第一种的(Test1
)。
Test2
和Test3
两种方式的传参方法:
1 | public function vars($vars, $val = '') |
并未做任何处理,也就是说Test2
和Test3
两种方式依然存在漏洞。
官方的这个修复方式在版本3.1.3
出现了变更。
取消了上面的检测代码,新添加了一个_ci_prepare_view_vars
方法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17protected function _ci_prepare_view_vars($vars)
{
if ( ! is_array($vars))
{
$vars = is_object($vars)
? get_object_vars($object)
: array();
}
foreach (array_keys($vars) as $key)
{
if (strncmp($key, '_ci_', 4) === 0)
{
unset($vars[$key]);
}
}
return $vars;
}
这个方法,在两个地方进行了调用,第一个是:
1 | public function view($view, $vars = array(), $return = FALSE) |
上面对Test1
的调用方式进行了修复。
1 | public function vars($vars, $val = '') |
上面对Test2
和Test3
的利用方式进行了修复。
这么看来问题是都修复了。
问题就在于上面的代码,用了一个三目运算符:
1 | $vars = is_string($vars) |
这意思就是说:$this->load->var($param)
这种方式,如果$param
是数组才会进行$this->_ci_prepare_view_vars($param)
处理。
如果是字符串就直接放过了,也就以下情况不处。也就是说Test3
的利用方式没做过滤。
1 | public function Test3() |
直到最新稳定版,这个问题依然存在。
当然直接这么写代码的情况比较少,但是审计的项目多了,你会发现,你所理解的少的写法,在项目代码当中都可能会遇到。
并且这个问题在某些复杂的业务逻辑问题下,依然可能会转化成这个代码模式。
- 本文链接:http://l4yn3.github.io/2019/04/17/Codeigniter始终未完全修复的文件包含漏洞/
- 版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN 许可协议。转载请注明出处!