龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > php编程 >

安全专家讲述PHP函数安全特性

时间:2009-12-17 12:00来源:未知 作者:admin 点击:
分享到:
(一)PHP的强制转换 PHP中的强制转换要在转换的变量前加上用括号括起来的目标类型,还可以使用函数settype(),代码0x1.php如下 $a=$_GET[a];//?a = "1abc"; $int = (int) $a; $float = (float) $a; $string = (

 (一)PHP的强制转换

  PHP中的强制转换要在转换的变量前加上用括号括起来的目标类型,还可以使用函数settype(),代码0x1.php如下

  

  $a=$_GET[a];//?a = "1abc";

  $int = (int) $a;

  $float = (float) $a;

  $string = (string) $a;

  $array = settype($int,'array');

  ?>

  还可以使用intval() floatval() strval() 函数进行强制转换,代码0x2.php如下

  

  $a=$_GET[a];//?a = "1.23abc"

  $int = intval($a);

  $flo= floatval($a);

  $string = strval($a)

  ?>

  当我们需要对变量进行强制类型转换时,通过以上方法,如若使用不当均会导致安全漏洞。

  (二)模拟测试

  我们对漏洞代码进行模拟测试,intval强制转换示例代码0x3.php:

  

  $a="123a and 1=1";

  intval($a);

  echo $a;

  echo "";

  $a_safe="123a";

  $a_safe=intval($a_safe);

  echo $a_safe;

  echo "";

  ?>

  运行结果:

  123a and 1=1

  123

  $a并未被转换未整型,而是原样输出来了。相应的我们$a_safe才真正被强制转换了。

  int强制转换示例代码0x4.php:

  

  $b="123b and 1=2";

  (int)$b;

  echo $b;

  echo "";

  $b_safe="123b";

  $b_safe=(int)$b_safe;

  echo $b_safe;

  echo "";

  ?>

  运行结果:

  123b and 1=2

  123

  $b并未被转换为整型,还是原样输出来了。相应$b_safe被转换。

  把上述安全隐患带入PHP的流程控制

  If 示例代码0x5.php:

  

  $c="123.3c";

  if(floatval($c)) {

  echo $c."";

  }

  $c_safe="123.3c";

  if($c_safe=floatval($c_safe)) {

  echo $c_safe."";

  }

  ?>

  运行结果:

  123.3c

  123.3

  我们可以看到第一个if判断条件并未将$c转换未浮点型数值,相应$c_safe被转换了。

  switch 示例代码0x6.php:

  

  $d = "123.3d";

  switch(intval($d)){

  case "123.3d" : echo $d."

";

  case "123" : echo $d."It's not safe";

  }

  $d_safe = "123.3d";

  $d_safe=intval($d_safe);

  switch($d_safe){

  case "123.3d" : echo $d_safe."

It's not safe";

  case "123" : echo $d_safe."It's safe";

  }

  ?>

  运行结果:

  123.3dIt's not safe

  123It's safe

  $d在switch中并未被转换为整型,还是原样输出。而$d_safe则被转换了。

  while 示例代码0x7.php

  

  $e=123e;

  while(intval($e)){

  echo $e."引发死循环";

  }

  ?>

  运行结果:

  Parse error: parse error in D:\xampp\htdocs\80vul\src\0x7.php on line 2

  while中的判断永远为真,引起死循环,但$e并未被强制转换未整型。

  经测试,得出结论,由于变量都是经过强制类型转换后,返回的值并未赋给某个变量,所以均存在漏洞隐患。

  实例演示,大家可以参照我博客上的《 PHP、MySQL注入总结》。

  地址:Http://hi.baidu.com/menzhi007

二,引申PHP函数共性

  引申示例1,当magic_quotes_gpc = Off,代码0x8.php如下:

  

  $id = $_GET[id];

  $id=htmlspecialchars($id);

  echo $id."

";

  $id_safe=$_GET[id];

  $id_safe= htmlspecialchars ($id_safe);

  echo $id_safe;

  ?>

  提交URL:http://127.0.0.1/80vul/src/0x8.php?id=1' and 1=2'

  运行结果:

  1' and 1=2'

  1\' and 1=2\'

  引申示例2,再看个有意思的例子,代码0x09.php 如下:

  

  $id = $_GET[id];

  $id=htmlspecialchars($id);

  echo $id."

";

  $id_safe=$_GET[id];

  $id_safe==htmlspecialchars($id_safe);//注意这里是双等号

  echo $id_safe;

  ?>

  运行结果:

  1' and 1=2'

  1' and 1=2'

  居然没有过滤,两个双等号并不是赋值语句,所以还是不会起到过滤作用。

  当我们提交 URL?id=a and 1=2时,变量 id并不会经过htmlspecialchars函数过滤,从而引发安全隐患。

  引申示例3,代码0x10.php如下:

  

  $str = 'one|two|three|four';

  explode('|', $str, 2);

  echo "

";

  print_r($str);

  $str_safe='one|two|three|four';

  $str_safe=explode('|', $str_safe, 2);

  echo "

";

  print_r($str_safe);

  ?>

  运行结果:

  Array ( [0] => one [1] => two|three|four )

  one|two|three|four

  倘若我们不将返回结果赋值给一个变量名,将导致过滤毫无意义。

  经测试,得出结论,分析PHP语言特性,PHP是一种弱类型语言,允许定义两个相同的变量名,后定义的变量将覆盖前定义的变量。若没有任何变量名指向这个变量时,PHP 垃圾回收机制(Garbage Collector),会将其在内存中销毁,防止内存溢出。__destruct() 析构函数,是在垃圾对象被回收时执行。unset 销毁的是指向对象的变量。我们得以扩充,所有经过函数过滤的变量,如果返回的结果未赋给另一个变量,那么这个变量将被PHP内存回收机制GC自动回收,其值并不会因其前函数的影响而变化。比如0x1.php示例中的代码“ (int)$b; ” 经过int强制转换的整型数据会放置于内存中,而后被内存回收,并未起到强制转换的作用。

  此文引申于80vul的pch-001,强烈致谢80vul、Ph4nt0m,并向他们致敬。导致此安全隐患的是PHP函数共性,作为程序设计人员我们应尽可能的做好自己的编码规范,以避免此类隐患。当然本文中出现的错误疏漏之处,望大家予以指正。

  三、实际利用

  Wordpress 2_0_5 Trackback UTF-7 Remote SQL Injection

  http://www.milw0rm.com/exploits/3095

  参考文献:

  http://www.80vul.com/pch/pch-001.txt

  http://superhei.blogbus.com/logs/4255503.html

精彩图集

赞助商链接