2017-12-15 (Fri) [長年日記]
_ ファイルオープンの罠
僕が書いたNet::FTPのコードに脆弱性報告があり、修正版がリリースされた。関係者のみなさん、ありがとうございました。
問題があったのは以下のようなコードだった。
def getbinaryfile(remotefile, localfile = File.basename(remotefile), blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data f = nil result = nil if localfile if @resume rest_offset = File.size?(localfile) f = open(localfile, "a") else rest_offset = nil f = open(localfile, "w")
ここでKernel#openを使っていたのが問題で、localfile
が|
で始まる文字列だと外部コマンドが実行されてしまう。
しかも、まずいことにlocalfile
のデフォルト値はFile.basename(remotefile)
なので、悪意のあるFTP上に|
で始まる名前のファイルがあって、ディレクトリ内のファイルをすべてダウンロードするようなプログラムを書いていると、クライアント側でコマンドが実行されてしまう。パイプ以外ではopen-uriをrequireしているようなケースでも何かまずいことができてしまうかもしれない。
普段書き捨てのコード以外ではFile.openの方を使うのだけど、確認したところ1997年8月13日リリースのruby-1.1a0のころからKernel#openを使っていたようだ。
ちなみにopen以外にも罠があって、例えば
p File.read("|echo hello") #=> "hello"
のようにしてもコマンドが実行されてしまう。
これは、Fileクラスには実はreadは定義されておらず、IO.readが呼び出されるため。
他には、binread, write, binwrite, foreach, readlinesなども同様の罠がある。
わざわざFile.
と書いてパイプをオープンしている意図的なコードはそうそうないと思うので、Fileクラスにパイプをオープンしないバージョンを追加してオーバーライドした方がよいのではないかと思うが、今さら2.5には間に合わないだろう。
当面は引数をFile.expand_pathでフルパスに展開するとか、先にFile.statするなどすれば、上記のような罠を回避することができると思う。
2017-12-20 (Wed) [長年日記]
_ PGP鍵の更新
PGP鍵の有効期限が切れたので新しい鍵を作成した。
pub rsa4096/AD744A13 2017-12-20 [SC] [expires: 2027-12-19] Key fingerprint = 7645 6F57 D834 E17B ACEF 5239 568A D8CE AD74 4A13 uid [ultimate] Shugo Maeda <shugo@ruby-lang.org> uid [ultimate] Shugo Maeda <shugo@netlab.jp> uid [ultimate] Shugo Maeda <shugo@debian.org> sub rsa4096/636AA7CD 2017-12-20 [E]
古い鍵で署名した上でpgp.mit.eduとpgp.nic.ad.jpに登録したので、古い鍵での署名が確認できる人は新しい鍵に署名していただけるとありがたい。
2017-12-21 (Thu) [長年日記]
_ PGP/MIME
MournmailにPGP/MIMEを実装した(表示は前から一部実装してあった)。
mail-gpgを使って
m = Mail.new ... m.gpg(sign: true, encrypt: true) m.deliver
とすると、PGP/MIMEで署名・暗号化されたメールが送信されるが、delivery_handlerとして実装されているのでdeliver!
だと署名・暗号化されないので注意。*1
署名と暗号化の両方を行った場合は、multipart/encryptedの中にmultipart/signedを入れる形式*2ではなく、以下のようにOpenPGPで署名と暗号化を同時に行ったものをmultipart/encryptedにする形式*3になる。
Content-Type: multipart/encrypted; boundary="--==_mimepart_5a3b0cf4ac39a_8953ff49d912018280a"; protocol="application/pgp-encrypted" Content-Transfer-Encoding: 7bit This is an OpenPGP/MIME encrypted message (RFC 2440 and 3156) ----==_mimepart_5a3b0cf4ac39a_8953ff49d912018280a Content-Type: application/pgp-encrypted Content-Transfer-Encoding: 7bit Content-Description: PGP/MIME Versions Identification Version: 1 ----==_mimepart_5a3b0cf4ac39a_8953ff49d912018280a Content-Type: application/octet-stream; name=encrypted.asc Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename=encrypted.asc Content-Description: OpenPGP encrypted message Content-ID: <5a3b0cfbd80bc_8953ff49d9120182843b@lexington.mail> -----BEGIN PGP MESSAGE----- Version: GnuPG v2 hQIMA/zS+2ljaqfNARAA2Zh9f6f5Y55AfzRhCzMSe13R5EXBD6uI+R/VtQomhsag ... -----END PGP MESSAGE----- ----==_mimepart_5a3b0cf4ac39a_8953ff49d912018280a--
Mewでは署名を検証できたけど、SEMIだと署名の検証方法がわからなかった(UI的に署名されているかどうかもわからないような)。
2017-12-23 (Sat) [長年日記]
_ 走り納め
少し暖かくなったので、バッテリーの充電のために近所を走ってきた。
峠道に融雪剤が撒いてあったので、帰ってからざっと洗車した。 多分しばらく乗らないのでバッテリーのマイナス端子を外しておいた。
次乗れるのはいつになるだろうか。
2017-12-25 (Mon) [長年日記]
_ Ruby 2.5.0へのアップグレード
Ruby 2.5.0がリリースされたので、この日記をRuby 2.5.0にアップグレードした。
今のところtDiaryの動作はとくに問題なさそうだが、2.5.0のバグっぽい挙動を見つけてしまったような……。
_ モジュールのrefineのバグ
モジュールをrefineした際のバグをいくつか直したつもりだったが、以下のケースでusing D
していないのにrefineしただけで挙動が変わってしまうようだ。
module A def foo puts "A#foo" super end end class B def foo puts "B#foo" end end class C < B include A def foo puts "C#foo" super end end module D refine A do def foo end end end C.new.foo
using D
した時にsuperでBを辿れないのは仕方ないかなと思っていたのだが、using D
してないのにこうなるのはちょっとまずい……。
とりあえず、Bug #14232として登録しておいた。
2017-12-29 (Fri) [長年日記]
_ Debian stretchへの移行
しばらくUbuntuを使っていたが、RubyコミッタでDebianをメインにしている人が少なくなっていそうなのでDebian strechに移行した。
VirtualBoxなので、クリーンインストールしたDebian上にUbuntuのディスクを追加して/home/shugoをbind mountしたので、セットアップは比較的楽にできた。 はじめてUbuntu使った時はセットアップが楽だと思ったけど、今だとDebianでもそんなに変わらないかも。
ちょっとはまったのは、
- .ssh/configに
IdentitiesOnly yes
と書かないと、Ed25519鍵を使う時にid_ed25519-certが見つからなくて認証に失敗した。 - gnome-keyring-daemonが自動起動するようになっていなかったので、Chromeの起動時に毎回パスワードを求められた。
- 最近のGnomeはかっこいいけど重かった(XFCEに戻した)。
といったところか。