CTFを助けるターミナルテクニック

この記事はm1z0r3 Advent Calendar 2018の5日目です。

本エントリではCTFの助けになる(CTFでしか役に立たないとは言ってない)ターミナルテクニックをいくつか紹介したいと思う。

cURL

Unix系を使ってれば一度は名前を聞いたことがあるであろうcurlだが、CTFでは使用される場面が少ないように感じる。

Web問では脆弱性をつくリクエストを発生させることが必須であり、入門にあたってはよくプロキシソフトウェアを使用する(筆者談)。
しかし、プロキシ設定やinterceptの切り替えに手間がかかるため、ちょっとした変更だけでこの手続きを踏むのは少々面倒である。
そこでcURLに慣れてればサクッと送りたいリクエストを作ることができ、大幅な時短を実現できる。

リクエストの書き換え

まずは基本であるHTTPメソッドの書き換えである。-Xオプションで設定する

$ curl -X POST http://example.com

ついでにデータを送りたい場合は-F-dをつける(-Xがなくても自動的にPOSTになる)。
-Fはデータごとに増やすことでHTMLフォームの送信をエミュレートする。

$ curl -F "key=value" -F "key2=value2" http://example.com

-dは生のPOSTデータを送りつける。@をつけることでファイルの中身を展開する。

$ curl -d "key=value&key2=value2" http://example.com
$ curl -d "@data.txt" http://example.com

ユーザエージェントの書き換えは-Aで行う。

$ curl -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" http://example.com

ヘッダは-Hで書き換え、あるいは追加する。

$ curl -H "X-Requested-With: XMLHttpRequest" http://example.com

ヘッダの出力

レスポンスヘッダは-Dオプションでファイルに出力できる。
ヘッダだけ取りたいなら-Iでとってこれる。
加えて、単純にヘッダを一緒に出したいなら-iでできる。

#ヘッダとhtmlをそれぞれファイルに出力する
$ curl -D head.txt -o index.html http://example.com
#ヘッダのみ取得する(HEADメソッド?)
$ curl -I http://example.com
#ヘッダとhtmlを両方とも標準出力に出す
$ curl -i http://example.com

Cookieの制御

与えられたCookieの保存は-cで行える。
またCookieの送信は-bで行う(-cで保存したファイルを参照してもいいし、 -Hの形式で直接書いても良い)。
まぁCookieとかHeaderを複数何度もゴリゴリ弄るくらい面倒だったら大人しくPostmanとか使った方が良さそうだけどね。

#Cookieの取得、保存
$ curl -c cookiejar.txt -o /dev/null http://example.com
#cookiejar.txtを編集し、改ざんしたCookieを送信
$ curl -b cookiejar.txt http://example.com

シェルの便利技

cURLでターミナルからリクエストが送れるようになればこっちのものである。
というのは、都度送信するデータを変えて攻撃を試したい時に、ツール間を移動してコピペしなくてもコマンド1本で片付けられるからである。

コマンド代入 (Command Substitution)

コマンド内で$()を記述すると、$()内のコマンドの実行を優先実行して結果を親のコマンドに用いる。
これを用いれば、今まで別々に実行していたコマンドを1本にまとめられることがある

例えば、GETリクエストのクエリストリングにbase64文字列が要求されたとする。もしあなたがこれを

  • オンラインツールでbase64して
  • 結果をコピーして
  • アドレスバーに貼り付けて

いる人なら朗報である。
この一連の操作は以下のコマンドだけで片付く。

$ curl http://example.com?base64str=$(echo -n m1z0r3 | base64)

このコマンドは、まず$(echo -n m1z0r3 | base64)を実行する。
m1z0r3の部分を任意の文字列に変えれば好きな文字列をbase64変換できる。
その結果得られたbTF6MHIzをcurlコマンドの引数として与えるため、結果として実行されるコマンドは以下の通りになる。

$ curl http://example.com?base64str=bTF6MHIz

コマンド編集の高速化

先の例でbase64する文字を編集しようと思ったら←キーをしばらく押していればいいので大した問題ではない。
しかし、例えばcurlをxurlに間違えてコマンドを打ってしまったら一番左まで戻らなければならず面倒である。

これを解決するには(Ctrl-Shift-cやCommand-cで後ろの文字をコピーしてもいいけど、ここではもっとエレガントに)、Ctrl-aを押せばカーソルが先頭に移る。


(出典:https://clementc.github.io/blog/2018/01/25/moving_cli/
この画像がわかりやすい。要するにEmacsキーバインドである。
Ctrl-aを打つと行の先頭にカーソルを移動させ、Alt-bを打つと単語の先頭に移動する。
また、Ctrl-uを打つとカーソルより手前が全消去される。
(ちなみにMacはalt+英字が特殊文字に割り当てられてる関係で使えない。大人しくLinux使おうな!割り当て解除の方法は調べれば出てきます。)

他にも、シェルに打つコマンドを普段使っている(環境変数EDITORに登録されている)エディタで編集することもできる。
コマンドを打っている途中でCtrl-x, Ctrl-eを押すとnanoやらvimやらが起動する。
そこで編集して保存すれば、保存されたコマンドがシェルに出現する。

それも面倒臭いっていうvimmerの皆さんは

$ set -o vi

してください。そうすればシェルのキーバインドがviモードになります。
元に戻すにはset -o emacsしてね。

クリップボード

コマンドで出力した結果をGUIで使いたかったり、その逆をしたかったりということはよくある。
ターミナルにそのままコピー貼り付けをしてもいいが、コマンド教に入信するとその辺もコマンドに解決させたくなってくる。

ここからの操作はOS依存になる。
Macを使っている人ならpbcopy(pbc)で標準入力をコピー、pbpaste(pbp)で標準出力に貼り付ける。
Linuxを使っている人はまずパッケージ管理ツールでxselをインストールする。
xsel -biで標準入力をコピー、xsel -bで標準出力に貼り付ける。

#m1z0r3をbase64してクリップボードに突っ込む
$ echo -n m1z0r3 | base64 | xsel -bi
#GUIからコピーした結果をcopied.txtに吐き出す
# xsel -b > copied.txt

進捗表示

CTFに限った話ではないが、時間がかかるスクリプトを打った時に進捗がわからないと困る。そこで手軽に進捗表示をする方法を紹介する。

$ for i in $(seq 0 9); do echo -ne "\r\033[KProgress: $i / 10"; sleep 1; done

このスクリプトはsleep 1を10回繰り返すだけのスクリプトだが、何かを解析したり、リクエストを総当たりで発行させる操作に置き換えてイメージしてほしい。

echo -ne "\r\033[K"が重要な部分で、-nは改行なし、-eはエスケープコードの入力を有効化する。"\r"はLine Feedであり、カーソルを先頭に移動する。さらに"\033[K"は現在カーソルが置かれている行のカーソルから末尾までを消去する。つまりこの一連のエスケープシーケンスで行の削除を行っていることになる。

この方法は例えばpythonなど、他のスクリプト言語でも同等に扱える。

from time import sleep

for i in range(10):
    print("\r\033[KProgress: " + str(i) + " / 10", end="")
    sleep(1)

おわりに

世の中GUIで提供されている機能は大体CUIでも提供されている(その方がコストが小さいし軽量なので)。
CUIを使い倒せるようになると作業が効率化できるから、積極的に使ってみよう!
自分はそろそろtshark使えるようになりたいなぁ

参考

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です