请选择 进入手机版 | 继续访问电脑版
收藏本站腾讯微博新浪微博
点点网模板设计大赛 phpchina

经典论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

蓝色理想 最新研发动态 用悬赏 三天解决问题 解决访问速度慢 论坛支持农历生日 - 给官方提建议

论坛活动及任务 归纳网站最新活动 地图任务 邮件更新任务:保护帐号安全

积分换实物,来参加蓝色理想积分兑换吧! 联系招聘客服 蓝色理想帮你找工作! 万元奖励等你拿——点点网模板设计大赛

查看: 4674|回复: 19

[php] 上传 文件头检查 [复制链接]

xling 楼主

艾克司令

荣誉管理

帖子
4230
体力
14923
威望
90
居住地
广东省 深圳市
发表于 2007-11-30 11:39:10 |显示全部楼层
各位达人,
有没有上传时,对文件头检查,以判断是不是真实的文件类型的例子?

谢谢。
我搜了老久,还没有找到。
xling.cnblogs.com
西部数码顶级域名注册商39元抢注!
帖子
1243
体力
3635
威望
1
居住地
山东省 济南市
发表于 2007-11-30 11:43:47 |显示全部楼层
这是ASP的最简短的!

if fileExt<>".gif" and fileExt<>".jpg" then
         response.write "<font size=2>图片格式只能为jpg/gif[ <a href=# onclick=history.go(-1)>重新上传</a> ]</font>"
        response.end
    end if
租服务器,上51IDC | [长沙]招聘:PHP经理10K/WEB前端6K/PHP开发6K

使用道具 举报

xling 楼主

艾克司令

荣誉管理

帖子
4230
体力
14923
威望
90
居住地
广东省 深圳市
发表于 2007-11-30 11:47:54 |显示全部楼层
楼上,我不会菜到连扩展名都不会判断吧!
xling.cnblogs.com

使用道具 举报

Fanbin 

霜之恋

钻石会员

帖子
4592
体力
5340
威望
5
居住地
欧洲 芬兰
发表于 2007-11-30 11:58:16 |显示全部楼层
刚要去吃饭,忍不住还是想回个帖

这问题我以前也想过,到是可以通过 $_FILES['file']['type'] 获取上传文件的MIME类型,可是浏览器判断MIME类型好像也是看扩展名,并不分析文件头。

可如果用PHP分析上传的文件要涉及到二进制操作,那可就头大了……

使用道具 举报

xling 楼主

艾克司令

荣誉管理

帖子
4230
体力
14923
威望
90
居住地
广东省 深圳市
发表于 2007-11-30 12:03:01 |显示全部楼层
看到一段JAVA的:不过,看不出来什么门道。

                bool xx=false;  //default sFileName is not Exe or Dll File
                System.IO.FileStream  fs=new System.IO.FileStream(sFileName,System.IO.FileMode.Open,System.IO.FileAccess.Read);
                System.IO.BinaryReader r=new System.IO.BinaryReader(fs);
                string bx="";
                byte buffer;
                try
                {
                    buffer=r.ReadByte();
                    bx=buffer.ToString();
                    buffer=r.ReadByte();
                    bx+=buffer.ToString();

                }
                catch (Exception exc)
                {
                    Console.WriteLine(exc.Message);
                }
                r.Close();
                fs.Close();
                if (bx=="7790"||bx=="8297"||bx=="8075")//7790:exe,8297:rar,8075k
                {
                    xx=true;
                }
                Console.WriteLine(bx);
                return xx;                 dll:MZ
                exe:MZ
                rar:Rar
                zip:PK
xling.cnblogs.com

使用道具 举报

Fanbin 

霜之恋

钻石会员

帖子
4592
体力
5340
威望
5
居住地
欧洲 芬兰
发表于 2007-11-30 12:35:26 |显示全部楼层
二进制读取文件,得到前两个字节并将其转换成字符串,就能得到 7790, 8297什么的?
如果是这样那我倒有点思路了……
ok,我试试去。

使用道具 举报

Fanbin 

霜之恋

钻石会员

