以前、某所に置いたサーバで SSL の秘密鍵を誤消去 (リダイレクトで上書き) してしまい、えらい目にあった。
秘密鍵のファイル自体は消えてしまったものの、Apache は再起動しておらず、SSL も問題なく動作している。つまり、メモリ上のどこかで秘密鍵を保持しているだろうと考え、Apache の ML に助けを求めた。復元は絶望的だと思われたが、最終的に メモリから秘密鍵を取り出すことに成功した。もうそろそろ時効だろうと言うことで、その際の手順をメモしておく。
手順
- ダミー (サンプル) の秘密鍵を数個生成する。
$ openssl genrsa -des3 2048 > test1.key $ openssl rsa -outform der -in test1.key -out key1dec.bin
- 生成した秘密鍵をバイナリエディタで開くと、最初の 3 バイトが毎回「30 82 04」になっていることがわかる。つまりメモリからこれを探せば良い。
$ od -tx1 key1dec.bin | head -n 1 0000000 30 82 04 a3 02 01 00 02 82 01 01 00 9c e4 bd d2
- gdb の gcore で httpd のコアをダンプする。方法は以前のエントリに書いた。
- バイナリエディタで、ダンプしたコアから「30 82 04」を検索する。2 箇所見つかるが、片方は公開鍵なので、まともな文字列を含まない方がたぶん本物。
- 秘密鍵と思われる部分から、ダミーで生成した秘密鍵の長さ+αくらいを切り出す。
- 切り出したデータの長さを色々変えて base64 encode し、公開鍵を使って検証する。今回は PHP の base64_encode() や openssl_x509_check_private_key() を使った。
$ cat test.key |php -r "echo(file_get_contents('php://stdin'));" > decoded.key
これでめでたく秘密鍵を復元できた。バックアップは大切だね!
参考ページ
(2012/07/24 追記)
当該 ML でも有益なアドバイスを下さいました、高知大名誉教授の菊地時夫先生のご冥福をお祈りいたします。
コメント