/ports/security/0d1n

河本孝之(Takayuki Kawamoto)

Contact: takayuki.kawamoto (at) gmail.com.

ORCID iD iconORCID, Google Scholar, PhilPapers, about.me.

First appeared: 2019-03-05 17:14:37,
Modified: [BLANK],
Last modified: [BLANK].

概要(pkg-descr の翻訳)

[root@BSD /usr/ports/security/0d1n]# cat pkg-descr 0d1n は、ウェブ・アプリケーションに対してカスタマイズされた自動攻撃ツールです。 以下のような特徴があります。 - 認証フォームのログイン名とパスワードに対するブルート・フォース攻撃 - ディレクトリの情報取得(PATH のリストに対する総当たりと HTTPS ステータス・コードの発見) - SQL インジェクション脆弱性とクロス・サイト・スクリプティング脆弱性を見つけるテスト - 個々のリクエストに CSRF 対策トークンを読み込むオプション - 個々のリクエストにランダムなプロキシ通信を使うオプション WWW: https://github.com/CoolerVoid/0d1n

新しく Ports に登録されたのは、FreeBSD BugZilla のログによると、2016年11月14日のようです。2年と少ししか経っていないため、新しい方の Port だと言えるでしょう。ただ、それ以降にバグが報告されておらず、それどころかコミットした様子もないため、12.0 release 以降での動作検証が不足している可能性があります。実際、下記で説明しているように、最初は全く動作しませんでした。

