#1 实例介绍

本案例采用的实例是:U-Mail邮件系统。

U-Mail邮件系统文件上传的地方代码是这样的:

code 区域

<?php

if(ACTION =="attach-upload"){

if($_FILES){

$file_name = $_FILES['Filedata']['name'];

$file_type = $_FILES['Filedata']['type'];

$file_size = $_FILES['Filedata']['size'];

$file_source = $_FILES['Filedata']['tmp_name'];

$file_suffix = getfilenamesuffix( $file_name );

$not_allow_ext = array( "php", "phps", "php3", "exe", "bat" );

if (in_array($file_suffix, $not_allow_ext )){

dump_json( array( "status" => 0, "message" => el( "不支持该扩展名文件上传", "" ) ) );

}

$path_target = getusercachepath( );

do{

$file_id = makerandomname( );

$file_target = $path_target.$file_id.".".$file_suffix;

} while ( file_exists( $file_target ) );

if ( move_uploaded_file( $file_source, $file_target )){

dump_json( array( "status" => 0, "message" => el( "写入文件出错,请与管理员联系!", "" ) ) );

}

$_SESSION[SESSION_ID]['attach_cache'][] = array( "id" => $file_id, "name" => $file_name, "type" => "1", "path" => $file_target, "size" => $file_size );

dump_json( array( "status" => "1", "filename" => $file_name, "filesize" => $file_size, "file_id" => $file_id ) );

}else{

dump_json( array( "status" => "0", "message" => el( "无法找到需要上传的文件!", "" ) ) );

}

}

我们注意到如下的代码

code 区域

$not_allow_ext = array( "php", "phps", "php3", "exe", "bat" );

if (in_array($file_suffix, $not_allow_ext )){

dump_json( array( "status" => 0, "message" => el( "不支持该扩展名文件上传", "" ) ) );

}

非常明显,采用的是黑名单验证,虽然我们可以采用类似这样的文件后缀绕过程序的检测,如:bypass.phpX(这里的X代表空格%20或其他特殊字符{%80-%99}),但这完全不是今天我想要讲的内容。

今天,通过这个实例给大家讲解一种新型的文件上传方式,且听我细细道来..

#2 代码poc实现

为了在本地测试方便,我们对上述代码进行简化,如下

code 区域

<?php

//U-Mail demo ...

if(isset($_POST['submit'])){

$filename = $_POST['filename'];

$filename = preg_replace("/[^\w]/i", "", $filename);

$upfile = $_FILES['file']['name'];

$upfile = str_replace(';',"",$upfile);

$upfile = preg_replace("/[^(\w|\:|\$|\.|\<|\>)]/i", "", $upfile);

$tempfile = $_FILES['file']['tmp_name'];

$ext = trim(get_extension($upfile)); // null

if(in_array($ext,array('php','php3','php5'))){

die('Warning ! File type error..');

}

if($ext == 'asp' or $ext == 'asa' or $ext == 'cer' or $ext == 'cdx' or $ext == 'aspx' or $ext == 'htaccess') $ext = 'file';

//$savefile = 'upload/'.$upfile;

$savefile = 'upload/'.$filename.".".$ext;

if(move_uploaded_file($tempfile,$savefile)){

die('Success upload..path :'.$savefile);

}else{

die('Upload failed..');

}

}

function get_extension($file){

return strtolower(substr($file, strrpos($file, '.')+1));

}

?>

<html>

<body>

<form method="post" action="upfile.php" enctype="multipart/form-data">

<input type="file" name="file" value=""/>

<input type="hidden" name="filename" value="file"/>

<input type="submit" name="submit" value="upload"/>

</form>

</body>

</html>

对于上述代码,虽然是通过黑名单进行文件名检测,但通过目前已知的上传方法,是没有办法成功上传php文件的(不考虑程序的Bug),因此可以说这段文件上传的代码是"安全"的,

可是,我蓦然回首,在那个灯火阑珊的地方,php邂逅了Windows,美丽的爱情故事便由此产生了..

#3 细说故事

某天,二哥在群里丢了一个url连接,我简单看了下,关于利用系统特性进行文件上传的,兴趣马上就来了,就细细研究了下,于是有了这篇文章..

