befs_anneの日記

雰囲気でネットワークをやっている

【CTF】CyberRebeatCTF Write-Up

概要

先日CyberRebeatCTFに単騎で参加したので、そのWrite-Up。1480点で82位だった。

ennach.sakura.ne.jp

f:id:befs_anne:20180911222407j:plain

※問題が全部表示されなかったので開発者ツールでCSSをいじったら右側が変な感じに

Binary(0/3)

全滅。幸先悪し。

Crypto(1/3)

Rotation

「P4P6S{9RN4RUNPXR45}」と換字式暗号?で暗号化されたflagを解読する問題。「P4P6S」が「CRCTF」であることは(他の問題から)明白なので、あとは力技で解読した。結局どういう対応なのかよく分かってないので、他のWrite-Upを見てみることにする。

|平文 |abcdefghijklmnopqrstuvwxyz|
|暗号文| opqrstuvwxyz0123456789   |
|確定 |  *  *           * *      |

Excercise(1/1)

Excercise

flagを送信するエクササイズ。

Misc(1/2)

Reame

ElectroHarmonixというカタカナっぽいアルファベットフォントで書かれた文章を読む。

www.ebook5.net

Programming(1/3)

Calculation

ncで接続すると、四則演算の計算問題が降ってきて、20問解くとflagが降ってくる。 Pythonでncするライブラリが公開されていたので、これをちょっといじってスクリプトに組み込んだ。便利。

Python Netcat · GitHub

$ diff netcat.py netcat_modified.py 
24c24,25
<             self.buff += self.socket.recv(1024)
---
>             #self.buff += self.socket.recv(1024)
>             self.buff += self.socket.recv(1024).decode('utf-8')

計算にはeval関数を使った。便利。

from netcat import Netcat                                                                                                                 

nc = Netcat('59.106.212.75', 8080)

while True:
    q = nc.read_until('\n')
    print(q)
    ans = str(eval(q.strip('\ufeff').strip('\n')))
    print(ans)
    nc.write(str(ans + '\n').encode('utf-8'))

flagが降ってくると例外で止まるのがちょっとダサい。

Recon(2/3)

Tweet

公式がflagをツイートしている。

CyberRebeatScripts

ennach/CyberRebeatScriptsというGithubリポジトリがあり、ファイルから削除されたflagをhistoryから見つける。

github.com

Stegano(1/3)

Secret.pdf

flag部分が黒く塗りつぶされたPDFを解析する問題。 ちょっとググったら以下のページが出てきたので、サンプルコードそのまま使ってクリアした。

tech.bita.jp

Trivia(2/2)

Monero

ヒントからソフトウェアの名前を導き出す問題(ソフトウェアの名前がそのままflagになる)。「Coinhive」が出てこなくてちょっとググるなどした。

Crossword

クロスワード。ググッてクリア。

Web(2/3)

White page

事前情報としてIDとパスワードが提示されているが、URLを開くと真っ白な画面にログインボタンのみ。ソースを見るとinputタグがstyle属性で消されているので、どうにかしてこれを無効化してIDとパスワードを入力してログインボタンを押せばクリア。他のWrite-Upを見ると開発者ツールでやってる人が多かったけど、私はBurp Proxyでやった。

Let's Tweet!

「#CyberRebeatCTF」が含まれるツイートを促すサイトが舞台。同ハッシュタグを含むツイートのURLを送信すると以下の処理が上から行われ、全てをパスできたらflagがもらえて、その時に使ったURLはDBに格納される(コードは事前に提供されている)。

  • ツイートのURLの形式(後述)であることのチェック
  • 指定したハッシュタグが含まれているかのチェック
  • データベースに同一URLがないかのチェック

素直にツイートすればflagが手に入るわけだけど、「もしツイートしたくない、あるいはツイッターのアカウントを持っていないという場合でも、FLAGの取得は可能です。」の一文がある以上、ツイートするわけにはいかない。

ガチャガチャいじってたらあっけなく通ってしまった。ツイートのURLは「https://twitter.com/{{アカウント名}}/status/{{ツイートID}}」のような作りになっているが、どうやらツイートIDさえ正しければ(実在するものであれば)、アカウント名が誤っていても本来のURLにリダイレクトされるようになっているらしい。例えば、以下のリンクは上が本来のURLだが、下のURLでも同じツイートに辿り着ける。

https://twitter.com/befs_anne/status/1039361451050196992 https://twitter.com/shinobe/status/1039361451050196992

これを利用して、既に存在している「#CyberRebeatCTF」が含まれたツイートのURLのアカウント名を適当に変えたURLを送信してやれば、表層的なURLのチェックしか行われないため、(たとえ実際のツイートがDBに登録済みであっても)別のツイートと判断されてクリアできるという寸法。

感想

ctf4bと比べて易しく感じた。問題数も多いので満足。スキルはまだ乏しいものの、WebやProgrammingなどはctf4bから着実に前進できていると思う。Binaryは引き続き課題。

【Burp】社内プロキシ環境下でlocalhost宛の通信をBurpでプロキシする時のtips

概要

