<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>程默的博客 &#187; 上存漏洞</title>
	<atom:link href="http://blog.chacuo.net/tag/%e4%b8%8a%e5%ad%98%e6%bc%8f%e6%b4%9e/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.chacuo.net</link>
	<description>web原理、web架构、web安全、web性能、服务器性能、服务器架构、服务器安全;你不能预知明天，但你可以利用今天。你不能样样顺利，但你可以事事尽力!</description>
	<lastBuildDate>Mon, 31 Aug 2020 15:33:40 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>web上存漏洞及原理分析、防范方法（安全文件上存方法）</title>
		<link>http://blog.chacuo.net/142.html</link>
		<comments>http://blog.chacuo.net/142.html#comments</comments>
		<pubDate>Mon, 03 Jun 2013 10:08:42 +0000</pubDate>
		<dc:creator>程默</dc:creator>
				<category><![CDATA[web安全]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[上存漏洞]]></category>

		<guid isPermaLink="false">http://blog.chacuo.net/?p=142</guid>
		<description><![CDATA[看我上两篇，我们知道，上存漏洞常见有，文件名检测漏洞，还有就是文件格式检查漏洞。 另外还有个一个，就是保存文件 [...]]]></description>
				<content:encoded><![CDATA[<p>看我上两篇，我们知道，上存漏洞常见有，<a href="http://blog.chacuo.net/136.html" target="_blank">文件名检测漏洞</a>，还有就是<a href="http://blog.chacuo.net/141.html" target="_blank">文件格式检查漏洞</a>。 另外还有个一个，就是保存文件存在漏洞。这类漏洞，主要是可以读取用户传入路径名称，采用不正确的过滤方法，导致恶意用户，将文件上存到非预期的地方，带来安全隐患。</p>
<p>其实，我们抓住几个地方即可，我们先来分析下，既然用户要上存文件，而且文件将是多种多样格式；可能有的文件内容与用户传入格式不一致，有的文件内容还夹杂木马代码。 那么，我们让用户上存文件，跟站点文件做一个分别授权，做隔离。</p>
<ul>
<li>
<h3><strong><span style="text-decoration: underline;">让保存上存目录独立开来，目录权限只读不能执行</span></strong></h3>
</li>
</ul>
<p>这一步从系统设计加以授权，无论你上次什么文件，都不可能执行到。就算我不做任何检测，你的文件都上存到这里了，也不会对我系统构成安全。（如果有用户上存一些反动言语的图片，那另外需要处理的）</p>
<h3></h3>
<ul>
<li>
<h3><strong><span style="text-decoration: underline;">不直接使用服务器传入值，所有都要进行检测</span></strong></h3>
</li>
</ul>
<p>这类跟我们做一切输入都是有害原则一样，对于客户端传入的：type, name ，都要进行判断，不直接使用。对于要生成到某个目录，某个文件名。</p>
<p><span style="text-decoration: underline;"><strong>文件名</strong>最好方法是：自己写死目录（不要读取传入目录），文件名，最好自己随机生成，不读取用户文件名。文件扩展名，可以取最右边”.”后面字符。</span></p>
<p>以上2个方法，刚好从2个方面对上存做了整体约束。</p>
<p>方法2 ： 保存上存文件名，按照自己指定目录写入，并且文件名自己生成的。</p>
<p>方法1：只要保证文件写对了位置，然后从配置上，对写入目录进行权限控制，这个是治本。可以做到，你无论上存什么文件，都让你没有权限跳出去可以运行。</p>
<p>&nbsp;</p>
<p>以上2个方法，一起使用，可以保证文件正确存到地方，然后，权限可以控制。 这里顺便说明下， 判断用户上存文件是否满足要求类型，就直接检查文件扩展名，只要满足扩展名就让上存。 反正，做了执行权限限制，你不按要求上存内容，也无妨。 反正，不能执行，也不会有多大危害性的。</p>
<ul>
<li><strong>正确步骤：</strong></li>
</ul>
<p><span style="text-decoration: underline;"><span style="color: #0000ff;">1.读取文件名，验证扩展名是不是在范围内</span></span></p>
<p><span style="text-decoration: underline;"><span style="color: #0000ff;">2.自己定义生成的文件名，目录，扩展名可以来自文件名扩展名。 其它值，都自己配置，不读取上存中内容</span></span></p>
<p><span style="text-decoration: underline;"><span style="color: #0000ff;">3.将文件 移到新目录(这个目录权限设置只读)</span></span></p>
<p>&nbsp;</p>
<p>好了，以上是一般操作方法，希望对大家有帮助，也欢迎朋友们交流！也希望提供更好的方法！接下来，我会在web 开发中，常见一些方法功能安全设计方面继续写一些我的心得，看法！ 欢迎大家随时交流！</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chacuo.net/142.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>web上存漏洞及原理分析、防范方法（文件类型检测漏洞）</title>
		<link>http://blog.chacuo.net/141.html</link>
		<comments>http://blog.chacuo.net/141.html#comments</comments>
		<pubDate>Sun, 02 Jun 2013 08:59:00 +0000</pubDate>
		<dc:creator>程默</dc:creator>
				<category><![CDATA[web安全]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[上存漏洞]]></category>

		<guid isPermaLink="false">http://blog.chacuo.net/?p=141</guid>
		<description><![CDATA[通过上一篇文章，我们知道wed上存漏洞，最常见一种是文件名检测漏洞，接下来，我们看看另外一种漏洞，上存文件类型 [...]]]></description>
				<content:encoded><![CDATA[<p>通过上一篇文章，我们知道wed上存漏洞，<a href="http://blog.chacuo.net/136.html" target="_blank">最常见一种是文件名检测漏洞</a>，接下来，我们看看另外一种漏洞，上存文件类型漏洞，这也是一种较为容易出现问题。</p>
<p>我当时就想，既然我知道我需要允许上存什么样的文件，那么，我就只允许你上存该文件。只要我文件类型判断准确了，你想上存能够执行的代码。我都给阻止掉，不就行了吗？ 这确实，是个好的方法，但是我们再做的时候，往往会出现下面一些问题。</p>
<p>这里我们看下常见实现的php代码。 这里，常见两个问题是：</p>
<blockquote><p><font style="background-color: #ffffff" face="Arial"></font></p>
<p><font style="background-color: #ffffff" face="Arial"><strong><u>1.读取文件type,直接做文件类型判断</u></strong></font></p>
<p><font style="background-color: #ffffff" face="Arial"><u><strong>2.通过工具分析文件格式，以此来确认文件类型</strong></u></font></p>
<p><font style="background-color: #ffffff" face="Arial"></font></p>
</blockquote>
<ul>
<li>
<h3><strong>问题一：读取文件type，判断文件类型</strong></h3>
</li>
</ul>
<blockquote><pre>&#160;</pre>
<pre style="text-indent: 0px">if(isset($_FILES['img']))
{
    $file = save_file($_FILES['img']);
	if($file===false) exit('上存失败！');
	
	echo &quot;上存成功！&quot;,$file;
}



function check_file($img)
{
	///读取文件
	if($img['error']&gt;0) return false;
	
	$type = $img['type'];
	$filename = $img['name'];
	
	
	///读取文件扩展名
	$len=strrpos($filename,&quot;.&quot;);
	if($len===false) return false;
	
	//得到扩展名
	$ext = strtolower(substr($filename,$len+1));
	
	///判断文件类型
	<strong><u><font color="#0000ff">if($type &amp;&amp; preg_match('%^image/.+$%',$type)) return $ext;</font></u></strong>
	
	return false;
}

function save_file($img)
{
	$ext = check_file($img);
	if(!ext) return false;
	
	//格式检测ok，准备移动数据
	<strong><u><font color="#0000ff">$filename = time().$ext;</font></u></strong>
	$newfile = &quot;upload/&quot; .$filename;
	if(!move_uploaded_file($img[&quot;tmp_name&quot;],$newfile)) return false;
	
	return $newfile;

}</pre>
</blockquote>
<h3><strong></strong></h3>
<p>以上加蓝色代码，是关键，这个里面我们直接读取type类型，也就是文件内容。通过第一篇知识：<a href="http://blog.chacuo.net/108.html" target="_blank">web上存漏洞及原理分析、防范方法</a> 我们知道，type来自浏览器端浏览器自动传入变量。 如果是浏览器，这个值一般没有问题。但是，如果是来自用户自己组织的包，他可以给type 设置个：image/jpeg值， 然后，给name 一个 index.php 值。 </p>
<p><u><font color="#ff0000">估计大家已经看到问题，这样一来，我们生成的文件$filename变成为：time().’php’了。 就创建一个php文件。</font></u></p>
<ul>
<li>
<h3><strong>通过工具分析文件格式，以此来确认文件类型</strong></h3>
</li>
</ul>
<h1><strong></strong></h1>
<p>我们已经清楚知道了,type值是可以随便构造的，这类检查用户类型方法。是没有任何作用，恶意用户，可以随便给一个php文件发送上来，传一个image类型。 那么，肯定有朋友会说，我直接用php程序，去分析用户传入的tmp_name 文件格式，这个总靠谱吧！ 我们看看下面代码。</p>
<blockquote>
<pre style="text-indent: 0px">function check_file($img)
{
	///读取文件
	if($img['error']&gt;0) return false;
	
	$typelist = array(array(&quot;FFD8FFE1&quot;,&quot;jpg&quot;),
	array(&quot;89504E47&quot;,&quot;png&quot;),
	array(&quot;47494638&quot;,&quot;gif&quot;),
	array(&quot;49492A00&quot;,&quot;tif&quot;),
	array(&quot;424D&quot;,&quot;bmp&quot;));
	
	$file = $img['tmp_name'];
	$filename = $img['name'];
	
	
	///读取文件扩展名
	$len=strrpos($filename,&quot;.&quot;);
	if($len===false) return false;
	
	//得到扩展名
	$ext = strtolower(substr($filename,$len+1));
	
	///判断文件类型
	//读取文件开头15字节，一般通过这些字节值，可以确定它的格式
	$file = @fopen($file,&quot;rb&quot;);
	$bin = fread($file, 15);
	
	foreach ($typelist as $v)
	{
		$blen=strlen(pack(&quot;H*&quot;,$v[0])); //得到文件头标记字节数
		$tbin=substr($bin,0,intval($blen)); ///需要比较文件头长度
		 
		<strong><u><font color="#0000ff">if(strtolower($v[0])==strtolower(array_shift(unpack(&quot;H*&quot;,$tbin))))</font></u></strong> 
		{
			return $ext;
		}
	}
	
	return false;
}</pre>
</blockquote>
<p>该方法，直接分析用户传入文件格式，然后决定该文件类型，是否允许保存！这套，我们看来非常可靠方法，应该很准确，应该没有问题，不读取type,自己来分析格式。 其实：如果用户传入一个文件，前面4字节是：89504E47， 然后，后面加入一段&lt;?php代码 。上存的文件名称是image.php 。这样一来，我们发现，这段代码保存为php文件了。 只是这个文件，前面一部分可能是图片格式，后面一部分，只纯粹的php 程序。 通过浏览器，去访问下这个，还真的可以运行呢。 很久以前，就有人做过image图片木马。可以去百度搜索：”<u>将php木马隐藏在图片里</u>” ，这样做出的文件，你用画图软件看是个图片，你如果用php运行这段代码，里面php能够执行了。 </p>
<p>&#160;</p>
<p>好了，我们总结下，看来通过type判断类型，以及通过文件格式检测类型。 都不能很好解决，准确判断用户上存文件格式了。 其实，我们反过来想想，文件格式，不是通过一个简单字节标识码就能够准确判断的。 如果真的要去检测文件类型，我们该用什么方法呢？如果真的要检测格式，例如是图片，可以用php gd库，直接去打开文件，然后再保存一次。 这样，里面不合法的代码会去掉的。但是，我们想想，这样该会花费多大的性能呢？</p>
<p>综上所述，其实，去判断文件内容格式，不是明智的方法。 会非常复杂，而且也容易出现问题。想准确判断，还会消耗大量的服务器资源。除非万不得已，我们不要去尝试做这种操作。 接下来，对于安全上存方法，我会说说思路，欢迎交流！</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chacuo.net/141.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>web上存漏洞及原理分析、防范方法（文件名检测漏洞）</title>
		<link>http://blog.chacuo.net/136.html</link>
		<comments>http://blog.chacuo.net/136.html#comments</comments>
		<pubDate>Sat, 01 Jun 2013 15:09:59 +0000</pubDate>
		<dc:creator>程默</dc:creator>
				<category><![CDATA[web安全]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[上存漏洞]]></category>

		<guid isPermaLink="false">http://blog.chacuo.net/?p=136</guid>
		<description><![CDATA[我们通过前篇：web上存漏洞及原理分析、防范方法 学习，已经知道后端获取服务器变量，很多来自客户端传入的。跟普 [...]]]></description>
				<content:encoded><![CDATA[<p>我们通过前篇：<a href="http://blog.chacuo.net/108.html">web上存漏洞及原理分析、防范方法</a> 学习，已经知道后端获取服务器变量，很多来自客户端传入的。跟普通的get,post没有什么不同。下面我们看看，常见出现漏洞代码。</p>
<h3><font style="font-weight: bold">1、检测文件类型，并且用用户上存文件名保存</font></h3>
<blockquote><pre style="text-indent: 0px">if(isset($_FILES['img']))
{
    $file = save_file($_FILES['img']);
	if($file===false) exit('上存失败！');
	
	echo &quot;上存成功！&quot;,$file;
}

function check_file($img)
{
	///读取文件
	if($img['error']&gt;0) return false;
	
	$tmpfile = $img['tmp_name'];
	$filename = $img['name'];
	
	
	///读取文件扩展名
	$len=strrpos($filename,&quot;.&quot;);
	if($len===false) return false;
	
	//得到扩展名
	$ext = strtolower(substr($filename,$len+1));
	if(!in_array($ext,array('jpg','jpeg','png'))) return false;
	return true;
}

function save_file($img)
{
	if(!check_file($img)) return false;
	
	//格式检测ok，准备移动数据
	<strong>$filename = $img['name'];</strong>
	$newfile = &quot;upload/&quot; .$filename;
	if(!move_uploaded_file($img[&quot;tmp_name&quot;],$newfile)) return false;
	
	return $newfile;

}
?&gt;</pre>
</blockquote>
<p>以上代码，对输入类型也做了判断，看了没有问题。但是问题，确恰恰出现在对获取的用户名变量检测上面。直接获取传入用户名，然后存为文件。 有朋友会说：<strong>这些文件名都是我电脑里面存在的，文件名格式都受限于操作系统对文件名定义。 </strong>但是，需要注意是，对于$_FILES里面获取变量，是直接来自http request请求。它跟普通获取其它get,post变量一样。 因此，别有用心的人，往往会自己模拟浏览器，给服务器发送一个特殊文件名。然后，让存文件时候，能够正常保存为自己格式。</p>
<p>前些年，”\0” 在字符串中，保存为文件，会自动截断后面内容。 如：$filename 构造为：”a.php\0.jpg” ，我们想想，将会变成怎么样？</p>
<p>$newfile = “upload/a.php\0.jpg” 因为，对扩展名验证，最右边”.”后面字符是jpg ，是允许图片格式。 但是，我们一以该文件名，保存。 发现磁盘会在upload目录下面生成a.php ，\0后面所有字符，被自动截断。</p>
<p>该漏洞，风靡一时。当时几乎大多数上存网站都有漏洞。一时，很多平台关闭了上存。其实，根本原因就在此。我们拿到文件名，自己作为最终生成文件名保存了。&#160; 好的方法，是<strong>自己随机生成文件名+读取扩展名 。</strong>这样可以组织输入特殊字符，在进行文件保存时候，被抛弃或截断了。</p>
<p>php4时代这个漏洞可以利用，到php5时代，生成的变量文件名值中，会自动过滤掉”\0” ，这样无论用户构造怎么样的特殊”\0”用户名，都会被截断。 但是 ，目前这类漏洞，在asp,jsp 等站点。还经常有出现。老版本的php站点也会经常出现。</p>
<p>&#160;</p>
<p>好了，今天先到这里，后面还有2种其它常见方法，后面给出！欢迎交流！</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chacuo.net/136.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>web上存漏洞及原理分析、防范方法</title>
		<link>http://blog.chacuo.net/108.html</link>
		<comments>http://blog.chacuo.net/108.html#comments</comments>
		<pubDate>Thu, 30 May 2013 15:42:34 +0000</pubDate>
		<dc:creator>程默</dc:creator>
				<category><![CDATA[web安全]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[上存漏洞]]></category>

		<guid isPermaLink="false">http://blog.chacuo.net/?p=108</guid>
		<description><![CDATA[网站提供上存功能，是很多站点经常会有功能，商城，论坛还有常见一些网盘站点。常见互联网上面，我们也是经常听说，某 [...]]]></description>
				<content:encoded><![CDATA[<p>网站提供上存功能，是很多站点经常会有功能，商城，论坛还有常见一些网盘站点。常见互联网上面，我们也是经常听说，某某站点出现上存漏洞，某某开源项目有上存漏洞。 从互联网开始出现动态程序，上存漏洞像幽灵一样，频繁的出现在各种系统中。为什么，一个上存漏洞会这么频繁出现呢。而且，有些系统反复修补，多次还没有修补成功！其实主要问题，还是出现在上存原理上面。我们先看看，上存过程。</p>
<ul>
<li>
<h3><span style="font-weight: bold">网站上存过程分析</span></h3>
</li>
</ul>
<blockquote><div>
<div>
<pre><span style="color: #0000ff">&lt;?</span>php
<a style="color: #ffa500" href="http://www.php.net/header">header</a>(&quot;<span style="color: #8b0000">Content-type: text/html; charset=utf-8</span>&quot;); 
<a style="color: #0000ff" href="http://www.php.net/if">if</a>($_FILES)
{
	<a style="color: #0000ff" href="http://www.php.net/echo">echo</a> '<span style="color: #8b0000">&lt;pre&gt;</span>';
	<a style="color: #ffa500" href="http://www.php.net/var_dump">var_dump</a>($_FILES);
	<a style="color: #0000ff" href="http://www.php.net/echo">echo</a> '<span style="color: #8b0000">&lt;/pre&gt;</span>';
}
<span style="color: #0000ff">?&gt;</span>
<span style="color: #0000ff">&lt;</span><span style="color: #800000">form</span> <span style="color: #ff0000">action</span>=<span style="color: #0000ff">&quot;&quot;</span> <span style="color: #ff0000">enctype</span>=<span style="color: #0000ff">&quot;multipart/form-data&quot;</span> <span style="color: #ff0000">method</span>=<span style="color: #0000ff">&quot;POST&quot;</span><span style="color: #0000ff">&gt;</span>
<span style="color: #0000ff">&lt;</span><span style="color: #800000">input</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">&quot;file&quot;</span> <span style="color: #ff0000">name</span>=<span style="color: #0000ff">&quot;txt&quot;</span> <span style="color: #ff0000">size</span>=<span style="color: #0000ff">&quot;50&quot;</span><span style="color: #0000ff">&gt;</span>
<span style="color: #0000ff">&lt;</span><span style="color: #800000">input</span> <span style="color: #ff0000">name</span>=<span style="color: #0000ff">&quot;Submit&quot;</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">&quot;submit&quot;</span> <span style="color: #ff0000">value</span>=<span style="color: #0000ff">&quot;提交&quot;</span> <span style="color: #0000ff">&gt;</span>
<span style="color: #0000ff">&lt;/</span><span style="color: #800000">form</span><span style="color: #0000ff">&gt;</span></pre>
</p></div>
<div></div>
</p></div>
</blockquote>
<p>&#160;</p>
<p>以上是个简单测试例子，我们看看</p>
<p><a href="http://blog.chacuo.net/wp-content/uploads/2013/05/image22.png"><img style="background-image: none; border-right-width: 0px; margin: 0px 0px 0px 10px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.chacuo.net/wp-content/uploads/2013/05/image_thumb22.png" width="738" height="459" /></a></p>
<p><strong>我们来分析下：</strong></p>
<p>name来自 上存时候选择文件名称</p>
<p>type 是文件类型， 这个类型那里来的呢？呵呵，这里非常关键的。 很多时候，很多同人会认为，这个是服务器自动判断生成的。 如果是这样想，觉得也有可能。 php 封装了上存，它自带类库好像可以的。&#160; 但是，反过来想想，你随便选择个什么格式文件，都会有格式类型。这样一想，我们推断这个值，可能也来自用户输入的。 我们来抓包看看我们类型。</p>
<p><a href="http://blog.chacuo.net/wp-content/uploads/2013/05/image23.png"><img style="background-image: none; border-right-width: 0px; margin: 0px 0px 0px 10px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.chacuo.net/wp-content/uploads/2013/05/image_thumb23.png" width="856" height="334" /></a></p>
<p><strong>type值 也来自，用户输入值了。</strong></p>
<p>size来自程序计算上存文件大小，这个是自动计算的。 相比我们都清楚的。</p>
<h3></h3>
<h3></h3>
<ul>
<li>
<h3><span style="font-weight: bold">你说这么多有啥样呢？</span></h3>
</li>
</ul>
<p>想必有朋友开始问了，我上面分析上存文件格式 ，跟开发出现漏洞有什么关联呢。 其实，我们想想，上面说的，一个文件名称name属性，以及文件类型type属性。 在我们上存文件，后端处理时候，会经常用到的。 作为开发者，在使用这2个变量，一定要继续执行“<strong>一切输入代码是有害的</strong>”原则。你在使用时候，要把它当作，跟其它get,post 获取变量一样处理。 要检测，过滤一切输入变量。</p>
<p>我们经常做功能是，限定用户输入必须是某种格式文件，然后保存为该格式。分析到这里，下面有很多需要继续分析地方，今天先提出大纲。接下来会分析这样常见3类上存漏洞。</p>
<p><span style="text-decoration: underline">1. 使用用户文件名，生成文件，特殊字符过滤不严格，导致文件生成出现漏洞</span></p>
<p><span style="text-decoration: underline">2.移动文件目录时候，由于采用用户传入的文件名拼接，生成到错误目录</span></p>
<p><span style="text-decoration: underline">3.相信用户输入type 类型，直接将用户文件名保存为文件</span></p>
<p>&#160;</p>
<p>好了，下一篇我会举例逐步分析这3种常见漏洞，欢迎朋友们提出你的观点，与我交流！</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chacuo.net/108.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
