phpMyAdminを攻撃されて本サイトのデータベースを全て消去されました

プログラミングor技術
つい先日の12月7日深夜2時40分ごろ、本サイトが攻撃を受けデータベースが(たぶん)全て消去されました。つまり記事とか設定とか殆どのデータが(たぶん)消えました。 phpMyAdminの脆弱性 CVE-2019-11768 を利用したSQLインジェクションによるものだと思います。

被害内容

12月7日深夜の2時40分ごろから本サイトが停止していることを死活監視サービスからの通知で気づきました。 (原因特定の項で後述しますが)本サイトのデータベースがダメになっていました。本サイトにアクセスすると「Error Establishing a Database Connection」というWordPressのエラーが表示されました。 DBの中身を確認する前に、WordPressの管理画面にアクセスし焦ってWordPressをインストールし直してしまったのでDBの内容がどうなっていたかは確認できていません。 まぁ、WordPressがエラー出すわけなのでたぶん消されてたとかなんじゃないかな…と思ってます。

原因の特定

あんまり慣れてないので適当にやっていきます。

サイト停止時刻あたりに変更されたファイルを調べる

3日以内に変更されたファイルをWordPress関連ディレクトリから探します。少ないので目grepすると以下のようなもの。
(データベースのファイルは調査前に自分で変更しちゃったので攻撃により変更された時刻は不明)
$ sudo find ./docker -mtime -3 -ls     
(中略)
 420512      4 -rw-r-----   1 999      999            35 Dec  7 02:41 ./docker/docker-for-wordpress/db-data/mysql/slow_log.CSM
 420529      4 -rw-r-----   1 999      999            35 Dec  7 02:41 ./docker/docker-for-wordpress/db-data/mysql/general_log.CSM
MySQLのログが消されてる…のかな? 「ん、MySQLになんかされた?!」とここで気づきました。でもどこからどうやって? 次に、障害発生時刻近辺で変更されたファイルをマシン全体から探します。
$ sudo find /  -type f -newermt "2020-12-06 12:00" -and ! -newermt "2020-12-07 05:00" -ls

   420512      4 -rw-r-----   1 999      999            35 Dec  7 02:41 /home/ubuntu/docker/docker-for-wordpress/db-data/mysql/slow_log.CSM
   420529      4 -rw-r-----   1 999      999            35 Dec  7 02:41 /home/ubuntu/docker/docker-for-wordpress/db-data/mysql/general_log.CSM
   690202      8 -rw-------   1 82       82           4673 Dec  7 02:41 /var/snap/docker/common/var-lib-docker/volumes/da8808f25f90fadf62f694200fce1349c22643d122f65a702710d457181a0a37/_data/sess_eac28d1b240bc53bcec2af9db3570356
   685378     12 -rw-r--r--   1 82       82           9435 Dec  7 02:41 /var/snap/docker/common/var-lib-docker/aufs/diff/7d2b2b0b82b66097a65da60a7de0b05dbf30148ceaa9448326f4a473ca2566b5/var/www/html/tmp/twig/db/db4bc723ddb53f10d92ac00dd700643338bce03048dc35600da98739d73b23da.php
   685351      8 -rw-r--r--   1 82       82           5076 Dec  7 02:41 /var/snap/docker/common/var-lib-docker/aufs/diff/7d2b2b0b82b66097a65da60a7de0b05dbf30148ceaa9448326f4a473ca2566b5/var/www/html/tmp/twig/f1/f19d9499191fade1040c64b74b1d9df9165db7e783bcc12330ed26746cb565d3.php
   689397      4 -rw-r--r--   1 82       82           2241 Dec  7 02:41 /var/snap/docker/common/var-lib-docker/aufs/diff/7d2b2b0b82b66097a65da60a7de0b05dbf30148ceaa9448326f4a473ca2566b5/var/www/html/tmp/twig/b8/b83a86f09cbf94b2a6239612e6f852d9476e73191c9959a327d9e4d9beb68f73.php
   688055     12 -rw-r--r--   1 82       82           8564 Dec  7 02:41 /var/snap/docker/common/var-lib-docker/aufs/diff/7d2b2b0b82b66097a65da60a7de0b05dbf30148ceaa9448326f4a473ca2566b5/var/www/html/tmp/twig/98/988f5db760fd8251b3fbe78c8bca3820beb66392c2a4c65f2ef5e201d559c4e4.php
   690018      4 -rw-r--r--   1 82       82           2853 Dec  7 02:41 /var/snap/docker/common/var-lib-docker/aufs/diff/7d2b2b0b82b66097a65da60a7de0b05dbf30148ceaa9448326f4a473ca2566b5/var/www/html/tmp/twig/4e/4e2e5f208bf76aa8d3d7c96bf3cbf3abf9d4470e3314183db7dc5d88cd29f7ac.php
   690021      4 -rw-r--r--   1 82       82           3235 Dec  7 02:41 /var/snap/docker/common/var-lib-docker/aufs/diff/7d2b2b0b82b66097a65da60a7de0b05dbf30148ceaa9448326f4a473ca2566b5/var/www/html/tmp/twig/e8/e84466685a966f023e32d2b453249ea06d6bc71eabd2e1bf48d69e1a97eb18ed.php
   682268      4 -rw-r--r--   1 82       82           2865 Dec  7 02:41 /var/snap/docker/common/var-lib-docker/aufs/diff/7d2b2b0b82b66097a65da60a7de0b05dbf30148ceaa9448326f4a473ca2566b5/var/www/html/tmp/twig/c1/c1c08af6ae5a283808da93f4ec8cdc089efc641945115b026903465ac992f47a.php
   682270      4 -rw-r--r--   1 82       82           3536 Dec  7 02:41 /var/snap/docker/common/var-lib-docker/aufs/diff/7d2b2b0b82b66097a65da60a7de0b05dbf30148ceaa9448326f4a473ca2566b5/var/www/html/tmp/twig/b9/b98256641ec17cb749884fd727919fb495d130ed10e8e345b2a1b5c04ce19aef.php
   690096      8 -rw-r--r--   1 82       82           4782 Dec  7 02:41 /var/snap/docker/common/var-lib-docker/aufs/diff/7d2b2b0b82b66097a65da60a7de0b05dbf30148ceaa9448326f4a473ca2566b5/var/www/html/tmp/twig/1b/1bea278047cbf4e7959a28009e3e424e57fc402d1e5adc7fbcb64843686ed290.php
   690297      4 -rw-r-----   1 root      adm           504 Dec  6 15:26 /var/snap/docker/common/var-lib-docker/aufs/diff/ac5c2991ee390293b8ee9441fff6f264b2337f19eb65250687ca53d16422c4fe/var/log/syslog.2.gz
   527015      0 -rw-r--r--   1 root      root            0 Dec  7 00:00 /var/lib/systemd/timers/stamp-fstrim.timer