帖子
4592
体力
5340
威望
5
居住地
欧洲 芬兰
发表于 2007-11-30 13:20:32 |显示全部楼层
好了,核心部分搞定,多谢xling提供的那段Java代码:
  1. <?php
  2. $filename = "D:\\296.mid";
  3. $file     = fopen($filename, "rb");
  4. $bin      = fread($file, 2); //只读2字节
  5. fclose($file);
  6. $strInfo  = @unpack("c2chars", $bin);
  7. $typeCode = intval($strInfo['chars1'].$strInfo['chars2']);
  8. $fileType = '';
  9. switch ($typeCode)
  10. {
  11.         case 7790:
  12.                 $fileType = 'exe';
  13.                 break;
  14.         case 7784:
  15.                 $fileType = 'midi';
  16.                 break;
  17.         case 8297:
  18.                 $fileType = 'rar';
  19.                 break;
  20.         case 255216:
  21.                 $fileType = 'jpg';
  22.                 break;
  23.         case 7173:
  24.                 $fileType = 'gif';
  25.                 break;
  26.         case 6677:
  27.                 $fileType = 'bmp';
  28.                 break;
  29.         case 13780:
  30.                 $fileType = 'png';
  31.                 break;
  32.         default:
  33.                 echo 'unknown';
  34. }

  35. echo 'this is a(an) '.$fileType.' file:'.$typeCode;
  36. ?>
复制代码
已有 1 人评分威望 收起 理由
kuhanzhu + 1 谢谢分享

总评分: 威望 + 1   查看全部评分

使用道具 举报

Fanbin 

霜之恋

钻石会员

帖子
4592
体力
5340
威望
5
居住地
欧洲 芬兰
发表于 2007-11-30 13:21:57 |显示全部楼层
关键是 unpack 这个函数,把读到的二进制内容转成 字符串!

好帖,收藏了

使用道具 举报

xling 楼主

艾克司令

荣誉管理

帖子
4230
体力
14923
威望
90
居住地
广东省 深圳市
发表于 2007-11-30 13:32:29 |显示全部楼层
打击你一下,
你百度一下:gif89a文件头欺骗
xling.cnblogs.com

使用道具 举报

Fanbin 

霜之恋

钻石会员

帖子
4592
体力
5340
威望
5
居住地
欧洲 芬兰
发表于 2007-11-30 13:39:36 |显示全部楼层

回复 #9 xling 的帖子

我汗…… 那怎么办?你再处理一下这个吧,解决了别忘了发上来

使用道具 举报

xling 楼主

艾克司令

荣誉管理

帖子
4230
体力
14923
威望
90
居住地
广东省 深圳市
发表于 2007-11-30 13:47:33 |显示全部楼层
不知道DZ是怎么处理的。
汗。。。没有做处理!
我记得以前上传一个改过后缀名的文件,会提示“看起来不是真实的***文件”云云
现在居然没有处理!

[ 本帖最后由 xling 于 2007-11-30 13:49 编辑 ]
附件: 你需要登录才可以下载或查看附件。没有帐号?注册
xling.cnblogs.com

使用道具 举报

苦寒竹

管理员

帖子
19772
体力
17930
威望
23
居住地
浙江省 金华市
发表于 2007-11-30 13:48:44 |显示全部楼层
检测图片类型和是否为图片都是无效的。
可以检测后缀再加文件头检测。这样就相对应了,让加了文件头的asp文件等后缀是jpg等图片后缀。
再加备份还原数据库路径检测等。(不要犯动网7.0的还原问题就行了)
搞IT的穷秀才。

使用道具 举报

xling 楼主

艾克司令

荣誉管理

帖子
4230
体力
14923
威望
90
居住地
广东省 深圳市
发表于 2007-11-30 13:50:37 |显示全部楼层

回复 #12 kuhanzhu 的帖子

没听明白。
能否细说?
xling.cnblogs.com

使用道具 举报

苦寒竹

管理员

帖子
19772
体力
17930
威望
23
居住地
浙江省 金华市
发表于 2007-11-30 13:58:32 |显示全部楼层

回复 #11 xling 的帖子

你的那个已经上传成功了。
而且DZ确实是检测了后缀jpg上传的。能显示,那是因为浏览器是不看后缀的,就跟一个会动的gif文件改为jpg后缀仍然能动一样。

gif89a文件头检测是指程序为了他人将asp等文件后缀改为gif后上传,读取gif文件头,检测是否有gif87a或gif89a标记,是就允许上传,不是就说明不是gif文件。