以下の記事を参照して、ブラウザとBurpの設定が完了しているにも関わらず、localhost(127.0.0.1)上で動いているアプリケーション(Badstore Pluginなど)への通信をBurpがプロキシしてくれない時のtips。

befs-anne.hatenablog.com

まずはブラウザのプロキシ設定を確認する

ブラウザのプロキシ設定画面に、プロキシを適用しないホストやIPアドレスを指定する欄がないか確認する。Firefoxにはそれがあって、デフォルトで127.0.0.1localhostが含まれていた。これらを削除すると、localhost宛の通信もプロキシ(Burp)を通すようになる(以下の画像は削除後)。

f:id:befs_anne:20180719230541p:plain

Upstream Proxy Serversにlocalhost用のエントリを追加する

このままだと127.0.0.1宛の通信も社内プロキシに投げてしまうので、Upstream Proxy Serversにlocalhost用のエントリを追加する(画像中の選択されているエントリを参照)。Proxy hostを指定しなくてもエントリが追加でき、このルールが適用された場合、プロキシを使わずBurp自身が転送することになる。

f:id:befs_anne:20180719230955p:plain

【Burp】社内プロキシ環境下でBurpを使う時はUpstream Proxy Serversを登録する

概要

タイトルの通り。社内プロキシという名の悲しき檻の中で働いている、可哀想な小鳥さん達には必須の設定。なのに、いつも忘れる。

設定方法

ブラウザ〜Burp間

ブラウザ〜Burp間は公式サイトで紹介されている通り。Burpを起動したらProxyタブ→Optionsタブ→Connectionタブ内のProxy ListenersでBurpがリッスンするIPアドレスとポート番号を指定して、ブラウザではBurpをプロキシとして設定する。

support.portswigger.net

Burp〜社内プロキシ間

本題。User optionsタブのUpstream Proxy Serversに社内プロキシを登録する。宛先ホスト毎にプロキシを指定できて、宛先ホスト名の指定にはワイルドカード("*"や"?")も使える。一番上の条件から評価されるので、私は特定のホストやドメインで使用するプロキシは上のほうに、そうでないプロキシは宛先を「*」として、一番下に置いている。

f:id:befs_anne:20180718073444p:plain

f:id:befs_anne:20180718073232p:plain

参考

github.com

【競プロ】defaultdictとCounter

概要

データサイエンスに関する本を買ってみたものの、サイエンスするための基礎知識が圧倒的に足りておらず身が入らない始末。サイエンス関連のアウトプットはひとまず置いといて、「2章 Python速習コース」の中で競プロに役に立ちそうなテクニックをメモして、3,200円 + 税はムダじゃなかったと思いたいがための記事。

ゼロからはじめるデータサイエンス ―Pythonで学ぶ基本と実践

ゼロからはじめるデータサイエンス ―Pythonで学ぶ基本と実践

defaultdict

文字列やリストに含まれている要素の種類をカウントする時、defaultdictクラスを使うとシンプルに書ける。

from collections import defaultdict

document = "zabbix"
count_dict = defaultdict(int) # 引数は初期値(int()は0らしい)

for cal in document:
        count_dict[cal] += 1

print(dict(count_dict))
# {'z': 1, 'a': 1, 'b': 2, 'i': 1, 'x': 1}

素で書くと、キーが既にある場合と新規の場合の両方を考慮しなくちゃならない。

# defaultdict使わない版

document = "zabbix"
count_dict = {}

for cal in document:
    if cal in count_dict:
        count_dict[cal] += 1
    else:
        count_dict[cal] = 1

print(count_dict)
# {'z': 1, 'a': 1, 'b': 2, 'i': 1, 'x': 1}

初期値はintだけではなく、dictや別の関数も指定可能。

Counter

defaultdictの「初期値指定できない代わりに短く書ける版」みたいな感じ。

from collections import Counter

document = "zabbix"
count_dict = Counter(document)

print(dict(count_dict))
# {'z': 1, 'a': 1, 'b': 2, 'i': 1, 'x': 1}

【競技プログラミング】標準入力の受け付けと各桁の合計

概要

競技プログラミングの復習。

近況

直近の記事から早2ヶ月。CCIEの勉強もロクにせず、僕は『ゼロからはじめるデータサイエンス』の写経もそこそこに、CTFや競技プログラミングに手を付けていた……。

ゼロからはじめるデータサイエンス ―Pythonで学ぶ基本と実践

ゼロからはじめるデータサイエンス ―Pythonで学ぶ基本と実践

Pythonでの標準入力の受け付け

「競プロやってみよう」と思い立ったその日から、AtCoder Programming Gude for BeginnersでC++のお勉強をしてたんだけど、身の回りの競プロに勤しんでいる人たちがPythonでやってるのを見て、自分もPyhtonistaとして参戦することを決意した(仕事でも使ってるし)。

先日のCodeFlyerが初参戦。結果は2完。事前にPythonでの練習をしていなかったので、問題以前に標準入力の受け付け方が分からず、慌ててググるなど。

Pythonで競技プログラミングする時に知っておきたいtips(入出力編)

input()