ファイルを全て目視で見ていきました。目が止まったのが次のファイル。
$ sudo cat /var/snap/docker/common/var-lib-docker/volumes/da8808f25f90fadf62f694200fce1349c22643d122f65a702710d457181a0a37/_data/sess_eac28d1b240bc53bcec2af9db3570356

 PMA_token |s:16:"EB)AZ3:SVeMP(VzY";browser_access_time|a:1:{s:7:"default";i:1607276505;}relation|a:1:{i:1;a:22:{s:11:"PMA_VERSION";s:5:"4.8.5";s:7:"relwork";b:0;s:11:"displaywork";b:0;s:12:"bookmarkwork";b:0;s:7:"pdfwork";b:0;s:8:"commwork";b:0;s:8:"mimework";b:0;s:11:"historywork";b:0;s:10:"recentwork";b:0;s:12:"favoritework";b:0;s:11:"uiprefswork";b:0;s:12:"trackingwork";b:0;s:14:"userconfigwork";b:0;s:9:"menuswork";b:0;s:7:"navwork";b:0;s:17:"savedsearcheswork";b:0;s:18:"centralcolumnswork";b:0;s:20:"designersettingswork";b:0;s:19:"exporttemplateswork";b:0;s:8:"allworks";b:0;s:4:"user";N;s:2:"db";N;}}cache|a:3:{s:13:"server_1_root";a:18:{s:14:"mysql_cur_user";s:6:"root@%";s:17:"is_create_db_priv";b:1;s:14:"is_reload_priv";b:1;s:12:"db_to_create";s:0:"";s:30:"dbs_where_create_table_allowed";a:1:{i:0;s:1:"*";}s:11:"dbs_to_test";b:0;s:9:"proc_priv";b:1;s:10:"table_priv";b:1;s:8:"col_priv";b:1;s:7:"db_priv";b:1;s:12:"is_grantuser";b:1;s:13:"is_createuser";b:1;s:12:"is_superuser";b:1;s:11:"binary_logs";a:0:{}s:18:"menu-levels-server";a:13:{s:9:"databases";s:9:"Databases";s:3:"sql";s:3:"SQL";s:6:"status";s:6:"Status";s:6:"rights";s:5:"Users";s:6:"export";s:6:"Export";s:6:"import";s:6:"Import";s:8:"settings";s:8:"Settings";s:6:"binlog";s:10:"Binary log";s:11:"replication";s:11:"Replication";s:4:"vars";s:9:"Variables";s:7:"charset";s:8:"Charsets";s:7:"plugins";s:7:"Plugins";s:6:"engine";s:7:"Engines";}s:14:"menu-levels-db";a:14:{s:9:"structure";s:9:"Structure";s:3:"sql";s:3:"SQL";s:6:"search";s:6:"Search";s:5:"query";s:5:"Query";s:6:"export";s:6:"Export";s:6:"import";s:6:"Import";s:9:"operation";s:10:"Operations";s:10:"privileges";s:10:"Privileges";s:8:"routines";s:8:"Routines";s:6:"events";s:6:"Events";s:8:"triggers";s:8:"Triggers";s:8:"tracking";s:8:"Tracking";s:8:"designer";s:8:"Designer";s:15:"central_columns";s:15:"Central columns";}s:19:"profiling_supported";b:1;s:17:"menu-levels-table";a:11:{s:6:"browse";s:6:"Browse";s:9:"structure";s:9:"Structure";s:3:"sql";s:3:"SQL";s:6:"search";s:6:"Search";s:6:"insert";s:6:"Insert";s:6:"export";s:6:"Export";s:6:"import";s:6:"Import";s:10:"privileges";s:10:"Privileges";s:9:"operation";s:10:"Operations";s:8:"tracking";s:8:"Tracking";s:8:"triggers";s:8:"Triggers";}}s:8:"server_1";a:4:{s:15:"userprefs_mtime";i:1607276430;s:14:"userprefs_type";s:7:"session";s:12:"config_mtime";i:1548476256;s:9:"userprefs";a:1:{s:7:"Console";a:1:{s:4:"Mode";s:8:"collapse";}}}s:13:"version_check";a:2:{s:8:"response";s:419:"{
    "date": "2020-10-15", 
    "version": "5.0.4", 
    "releases": [
        {
            "date": "2020-10-15", 
            "php_versions": ">=5.5,<8.0", 
            "version": "4.9.7", 
            "mysql_versions": ">=5.5"
        }, 
        {
            "date": "2020-10-15", 
            "php_versions": ">=7.1,<8.0", 
            "version": "5.0.4", 
            "mysql_versions": ">=5.5"
        }
    ]
}";s:9:"timestamp";i:1607276430;}}userconfig|a:2:{s:2:"db";a:1:{s:12:"Console/Mode";s:8:"collapse";}s:2:"ts";i:1607276430;}two_factor_check|b:1;git_location|N;is_git_revision|b:0;tmpval|a:16:{s:15:"favorite_tables";a:1:{i:1;a:0:{}}s:13:"recent_tables";a:1:{i:1;a:2:{i:0;a:2:{s:2:"db";s:5:"wpdb1";s:5:"table";s:10:"wp_options";}i:1;a:2:{s:2:"db";s:5:"wpdb1";s:5:"table";s:8:"wp_users";}}}s:18:"table_limit_offset";i:0;s:21:"table_limit_offset_db";s:5:"wpdb1";s:13:"table_uiprefs";a:1:{i:1;a:1:{s:5:"wpdb1";a:2:{s:8:"wp_users";a:0:{}s:10:"wp_options";a:0:{}}}}s:5:"query";a:2:{s:32:"58c77f0f1b92929f0ad222245b13a59c";a:8:{s:3:"sql";s:24:"SELECT * FROM `wp_users`";s:12:"repeat_cells";i:100;s:8:"max_rows";i:25;s:3:"pos";s:1:"0";s:6:"pftext";s:1:"P";s:18:"relational_display";s:1:"K";s:9:"geoOption";s:4:"GEOM";s:14:"display_binary";b:1;}s:32:"1b566d4cd9b0ce1178a95d0fa81586c1";a:8:{s:3:"sql";s:26:"SELECT * FROM `wp_options`";s:12:"repeat_cells";i:100;s:8:"max_rows";i:25;s:3:"pos";s:1:"0";s:6:"pftext";s:1:"P";s:18:"relational_display";s:1:"K";s:9:"geoOption";s:4:"GEOM";s:14:"display_binary";b:1;}}s:6:"pftext";s:1:"P";s:18:"relational_display";s:1:"K";s:9:"geoOption";s:4:"GEOM";s:14:"display_binary";b:1;s:12:"display_blob";b:0;s:19:"hide_transformation";b:0;s:3:"pos";s:1:"0";s:8:"max_rows";i:25;s:12:"repeat_cells";i:100;s:20:"possible_as_geometry";b:1;}ConfigFile1|a:2:{s:7:"Console";a:1:{s:4:"Mode";s:8:"collapse";}s:7:"Servers";a:1:{i:1;a:2:{s:7:"only_db";s:0:"";s:7:"hide_db";s:0:"";}}}debug|a:0:{}is_multi_query|b:0;sql_history|a:2:{i:0;a:3:{s:2:"db";s:5:"wpdb1";s:5:"table";s:8:"wp_users";s:8:"sqlquery";s:24:"SELECT * FROM `wp_users`";}i:1;a:3:{s:2:"db";s:5:"wpdb1";s:5:"table";s:10:"wp_options";s:8:"sqlquery";s:26:"SELECT * FROM `wp_options`";}}errors|a:0:{}
何やってるのかはっきりはわからないけどPHPとSQLが関係していそうです。何やらSQLのクエリもちらほら見えます。タイムスタンプの1607276430等はUNIX Epoch Time、日本時間だと2020年12月7日 02:40:30のこと。障害発生時刻にかなり近いので、攻撃に関連したものでしょう。 ここまでで「SQLとPHPということは…phpMyAdminかも?!」と思い至りました。いやまぁそれ以外でもあるかもしれませんが。

開いてるポートを調べる

「あれ、Webサイト提供用とSSH用以外はポート閉じてた気が…」と確認すると、phpMyAdmin用ポートが開いてました…!!! 使用しているWebArenaのVPSクラウドでは、許可するポートを「セキュリティグループ」としてまとめられます。phpMyAdminを昔使った時、ユルユルなセキュリティグループを適用し、そのままにしていたようです。 つまり攻撃はphpMyAdmin経由説が濃厚になりました。

phpMyAdminのバージョンを調べる

dockerで動かしてるんですが、phpMyAdminのは1年か2年位前にpullしたイメージなはず。 調べてみるとphpMyAdminはVersion 4.8.5 でした。。 ちなみに 2019-01-26.にリリースされたものです。

phpMyAdminの脆弱性を調べる

CVE Details というサイトで、ツールやアプリごと、そのバージョンごとの脆弱性を調べられます。 phpMyAdmin 4.8.5のページはなかったので代わりに4.8.3の脆弱性一覧を見ました。
よく読めば、4.8.5が対象になっているのは5個中で1~3番目だけです。それらを読んでいくと、脆弱性タイプがSqlとなっている CVE-2019-11768 が一番怪しい。

アクセスログを見る

phpMyAdminのdockerコンテナのログを見ます。 コンテナ中のWebサーバのログは保存されてなかった(?)ので、dockerが保存してるログ(コンテナのstdoutとstderr)を見ます。
$ sudo docker logs <コンテナID>  1>~/stdout.txt 2>~/stderr.txt
このstderrから、攻撃くらった時刻の周りを抜粋します。なおphpMyAdminのコンテナの時刻は設定ミスでGMT+0000になってます。 06/Dec/2020:17:40:21 は日本時間(GMT+0900)の 07/Dec/2020:02:40:21 です。
127.0.0.1 -  30/Nov/2020:02:17:57 +0000 "GET /index.php" 200
127.0.0.1 -  03/Dec/2020:01:41:17 +0000 "GET /index.php" 200
127.0.0.1 -  03/Dec/2020:05:42:26 +0000 "GET /index.php" 200
127.0.0.1 -  03/Dec/2020:13:35:23 +0000 "GET /index.php" 200
127.0.0.1 -  06/Dec/2020:17:40:21 +0000 "GET /index.php" 200
127.0.0.1 -  06/Dec/2020:17:40:23 +0000 "GET /phpmyadmin.css.php" 200
127.0.0.1 -  06/Dec/2020:17:40:23 +0000 "GET /js/whitelist.php" 200
127.0.0.1 -  06/Dec/2020:17:40:25 +0000 "GET /js/messages.php" 200
127.0.0.1 -  06/Dec/2020:17:40:29 +0000 "POST /ajax.php" 200
127.0.0.1 -  06/Dec/2020:17:40:29 +0000 "POST /navigation.php" 200
127.0.0.1 -  06/Dec/2020:17:40:29 +0000 "POST /ajax.php" 200
127.0.0.1 -  06/Dec/2020:17:40:30 +0000 "POST /ajax.php" 200
127.0.0.1 -  06/Dec/2020:17:40:30 +0000 "POST /version_check.php" 200
127.0.0.1 -  06/Dec/2020:17:41:04 +0000 "GET /db_structure.php" 200
127.0.0.1 -  06/Dec/2020:17:41:05 +0000 "GET /navigation.php" 200
127.0.0.1 -  06/Dec/2020:17:41:08 +0000 "GET /sql.php" 200
127.0.0.1 -  06/Dec/2020:17:41:08 +0000 "GET /index.php" 200
127.0.0.1 -  06/Dec/2020:17:41:18 +0000 "GET /sql.php" 200
127.0.0.1 -  06/Dec/2020:17:41:19 +0000 "GET /index.php" 200
127.0.0.1 -  06/Dec/2020:17:41:38 +0000 "GET /db_structure.php" 200
127.0.0.1 -  06/Dec/2020:17:41:39 +0000 "GET /index.php" 200
127.0.0.1 -  06/Dec/2020:17:41:39 +0000 "POST /version_check.php" 200
127.0.0.1 -  06/Dec/2020:17:41:39 +0000 "GET /server_databases.php" 200
127.0.0.1 -  06/Dec/2020:17:41:43 +0000 "POST /server_databases.php" 200
127.0.0.1 -  06/Dec/2020:17:41:44 +0000 "GET /server_databases.php" 200
127.0.0.1 -  06/Dec/2020:17:41:45 +0000 "POST /navigation.php" 200
127.0.0.1 -  07/Dec/2020:00:25:13 +0000 "GET /index.php" 200
このあたりで攻撃くらってるんだな〜ってログです。リクエストの内容が残ってないので本当にCVE-2019-11768を利用したSQLインジェクションだったかはわかりません…。 ちなみに WordPressコンテナのログをみると、正確な障害発生時刻がわかります。
192.168.176.9 - - [06/Dec/2020:17:41:25 +0000] "GET /wp-content/uploads/2018/01/cropped-IMG_0198-192x192.jpg HTTP/1.1" 200 9491 "https://taiyakon.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0"
192.168.176.9 - - [06/Dec/2020:17:41:25 +0000] "GET /wp-content/uploads/2018/01/cropped-IMG_0198-32x32.jpg HTTP/1.1" 200 1382 "https://taiyakon.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0"
127.0.0.1 - - [06/Dec/2020:17:41:25 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.25 (Debian) PHP/7.2.15 (internal dummy connection)"
192.168.176.9 - - [06/Dec/2020:17:41:27 +0000] "GET /sitemap-pt-post-2020-08.xml HTTP/1.1" 200 763 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
192.168.176.9 - - [06/Dec/2020:17:42:16 +0000] "HEAD /feed HTTP/1.1" 500 285 "-" "Slackbot 1.0 (+https://api.slack.com/robots)"
192.168.176.9 - - [06/Dec/2020:17:42:17 +0000] "GET /feed HTTP/1.1" 500 2953 "-" "Slackbot 1.0 (+https://api.slack.com/robots)"
192.168.176.9 - - [06/Dec/2020:17:42:34 +0000] "GET /2016/02/day6in.html HTTP/1.1" 500 2953 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
192.168.176.9 - - [06/Dec/2020:17:43:36 +0000] "GET /2018/11/lightroomnas.html HTTP/1.1" 500 2953 "-" "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.96 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
192.168.176.9 - - [06/Dec/2020:17:45:13 +0000] "GET /wp-login.php HTTP/1.1" 500 2953 "http://taiyakon.com/wp-login.php" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
192.168.176.9 - - [06/Dec/2020:17:45:51 +0000] "HEAD / HTTP/1.1" 500 285 "-" "jetmon/1.0 (Jetpack Site Uptime Monitor by WordPress.com)"
06/Dec/2020:17:42:16 +0000 つまり日本時間で2020年12月07日 02:42:16 のアクセスからレスポンスコード 500 Internal Server Error を返し始めており、障害発生していることがわかります。(各コンテナ間の時刻の同期は行ってないので、ログ間で微妙にズレてる可能性あり)

原因のまとめ

大きな原因は以下の2つです。これらが無ければ CVE-2019-11768 を利用されSQLインジェクションを受けることはありませんでした。たぶん。
  • phpMyAdminのポートを開けてたこと
  • phpMyAdminのバージョンが古かったこと(利用されたと思われる脆弱性が4.9.0.1以降なら修正済み)

復元

原因がわかったところで、戻しましょう!

バックアップが不完全だった

バックアップは抜かりなくとってあるんだよ〜と確認したら…大事なファイルが抜け落ちてました。 tar.gzに固めて記事書いた後などにバックアップを取ってるんですが、必要なファイルが一部含まれていませんでした。固めるときに sudo をつけ忘れたせいで、権限の関係で一部のファイルが入っていなかったのです。 原因はバックアップを手動でやってること、またちゃんと戻せるか最近確かめてなかったことです。 記事の更新頻度が高く無いサイトなので手動バックアップで間に合っちゃうので手を抜いてました。 完全なバックアップが取ってあるのは、2020年6月ごろが最後でした。それ以降の記事は失われてしまいます。

extundelete でファイル復活を試みる → 失敗

それならとファイル復活を試みます。結論からいって失敗しました。

VPS上で extundelete を試す→失敗

extundeleteという失われたファイル復活ツールがあります。ファイルの情報をジャーナルログから読んで、ファイルのあった場所を読みだしてくれるらしいです。 マウントして使用中のパーティションには使うなと警告がでますが、他に道が無いので使ってみました。しかし… Segmentation fault で失敗。
$ sudo extundelete   --after 1607180400 --before 1607353200 --restore-directory 

/home/ubuntu/docker/docker-for-wordpress/ /dev/sda1
[sudo] password for ubuntu: 
Only show and process deleted entries if they are deleted on or after 1607180400 and before 1607353200.
NOTICE: Extended attributes are not restored.
WARNING: EXT3_FEATURE_INCOMPAT_RECOVER is set.
The partition should be unmounted to undelete any files without further data loss.
If the partition is not currently mounted, this message indicates 
it was improperly unmounted, and you should run fsck before continuing.
If you decide to continue, extundelete may overwrite some of the deleted
files and make recovering those files impossible.  You should unmount the
file system and check it with fsck before using extundelete.
Would you like to continue? (y/n) 

y                                                                                                                                                        
Loading filesystem metadata ... 160 groups loaded.                                                                                                        
Loading journal descriptors ... Segmentation fault    
どうやら e2fsprogs というライブラリ/パッケージとのバージョンの不整合らしいです。e2fsprogs-1.42.12-2-x86_64 以前でないと動かないそうな。
The segmentation fault comes from the e2fsprogs library/package being too recent. From downgrading e2fsprogs I have found that the most recent version that extundelete works with is e2fsprogs-1.42.12-2-x86_64. Once you upgrade to e2fsprogs-1.42.13-1-x86_64, extundelete will no longer work.

https://bugs.archlinux.org/task/56585#comment168229

古いUbuntuで試す→失敗

必要なバージョンの e2fsprogs が入ってるのは Ubuntu14.04LTSです。16.04LTSはこれより新しいバージョンの e2fsprogsが入っており、また簡単に apt でダウングレードできそうにありませんでした。 以下は Ubuntu14.04LTSの e2fsprogs です。
$ sudo dpkg -l  | grep e2fs
[sudo] password for user1: 
ii  e2fslibs:amd64                                        1.42.9-3ubuntu1                                     amd64        ext2/ext3/ext4 file system libraries
ii  e2fsprogs                                             1.42.9-3ubuntu1                                     amd64        ext2/ext3/ext4 file system utilities
ii  libuuid-perl                                          0.05-1  
VPSのパーティションイメージをダンプし、手元の古いUbuntu環境で extundelete を使い復元を試みます。 今回は、仕方なく動いてる状態のパーティションをイメージダンプしました。 マウントした状態でイメージダンプするとちゃんと取れないことがあるので、本来なら目的のパーティションをアンマウントすべきです。しかし今回はOSが入ってるパーティションなためアンマウントできません。そういう時はUSBやCDから起動した別なLinuxでダンプしたりしますが、今回使用してるVPSではできません。 そして使ってるVPSのサービスにイメージダンプの機能はなく、またシングルユーザモードも使えないっぽいです。 イメージダンプを取るにはまず、VPS上でvisudoで Defaults visiblepw を追加し、ssh で sudo ができるようにします。 これをしないと、エコーの制御ができない場合はsudoは実行を拒否するそうです。 以下のようなコマンドをローカルマシンで打ち、パーティションイメージを保存します。
 ssh vps1 "sudo dd if=/dev/sda1 | gzip -1 -" | gdd of=vps_partision_image_2020_12_08.gz status=progress
あとはパーティションイメージに extundelete を使うだけです。 しかし失敗しました。 そもそもパーティションイメージがちゃんと取れて無い感じです。ちゃんとアンマウントせず動かしてる状態で取ったからか、それとも操作が間違ってたか。 Ubuntu14.04LTSだとマウントしようとすると以下の表示。
$ sudo mount -o loop,offset=$((512*2048)) vps_image_2020_12_08-17_00 /mnt
mount: wrong fs type, bad option, bad superblock on /dev/loop0,
       missing codepage or helper program, or other error
       In some cases useful info is found in syslog - try
       dmesg | tail  or so
dmesgでは JBD2: Unrecognised features on journal なんてエラーが出てます。 古いせい?
$ dmesg | tail
[  583.115383] FAT-fs (loop0): bogus number of reserved sectors
[  583.115386] FAT-fs (loop0): Can't find a valid FAT filesystem
[  642.798193] JBD2: Unrecognised features on journal
[  642.798196] EXT4-fs (loop0): error loading journal
VPSのOSと同じUbuntu18.04LTSでも試してみます。マウントできません。
$ sudo mount -o loop vps_image_2020_12_08-partition-sda1 /mnt
mount: /mnt: /dev/loop7 のスーパーブロックを読み込むことができません.
ファイルシステムのチェックをします。なんか間違ってたみたいですが、相変わらずマウントできません。
$ e2fsck -f ./vps_image_2020_12_08-partition-sda1
e2fsck 1.44.1 (24-Mar-2018)
./vps_image_2020_12_08-partition-sda1: recovering journal
Clearing orphaned iノード 682258 (uid=0, gid=0, mode=0100600, size=0)
Clearing orphaned iノード 672989 (uid=0, gid=0, mode=0100600, size=0)
Clearing orphaned iノード 672925 (uid=0, gid=0, mode=0100600, size=0)
Pass 1: Checking iノードs, blocks, and sizes
Pass 2: Checking ディレクトリ structure
Pass 3: Checking ディレクトリ connectivity
Pass 4: Checking reference counts
Pass 5: Checking グループ summary information
Free blocks count wrong (423471, counted=423225).
修正<y>? yes
Free iノードs count wrong (994281, counted=994251).
修正<y>? yes

./vps_image_2020_12_08-partition-sda1: ***** ファイルシステムは変更されました *****
./vps_image_2020_12_08-partition-sda1: 316469/1310720 files (0.2% non-contiguous), 4819143/5242368 blocks
ということでファイルの復活は諦めました。

ネット上のキャッシュやアーカイブから復元する

最終的に取ったのはこの方法です。2020年6月までは完全なバックアップが手元にあるので、それ以降の記事はネット上のキャッシュやアーカイブから見つけてきて、手作業で戻すという方法です。 キャッシュはGoogleのキャッシュ、アーカイブはInternetArchiveで事足りました。 文章はコピペし、画像は現在のVPSサーバの wp-content/uploads から探します。消されたのはDBであって画像は残っていますからね。 大変面倒くさかったですが、これで無事復活させることができました。もちろん認証情報は復元後に変更しておきました。

反省

開けるポートは最小限に!!」ですね。 あと「バックアップは取れてないこともあるから時々復元してみろ!」ですかね。 知識としてわかっちゃいるけどどっちも守れてませんでした。

コメント