【c4r0@log】history

個人の備忘録。セキュリティ関連多め。

【資格】CISSP受験記

今年の頭にCISSPを受験し合格しましたので、誰かの参考になればと思い、合格までに何をしたかを記しておこうと思います。



CISSPとは

ご存知の方も多いと思いますが、情報セキュリティに関する資格です。CISSPはCertified Information Systems Security Professionalの略称となっており、(ISC)² (International Information Systems Security Certification Consortium)が認定を行っている国際資格です。
以下のサイトでも紹介されているように、情報セキュリティに関する資格の中でもかなり幅広い分野が試験範囲に含まれていますので、合格するためには一つの分野だけでなく、複数分野でのセキュリティの深い知識が必要となっています。

Security Certification Roadmap - Paul Jerimy Media

認定要件もいくつかあり、試験に合格しただけではCISSPと認められません。私も現状認定要件を満たしていないため、アソシエイトという立ち位置(認定要件を満たした時にCISSPとして認定される)にいます。 試験に関する詳細はここ(ISC2 - CISSPとは)から確認できます。

受験の動機

簡単に自分のことと受験の動機を記しておきます。

自分はセキュリティ関連の研究室に所属している修士2年の大学院生で、次の4月から社会人となります。他の資格はCISSPの勉強を始める時点でNWと登録セキスペ(登録してない)を取得しており、それなりに基礎知識はあった方だと思います。

次に受験の動機になるのですが、そもそもCISSPの勉強を始めた理由は受験のためではなく、英語とセキュリティを同時に勉強できるものを探していたためです。自分は英語が全くダメで、英語の論文もろくに読めなかったので、英語もセキュリティの勉強も同時にできるCISSPの勉強はやっておいてもいいかもなと思い、かなり軽い気持ちで勉強をはじめました。勉強を始めた時点では二年後くらいに取れればいいかなと思ってました。

受験を決めた理由は新型コロナウイルスの影響がかなり大きいです。就活を終えて研究と遊びに費やそうと思っていましたが、外出の自粛&研究もリモートで行うことになり、結構自分の時間が取れるようになりました。ずっと研究をやっているのも気が滅入ってしまうし、どうせなら在学中にとってしまおう考え、真剣に勉強して受験に踏み切った次第です。 なお、CISSP試験の受験料は8万くらいかかるのですが、卒業旅行の為に貯めておいたバイト代をぶち込みました。絶対海外にいくと意気込んで貯めていたものなので、資格だけでも国際感を味わいたいと思ったのも受験に踏み切った理由の一つです。

試験の申し込み

試験の申し込みについては他の方の受験記に詳しく書かれていますので詳細は割愛します。
こちらを参考に、以下のピアソンVUEサイトから申し込みを行います。申し込み方法は各ページに記載されている手順を踏めば特に問題ないと思います。

(ISC)2 :: ピアソンVUE

勉強方法

参考書や問題集は書籍2冊と公式アプリを使用しました。

公式ガイドブックは分厚すぎて勉強する気になれなかったので、内容がコンパクトにまとまっているStudy Guideを選びました。勉強方法としては

  1. Study Guideの内容を簡単にノートにまとめ、概要を理解する (3ヶ月)
  2. 公式問題集を各分野ひと通り問いてみる (3週間)
  3. 点数が低い分野をStudy Guideで復習する (1週間)
  4. 公式問題集2回目 (1週間)
  5. Study Guide復習 (1週間)
  6. アプリでひたすら問題を解く(2週間)
  7. 公式問題集及びアプリに付属している模擬テストを解く (4週間)

といった感じです。用語については知らないものもたくさんあったので、インターネットで検索しつつ、Notion(いろいろできるメモ帳みたいなもの)に全てまとめました。それぞれの勉強に費やした期間は上記の通りですが、順々に行なったわけではなく、同時に進める箇所もありました。 勉強を始めたのが2020年の7月からなので、勉強した期間はちょうど半年くらいになります。

試験を終えて

