你真的会PHP吗?

Note:

1) PHP中的数据类型

PHP一共支持八种数据类型,

4种标量类型,boolean(布尔型),integer(整形),float/double(浮点型)和string(字符串类型),

2种复合类型,array(数组),和object(对象),

2种特殊类型,resource(资源)与null.

2)  intval()函数所引发的溢出

Intval()函数最大的值取决于操作系统位数,

32 位系统最大带符号的 integer 范围是 -2147483648 ~~ 2147483647,

64 位系统上,最大带符号的 integer 值是 -92233720368547758078 ~~ 92233720368547758077

当超过相应的最大值时会发生溢出(如:32为系统:2147483648时会溢出为2147483647)


利用:判断数值上是回文,字符本身不是回文

@ 如果参数为2147483647,那么当它反过来时,由于超出限制,所以依然等于2147483647,即为数值上回文

@ 其它方法判断(科学计数法)如果参数为0e-0,那么当它反过来时,数值上还是0,即为数值上回文

3)is_numeric()函数所引发的SQL注入以及其它问题

is_numeric()函数判断参数是否是数值型数据(常见:十进制,十六进制)


@ is_numeric()函数对于空字符%00,无论%00放在前后都可以判断为非数值,而%20空格字符只能放在数值      后,当%20放在数值前时,函数会对数值前面的空格字符进行跳过,接着后面的判断

@ SQL注入

    简单例子

    $s = is_numeric($_GET['s'])?$_GET['s']:0;

    $sql="insert into test(type)values($s);";     //是 values($s) 不是values('$s'),后者将会解析成字符串不变

    当参数为0x31206f722031转化为ASCII时为 1 or 1(特殊SQL关键字)

    将该参数插入数据库之后,如果再重新查询这个表的字段出来,不做过滤带入另一个SQL语句,将会造成2        次注入.


PHP代码中尽量不要使用该函数,如果要使用这个函数,建议使用规范的sql语句,条件加入单引号,这样16进制0x31206f722031就会在数据库里显示出来,而不会出现1 or 1

考点  :PHP源码审计


进去之后发现就一句话,没什么用,抓包发现返回的数据包头部有一个文本文档,访问之后是一段PHP代码

<?php


$info = ""; 
$req = [];
$flag="xxxxxxxxxx";

ini_set("display_error", false); 
error_reporting(0); 


if(!isset($_POST['number'])){
   header("hint:6c525af4059b4fe7d8c33a.txt");

   die("have a fun!!"); 
}

foreach([$_POST] as $global_var) { 
    foreach($global_var as $key => $value) { 
        $value = trim($value);  //trim() 函数移除字符串两侧的空白字符或其他预定义字符
        is_string($value) && $req[$key] = addslashes($value); //addslashes() 函数在指定的预定义字符前添加反斜杠。这些字符是单引号(')、双引号(")、反斜线(\)与NUL(NULL字符)
} 


function is_palindrome_number($number) { //回文函数
    $number = strval($number);   //将数组及类之外的变量类型转换成字符串类型
    $i = 0; 
    $j = strlen($number) - 1; 
    while($i < $j) { 
        if($number[$i] !== $number[$j]) { 
            return false; 
        } 
        $i++; 
        $j--; 
    } 
    return true; 
} 


if(is_numeric($_REQUEST['number'])){   //判断传入的参数是否是数值
    
   $info="sorry, you cann't input a number!";

}elseif($req['number']!=strval(intval($req['number']))){
      
     $info = "number must be equal to it's integer!! ";  

}else{

     $value1 = intval($req["number"]);           //intval()函数将字符串转化为数值
     $value2 = intval(strrev($req["number"]));   //strrev()函数反转字符串

     if($value1!=$value2){
          $info="no, this is not a palindrome number!";
     }else{
          
          if(is_palindrome_number($req["number"])){
              $info = "nice! {$value1} is a palindrome number!"; 
          }else{
             $info=$flag;
          }
     }

}

echo $info;


?>

PHP代码审计之后,最后打印flag需要$_POST['number']满足以下条件:

1) 不能为空,且不能传递数值型数据

2)该数所反转的整数值应该和它本身的整数值相等

$value1 = intval($req["number"]);           //intval()函数将字符串转化为数值
$value2 = intval(strrev($req["number"]));   //strrev()函数反转字符串
$value1=$value2

3) 不能是一个回文数

构造$_POST['number']使其满足条件

不能传递回文数据,又让该数所反转的整数值应该和它本身的整数值相等,前后矛盾,

但可以利用intval()函数溢出进行解决问题,$_POST['number']=%002147483647(通过返回的数据包可知是32的操作系统)即可,intval(strrev(2147483647))发生溢出等于2147483647,即$value1=$value2=2147483647

另一种方法,利用科学计数法进行解决问题,$_POST['number']=%000e-0即可,即$value1=$value2=0


猜你喜欢

转载自blog.csdn.net/tc125/article/details/81017674