这几行英文的意思大致是,在php+window+iis环境下:

双引号(">") <==> 点号(".")';

大于符号(">") <==> 问号("?")';

小于符号("<") <==> 星号("*")';

有这么好玩的东西,那不就可以做太多的事了?但事实并不是这样,通过一系列的测试发现,该特性只能用于文件上传时覆盖已知的文件,于是这个特性便略显鸡肋..

原因有二:

1)上传文件的目录一般我们都不可控;

2)同时,一般文件上传的目录不可能存在我们想要的任何php文件,因此没办法覆盖;

后来,经过反反复复的思考,终于找到了可以完美利用的办法..

思路如下:

首先我们先利用特殊办法生成一个php文件,然后再利用这个特性将文件覆盖..

可问题又来了,怎样生成php文件呢?如果可以直接生成php文件的话,干嘛还要利用那什么特性?

别急,办法总是有的..

我们都知道在文件上传时,我们往往会考虑到文件名截断,如%00 等..

对!有的人可能还会用冒号(":")去截断,如:bypass.php:jpg

但是你知道吗?冒号截断产生的文件是空白的,里面并不会有任何的内容,呵呵
说到这里
明白了没有? 虽然生成的php文件里面没有内容,但是php文件总生成了吧,所以
我们可以结合上面所说的特性完美成功利用..

#4 冒号+特性成功利用

按照#3提供的思路,实现..

本地测试地址:http://www.secmap.cn/upfile.php 环境:Windows+IIS7.5

1)首先利用冒号生成我们将要覆盖的php文件,这里为:bypass.php,如图

点击forward后,可以看见成功生成空白的bypass.php文件

2)利用上面的系统特性覆盖该文件

从上面已经知道"<" 就等于 "*",而"*"代码任意字符,于是乎..

我们可以这样修改上传的文件名,如下:

code 区域

------WebKitFormBoundaryaaRARrn2LBvpvcwK

Content-Disposition: form-data; name="file"; filename="bypass.<<<"

Content-Type: image/jpeg

//注意!文件名为:bypass.<<<

点击go..,即可成功覆盖bypass.php文件,如图

对比上面的两个图,bypass.php被我们成功的写入了内容..

#5 特性二

首先来看看微软MSDN上面的一段话,如图

注意红色圈起来的英文

code 区域

The default data stream has no name. That is, the fully qualified name for the default stream for a file called "sample.txt" is "sample.txt::$DATA" since "sample.txt" is the name of the file and "$DATA" is the stream type.

看不去不错哟,试试吧..

同样,我们可以这样修改上传的文件名,如下:

code 区域

------WebKitFormBoundaryaaRARrn2LBvpvcwK

Content-Disposition: form-data; name="file"; filename='DataStreamTest.php::$DATA'

Content-Type: image/jpeg

//注意!文件名为:DataStreamTest.php::$DATA

点击GO,奇迹出现了..

访问之...

漏洞证明:

#6 漏洞证明

U-Mail,具体利用方法,同上述的方法一样,为了简单快捷的话,可直接抓包修改文件名为:

shell.php::$DATA 即可成功上传,这里不再演示,附shell