試験問題自体は規定により紹介することはできませんが、自分からすると四択とはいえかなり難しかったです。試験に受かったからプロなんてこともなく、今後もさらに勉強が必要だなと感じました。あと認定要件にもあるように、この資格は業務経験者を対象にしているようなものなので、よほどの理由がない限り学生のうちに受験しなくていいと思います。就活ではIPA情報処理技術者試験で十分アピールできますし、それよりも他のこと(研究とか研究とか研究とか...)に注力したほうがいいです。

とりあえずざっくり書きましたが、何か質問等あればTwitterとかで気軽に聞いていただければと思います。

【writeup】justCTF2020 振り返り

久しぶりですが友達を誘ってCTFに参加したのでwriteupまとめておきます。

Sanity Check 

問題文

https://www.youtube.com/watch?v=CM3jcGsS0Po :)

やったこと

YoutubeのリンクはRule The Worldというタイトルので、最初はコメントとかにフラグがあるかなーとか思っていたんですが見つからず。
タイトルからしてRuleに関連ありそうだなと思ったので、justCTF2020のRulesページを探してみても見つからず。
Sanity Checkなのでフラグ例とかありえそうだなと思って入力してみたらとおりました。

justCTF{something_h3re!}

MyLittlePwny

問題文

Ponies like only one type of numbers!

nc mylittlepwny.nc.jctf.pro 1337

やったこと

ncで接続すると>の後に入力を求められ、適当な文字を入れてみると可愛いお馬さんがお出迎えしてくれました。
適当にいくつか入力してみると、バッククォートを入れてみるとエラーを吐きました。

[sfera]~ » nc mylittlepwny.nc.jctf.pro 1337  

