password
主訴: OpenBSDで man ls とかすると、ls.1 なんて見つかりませんと言われました。
あなたなら、こんな訴えが有った時、どういう対処をしますか?
正直、うろたえました。今まで何度もmanのお世話になってたのに、それが突然、縁を切られた ようで、寂しいです、と、情緒に訴えても、何の解決にもならない。
医者なら、最後にmanしたのは何時ですかって問診するだろうね。それから現在までの間に 何か変わった事がありませんでしたか? 何か悪い事をしませんでしたか?
そんな何時まで動いていたかって聞かれても、manは空気みたいなもので、いつまで動いて いたか気にした事もありません。
まあ、こんなものだろう。昨日の夕食で何を食べましたかって保健所の人に聞かれて、すらすら 答えられる人っているのだろうか? 刑事ドラマで、何年何月の何日の何時にあなたは、あそこ で、犯人とおぼしき人を見ましたかって聞かれて、すらすら答えるシチエーション、絶対に 嘘だと思うぞ。
話を戻して、さあどうする? man manすれば。隣の7機でOpenBSDが元気に動いていたので、 聞いてみた。
manの原稿は、/etc/man.confに登録されてるMANPATHを元に検索されますって書いてあった。 で、どんなPATHが登録されてるかみたら、そんなファイルは無かった。でも、ちゃんと検索 出来て、表示もしてる。どんなからくりが仕込まれているの?
manのソースから、etc/man.confを探し出して、眺めてみろ。/usr/src/usr.bin/mandocが 本拠地みたい。
[ob: mandoc]$ grep /etc/man.conf *.[ch] manpath.c:#define MAN_CONF_FILE "/etc/man.conf"
それらしい名前のファイルが引っかかってきましたなあ。取り合えず、開腹して、中を覗いて みますか、と、医者の口調を呟いてみる。
#define MAN_CONF_FILE "/etc/man.conf" #define MANPATH_DEFAULT "/usr/share/man:/usr/X11R6/man:/usr/local/man"
もう、答えが見えちゃったような気がするぞ。/etc/man.confが無い時は、(諦めて)デフォルトの検索PATHを使うんだろう。/etc/man.confが有ると、そちらを優先かな。
Windows10機のOpenBSDでは案の定、/etc/man.confが登録されてて、そこには、
manpath /usr/local/lib/tcl/tcl8.5/man manpath /usr/local/lib/tcl/tk8.5/man
が登録されてた。作成日は、今年の1月末。かすかな記憶をたどると、何かのpkgを入れた時、 tcl/tkも一緒に付いてきて、/etc/man.confに登録しとくと、いいよって言われたんで、 登録した覚えがある。
で、登録と同時に、他のmanは無視されるようになっちゃんだな。裏を取っておけ。
manconf_parse(struct manconf *conf, const char *file, char *defp, char *auxp) { : /* MANPATH and man.conf(5) cooperate. */ defp = getenv("MANPATH"); if (NULL == file) file = MAN_CONF_FILE; /* No MANPATH; use man.conf(5) only. */ if (NULL == defp || '\0' == defp[0]) { manconf_file(conf, file); return; } :
manconf_file(struct manconf *conf, const char *file) { const char *const toks[] = { "manpath", "output", "_whatdb" }; char manpath_default[] = MANPATH_DEFAULT; : if ((stream = fopen(file, "r")) == NULL) goto out; : switch (tok) { case 0: /* manpath */ manpath_add(&conf->manpath, cp, 0); *manpath_default = '\0'; break; : out: if (*manpath_default != '\0') manpath_parseline(&conf->manpath, manpath_default, 0); }
confファイルが有ってそこにmanpathが設定されてたら、デフォルトの設定は無視されるようになってた。なる程ね。 これにて一件落着。
まてまて、今回は近くに別のシステムが有ったから助かったけど、無かった時はどうする? 何せ、OpenBSDは、世間から隔絶された絶海の孤島ですから。自給自足で何とかするように 索を巡らせておけ。それが孤高に生きる道。
えとね、manコマンドを調べ尽くすに限るな。それしか手は無いんだから。
1. /usr/share/man/man1/man.1 の生原稿を頑張って読んでみる 2. ktrace man ls ; kdump して、挙動を探る 3. strings /usr/bin/man | grep man とかやって、ヒントを探す 4. man の一言で、使い方を復習する
思いつくのは、これぐらいかなあ。まだ、何か有りそうな気がするけどな。
password
以前ちょっと妄想した、Webサイトの会員登録方法をコンピュータに計算させちゃうって方法、 我ながら良案と思えるようになってきた。
大体どのサイトを見てもそうだけど、パスワードは、容易に想像されがたく、覚えやすいものを 考えましょうと矛盾した事を言っている。
どうしてもダメなら、パスワードを一括で管理してくれる、パスワード管理プログラムを 使いましょうとも勧めている。そんな管理プログラムが壊れたらどうするんや? オイラーは、そっちの方が心配。
Webにログインするって考えたら、当然目の前にパソコンが有るんだから、そいつに計算 させればいいじゃん。(スマホとかタブレットは、今回は眼中に無いです。)
で、どんなパソコンでも備えているであろうコマンドだけを使って、パスワード計算のための 一行野郎を書いた積り。再掲すると、
[ob: ~]$ echo trump | openssl sha512 | openssl base64 | cut -c 13-21 YThmOGFmY N2VkNjk4Y ZGZkYTIzO
trumpってのが秘密のキーワード。秘密なんで初恋の人の名前でも尊敬する人の名前でも 何でもよい。そいつのハッシュを作ってあげる。この結果がどうなるか?
[ob: ~]$ echo trump | openssl sha512 (stdin)= a8f8afb3ef495e10ad718d3235733015bb2e3920c6f8115f7ed698ae4f61815fdaafaa3f6eb745c735e69e38f2b7d097dfda239fa06894a8f87489f6780334e4
こんな16進数の羅列が得られる。それがパイプを流れて行って、64進数に変換される。
[ob: ~]$ echo trump | openssl sha512 | openssl base64 KHN0ZGluKT0gYThmOGFmYjNlZjQ5NWUxMGFkNzE4ZDMyMzU3MzMwMTViYjJlMzky MGM2ZjgxMTVmN2VkNjk4YWU0ZjYxODE1ZmRhYWZhYTNmNmViNzQ1YzczNWU2OWUz OGYyYjdkMDk3ZGZkYTIzOWZhMDY4OTRhOGY4NzQ4OWY2NzgwMzM0ZTQK
16進数だと、使われている文字種が0-9a-fまでしか無いから、文字種の幅を広げたって 事になる。そして、最後に適当な所を切り出すって訳。
このアルゴリズムと秘密のキーワードさえ頭の中に叩き込んでおけば、メモを取る必要も なく、プログラムとして保存しておく必要さえ無い。
そんじゃ、複数のサイトで同じidとpasswordを使いまわすのか? 別にそんな危険な事を する必要は無い。サイトの名前と秘密のキーワードを連結すればおk。例えば、@ITなら
[ob: ~]$ echo trump@IT | openssl sha512 | openssl base64 | cut -c 13-21 ZGJjZjVkM OWNkMjJjN NzMzNDlkN
こんな具合になる。
なお、キーワードから乱数を作り出すのに、俗に言うsha-2系を使ったけど、セキュリティーに 敏感な人達は、 知られざる暗号の 2017年問題、安全サイトが突如警告サイトに(2/4)こんな警告を発しているから、 ご注意めされ。そして、こんなのも。 SHA-1ハッシュの衝突を現実的な時間で生成する攻撃「Shatterd」
で、ここで使ってるコマンド類はunix敬OSでは普通に入っているはず。問題は素のWindowsだな。特に問題になりそうなのは、openssl。オイラーの場合、mobaXtermと言う偽unixアプリが 有るんで、これに追加してあげればいいだろう。
追加は出来たんだけど、動かしてみるとopensslが応答を返さない。やっぱり偽unixだったよ。 諦めて、Windows用のアプリとして、 WindowsにOpenSSLをインストールして証明書を取り扱う(基本編) を入れてあげたよ。
それから、Windows用のbusybox.exeも入れて みた。その結果、こんな風に使える。
c:\>busybox echo trump | openssl sha512 | openssl base64 | busybox cut -c 13-21 YThmOGFmY N2VkNjk4Y ZGZkYTIzO
busyboxの付け忘れがありそうなので、スクリプトにしておくのがよさそう。特に、echoは素のWindowsにも用意されてるけど、挙動が違うので注意の事。面倒なら、下記のような、 バッチを登録しとくと、bashって叩くだけで、Bash on Windows 環境が出来上がるぞ。 この環境の中に入ってしまえば、viも普通に使えるし、面倒な前置詞 busyboxも不要になる。
~ $ cd c:/app/OpenSSL-Win64/bin/ c:/app/OpenSSL-Win64/bin $ cat bash.bat busybox.exe busybox.exe sh -
これにて、一件落着。
password 発生器
とまあ、一行野郎の発生器を作った訳だけど、世間一般ではどうやってパスワードを発生 させてるか、参考までに見ておく。
# -*- coding:utf-8 -*- from string import ascii_lowercase, ascii_uppercase, digits import random def iter_password(length=8, num_of_numbers=2, num_of_uppers=2): numbers = list(digits) uppers = list(ascii_uppercase) lowers = list(ascii_lowercase) num_of_lowers = length - num_of_numbers - num_of_uppers while True: random.shuffle(numbers) random.shuffle(uppers) random.shuffle(lowers) p = numbers[:num_of_numbers] + \ uppers[:num_of_uppers] + \ lowers[:num_of_lowers] random.shuffle(p) yield ''.join(p) p = iter_password(length=6, num_of_numbers=1, num_of_uppers=1) print(next(p)) # wSqvb7 print(next(p)) # caw4nR
それぞれの文字種を取り出して、かき回しておき、そこから必要な個数を取ってきて連結。 最後にまたかき回しているんだな。みんなこういう仕組みで、ガラガラ・ポンしてるんだな。
パスワードの強度
最近はパスワードをクラックする技術が発達してて、へなちょこパスワードは直ぐに 見破られてしまうそうだ。チェッカーが出ている。
こういうクリチカルな事案は、是非セカンドオピニオンしとけ。
最初のURLでは、入力したパスワードが、どれぐらいの時間で破られるか教えてくれる。 後の方は、どんな文字をどのように混ぜれば良いか、点数をもって示してくれる。
&X7f9w%z3 なんてのが、Very Strong と言ってきた(減点なしのパターン)。これを 前の方で試すと、4週間で破られますってさ。
前の方でpassなんてのを試すと、即破られます、時間をかけるまでもないとの事。ipadのロックに使ってる4桁の数字だと、200ns。但し、メモリアルな数字0911はあれかと思ったら、通報番号になるのか知らんけど、特別危険な番号らしい。
長い々パスワードを入力したら、4 sextillion years こんな風に言ってきた。こう言われても、どれぐらいの長さか分からん。
「じゅげむ じゅげむ ごこうのすりきれ かいじゃりすいぎょの すいぎょうまつ うんらいまつ ふうらいまつ くうねるところにすむところ やぶらこうじのぶらこうじ ぱいぽ ぱいぽ ぱいぽのしゅーりんがん しゅーりんがんのぐーりんだい ぐーりんだいのぽんぽこぴーの ぽんぽこなーの ちょうきゅうめいのちょうすけ」これぐらいかな?
こういう時は、commonLispに聞いてみる。OpenBSDにRを入れたら、世迷いでclispも紛れ こんできたからね。
[15]> (format nil "~r" 4000000000000000000000) "four sextillion"
無駄な機能がやっと役にたったわい。ああ、折角だからschemeにも登場願おう。 sha1とかやると、hexで答えが返ってくるんだけど、10進数に直すと、どんだけーー?
[ob: ~]$ echo hoge | openssl sha1 (stdin)= eefd5bc2c547bf82b177b6259c13f7723dc876d9 [ob: ~]$ gsi Gambit v4.8.4 > #xeefd5bc2c547bf82b177b6259c13f7723dc876d9 1364389885486331479808206927430906730536254338777
schemeだと、#xを前置すると、16進数として扱ってくれる。そんじゃ、pythonとかは?
In [1]: 0xeefd5bc2c547bf82b177b6259c13f7723dc876d9 Out[1]: 1364389885486331479808206927430906730536254338777
rubyも同様だね。
乱数
パスワードには乱数が付きもの。pythonのパスワード発生器でも使われている。オイラーが ハッシュを乱数と見做して、使ってみたけど、本当に乱数なの?
調べてみるか。sha512だと、512Bitの出力なんで、バイトに直すと64Byteになる。 1byteのhex表現は、00からffまでだな。幾つもハッシュを取って、バイトの分布を取って みるか。
解析に使うのは、awkでいいだろう。
[ob: tmp]$ cat hex.awk # count hex { for (p=0; p<length($0); p+=2) { cnt[ substr($0,p,2) ] += 1; } } END { for (k in cnt) { print k, cnt[k] } }
2文字づつ切り出して、それを連想配列のキーにして、個数を数える。昔取った杵柄だな。 で、sha512の種はどうする? 3秒考えて、/usr/local/binの下にあるコマンド名を種に すればいいだろう。
[ob: tmp]$ for f in /usr/local/bin/* > do > echo $f | openssl sha256 | cut -d' ' -f2 >> seed > done [ob: tmp]$ wc seed 1659 1659 107835 seed
いつの間にかコマンドが増えているな。望まない者も結構密入国してるからなあ。トランプの 気持ちも分からないではないよ。 これで、5万回以上、サイコロを振った事になるな。
じゃ、早速、分類してみる。
[ob: tmp]$ cat seed | awk -f hex.awk | sort 00 218 01 205 02 197 : fd 183 fe 197 ff 215
大体200回前後の目が出てるな。後はこれを統計分析すればいいのか。
以上で検定のやり方も分かったので、やってみるかとなったんだけど、その前に、16進数を 完全に分解して、その現れ方を調べてみる。(言ってみれば、16面のサイコロを何回も振って、 その出目を調べる訳。)
[ob: tmp]$ cat LOG | awk -f nibble.awk | sort 0 13366 1 13253 2 13155 3 13293 4 13236 5 13239 6 13307 7 13356 8 13163 9 13109 a 13263 b 13378 c 13433 d 13079 e 13380 f 13342
これを見れば、いかさまじゃない事が一目瞭然。検定はpassしても大丈夫だろう。 じゃ、16進数の文字列をそのまま使っちゃえ。
[ob: tmp]$ head LOG | cut -c -10 126b63ea02 1 day 81% 8814f0fe5f 0ad4c06d26 4035811622 300 ms 26% 089c68709b 192b800f4f 4e6dcefb3e 468f9e9eda b727873ffa ce567ab1db 58%
生のhexを10桁で、どれぐらいでクラックされるか確認。殆どが1日となった。不幸にも 数字だけのものを選んじゃうと、瞬きする間にクラックされてしまう。
そこで、換字ですよ。1,2,3,a,b,c とかは、人間が好みそうな文字なんで、それを別な文字に ワープさせてみた。
[ob: tmp]$ head LOG | cut -c -10 | tr '123abc' '-@.QRZ' -@6R6.eQ0@ 53 year 100% 88-4f0fe5f 0Qd4Z06d@6 40.58--6@@ 1 week 100% 089Z68709R 1 day 89% -9@R800f4f 4e6dZefR.e 468f9e9edQ 8 month 99% R7@787.ffQ Ze567QR-dR 6 year 94%
中にはちょっと強度不足のものも混じっているな。もう少し数字を別の文字に変えるように すれば、良くなるだろう。なお、最初に考えたbase64を使って文字種を散らすというのは、 愚策であった。出現頻度の割合に平等さがなくなり、折角のhex文字出現の平等さが消されて しまう。(出目に偏りが有る、サイコロを作ってたという事です)
/etc/password
パスワードとくれば、/etc/passwordだな。久しぶりに眺めてみたら、大事なパスワードは 管理者しか手が届かない別ファイルに保存されてた。
よくニュースになる、ユーザー情報が何万件も盗まれましたってのは、この別ファイル(データベース)を取られてしまったって事だな。
後は、そのファイルを元に総当たり攻撃で、解読するとな。1アカウントの解読に何日も かかるようじゃ効率が悪いだろうから、せいぜい数分で破れなければ、次のユーザーを試す んだろうね。
上のURLで何日で破れるってのは、特定ユーザーに的を絞って、どうしても破りたい。 破ったら莫大な金銭、あるいは秘密情報を利用出来るようになるって目標を定めた場合 だろう。そういう目的が無いなら、ビットコインでも発掘してた方が儲かるぞ。
で、OpenBSDの場合には、パスワードの暗号化にブロウフィッシュってのが使われて いるのね。どんな風に暗号化されるか試せるようになってた。
[ob: tmp]$ encrypt hoge $2b$10$onFLvW1TW6RFWigmWFYjdOd.bbTO82mX/drFqS.NOE38jx0BV8rSe
色々な文字種が散りばめられていて、これ自体が良パスワードとして使えそう。 この技を盗めないか。後でソースを参照しとけよ。
crypt_newhashというライブラリィーが核になる部分を担当してた。mainの中で使った バッファー類は、コマンドを終了する時にちゃんと掃除してるのね。抜け目ない。