githubが脆弱性をつかれて自分のリポジトリに意図しない公開鍵が登録されている可能性があるとの事

3月頭の話だからちょっとタイミング逃してるけど・・・

$ git clone git@github.com:kanonji/link2player.git
Cloning into link2player...
ERROR: Hi kanonji, it's GitHub. We're doing an SSH key audit.
Please visit https://github.com/settings/ssh/audit/000000 #数値がついてたけど、個別のidだとまずいので0に変更
to approve this key so we know it's safe.
Fingerprint: ff:00:ff:00:ff:00:ff:00:ff:00:ff:00:ff:00:ff:00
fatal: The remote end hung up unexpectedly

Ruby on Railsで作られているgithubが、RoRで作るとうっかり対策を忘れてしまいやすい脆弱性の、Mass assignmentという脆弱性を持ったまま今まで運営されていました。細かい経緯はリンクを貼るとして、先日その脆弱性が存在する事を証明する為に実際についた人がいて、修正されました。ただ、今までその脆弱性があったということは、ユーザーが意図しない公開鍵が登録されている可能性があるという事で、全公開鍵の確認が必要になりました。確認をするまでは、上記の様にその確認が必要な旨を説明したメッセージが表示され、リポジトリにはアクセスできません。github.comにログインした状態でhttps://github.com/settings/sshにて、公開鍵をApproveかRejectする必要があります。

Mass assignmentとは

RoRや、その影響を受けているフレームワークで開発した場合に、埋め込んでしまいやすい脆弱性です。いわゆるActiveRecordでデータベースを扱ってる場合、テーブルと対になる構造をした、ハッシュやオブジェクト*1save()のような格納用のメソッドに渡すと、うまい事INSERTやUPDATEが出来るものです。ブラウザから送信されてきたデータを、無検証で格納するコードを書くと、Mass assignment脆弱性になります。

<?php
array(
  'id' => 1
  'name' => 'foo',
  'ssh_public_key' => '自分の公開鍵'
);

かなり的当なサンプルだけど、仮に公開鍵がssh_public_keyというカラム名だった際、nameを更新する為のフォームのPOST先URLに、ssh_public_keyをくっつけて送信すると、無対策ならそのままsave()に渡されて更新されてしまいます。

対策
  1. ブラウザからデータを受けるアクション毎に、ホワイトリストで受け入れるキー名を制限する。
  2. 普通にバリデーションをする。

ブラウザから送信されてきたデータを無検証で格納するから埋め込んでしまう脆弱性なので、ちゃんと検証するってだけです。割と当たり前の事だけど、それだけについ埋め込んでしまう事があります。考えられるのは、フォームに入力欄がある、送信されてくる事が想定されるデータの、型や値の範囲とかはバリデートしてるのに、それ以外のキーを無条件で通してしまう事。ActiveRecordがあるフレームワークは、入力や更新用のフォーム(ビュー)からコントローラー、モデルまでをスケルトンから生成する機能があったりします。プロトタイプで作ったまま、バリデートを実装するのを忘れてしまう事など。まぁ、ホワイトリストでの制限も、普通のバリデーションの一部としてやるべきとも言えます。

参考

github の mass assignment 脆弱性が突かれた件 - blog.sorah
Public Key Security Vulnerability and Mitigation - The GitHub Blog

この件については、1個目のリンク先が日本語で詳しく解説されています。2個目がgithub.comのアナウンスです。

その他

3月11日に書いていながら下書きのままだった・・・

*1:連想配列など