FleaPHP默认上传类的一个隐患

Published on 2007 - 05 - 30

随着各种开发框架的盛行,程序员也不愿意做那么多重复的事情了,开发,速度最重要.现在开发什么东西都讲究一个效率.
目前国内似乎还没有多少人对框架的安全性有多少研究.毕竟如果一个底层的编程框架出了问题,很多程序都将受到威胁.
我下了个国内现在很流行的php框架中一个:FleaPHP 1.0.70 beta.翻了翻他的FLEA/FLEA/Helper/FileUploader.php,这个是此框架默认的文件上传类.它有一个检查上传文件是否合法的函数:

function check($allowExts = null, $maxSize = null)
{
if (!$this->isSuccessed()) { return false; }
//允许上传的扩展名
if ($allowExts) {
if (strpos($allowExts, ',')) {
$exts = explode(',', $allowExts);
}
elseif (strpos($allowExts, '/')) {
$exts = explode('/', $allowExts);
}
elseif (strpos($allowExts, '|')) {
$exts = explode('|', $allowExts);
}
else {
$exts = array($allowExts);
}

$fileExt = strtolower($this->getExt());//获取扩展名
$passed = false;
$exts = array_filter(array_map('trim', $exts), 'trim');
foreach ($exts as $ext) {
if (substr($ext, 0, 1) == '.') {
$ext = substr($ext, 1);
}
if ($fileExt == strtolower($ext)) {
$passed = true;
break;
}
}
if (!$passed) {
return false;
}
}

if ($maxSize && $this->getSize() > $maxSize) {
return false;
}

return true;
}

再看getExt函数:

function getExt()
{
if ($this->isMoved()) {
return pathinfo($this->getNewPath(), PATHINFO_EXTENSION);
}
else {
return pathinfo($this->getFilename(), PATHINFO_EXTENSION);
}
}

继续跟踪php的pathinfo函数:

/* {{{ proto array pathinfo(string path[, int options])
Returns information about a certain string
*/

PHP_FUNCTION(pathinfo)
{
zval
*tmp;
char *path, *ret = NULL;
int path_len, have_basename;
size_t ret_len;
long opt = PHP_PATHINFO_ALL;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &path, &path_len, &opt) == FAILURE) {
return;
}


have_basename
= ((opt & PHP_PATHINFO_BASENAME) == PHP_PATHINFO_BASENAME);

MAKE_STD_ZVAL(tmp);
array_init(tmp);

......
......

if ((opt & PHP_PATHINFO_EXTENSION) == PHP_PATHINFO_EXTENSION) {
char *p;
int idx;

if (!have_basename) {
php_basename(path, path_len, NULL,
0, &ret, &ret_len TSRMLS_CC);
}


p
= zend_memrchr(ret, '.', ret_len);

if (p) {
idx
= p - ret;
add_assoc_stringl(tmp,
"extension", ret + idx + 1, ret_len - idx - 1, 1);
}

}


......
......

zval_ptr_dtor(
&tmp);
}

/* }}} */

到这里明白了,原来都只看文件名最后一个 "." 之后的部分作为文件的扩展名.那么如果根据apache的一个特性,我们可以使用多扩展名的方式上传php文件而绕过验证.(比如允许的扩展名里有rar,pdf等apache不认识但常见的类型,我们就可以上传shell.php.rar并得以执行)

当然这个只是个安全隐患而已.并不是所有用FleaPHP的程序都有这个问题.
就像superhei说的那样,关键在于看开发者如何去使用框架,不能太过依赖于框架提供的函数.而必须自己做些必要的前提验证.就能避免漏洞

Comments
Write a Comment