標準入力から1行読み込んで、末尾の改行を除いて標準出力に出す。複数行を読み込みたい場合、ケースに合わせて工夫が必要(行数が固定ならfor in range(行数)でリスト内包する、など…引用記事中にケース毎の説明があるのでいったん割愛)。

$ cat input.py 
N = input()

print("input is " + N)

# 文字列型の場合
$ echo "ABC" | python input.py 
input is ABC
$

# 数値型の場合
$ echo 123 | python input.py 
input is 123
$

# 複数行の場合
$ python -c "print('THIS\n IS\n TEST')" | python input.py 
input is THIS
$ 

各桁の合計を求める

……必要のある問題が出てきて、これも先人の知恵を頼った。

http://suzu6.hatenablog.com/entry/2017/09/22/004355

def digitSum(n):
    s = str(n) # 1
    array = list(map(int, list(s))) #2
    return sum(array) #3
  1. 値nをstr()で文字列に変換する
  2. map()でsを1文字ずつint型に変換してリスト(array)に追加する
  3. sumでarrayの合計を算出し、returnする

map()

mapは第1引数に関数、第2引数にイテレータを指定して、第2引数の各要素を引数として第1引数を実行した結果をイテレータとして返す関数っぽい。どうやらPython3の場合、そのままだとmapオブジェクト(print()すると「」みたいなのが出力される)なので、リストとして扱いたい場合はlist()で包んでやればよい。

2. 組み込み関数 — Python 3.6.5 ドキュメント

引用したブログ記事内にも説明がある通り、リスト内包で同じことができる。

array = list(int(i) for i in list(s))

2018年(度)の抱負

はじめに

さっそく約束を破っていて幸先が悪い。

技術

ネットワーク

実務ではコアな技術はあまり必要なくCCNPも失効したので、CCNP再取得するぐらいならCCIEを取ってしまいたい。Labスキル的にも金銭的にも厳しいけど、Writtenならなんとかなるだろう(フラグ

年内でがんばります。VIRLも契約するよ。

Linux(低レイヤ)

数年前までネットワークのことしか分からず、検証でSyslogサーバーやNTPサーバーを立てる必要が出てくるとガクガク震えだすという始末だったんだけど、環境の変化(サーバーをいじらないと仕事ができない)や周囲の助けで最低限のことはできるようになった。自分を助けられるようになってきたので、他人を助けられるレベルにまで引き上げていきたい。とは言え、仕事で触れるミドルウェアはたいてい周りも自分と同等かそれ以上に触れる。そんな折に手にとったのが「Linuxのしくみ」。

[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識

[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識

「パッケージ管理システムすらややこしくて苦手なのに、低レイヤなんてやってられるかー」と思ってたけど、この本の分かりやすいのなんの。色んなミドルを触る機会もないし、低レイヤの知見を組織に提供できるようになる方向でLinuxに詳しくなることにした。とりあえずお勉強野郎になって、サーバーのサイジングの時とか「同じようなサーバーを○コア、メモリ○GBで作ったから今回も一緒で~」みたいな根拠をチケットに書いてたのをもうちょっと内容を変えるところから始めようと思う。

セキュリティ

BurpやOWASP ZAPあたりをモノにする。CTFも低レイヤの勉強がてらやっていく。仕事で役に立つ機会は(今のところ)ないので、趣味がてら続けたい。

仕事

担当するプロダクトをモノにする

仕事で使うプロダクトはその仕事の範囲に似つ様なことしか調べなかったけど、ドキュメント全部読んで仕事に関係のないことまで身につけるようにする。

カネを稼ぐ

カネを稼ぎたい。オリンピック後は地獄だと聞いているので今のうちに稼ぎ逃げしたい。

vagrant upで生成された秘密鍵が666なせいでVMにSSHできない

……ということが発生した。

環境

事象

vagrant sshが失敗してパスワード認証に切り替わってしまう原因が分からず、sshの-p、-iオプションでそれぞれポート番号と秘密鍵を指定してログイン試行したところ、以下のエラーメッセージが出力されて同様にパスワード認証に切り替わった。

Permissions 0666 for '/home/shino/vagrant/testdir/.vagrant/machines/testhost/virtualbox/private_key' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
bad permissions: ignore key: /home/shino/vagrant/testdir/.vagrant/machines/testhost/virtualbox/private_key
Password:

秘密鍵を666にするのはオープンにも程があるでしょう!」とのことなので実際に確認してみたら本当に666だった。

-rw-rw-rw- 1 shino shino 1679 Jan 28 22:46 /home/shino/vagrant/testdir/.vagrant/machines/testhost/virtualbox/private_key

対策

chmod 600 /home/shino/vagrant/testdir/.vagrant/machines/testhost/virtualbox/private_keyして解決。

※参考

yachibit.hatenablog.jp

調査は頓挫

他の方が公開しているVagrantfileで発生した事象で、原因を突き詰めようと自分で簡単なVagrantfileを作ってupしてみたら600で生成されていた。他に目的があってVagrantに手を付けているので、原因究明は置いておいて一旦対策だけメモしておく。バグではなくVagrantへの理解が足らないだけな気もしている。