PHP弱类型

本文探讨了弱类型语言中常见的安全问题,包括整数大小比较的绕过技巧、字符串比较的漏洞、MD5哈希比较的缺陷、JSON数据绕过方法、strcmp函数的漏洞以及array_search函数与is_array函数的结合使用中的安全隐患。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0x01 什么是弱类型

强类型语言,当你定义一个变量是某个类型,如果不经过代码显式转换(强制转化)过,它就永远都是这个类型,如果把它当做其他类型来用,就会报错

弱类型语言,你想把这个变量当做什么类型来用,就当做什么类型来用,语言的解析器会自动(隐式)转换。
弱类型

0x02 弱类型整数大小比较

$temp = $_GET['password'];
is_numeric($temp)?die("no numeric"):NULL;
if($temp>1336){
echo $flag;

is_numeric() 函数用于检测变量是否为数字或数字字符串。
如果指定的变量是数字和数字字符串则返回 TRUE,否则返回 FALSE(PHP 版本要求:PHP 4, PHP 5, PHP 7)

在这里先判断是不是数字。
然后再判断这个数字是不是大于1336。

可以用数组绕过、%00截断、添加其他字符
PHP数组有一个缺陷就是大多数的函数都没有办法去判断数组。

http://123.206.87.240:9009/22.php?password[]=1

http://123.206.87.240:9009/22.php?password=9999a

http://123.206.87.240:9009/22.php?password=9999%00

0x03 “”和“=”

php中有两种比较的符号 == 与 ===

 <?php
$a = $b ;
$a===$b ;
?>```

=== 在进行比较的时候,会先判断两种字符串的类型是否相等,再比较

== 在进行比较的时候,会先将字符串类型转化成相同,再比较。
如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行

例子:
```bash
在$a==$b;$a=' ';$b=null        //true
$a=null;$b=true      //true      
$a=0;$b='0'       //true
$a=0;$b='abcdef '  //true 
($a===$b //false)
var_dump("admin"==0);  //true
var_dump("1admin"==1); //true
var_dump("admin1"==1) //false
var_dump("admin1"==0) //true
var_dump("0e123456"=="0e4456789"); //true

“admin”==0 比较的时候,会将admin转化成数值,强制转化,由于admin是字符串,转化的结果是0,和0相等

“1admin”==1 比较的时候会将1admin转化成数值,结果为1
“admin1“被转化为0。当一个字符串欸当作一个数值来取值,其结果和类型如下:如果该字符串没有包含’.’,‘e’,'E’并且其数值值在整形的范围之内
该字符串被当作int来取值,其他所有情况下都被作为float来取值,该字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则使用该数值,否则其值为0。

“0e123456”=="0e456789"相互比较的时候,会将0e这类字符串识别为科学技术法的数字,0的无论多少次方都是零,所以相等

0x04 md5绕过(Hash比较缺陷)

<?php
if (isset($_GET['Username']) && isset($_GET['password'])) {
    $logined = true;
    $Username = $_GET['Username'];
    $password = $_GET['password'];

     if (!ctype_alpha($Username)) {$logined = false;}
     if (!is_numeric($password) ) {$logined = false;}
     if (md5($Username) != md5($password)) {$logined = false;}
     if ($logined){
    echo "successful";
      }else{
           echo "login failed!";
        }
    }
?>```
意思:输入Username(字符串型)和password(数字型),并且两者md5相等,即可成功。

做法:0e在比较的时候会将其视作为科学计数法,所以无论0e后面是什么,0的多少次方还是0。md5('240610708') == md5('QNKCDZO')成功绕过
下列是md5开头是0e的字符串:
```bash
QNKCDZO
0e830400451993494058024219903391

s878926199a
0e545993274517709034328855841020
  
s155964671a
0e342768416822451524974117254469
  
s214587387a
0e848240448830537924465865611904
  
s214587387a
0e848240448830537924465865611904
  
s878926199a
0e545993274517709034328855841020
  
s1091221200a
0e940624217856561557816327384675
  
s1885207154a
0e509367213418206700842008763514

240610708
0e462097431906509019562988736854

0x05 json绕过

<?php
if (isset($_POST['message'])) {
    $message = json_decode($_POST['message']);
    $key ="*********";
    if ($message->key == $key) {
        echo "flag";
    } 
    else {
        echo "fail";
    }
 }
 else{
     echo "~~~~";
 }
?>

输入一个json类型的字符串,json_decode函数解密成一个数组,判断数组中key的值是否等于 k e y 的 值 , 但 是 key的值,但是 keykey的值我们不知道,但是可以利用0=="admin"这种形式绕过

最终payload: message={“key”:0}

0x06 strcmp漏洞绕过

strcmp是比较两个字符串,如果两者相等 返回0
str1小于str2,返回负数

<?php
    $password="***************"
     if(isset($_POST['password'])){

        if (strcmp($_POST['password'], $password) == 0) {
            echo "Right!!!login success";n
            exit();
        } else {
            echo "Wrong password..";
        }
?>

要求我们post一个password值,要与给定的password变量的值相等。

password[]=xxx
可以绕过 。因为函数接受到了不符合的类型,将发生错误,但是还是判断其相等。

0x07 "array_search"与is_array"绕过

is_array:判断传入的是不是一个数组,array_search(x,$数组):在数组中寻找与指定值(x)相等的值.

实例
在数组中搜索键值 “red”,并返回它的键名:

<?php
$a=array("a"=>"red","b"=>"green","c"=>"blue");
echo array_search("red",$a);
?>

array_search() 函数在数组中搜索某个键值,并返回对应的键名。
详细说明

array_search() 函数与 in_array() 一样,在数组中查找一个键值。如果找到了该值,匹配元素的键名会被返回。如果没找到,则返回 false。

如果第三个参数 strict 被指定为 true,则只有在数据类型和值都一致时才返回相应元素的键名

<?php
if(!is_array($_GET['test'])){exit();}
$test=$_GET['test'];
for($i=0;$i<count($test);$i++){
    if($test[$i]==="admin"){
        echo "error";
        exit();
    }
    $test[$i]=intval($test[$i]);
}
if(array_search("admin",$test)===0){
    echo "flag";
}
else{
    echo "false";
}
?>

array_search函数 类似于== 也就是 a = = " a d m i n " 当 然 是 a=="admin" 当然是 a=="admin"a=0 当然如果第三个参数为true则就不能绕过

先判断传入的是不是数组,然后循环遍历数组中的每个值,并且数组中的每个值不能和admin相等,并且将每个值转化为int类型,再判断传入的数组是否有admin,有则返回flag

payload: test[]=0可以绕过

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

如歌_Velpro

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值