上記は僕が FreeBSD マシンにアクセスしている TeraTerm Pro という Windows 用のターミナル・エミュレータでの表示を模しています(もちろん日本語で表示しているわけではありませんが。ロケールは C のままで、日本語化などという面倒でトラブルの元になるようなことはしていません)。プロンプトだけ色が違っていますが、これは実際に tcsh というシェルの設定ファイル(HOME/.cshrc)で、set prompt = "%{\e[32;1m%}[%n@BSD %/]#%{\e[0m%} " と設定しているからです。「%{\e[32;1m%}」がライト・グリーンの色で着色する設定箇所になっていて、「%{\e[0m%}」が着色を終了する指示です。

冒頭に戻る

インストール

[root@BSD /usr/ports/security/0d1n]# make install clean [...省略...] Installing 0d1n-2.3... ===> Cleaning for curl-7.64.0_1 ===> Cleaning for brotli-1.0.7_1,1 ===> Cleaning for libnghttp2-1.36.0 ===> Cleaning for libssh2-1.8.0_1,3 ===> Cleaning for 0d1n-2.3

冒頭に戻る

解説

0d1n” は、“odin” という綴りの munged phrase で*1、北欧神話に出てくる戦いと智の神である「オーディン」を表します(セキュリティ・ツールには、こういう勇ましい名前のものが多いので、多少の厨二病テイストは慣れた方がいいでしょう)。冒頭の概要にもあるとおり、ウェブ・アプリケーションのコードに対して攻撃を行い、セキュリティ・レベルをチェックするためのツールです。「ブルート・フォース攻撃(総当たり攻撃)」は、可能な値を全て一つずつ試して攻撃する手法のことで、たとえば(こんな認証システムはありませんが)「0 から 9 までの一桁の数字でパスワードを設定してある認証フォーム」なんてものがあったら、それこそ “0,” “1,” “2,” ... “8,” “9” と順番に全ての数字を試して攻撃すれば、その中のどれかで攻撃が成功するのは自明でしょう。同じく、もし銀行のキャッシュカードのように四桁の数字で設定するようなパスワードのウェブ・アプリケーションがあったら、“0000” から “9999” まで 10,000 個のパターンを試せばいいわけです。とりあえず、本稿はソフトウェア品質検査入門ではないので(笑)、こうした知識は既にお分かりのこととして話を進めます。

*1“Modify Until Not Guessed Easily” の頭文字を取った言葉。パスワードを作る際に使われる、アルファベットを形の似ている数字で置き換える初歩的な方法です。置き換えそのものに規則性があって数も少ないため、桁数が少ないと殆どパスワードの強度は上がりません。

開発者である Antonio Costa (CoolerVoid) さんの GitHub ページにあるとおり、使い方など詳しい説明は 0d1n を実行して表示されるテキストを参照するのがいいようです。

[root@BSD /usr/local]# od1n ~. ~ 01...___|__..10. 1010 101 101 0101 :Bug :Sec `.oo' :101 |010 |101 ( (`-' .---. 1010 ;110 ;010 `.`. / .-._) 111-"""|"""'-000 `.`. ( (`._) .-. .-. |.-. .-. .-. ) ) \ `---( 1 )( 0 )( 1 )( 1 )( 0 )-' / `. `-' `-' `-' `-' `-' .' `---------------------------' 0d1n Web Hacking Tool 2.3 BeTa --host : Host to scan or GET method to fuzz site.com/page.jsp?var=^&var2=^ --post : POST method fuzz params ex: 'var=^&x=^...' --cookie : COOKIE fuzz params ex: 'var=^&var2=^...' --custom : Load external HTTP Request template file to change points with lexical char '^' to fuzzing (note: if you use this argv the payload list need be urlencoded) ' --agent : UserAgent fuzz params ex: 'firefox version ^...' --method : Change method to Custom http method like DELETE, PUT, TRACE, CONNECT... --header : Add line on http header --payloads : Payload list to inject --find_string_list : Strings list to find on response --find_regex_list : Regex list to find on response(this regex is posix) --cookie_jar : Load cookie jar file --log : Create text output of result --UserAgent : Custom UserAgent --CA_certificate : Load CA certificate to work with SSL --SSL_version : Choice SSL version by number: 1 = SSLv1 2 = SSLv2 3 = SSLv3 4 = TLSv1.0 5 = TLSv1.1 6 = TLSv1.2 --threads : Number of threads to use, default is 4 --timeout : Timeout to wait Response --proxy : Proxy_address:port to use single proxy tunnel example: format [protocol://][user:password@]machine[:port] --proxy-rand : Use proxy list to use random proxy per Request example: format [protocol://][user:password@]machine[:port] --tamper : Payload tamper to try bypass filters Choice one option : encode64 : to encode payload to 64 base randcase : to use lower and upper case random position in string urlencode : converts characters into a format that can be transmitted over the Internet, percent encoding double_urlencode : converts payload two times with urlencode spaces2comment: change spaces ' ' to comment '/**/' unmagicquote: change apostrophe to a multi-byte %bf%27 apostrophe2nullencode: change apostrophe to illegal double unicode counterpart rand_comment: to use random comment '/**/' position in payload string rand_space: write random ' ' blank spaces replace_keywords: replace especial words, SELECT to SELselectECT etc... --token_url : Url of form that you need get anti-csrf token --token_name : Name of anti-csrf token to get and use at your request NOTE: if you using any token to bypass anti-csrf protection, you use {token} var at your POST or GET or custom request if you make this 0d1n change {token} to token of form... example --post 'var=^&token={token}&var2=test' Enable-options-args: --save_response : Enable save response highlights view when you click at http status code in datatables --json_headers : Enable add JSON headers in Request example 1 to find SQL-injection: ./0d1n --host 'http://site.com/view/1^/product/^/' --payloads payloads/sqli_list.txt --find_string_list sqli_str2find_list.txt --log log1337 --tamper randcase --threads 5 --timeout 3 --save_response example 2 to Bruteforce in simple auth: ./0d1n --host 'http://site.com/auth.py' --post 'user=admin&password=^' --payloads payloads/wordlist.txt --log log007 --threads 10 --timeout 3 example 3 to search XSS and pass anti-csrf token: ./0d1n --host https://page/test.php --post 'csrf={token}&pass=^' --payloads payloads/xss.txt --find_string_list payloads/xss.txt --token_url https://page/test.php --token_name name_token_field --log logtest --save_response Notes: Look the character '^', is lexical char to change to payload list lines... Coded by Cooler_ coolerlair[at]gmail[dot]com

三つの事例が紹介されているのを見ても分かるように、攻撃対象となるホストとパラメータ(GET/POST)を指定して、ログやレスポンスを記録するというのが書式の概略となっています。

それでは、さっそく 0d1n を使ったブルート・フォース攻撃を試してみましょう。0d1n にはパスが通っているので、/usr/local/bin/0d1n のようなフルパスは必要ありません。攻撃対象は PHP ファイルとします。FreeBSD に Apache と PHP モジュールがインストールされている環境を前提に、なんらかの HTML ファイルからフォームなどで “password” という名前のデータが GET メソッドで送信されたとします。受ける側のファイルを check.php としておき、そこでは $_GET[ 'password' ] に格納された値を使って何らかの判定(このケースでは単純に “administrator” をパスワードとする認証)を行い、その結果を error.html もしくは finish.html への遷移(PHP だと header() 関数によるリダイレクトのステータス・コードを返して、リダイレクト)として終了させます。したがって、0d1n は check.php に対して GET メソッドでのブルート・フォース攻撃を仕掛けます。

[root@BSD /root]# 0d1n --host 'http://192.168.1.201/check.php?password=^' --log test_20190304-001 --payloads payloads/password_brute.txt --threads 10 --timeout 3 --save_response

上記はウェブページ上で改行しているように見えますが、実際には1行の(引数やオプションがたくさん付いている)コマンドです。バックスラッシュ(「\」)を使って、見た目は改行していても実際のコマンド入力では改行していないことを表記する場合もありますが、それはあくまでもバックスラッシュを書くまでの間に改行しない場合の表記方法ですから、ページの幅を変えたらどこで改行するように見えるか分からないウェブページでは、有効とは言えない表記方法だと思います。当サイトに限らず、プロンプトごとに1行と見做しておいた方がシンプルでしょう。これを本当に1行のテキストとしてページの右へ突き抜けるようにしてもいいのですが、一覧性も悪くなりますし、あまりそんなものを見たいと思う人はいないでしょう。それに、TeraTerm のようなターミナル・エミュレータのウィンドウや、FreeBSD のマシンへ直にログインした物理スクリーン上でも、どのみち改行するものは改行するのです。

さて、では上記と同等のコマンドを打ち込んだらどうなるでしょうか。僕の環境(「192.168.1.201」という IP アドレスは僕が使っているので、この記事を読んでいる方は使わないようにしてくださいっ!)では、

[root@BSD /root]# 0d1n --host 'http://192.168.1.201/check.php?password=^' --log test20190304-001 --payloads payloads/password_brute.txt --threads 10 --timeout 3 --save_response HTTP/1.1 302 Found Date: Sun, 03 Mar 2019 23:21:48 GMT Server: Apache/2.4.38 (FreeBSD) OpenSSL/1.1.1a-freebsd PHP/7.3.2 X-Powered-By: PHP/7.3.2 location: /error.html Content-Type: text/html; charset=UTF-8 HTTP/1.1 200 OK Date: Sun, 03 Mar 2019 23:21:48 GMT Server: Apache/2.4.38 (FreeBSD) OpenSSL/1.1.1a-freebsd PHP/7.3.2 X-Powered-By: PHP/7.3.2 Content-Type: text/html; charset=UTF-8 Host: http://192.168.1.201/check.html?password=^ Log file: test20190304-001 Payloads: payloads/password_brute.txt --- DEBUG-START --- Mon Mar 4 08:21:48 2019 spider.c[621] scan(): error to open Payload list --- DEBUG-END ---

こんな結果となりました。最後にデバッグ情報が出ているのは、0d1n を make install するときに、わざとデバッグの設定を付けたからです。この情報によると、spider.c で、ブルート・フォース攻撃のために読み込もうとした、パスワードの一覧ファイル(payload)が見つからなかったというエラーが出ています。そこで、実行する場所に pass.txt というファイルを作って、payloads/password_brute.txt の中身(数百キロバイトぶんのテキスト)を移します。そして、書き出すログファイルも、あらかじめ touch で 0666 のパーミッションで作っておいたファイルを用意します。しかし・・・

--- DEBUG-START --- Mon Mar 4 17:54:38 2019 file_ops.c[82] FileSize(): error in file --- DEBUG-END --- --- DEBUG-START --- Mon Mar 4 17:54:38 2019 file_ops.c[82] FileSize(): error in file --- DEBUG-END --- --- DEBUG-START --- Mon Mar 4 17:54:38 2019 file_ops.c[16] readLine(): error in to open() file --- DEBUG-END ---

このようになります。そして、このようなエラーを検索してみても類例が全くヒットしないということは、要するに世界中のセキュリティ技術者の殆どが、このツールを FreeBSD どころか他の UNIX/Linux 環境でインストールして動かしてみたことすらないということを示唆しています。そもそも、全く何のカスタマイズもしていないような FreeBSD 12.0 release の環境で、テキストファイルの読み書きに payloads/ などと特定の相対パスを想定しているという奇怪な条件で動作するプログラムが動くと思ってる方がどうかしているからです。(ふつう、パスが通っていないファイルの読み書きなど、プログラムの作者の環境ですら不可能なのです。)冒頭で紹介したように、0d1n が Ports に登録されたのは二年前のことでした。そして、多くのユーザに使われてフィードバックを受けてきているようには見えないので、まともに動く条件を自力で特定した方がいいかもしれません。

念のため、いったんアンインストールしてから入れなおしてみます。

[root@BSD /usr/ports/security/0d1n]# make deinstall clean ===> Deinstalling for 0d1n ===> Deinstalling 0d1n-2.3 Updating database digests format: 100% Checking integrity... done (0 conflicting) Deinstallation has been requested for the following 1 packages (of 0 packages in the universe): Installed packages to be REMOVED: 0d1n-2.3 Number of packages to be removed: 1 [1/1] Deinstalling 0d1n-2.3... [1/1] Deleting files for 0d1n-2.3: 100% ===> Cleaning for 0d1n-2.3 [root@BSD /usr/ports/security/0d1n]# make install clean ===> License GPLv3 accepted by the user ===> 0d1n-2.3 depends on file: /usr/local/sbin/pkg - found ===> Fetching all distfiles required by 0d1n-2.3 for building ===> Extracting for 0d1n-2.3 => SHA256 Checksum OK for CoolerVoid-0d1n-2.3_GH0.tar.gz. ===> Patching for 0d1n-2.3 ===> Applying FreeBSD patches for 0d1n-2.3 ===> 0d1n-2.3 depends on shared library: libcurl.so - found (/usr/local/lib/libcurl.so) ===> Configuring for 0d1n-2.3 ===> Building for 0d1n-2.3 --- all --- cc -O2 -pipe -fstack-protector -fno-strict-aliasing -W -Wall -Wextra -fstack-protector-all -D_FORTIFY_SOURCE=2 -I /usr/local/include -c *.c cc -o 0d1n *.o -Wl,-z,relro,-z,now,-L,/usr/local/lib,-lcurl ===> Staging for 0d1n-2.3 ===> Generating temporary packing list install -s -m 555 /usr/ports/security/0d1n/work/0d1n-2.3/0d1n /usr/ports/security/0d1n/work/stage/usr/local/bin install -m 0644 /usr/ports/security/0d1n/work/0d1n-2.3/README.txt /usr/ports/security/0d1n/work/stage/usr/local/share/doc/0d1n ====> Compressing man pages (compress-man) ===> Installing for 0d1n-2.3 ===> Checking if 0d1n is already installed ===> Registering installation for 0d1n-2.3 Installing 0d1n-2.3... ===> Cleaning for 0d1n-2.3

それから、敢えて README だけを make readme で出力して眺めていると、次のような箇所を見つけました。

<p>Please read the "<a href="pkg-descr">description file</a>" for a longer description and/or visit the <a href="https://github.com/CoolerVoid/0d1n">web site</a> for further information.</p>

ご覧のように、Port の作業ディレクトリにしか存在しない pkg-descr ファイルに対して相対パスでアンカーリングしています。ということは、この README.html というファイルは Port の作業ディレクトリに出力されるだけではなく、ウェブサーバでアクセス可能なディレクトリとして(どういうわけか)設定されているという前提のもとで正しく動作するようになっています。先ほどの相対パスと合わせて考えてみると、この 0d1n というツールは FreeBSD どころか相当に特殊な手順でなければ導入できないことが明白であるにも関わらず、その手順が全く説明されていない欠陥 Port だと断定できるでしょう。暇つぶしに趣味としてトラブルシュートするのも悪くありませんが、残念ながら業務上の関心で取り組んでいる場合、このような欠陥 Port に付き合う必要はありません。

冒頭に戻る


※ 以下の SNS 共有ボタンは JavaScript を使っておらず、ボタンを押すまでは SNS サイトと全く通信しません。

Twitter Facebook