CTF之PHP代码审计1

文章目录

  • 弱类型
    • 例题1
    • 例题2
    • 例题3
  • md5强碰撞
  • 弱类型相关函数:
    • json绕过
    • switch绕过
    • strcmp绕过
    • in_array绕过
    • array_search绕过

弱类型

$a==$b 等于 ture:如果类型转换后$a等于$b
$a===$b 全等 ture:如果$a等于$b,并且他们的类型也相同
如果一个数值和一个字符串比较,那么会将字符串转换为数值


var_dump(true==2);//true
var_dump(true==0);//false
var_dump(''==0);//true
var_dump(0==false);//true
var_dump(intval(false));//int(0)
var_dump('123'==123);//字符串转换为数字类型,true
var_dump('abc'==0);//true
var_dump('123a'==123);//true
var_dump(intval('123a'));//int(123)
var_dump('a123'==123);//false
var_dump(intval('a123'));//int(0)

可以自己测试一下,能看到true不为0时都为真,字母开头的话转换为int型就为0

var_dump('0x01'==1);//0x01为16进制,true
var_dump(intval(0x01));//int(1)
var_dump(intval(0x11));//int(17)
var_dump('0e123456789'=='0e987654321');//true
var_dump(intval(0e12345678))//int(0)
var_dump('1e3'==1000);//true
var_dump([0]=='');//false
var_dump([0]==['']);//true

可以看出能分辨出16进制和科学计数法,并且数组和非数组比较时都为假

例题1

实验环境:南邮ctf:起名字真难
给出的源码如下:


function noother_says_correct($number)
{
       $one = ord('1');
       $nine = ord('9');
       for ($i = 0; $i < strlen($number); $i++)
       {   
               $digit = ord($number{$i});
               if ( ($digit >= $one) && ($digit <= $nine) )
               {
                       return false;
               }
       }
          return $number == '54975581388';
}
$flag='*******';
if(noother_says_correct($_GET['key']))
   echo $flag;
else 
   echo 'access denied';
?>

意思是我们输入的key中不能有数字,但是要和54975581388相等,所以使用弱类型比较,使用0x的格式输入,先查看要求的数字的16进制
CTF之PHP代码审计1_第1张图片
刚好没有数字,那么我们传入0xccccccccc进去就可以得到flag了
CTF之PHP代码审计1_第2张图片

例题2

实验环境:bugku:md5 collision(NUPT_CTF)
这里借用师傅的源代码


$md51 = md5('QNKCDZO');
$a = @$_GET['a'];
$md52 = @md5($a);
if(isset($a)){
if ($a != 'QNKCDZO' && $md51 == $md52) {
    echo "nctf{*****************}";
} else {
    echo "false!!!";
}}
else{echo "please input a";}
?>

进入题目发现要我们提交一个参数a,随便传一个a的值发现返回false。由于不是===,0e开头的md5都为0,我们可以传入一个经过md5加密后为0e的值即可
CTF之PHP代码审计1_第3张图片

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

随便选一个传入得到flag
CTF之PHP代码审计1_第4张图片
可参考bugku(md5 collision(NUPT_CTF))

例题3

实验环境:bugku:各种绕过
CTF之PHP代码审计1_第5张图片
uname的值不能为passwd的值,但他们的哈希值要全相等,并且当id传值为margin,满足这三个条件,就返回flag,全相等就不能用0e绕过了。这里还有一个类型:数组。
CTF之PHP代码审计1_第6张图片
当传入数组时返回NULL,但两个的值还是相等的,传入
CTF之PHP代码审计1_第7张图片
得到Flag: flag{HACK_45hhs_213sDD}

md5强碰撞

if((string)$_POST['param1']!==(string)$_POST['param2'] 
&& md5($_POST['param1'])===md5($_POST['param2'])){
        die("success!");
        }

网强杯的一个md5强碰撞的题目,只能用两个值的md5相等来解,这里有一个工具可以生成,在参考文章可以下载,我就简单演示一遍。
CTF之PHP代码审计1_第8张图片
首先创建一个空的1.txt文件,然后进入cmd
CTF之PHP代码审计1_第9张图片
生成了2.txt和3.txt,判断一下md5值是否相等
CTF之PHP代码审计1_第10张图片
发现是相等的,那么我们就将数据转换为url编码的形式
CTF之PHP代码审计1_第11张图片
也可以用师傅的脚本生成url编码的结果

 
function  readmyfile($path){
    $fh = fopen($path, "rb");
    $data = fread($fh, filesize($path));
    fclose($fh);
    return $data;
}
echo '二进制hash '. md5( (readmyfile("2.txt")));
echo "

\r\n"
; echo 'URLENCODE '. urlencode(readmyfile("2.txt")); echo "

\r\n"
; echo 'URLENCODE hash '.md5(urlencode (readmyfile("2.txt"))); echo "

\r\n"
; echo '二进制hash '.md5( (readmyfile("3.txt"))); echo "

\r\n"
; echo 'URLENCODE '. urlencode(readmyfile("3.txt")); echo "

\r\n"
; echo 'URLENCODE hash '.md5( urlencode(readmyfile("3.txt"))); echo "

\r\n"
;

可参考文章:如何用不同的数值构建一样的MD5 - 第二届强网杯 MD5碰撞 writeup

弱类型相关函数:

json绕过

json_decode — 对 JSON 格式的字符串进行解码
代码如下:


highlight_file(__FILE__);
if (isset($_GET['message'])) {
    $message = json_decode($_GET['message']);
    $key ="admin********";
    if ($message->key == $key) {
        echo "flag";
    }
    else {
        echo "fail";
    }
}
else{
     echo "~~~~";
}
?>

由于是==我们可以传入0使0==admin********一样成立的
CTF之PHP代码审计1_第12张图片

switch绕过

如果switch是数字类型的case的判断时,switch会将其中的参数转换为int类型。可以看到显示为flag
CTF之PHP代码审计1_第13张图片

strcmp绕过

strcmp — 二进制安全字符串比较
如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。strcmp函数比较字符串的本质是将两个变量转换为ascii,然后进行减法运算,根据运算结果来决定返回值。


highlight_file(__FILE__);
$password = "***************";
if(isset($_GET['password'])){
    if (strcmp($_GET['password'], $password) == 0) {
        echo "Right!!!login success";
        exit();
    }else {
        echo "Wrong password..";
          }
}
?>

要使strcmp($_GET['password'], $password) == 0成立,我们又不知道password的值,只能从strcmp入手,发现:
CTF之PHP代码审计1_第14张图片
传入数组的时候为NULL,而0==NULL的值又为真,成立。
CTF之PHP代码审计1_第15张图片

in_array绕过

CTF之PHP代码审计1_第16张图片
CTF之PHP代码审计1_第17张图片
由于判断是以==来判断的,所以返回的值都为true
CTF之PHP代码审计1_第18张图片
第一个'abc'为0,第二个'1bc'为1,第三个为3

array_search绕过

array_search — 在数组中搜索给定的值,如果成功则返回首个相应的键名
此函数可能返回布尔值 FALSE,但也可能返回等同于 FALSE 的非布尔值。

CTF之PHP代码审计1_第19张图片
这个题先判断是不是数组,然后再把数组中的内容一一遍历,所有内容都不能等于admin,类型也必须相同,然后转化成int型,然后再进行比较如果填入值与admin相同,则返回flag
我们在数组的第一个传0,就可以绕过了,值为:array(1) { [0]=> int(0) }
CTF之PHP代码审计1_第20张图片

你可能感兴趣的:(ctf)