那些世人皆知的php-Trick(上)

基础篇

MD5

1.PHP弱比较

 $_GET['a'] != $_GET['b'] 
 &&
 MD5($_GET['a']) == MD5($_GET['b'])

php中 ==只是判断值是否相等,而不会判断数据类型是否相同,如果类型不同先转换为相同类型再进行比较而PHP在处理哈希字符串时后,会把0E开头的哈希值解释为0。所以如果两个值通过md5后值都已0E开头,就会相等。

例子

 md5(str)
 QNKCDZO
 240610708
 s878926199a
 s155964671a
 s214587387a
 s214587387a
 sha1(str)
 sha1后以0E开头
 sha1(‘aaroZmOk’)
 sha1(‘aaK1STfY’)
 sha1(‘aaO8zKZF’)
 sha1(‘aa3OFF9m’)

2.PHP特性

 $_POST['a']!==$_POST['b'] 
 &&
 md5($_POST['a'])===md5($_POST['b'])

php中md5和sha1函数都无法处理数组,会返回NULL

3.md5碰撞

 (string)$_POST['a']!==(string)$_POST['b'] 
 &&
 md5($_POST['a'])===md5($_POST['b'])
 }

字符串类型,强相等,且MD5相等

 a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2
 b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2

相等即可。

ereg函数漏洞

新版本去除了,官网没查到,适用低版本php

 <?php
  if(ereg("^[a-zA-Z0-9]+$",$_GET['pass'])===FALSE){
  echo "yes";
  }
 ?>
   
  // ?pass = %00123

ereg() 只能处理字符串,遇到数组会返回null ,可以用 数组绕过

也可以使用NULL截断

extract()变量覆盖

extract(),它的主要作用是将数组展开,键名作为变量名,元素值为变量值,前后端处理参数很方便。

触发条件:函数在指定参数为EXTR_OVERWRITE或者没有指定函数

 <?php  
     $auth = '0';  
     $b =array("auth"=>'1');
     // 这里可以覆盖$auth的变量值
     extract($b);
     echo ($auth);
 ?>
   //输出 1

is_numeric

判断变量是否为数字

参考如下即可

 <?php
 echo is_numeric(233333);       # 1
 echo is_numeric('233333');   # 1
 echo is_numeric(0x233333);   # 1
 echo is_numeric('0x233333');   # 1
 echo is_numeric('233333abc'); # 0
 ?>

parse_str()

功能:parse_str() 函数用于把查询字符串解析到变量中,如果没有array 参数,则由该函数设置的变量将覆盖已存在的同名变量。 极度不建议 在没有 array参数的情况下使用此函数,并且在 PHP 7.2 中将废弃不设置参数的行为。此函数没有返回值

 <?php
   $name="Jenny";
 parse_str("name=Peter&age=43");
 echo $name;
 ?>
   #新版本必须要两个参数参数,不然报错
   
 

image-20211209085510338

7.2以前版本测试成功,实现变量覆盖

image-20211209085614772

弱类型比较

主要是使用 ==时,如果一个数值和一个字符串比较,那么会将字符串转换为数值。

参考网上集合

 <?php  
 echo 0 == 'a' ;// a 转换为数字为 0 此处php版本要大于7.0 重点注意
 
 // 0x 开头会被当成16进制54975581388的16进制为 0xccccccccc
 // 十六进制与整数,被转换为同一进制比较
 '0xccccccccc' == '54975581388' ;  //php要小于7.0
 // 字符串在与数字比较前会自动转换为数字,如果不能转换为数字会变成0
 1 == '1';
 1 == '01';
 10 == '1e1';
 '100' == '1e2' ;    
 
 // 十六进制数与带空格十六进制数,被转换为十六进制整数
 '0xABCdef'  == '     0xABCdef';  //版本要小于7.0
 echo '0010e2' == '1e3';
 // 0e 开头会被当成数字,又是等于 0*10^xxx=0
 // 如果 md5 是以 0e 开头,在做比较的时候,可以用这种方法绕过
 '0e509367213418206700842008763514' == '0e481036490867661113260034900752';
 '0e481036490867661113260034900752' == '0' ;
 
 var_dump(md5('240610708') == md5('QNKCDZO'));
 var_dump(md5('aabg7XSs') == md5('aabC9RqS'));
 var_dump(sha1('aaroZmOk') == sha1('aaK1STfY'));
 var_dump(sha1('aaO8zKZF') == sha1('aa3OFF9m'));
 ?>

unset

用来销毁指定的变量

场景:销毁变量,实现变量覆盖,或者变量删除

intval()

会将从字符串的开始进行转换知道遇到一个非数字的字符

 var_dump(intval('2')) //2  
 var_dump(intval('3abcd')) //3  
 var_dump(intval('abcd')) //0

in_array()

搜索数组中是否存在指定的值。

 $array=[0,1,2,'3'];  
 var_dump(in_array('abc', $array)); //true  
 var_dump(in_array('1bc', $array)); //true
 
 # 仍然是PHP在数据自动转换的过程中的问题

参考

https://blog.csdn.net/qq_31481187/article/details/60968595

posted @ 2021-12-11 14:39  kzd的前沿思考  阅读(133)  评论(0编辑  收藏  举报