PHP黑魔法学习总结

php黑魔法

最近打ctf,发现了php新世界,所以来学习以及总结以下所遇到php新玩法(对我而言是新玩法),毕竟我菜嘛

php黑魔法就是所谓的弱类型比较,一些函数返回null,利用数组返回True的一些问题

弱类型比较

<?php
$a = 'betao.cn';
if ($a == 0){
    echo 'Ture';
}else{
    echo 'False';
}
 // 以上代码输出 Ture
echo '<hr>';
$b = '3betao.cn'; 
if ($b > 2){
    echo "True"; 
}else{
    echo 'False';
}
// 输出True

// 以上代码说明了:若字符串以数字开头,则取开头数字作为转换结果,若无则输出0

image-20191115143819321

总结: 以上代码说明了,若字符串以数字开头,则取开头数字作为转换结果,若无则输出0

md5(),sha1()

  1. PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0
  2. md5()是不能处理数组的,md5(数组)会返回null,两个null相等绕过,sha1()也是同理
<?php
$a = 'QNKCDZO';
$b = 's878926199a';
$md5_a = md5($a); echo $md5_a.'<br>';
$md5_b = md5($b); echo $md5_b.'<br>';
if ($md5_a == $md5_b){
    echo 'True';
}else{
    echo 'False';
}
?>

image-20191115144641604

这种问题也叫MD5碰撞,更详细更多的可以参考我之前的文章:https://www.betao.cn/archives/md5same.html

<?php
$a = $_GET['a'];
$b = $_GET['b'];
echo md5($a).'<br>';
echo md5($b).'<br>';
if (md5($a) === md5($b)){
    echo 'True'; // 输出True
}else{
    echo 'Flase';
}
// betao.cn
?>

image-20191115145023251

上面代码产生的原因为,md5不能处理数组,返回null

转换

php会自动进行转换,比如16进制,科学计数法等,有时也用这点绕过

strcmp函数数组绕过

image-20191115151108336

<?php
$a = $_GET['a'];
if (strcmp('betao.cn', $a)){
    echo 'Flase';    
}else{
    echo 'True';
}
?>

image-20191115151220918

利用数组a[]=1, 返回True,成功绕过验证

strcmp()函数只有在相等的情况下返回0。
那么我们传入一个数组,它会返回NULL,而判断使用了,而NULL=0是bool(true),这样就成功绕过。

ereg() 或者 eregi()

ereg() 函数或 eregi() 函数存在空字符截断漏洞,即参数中的正则表达式或待匹配字符串遇到空字符则截断丢弃后面的数据

详细的说明,参考: https://www.betao.cn/archives/giveup.html

is_numeric()

is_numeric()作用: 判断变量是否为数字或数字字符串,不仅检查10进制,16进制是可以

  1. 当有两个is_numeric判断并用and连接时,and后面的is_numeric可以绕过
  2. 16进制也可以绕过is_numeric()检验,可以用来绕过sql注入里的过滤
<?php
$a = $_GET['a'];
$b = $_GET['b'];
$c = is_numeric($a) and is_numeric($b);
var_dump(is_numeric($a));
echo '<br>';
var_dump(is_numeric($b));
echo '<br>';
var_dump($c);  // 返回True
echo '<br>';
$test = false and true; // 返回False
var_dump($test);
?>

image-20191115152253240

​ is_numeric函数对于空字符%00,无论是%00放在前后都可以判断为非数值,而%20空格字符只能放在数值后。所以,查看函数发现该函数对对于第一个空格字符会跳过空格字符判断,接着后面的判断!

​ 该函数还可能造成sql注入,例如将‘1 or 1'转换为16进制形式,再传参,就可以造成sql注入

switch()

当switch()没有break时可以继续往下执行
这里也有自动转换,比如$a = a,会当0执行,$a=1a,会当1执行……

image-20191115153145283

NULL,0,”0″,array()使用==和false比较时,都会返回true

<?php
$a = NULL;
$b = 0;
$c = "0";
$d = array();

// 以下是三元运算符
echo $a == false ? 'True': 'False';
echo '<hr>';
echo $b == false ? 'True': 'False';
echo '<hr>';
echo $b == false ? 'True': 'False';
echo '<hr>';
echo $b == false ? 'True': 'False';
?>

image-20191115153842529

php://伪协议绕过

接收参数中不能出现某一字符,但下面又必须使用可以php://伪协议绕过

目前遇到的是file_get_contents(),其他情况具体而定

本文链接:

https://www.betao.cn/archives/hmofa.html
1 + 5 =
快来做第一个评论的人吧~