而欺骗刚好是利用检测这两个标记,只要在木马代码前加gif87a就能骗过去。

有些程序因为有了检测功能,就更省事,直接检测文件头,上传(所有文件都检测文件头)。因此比如一个后缀为asp的木马,前面加了gif文件头标记,就直接上传了。这样,一个木马很容易就利用了。

而对于还要检测后缀的程序来说。木马只能把后缀改为gif来欺骗程序以gif形式上传,传上去之后再利用备份还原的方式进行asp后缀改回,再进行利用。
搞IT的穷秀才。

使用道具 举报

苦寒竹

管理员

帖子
19772
体力
17930
威望
23
居住地
浙江省 金华市
发表于 2007-11-30 14:05:17 |显示全部楼层
第一个典型例子是动网7.0头像上传漏洞。
系统检测后缀,不允许的文件为asa、asp、cdx、cer等一些常见的ASP环境下的后缀,却没想到全能空间需要过滤如php\aspx等后缀。
而程序又同时这样处理了:split(FileMIME,"/")(0)<>"image"(我已经找到硬盘上很久前的录像了
也就是说非gif和jpg文件不嫁了
因此把文件头写到一个php或aspx木马前就利用了

而后一个例子是动网7.0后台备份还原问题,只要进入后台且上传了张后缀为jpg的木马图片,利用备份还原就能把jpg木马图片恢复为asp文件进行利用。
因此只要扣好上面几点途径就好了。
搞IT的穷秀才。

使用道具 举报

xling 楼主

艾克司令

荣誉管理

帖子
4230
体力
14923
威望
90
居住地
广东省 深圳市
发表于 2007-11-30 14:18:15 |显示全部楼层
谢谢版主。

Fanbin
你的代码很好,让我认识了unpack这个函数。

但是dll的头两个字节解压回来也是:7790,和exe的一样。
xling.cnblogs.com

使用道具 举报

Fanbin 

霜之恋

钻石会员

帖子
4592
体力
5340
威望
5
居住地
欧洲 芬兰
发表于 2007-11-30 14:29:24 |显示全部楼层
dll就是动态链接库文件,在某些方面上它就是和exe差不多的,甚至有些程序只把exe做为一个外壳,而核心在dll里
至于头两个字节一样,我也没办法,它就是那样的

是你的Java代码给了我提示哈!

使用道具 举报

灰色系

银牌会员

帖子
2419
体力
2374
威望
11
居住地
湖北省 黄冈市
发表于 2007-12-3 17:14:21 |显示全部楼层
jpg和gif 验证错误没有很大关系,一些关键的文件类型不要检测错误了才是最要的

使用道具 举报

微笑的海豚

荣誉管理 手机认证 

帖子
2408
体力
13345
威望
39
发表于 2007-12-3 23:02:09 |显示全部楼层
如果检测GIF/JPG/PNG/BMP格式图片,可以使用getimagesize函数。
如果是其它的文件,可以检测文件头与扩展名。

附一个检测函数
  1. /**
  2. * 检查文件类型
  3. *
  4. * @access      public
  5. * @param       string      filename            文件名
  6. * @param       string      realname            真实文件名
  7. * @param       string      limit_ext_types     允许的文件类型
  8. * @return      string
  9. */
  10. function check_file_type($filename, $realname = '', $limit_ext_types = '')
  11. {
  12.     if ($realname)
  13.     {
  14.         $extname = strtolower(substr($realname, strrpos($realname, '.') + 1));
  15.     }
  16.     else
  17.     {
  18.         $extname = strtolower(substr($filename, strrpos($filename, '.') + 1));
  19.     }

  20.     $str = $format = '';

  21.     $file = @fopen($filename, 'rb');
  22.     if ($file)
  23.     {
  24.         $str = @fread($file, 0x400); // 读取前 1024 个字节
  25.         @fclose($file);
  26.     }
  27.     else
  28.     {
  29.         if (stristr($filename, ROOT_PATH) === false)
  30.         {
  31.             if ($extname == 'jpg' || $extname == 'jpeg' || $extname == 'gif' || $extname == 'png' || $extname == 'doc' ||
  32.                 $extname == 'xls' || $extname == 'txt'  || $extname == 'zip' || $extname == 'rar' || $extname == 'ppt' ||
  33.                 $extname == 'pdf' || $extname == 'rm'   || $extname == 'mid' || $extname == 'wav' || $extname == 'bmp' ||
  34.                 $extname == 'swf' || $extname == 'chm'  || $extname == 'sql' || $extname == 'cert')
  35.             {
  36.                 $format = $extname;
  37.             }
  38.         }
  39.         else
  40.         {
  41.             return '';
  42.         }
  43.     }

  44.     if ($format == '' && strlen($str) >= 2 )
  45.     {
  46.         if (substr($str, 0, 4) == 'MThd' && $extname != 'txt')
  47.         {
  48.             $format = 'mid';
  49.         }
  50.         elseif (substr($str, 0, 4) == 'RIFF' && $extname == 'wav')
  51.         {
  52.             $format = 'wav';
  53.         }
  54.         elseif (substr($str ,0, 3) == "\xFF\xD8\xFF")
  55.         {
  56.             $format = 'jpg';
  57.         }
  58.         elseif (substr($str ,0, 4) == 'GIF8' && $extname != 'txt')
  59.         {
  60.             $format = 'gif';
  61.         }
  62.         elseif (substr($str ,0, 8) == "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
  63.         {
  64.             $format = 'png';
  65.         }
  66.         elseif (substr($str ,0, 2) == 'BM' && $extname != 'txt')
  67.         {
  68.             $format = 'bmp';
  69.         }
  70.         elseif ((substr($str ,0, 3) == 'CWS' || substr($str ,0, 3) == 'FWS') && $extname != 'txt')
  71.         {
  72.             $format = 'swf';
  73.         }
  74.         elseif (substr($str ,0, 4) == "\xD0\xCF\x11\xE0")
  75.         {   // D0CF11E == DOCFILE == Microsoft Office Document
  76.             if (substr($str,0x200,4) == "\xEC\xA5\xC1\x00" || $extname == 'doc')
  77.             {
  78.                 $format = 'doc';
  79.             }
  80.             elseif (substr($str,0x200,2) == "\x09\x08" || $extname == 'xls')
  81.             {
  82.                 $format = 'xls';
  83.             } elseif (substr($str,0x200,4) == "\xFD\xFF\xFF\xFF" || $extname == 'ppt')
  84.             {
  85.                 $format = 'ppt';
  86.             }
  87.         } elseif (substr($str ,0, 4) == "PK\x03\x04")
  88.         {
  89.             $format = 'zip';
  90.         } elseif (substr($str ,0, 4) == 'Rar!' && $extname != 'txt')
  91.         {
  92.             $format = 'rar';
  93.         } elseif (substr($str ,0, 4) == "\x25PDF")
  94.         {
  95.             $format = 'pdf';
  96.         } elseif (substr($str ,0, 3) == "\x30\x82\x0a")
  97.         {
  98.             $format = 'cert';
  99.         } elseif (substr($str ,0, 4) == 'ITSF' && $extname != 'txt')
  100.         {
  101.             $format = 'chm';
  102.         } elseif (substr($str ,0, 4) == "\x2ERMF")
  103.         {
  104.             $format = 'rm';
  105.         } elseif ($extname == 'sql')
  106.         {
  107.             $format = 'sql';
  108.         } elseif ($extname == 'txt')
  109.         {
  110.             $format = 'txt';
  111.         }
  112.     }

  113.     if ($limit_ext_types && stristr($limit_ext_types, '|' . $format . '|') === false)
  114.     {
  115.         $format = '';
  116.     }
  117.     if ($extname != $format)
  118.     {
  119.         $format = '';
  120.     }

  121.     return $format;
  122. }
复制代码

[ 本帖最后由 wenming 于 2007-12-3 23:03 编辑 ]
珍视拥有的、遗忘失去的。

使用道具 举报

修行的魔法师

金牌会员

帖子
1527
体力
3049
威望
4
发表于 2007-12-4 08:34:01 |显示全部楼层
那段代码明显不是Java是.net的。
修行的魔法师

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

Archiver|手机版|安久科技提供CDN|blueidea.com ( 京ICP备05002321号 )  

GMT+8, 2012-2-13 08:31 , Processed in 0.138168 second(s), 11 queries , Gzip On, Memcache On.

Powered by Discuz! X2

© 2001-2011 Comsenz Inc.

回顶部