php懈垢windows通用上传缺陷的更多相关文章

  1. pkav之当php懈垢windows通用上传缺陷

    $pkav->publish{当php懈垢windows}剑心@xsser抛弃了我,但我却不能抛弃乌云..php懈垢windows,就像男人邂逅女人,早晚都会出问题的..感谢二哥@gainove ...

  2. 当php懈垢windows通用上传缺陷

    转自独自等待博客 早上逛乌云发现了PKAV大牛的一篇文章,针对php和windows文件上传的分析,思路很YD,果断转之与大家分享. 虽然此文可能有许多的限制条件,但是如果你认真阅读会发现,其实还是比 ...

  3. 当php邂逅windows通用上传缺陷

    早上逛乌云发现了PKAV大牛的一篇文章,针对php和windows文件上传的分析,思路很YD,果断转之与大家分享. 虽然此文可能有许多的限制条件,但是如果你认真阅读会发现,其实还是比较实用的. 另外一 ...

  4. Windows如何上传代码到Github

    1.首先得安装git客户端 进入官网:https://git-scm.com/ ,点击右侧下载windows版本的软件包,然后双击安装就可以了. 安装完成之后,在开始菜单可以看到,此时,在想上传的文件 ...

  5. windows下上传shell脚本不能运行—将dos模式修改为unix 文件格式

    windows下上传shell脚本至linux,其格式将为dos.dos模式的shell脚本将不能再linux下正确运行,需要修改文件模式为unix. 1 查看文件模式方法 linux服务器上,用vi ...

  6. C# 通用上传文件类

    1.Upfile.aspx: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="U ...

  7. Git在windows下上传文件至github流程

    github是开发者分享的一个平台,这里不多说,想要上传文件至github需要有一个开发者账号,还需要在windows下安装好了git. 做好准备工作之后,接下来操作 一:登录github,创建项目 ...

  8. 解决PHP在Windows IIS 上传的图片无法访问的问题

    最近在做一个网站项目遇到了一个很奇怪的问题,现记录下来希望可以帮助到其他的朋友   问题描述: 最近公司刚刚在香港购买了一个Windows Server 2008 服务器用于将一个客户的N个php网站 ...

  9. 某p2p存在通用上传漏洞

    google链接查找: inurl:shouyi.asp inurl:itemlist_xq.asp?id= 很多存在Fckeditor上传链接: FCKeditor/editor/filemanag ...

随机推荐

  1. i.mx6 Android6.0.1分析input子系统:测试

    getevent与sendevent工具 Android系统提供了getevent与sendevent两个工具供开发者从设备节点中直接读取输入事件或写入输入事件. 在这里,我们测试音量加和音量减按键 ...

  2. Spring发送基于freemarker模板的邮件

    在项目开发过程中,我们经常会遇到需要发送邮件的场景,比如:用户验证邮箱的时候,有活动通知或者提醒通知的时候……有些时候我们可能只需要发送一些简单文本内容即可,但是大多数情况下我们更希望邮件的内容是丰富 ...

  3. 利用jquery的ajax实现跨域,内部其实是jsonp协议了,不是XHRhttp协议

    一.同源策略 要理解跨域,先要了解一下“同源策略”.所谓同源是指,域名,协议,端口相同.所谓“同源策略“,简单的说就是基于安全考虑,当前域不能访问其他域的东西. 一些常见的是否同源示例可参照下表: 在 ...

  4. 整理一些前端开发比较好的node包

    1.一个base64转换的包 !https://www.npmjs.com/package/js-base64 2 js 压缩 !https://www.npmjs.com/package/uglif ...

  5. SQL Server中的小技巧(重复、替换、截取、去空格、去小数点后的位数)

    PS:随笔写的在SQL Server中要用到的 (重复.替换.截取.去空格.去小数点后的位数) /*---------------------------重复--------------------- ...

  6. VS中自定义C#快速简写代码

     首先在VS中找到工具——代码片段管理器——语言选择(CSharp)——Visual C#——赋值路径——根据路径找到对应的代码片段用VS打开 修改: Title——标题 ShortCut——缩写 D ...

  7. nodejs简易代理服务器

    直接代码: var http = require('http') var proxy = http.createServer(function (request, response) { var op ...

  8. Java学习--java中的集合框架、Collection接口、list接口

    与数组相比:1.数组的长度固定,而集合的长度可变2.数组只能通过下表访问元素,类型固定,而有的集合可以通过任意类型查找所映射的具体对象 java集合框架:collection(list序列,queue ...

  9. Java 类 ThreadLocal 本地线程变量

    前言:工作中将要使用ThreadLocal,先学习总结一波.有不对的地方欢迎评论指出. 定义 ThreadLocal并不是一个Thread,而是Thread的局部变量.这些变量不同于它们的普通对应物, ...

  10. java设计模式-----6、建造者模式

    Builder模式也叫建造者模式或者生成器模式,是由GoF提出的23种设计模式中的一种.Builder模式是一种对象创建型模式之一,用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象,通过子类 ...