<?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/%e6%96%87%e4%bb%b6%e6%93%8d%e4%bd%9c%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/152.html</link>
		<comments>http://blog.chacuo.net/152.html#comments</comments>
		<pubDate>Wed, 05 Jun 2013 10:35:54 +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=152</guid>
		<description><![CDATA[做web开发，我们经常会做代码走查，很多时候，我们都会抽查一些核心功能，或者常会出现漏洞的逻辑。随着技术团队的 [...]]]></description>
				<content:encoded><![CDATA[<p>做web开发，我们经常会做代码走查，很多时候，我们都会抽查一些核心功能，或者常会出现漏洞的逻辑。随着技术团队的壮大，组员技术日益成熟。 常见傻瓜型SQL注入漏洞、以及XSS漏洞。会越来越少，但是我们也会发现一些新兴的隐蔽性漏洞偶尔会出现。这些漏洞，跟多来自开发人员，对一个函数、常见模块功能设计不足，遗留下的问题。以前我们能够完成一些功能模块，现在要求是要安全正确方法完成模块才行。 接下来，我会分享一些常见功能模块，由于设计原因导致漏洞出现。下面，我们先看下，读取文件型功能漏洞。</p>
<p>我们先看下下面一段代码，通过用户输入不同目录，包含不同文件</p>
<blockquote><pre style="text-indent: 0px" lang="php">&lt;?php
///读取模块名称
$mod = isset($_GET['m'])?trim($_GET['m']):'index';

///过滤目录名称不让跳转到上级目录
<strong><u>$mod = str_replace("..",".",$mod);</u></strong>

///得到文件
<strong><u>$file = "/home/www/blog/".$mod.".php";</u></strong>

///包含文件
@include($file);

</pre>
<pre></pre>
</blockquote>
<p>这段代码，可能在很多朋友做的程序里面有遇到过，对于新人来说，也是很容易出现这样问题，记得走查遇到该代码时候，我问到，你这个代码安全方面能做到那些？</p>
<p>答：1. 对”..”目录有做替换，因此用户传入模块名里面有有..目录都会被替换掉了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.构造拼接file名称，有前面目录限制，有后面扩展名限制，包含文件就会限制在该目录了</p>
<ul>
<li>
<h3><strong>这段代码真的做到了目录安全检测吗？</strong></h3>
</li>
</ul>
<p>我们来测试下，如果$mod传入这个值将会是什么样的结果。</p>
<p><a href="http://blog.chacuo.net/wp-content/uploads/2013/06/image1.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.chacuo.net/wp-content/uploads/2013/06/image_thumb1.png" width="587" height="96"></a> </p>
<p>$mod 通过构造输?mod=&#8230;%2F&#8230;%2F&#8230;%2F&#8230;%2Fetc%2Fpasswd%00 ，我们看结果将是：</p>
<p><a href="http://blog.chacuo.net/wp-content/uploads/2013/06/image2.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog.chacuo.net/wp-content/uploads/2013/06/image_thumb2.png" width="593" height="304"></a> </p>
<p>居然include(“/etc/passwd”)文件了。 </p>
<ul>
<li>
<h3><strong>怎么逃脱了我参数限制呢？</strong></h3>
</li>
</ul>
<h3><strong></strong>&nbsp;</h3>
<p><strong>首先：</strong>做参数过滤类型去限制用户输入本来就不是一个好方法，一般规则是：<u><font color="#0000ff">能够做检测的，不要做替换 </font></u>只要是检测不通过的，直接pass 掉！这是我们的一个原则。过滤失败情况，举不胜举，我们来看看，实际过程。</p>
<p>1、输入”…/…/…/” 通过把”..” 替换为”.”后</p>
<p>2、结果是”../../../” 就变成了这个了</p>
<p>有朋友就会说，如果我直接替换为空格是不是就好了？在这个里面确实可以替换掉。但是不代表以后你都替换为空格就好了。再举例子下。如：有人将字符串里面javascript替换掉。代码如下：</p>
<blockquote>
<p>……</p>
<p><font style="background-color: #ffffff" face="Arial">$msg = str_replace(“javascript”,””,$msg);</font></p>
</blockquote>
<p><u>看似不会出现了javascript了，但是，如果输入:jjavascriptavascript 替换，会替换掉中间一个变为空格后。前面的”j” 跟后面的会组成一个新的javascript了。 </u></p>
<p><strong>其次：</strong>我们看看，怎么逃脱了，后面的.php 限制呢。用户输入的参数有：”etc/passwd/0” ，\0字符非常特殊，一段连接后，文件名称变成了”……etc/passwd\0.php”，你打印出该变量时候，还是正确的。但是，一段放入到文件读写操作方法里面，\0后面会自动截断。操作系统，只会读取……etc/passwd文件了。 “\0”会出现在所有文件系统读写文件变量中。都会同样处理。这根c语言\0作为字符串完整标记有关系。</p>
<p>通过上面分析，大家发现做文件类型操作时候，一不注意将产生大的漏洞。而且该漏洞就可能引发一系列安全问题。</p>
<ul>
<li>
<h3><strong>该怎么做文件类操作呢？</strong></h3>
</li>
</ul>
<p>到这里，估计有人就会思考这个，做文件读写操作时候，如果路径里面有变量时候，我该怎么样做呢？有人会说，替换可以吗？ “可以”，但是这个方法替换不严格，将会出现很多问题。而且，对于初写朋友，也很难杜绝。做正确的事情，选择了正确的方法，会从本身杜绝问题出现可能了。 这里，我建议：对于变量做白名单限制。</p>
<ol>
<li><strong>什么是白名单限制</strong><br />
<blockquote>
<p><font style="background-color: #ffffff" face="Arial">举例来说：</font></p>
<p>$mod = isset($_GET['m'])?trim($_GET['m']):&#8217;index&#8217;;<font style="background-color: #ffffff" face="Arial"> ///读取模块名称后</font></p>
<p><font style="background-color: #ffffff" face="Arial">mod变量值范围如果是枚举类型那么：</font></p>
<p><font style="background-color: #ffffff" face="Arial">if(!in_array($mod,array(‘user’,’index’,’add’,’edit’))) exit(‘err!!!’);</font></p>
<p><font style="background-color: #ffffff" face="Arial">完全限定了$mod，只能在这个数组中，<strong>够狠！！！！</strong></font></p>
<p>&nbsp;</p>
</blockquote>
<li><strong>怎么做白名单限制</strong></li>
</ol>
<p>通过刚才例子，我们知道如果是枚举类型，直接将值放到list中即可，但是，有些时候，这样不够方面。我们还有另外一个白名单限制方法。就是<strong>限制字符范围</strong></p>
<blockquote>
<p><font style="background-color: #ffffff" face="Arial">举例来说：</font></p>
<p>$mod = isset($_GET['m'])?trim($_GET['m']):&#8217;index&#8217;;<font style="background-color: #ffffff" face="Arial"> ///读取模块名称后</font></p>
<p>我限制知道$mod是个目录名称，对于一般站点来说，就是字母加数字下划线之类。</p>
<p>if(!preg_match(“/^\w+$/”,$mod)) exit(‘err!!!’);</p>
<p>字符只能是：[A-Za-z0-9_] 这些了。<strong>够狠！！！</strong></p>
</blockquote>
<p>&nbsp;</p>
<p><strong>总结：</strong>是不是发现，白名单限制方法，做起来其实很简单，你知道那个地方要什么，就对输入检测必须是那些。而且，检测自己已知的，比替换那些未知的字符，是不是简单多了。 好了，先到这里，正确的解决问题方法，会让文件简单，而且更安全！！欢迎交流！</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chacuo.net/152.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
