好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

TEXTCUBE鸡肋读取文件漏洞 - 网站安全 - 自学php

韩国的一个博客程序TEXTCUBE  读了下发现个奇怪的问题  技术有限 希望大家点拨下!   \framework\Dispatcher.php (57行)   $part = strtok($uri['input'], '/');   // $uri['input'] == resources/locale/messages.php. if (in_array($part, array('resources','plugins','cache','skin','attach','thumbnail'))) {  //限制了读取目录 无法直接读根目录     $part = ltrim(rtrim($part == 'thumbnail' ?           preg_replace('/thumbnail/', 'cache/thumbnail', $uri['input'], 1) :           $uri['input']), '/');     $part = (($qpos = strpos($part, '?')) !== false) ? substr($part, 0, $qpos) : $part;     if(file_exists($part)) {         require_once ROOT.'/library/function/file.php';         dumpWithEtag($part); //读取 www.2cto.com         exit;     } else {         header("HTTP/1.0 404 Not Found");exit;     } }\library\function\file.php(138行)   function dumpWithEtag($path) {     $path = urldecode($path);     $qIndex = strpos($path,'?');     if( $qIndex !== false ) {         $path = substr($path,0,$qIndex);     }     /* I think, it is a bad idea to check '..' and skip.        but this is an annoyance to solve gracefully about whole HTTP request */     /* Kill them all requests with referencing parent directory */     if( strpos( $path, "/.." ) !== false ||         strpos( $path, "\\.." ) !== false || //卡在此处         strcasecmp( substr( $path, -3 ), "php" ) == 0 ||         !file_exists( $path ) ) {         header("HTTP/1.0 404 Not found");         exit;     }     $fs = stat( $path );     if( !$fs || !$fs['size'] ) { header('HTTP/1.1 404 Not Found');exit; }     $etag = sprintf( "textcube-%x", (0x1234*$fs['size'])^$fs['mtime'] );     $lastmodified = gmdate("D, j M Y H:i:s ", $fs['mtime']) . "GMT";     $length = $fs['size'];       if( !headerEtag($etag,$length,$lastmodified) ) {         //echo $path;     //exit;         header('Content-type: '.getMIMEType(null,$path));                 $f =  fopen($path,"r");         if( !$f ) {             header("HTTP/1.0 404 Not found");             exit;         }         while( ($content=fread($f,8192)) ){             echo $content;         }         fclose($f);     } } 我这里的提交格式是http://www.2cto.com /tc/index.php?resources/locale/messages.php.   后面的resources/locale/messages.php.即是$uri['input']的值   www.2cto.com 测试环境是 windows 7+apache2.0+php5.2.14  由于是windows下  所以可以绕过strcasecmp(substr( $path, -3 ), "php" ) 这句的限制  直接在php后面加个点即可       下面问题来了, 程序中限制了读取文件的几个目录   array('resources','plugins','cache','skin','attach','thumbnail')  所以要读取根目录的config肯定得跳到上层的   而dumpWithEtag函数里总共有3个过滤   分别是/.. \\.. 以及后缀是否为php       看样子很白痴的一个验证  很轻松就能绕过的  因为/..可以用\..替换  \\..更是不用说了, 所以构造了以下格式   http://127.0.0.1/tc/index.php?resources/\..\config.php.   因为最开头有一句$part = strtok($uri['input'], '/')   用来获取目录  所以在白名单目录后必须有一个/号  这格式看似是没问题的吧   但是却卡在了strpos( $path, "\\.." ) !== false   这里 百思不得其解       随后分别用了以下格式:   http://127.0.0.1/tc/index.php?resources/.\..\config.php.   http://127.0.0.1/tc/index.php?resources/1212\..\..\config.php.   通通都卡在那一句了  明明没出现\\..字符串的  为何不行呢?     --------------------------------------------------------------------------------   alibaba:在双引号 [] 里,\\ 就是\,所以这句"\\.." 就是争对\.. 而写   from:t00ls.net

查看更多关于TEXTCUBE鸡肋读取文件漏洞 - 网站安全 - 自学php的详细内容...

  阅读:38次