>  `
/bin/sh: 2: Syntax error: EOF in backquote substitution
>

バッククォートが閉じられていないエラーっぽいので、lsのような形で任意のコマンドを送ってみます。

> `ls`
 __________________________________
< bin flag lib lib64 server.py usr >
 ----------------------------------
 \
  \
   \
     ▄      ▄▄▄██████▄▄
     █▄▄ ▄████████████████▄▄
   ▄ ▄███▄███▄██████████▄▄ ▀▀
  ▄██████▄▄▄▄████████▄█████▄
  ██▄▄███▄▄▄▄████▄▄█▄████████
  █▄█▄█▄█▄▄███▄█▄██▄▄█▄█████▄
   ▄█▄████████▄▄▄███▄█████████
 ▀▀█▄▄█▄▄█▄▄██▄▄▄▄▄▄████▄█████
   ▀█▄▄▄▄▄▄▄▄▄▄▄▄████▄▄█████▀
    ▄▄▄▄█▄██▄▄▄▄▄▄▄████████▄▄▄▄
    ▀█▄▄██▄█▄█▄███▄██████████▀
     ▀▄▄▄▄▄▄█▄▄▄▄▄▄██████▀▀
       ▄▄▄▄▄▄▄▄▄▄▄▄▄████▄       ▄▄▄▄▄▄▄▄▄
       █▄▄▄▄▄▄▄▄████▀▀████▄   ▄███████████▄
       ███▄▄█████▄▄▄█▄       ▄██████████████▄
       ████████▄▄▄▄▄▄█▄▄▄▄▄▄▄▄▄██████████████
      ▄██████▄▄▄▄▄▄▄███████████▄▄▀███████████
     █▄█▄▄█▄▄▄▄▄▄██████▄▄▄▄▄▄▄██▄▄▄██████████
     ▄▄▄▄▄█▄▄▄▄█▄▄▄▄████████████▄▄▄██████████
     ██▄▄█▄▄▄█▄▄▄▄█▄▄▄▄▄▄▄▄▄▄▄▄▄█▄▄▀▀██████▀
      ▀▀▀▄▄▄▄▄▄███▄▄▄███▄███▄▄▄▄▄▄    ▀████
         ▀█▄▄██▄▄▄▄▄█▄▀▀▀▄▄▄██▄██▄▄      ▀██▄
           ███▄▄█████▄█  ▀▄█▄█▄▄█▄█
           ████▄███▄█▄▄   ██▄████▄▄▄
           ██▄▄▄████▄██   ██▄███▄▄██
          ██▄█▄██▄▄▄█▄▄  ██▄███▄▄▄▄█
          ▀▀▀▀▀████████  ▀▀▀██▄█████
               ▀▀▀▀▀▀▀      ▀▀▀▀▀▀▀

うまく実行できてflagファイルがあることが確認できました。 あとはこれを表示してフラグゲットです。(catコマンドなど特定のコマンドは実行できないように処理されていたのでstringsを使いました)

> `strings flag`
 _________________________________
< justCTF{p0nY_t4lEs_b3giN5_h3r3} >
 ---------------------------------
           \
            \
             \
              \
               ▄▄▄▄
           █▄▄▄▄▄██▄▄▄▄▄
          ▄▄▄▄▄██▄▄▄▄▄█▄▄▄▄
         ████▄█▄▄█▄▄▄███▄▄▄█
 ▀▄▄▄▄▄▄████████▄▄███▄█████▄▄▄▄▄▄▄▄▄▄
   ████▄▄███▄▄▄▄█████████▄███████████▄
   ▀▄▄▄███▄▄█▄█▄███████▄▄████▄▄▄▄▄▄▄▄▄▄
    ▀▄▄█▄▄▄███▄████▄██▄▄█▄██▄▄▄▄▄▄▄▄▄▄▄▄
     ██████▄▄█▄▄▄▄▄████▄▄█▄▄████████████
     █████▄▄█████████████▄▄█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
     ▄▄▄▄▄▄▄▄▄▄▄▄▄████▄▄▄█████████▄▄▄▄██▄▄▄▄▄▄
    ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄████▄▄▄▄████████▄▄███▄▄███▄▄
   ██████████▄▄███▄▄▄▄▄▄▄▄███▄▄▄▄▄▄▄▄▄█▄▄▄▄██████
  ▄█▀ ▀▀▀▄▄▄▄█▄▄▄██████████████████▄▄▄▄▄▄█████████
  █▄       ▀▀████▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄██████▄▄▄██████▄
▄  ▀█         ▄▄▄▄▄▄▄▄▄▄▄▄▄████████▄▄▄▄▄▄████▄▄█▄▄▄
 ▀▀▀▀       ▀▀▀▄▄▀▀▀▀▀▀▀▄▄█▄▄▄▄▄▄▄▄████████▄▄██▄▀▀
               ▄█       █▄▄████████▄▄▄▄▄▄▄▄█▄▄▄█
              █▀  ▄     ▀████▄▄▄▄▀▀    ▄█▀▀▀ █▀  ▄
              ▀▀▀▀       ████                ▀▀▀▀
                          ██
                           ▀
 justCTF{p0nY_t4lEs_b3giN5_h3r3}

That's not crypto

問題文

This is very simple RE task, but you may need some other skills as well. :)

https://ams3.digitaloceanspaces.com/justctf/11456603-38e8-4b10-9863-296fc0cf0342/checker.pyc

やったこと

pycファイルが与えられます。.pycはPythonのコードをコンパイルしたデータが入っている認識だったので、とりあえずデコンパイルする方法を探しました。
検索してみるとuncompyle6を用いれば可能とのことなのでpipでインストールします。

# uncompyle6 version 3.7.4

from random import randint

def make_correct_array(s):
    from itertools import accumulate
    s = map(ord, s)
    s = accumulate(s)
    return [x * 69684751861829721459380039 for x in s]


def validate(a, xs):

    def poly(a, x):
        value = 0
        for ai in a:
            value *= x
            value += ai

        return value

    if len(a) != len(xs) + 1:
        return False
    else:
        for x in xs:
            value = poly(a, x)
            if value != 24196561:
                return False

        return True


if __name__ == '__main__':
    a = [1,
     -12036995612853156936286011036665,...] # 長いので省略
    a = [ai * 4919 for ai in a]
    flag_str = input('flag: ').strip()
    flag = make_correct_array(flag_str)
    if validate(a, flag):
        print('Yes, this is the flag!')
        print(flag_str)
    else:
        print('Incorrect, sorry. :(')
# okay decompiling checker.pyc

なんか色々やってますね。大雑把に読んでみると、処理の内容は入力した文字を用いてリスト作って比較してる感じですかね。
とりあえずvalidateメソッド内の最初if文から、フラグの長さが57とわかるので、あとはその後の処理でFalseが返らないよう適当に入力文字列変えてけばフラグがでそうですね。 汚いコードですがこんなのでも問題ないです。

# uncompyle6 version 3.7.4

from random import randint

ANS_FLAG = [''] * 57

def make_correct_array(s):
    from itertools import accumulate
    s = map(ord, s)
    s = accumulate(s)
    return [x * 69684751861829721459380039 for x in s]


def validate(a, xs, flag_str):

    def poly(a, x):
        value = 0
        for ai in a:
            value *= x
            value += ai

        return value

    if len(a) != len(xs) + 1:
        #print('not match len')
        return False
    else:
        for j, x in enumerate(xs):
            value = poly(a, x)
            #print(value)
            if value != 24196561:
                return False
            ANS_FLAG[j] = flag_str[j] 


        return True


if __name__ == '__main__':
    a = [1,
     -12036995612853156936286011036665,...] # 長いので省略
    a = [ai * 4919 for ai in a]
    import string
    printable_list = [i for i in string.printable]

    for num in range(0,57):
        for i in printable_list:
            #flag_str = input('flag: ').strip()
            correct_str = ''
            if not ANS_FLAG[num-1] == '':
                for k in range(0, num):
                    correct_str += ANS_FLAG[k]


            flag_str = correct_str + i + 'a'*(57 - len(correct_str) - 1)
            flag = make_correct_array(flag_str)
            if validate(a, flag, list(flag_str)):
                print('Yes, this is the flag!')
                print(flag_str)
            else:
                pass
                #print('Incorrect, sorry. :(')
# okay decompiling work/checker.pyc

justCTF{this_is_very_simple_flag_afer_so_big_polynomails}

PDF is broken, and so is this file

問題文

This PDF contains the flag, but you’ll probably need to fix it first to figure out how it’s embedded. Fortunately, the file contains everything you need to render it. Follow the clues to find the flag, and hopefully learn something about the PDF format in the process.

https://ams3.digitaloceanspaces.com/justctf/eccb3bff-69aa-4232-8087-a5e8eea0f581/challenge.pdf

やったこと

ダウンロードしたPDSファイルをとりあえず開いてみると、真っ白なページが表示されました。表示させる情報はファイルの中に全て入っているとのことなので、Hex Fiendで中身を覗いてみると、requireから始まるrubyのコードから始まっていました。
PDFの構造を調べてみるとヘッダ、ボディ、クロスリファレンステーブル、トレイラーから構成されるみたいです。以下のサイトとかかなり参考になります。

PDF 構文 ファイル構造 (各部)

中身をもう少し見てみるとクロスリファレンステーブル(xref)が2つあるので、何か間に挿入されたのかな?と推測できます。その辺りに注目してみると、PK...からはじめるzipっぽいバイナリが見えます。

これらのファイルを抽出したいのでbinwalkを使ってみると、ZIPやその中身が抽出できました。

[sfera]~/Downloads » binwalk -e ./challenge.pdf

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
53            0x35            PDF document, version: "1.5"
350           0x15E           HTML document footer
1636          0x664           HTML document header
1843          0x733           HTML document footer
1936          0x790           Zlib compressed data, best compression
3882          0xF2A           Zlib compressed data, best compression
745265        0xB5F31         Zlib compressed data, default compression
745469        0xB5FFD         Zlib compressed data, default compression
835474        0xCBF92         Zlib compressed data, best compression
836261        0xCC2A5         JPEG image data, JFIF standard 1.01
1866761       0x1C7C09        JPEG image data, EXIF standard
1866773       0x1C7C15        TIFF image data, little-endian offset of first image directory: 8
2716590       0x2973AE        Zlib compressed data, best compression
2726679       0x299B17        Zlib compressed data, best compression
2734100       0x29B814        Zlib compressed data, best compression
2747120       0x29EAF0        Zlib compressed data, best compression
2757397       0x2A1315        Zlib compressed data, best compression
2767356       0x2A39FC        Zlib compressed data, best compression
2774636       0x2A566C        Zlib compressed data, best compression
2788994       0x2A8E82        Zlib compressed data, best compression
2797259       0x2AAECB        Zlib compressed data, best compression
2811290       0x2AE59A        Zip archive data, at least v1.0 to extract, name: feelies/
2811356       0x2AE5DC        Zip archive data, at least v2.0 to extract, compressed size: 27832169, uncompressed size: 38061512, name: feelies/mutool
30643597      0x1D3958D       Zip archive data, at least v2.0 to extract, compressed size: 220, uncompressed size: 289, name: feelies/false_flag.md
30644149      0x1D397B5       End of Zip archive, footer length: -28825
30658564      0x1D3D004       Zlib compressed data, best compression
30666829      0x1D3F04D       Zlib compressed data, best compression

false_flag.mdにはmutoolの使い方などが書かれていたので、mutoolを使ってみるとpngが出力されました。 f:id:c4r0:20210202162306p:plain

英弱なので内容を正しく理解できているわけではないですが、なんとなく分かったことは

  • 0x06がなんか悪さをしている

  • 2642 didder "42bytes" object で検索すれば何かヒントが得られそう

くらいですかね。
PDFファイルの中で0x06の箇所を探してみると、streamオブジェクトの記述あたりで使用されていました。これを他の正常なPDFを参考に0Aに変更してみるとAdobeで表示させることができました。ただ内容としてはmutoolを使って出てきたpngと同様で、特に目新しい情報は得られませんでした。

次に 2642 didder "42bytes" objectで検索をかけてみると以下のサイトがヒットしました。
PDF Stream Objects | Didier Stevens
Stream Objectのフォーマットについて書かれていたので、PDFファイルの中で正しいフォーマットでない箇所を探すと、ZIPの箇所でLengthやFilterが指定されていないです。ただこの箇所は表示させる内容とは考えにくかったので、ここでかなりつまづきました...。

どこに目をつけたらいいのかわからなかったので、PDFに含まれているオブジェクトをとりあえず手当たり次第見てみました。xrefから50個のオブジェクトがあることは分かったいたので、順に探しているところ、オブジェクト番号が4919のものがありました。こいつを表示できれば何かヒントが得られそうです。
しかし、xrefやオブジェクト番号をいじってみても、うまく表示させることができませんでした。もう少しPDFのフォーマットについて詳しく調べる必要がありそうです。

ここでbinwalkで抽出したデータを眺めてると、気になるファイルがあることに気付きます。

FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 01 2C
01 2C 00 00 FF DB 00 43 00 08 06 06 07 06 05 08
07 07 07 09 09 08 0A 0C 14 0D 0C 0B 0B 0C 19 12
13 0F 14 1D 1A 1F 1E 1D 1A 1C 1C 20 24 2E 27 20
22 2C 23 1C 1C 28 37 29 2C 30 31 34 34 34 1F 27
39 3D 38 32 3C 2E 33 34 32 FF DB 00 43 01 09 09
09 0C 0B 0C 18 0D 0D 18 32 21 1C 21 32 32 32 32
32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32
32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32
---略---

なんかのバイナリですね。
これをHex Fiendにコピーして保存すると画像が表示されました。

f:id:c4r0:20210202164441j:plain

justCTF{BytesAreNotRealWakeUpSheeple}

簡単なのしか解けませんでしたが久しぶりのCTF楽しかったです。
またやりたい。