巷では、少し前からアフィブログを WordPress で作るのが流行っているようですが、主に PHP 開発者&サーバー管理者の観点から、WordPress のダメだと思うところを、思うままに書いてみました。
WordPress をディスるつもりはありませんので、注意喚起:解決法:ポエム = 4:1:5 ぐらいの感覚でご覧いただければ幸いです。
1.設計が古すぎる
先日書いた記事で、気になって admin-ajax.php
のコードを眺めてみましたが、Oh... これは酷い…。
require_once
が連呼され、global 空間に define()
とコンフィグ用の配列が入り乱れ、$_GET
$_POST
$_REQUEST
が舞い踊り、ファイルはクラスどころか関数にすらなっていない…200 行に満たないコードはネタの宝庫で、15 年程前?の PHP4 時代までタイムスリップした感覚になれます。
WordPress は、つい最近まで PHP5.2.4(2007年8月30日リリース!) というとんでもなく古い PHP をサポートし続けてきた事からも分かる通り、ポリシーとして後方互換性をとても大切にしてきました。1
WordPress が世界一のシェアを誇るまでに成長したのは、このポリシーによるところも大きいと思います。
しかし、古い PHP では、namespace
やクロージャも使えなければ、型を強制する事もできません。2
PHP は、他の言語の良いところも積極的に取り入れながらどんどん進化しているのに、これはとても悲しい事です。
1-1.型キャストの多用
WordPress では、型キャストが多用されています。
例えば、ソースコード全体を (int)
で検索すると、1,500 箇所以上見つかります。
var_dump((int) 'a');
上記の結果は、int(0)
になりますが、このような挙動は人間にとってあまり直感的ではなく、安易に使用するとバグや脆弱性の温床となります。
WordPress が型キャストを多用しているのは、PHP4 時代を彷彿をさせる古い設計や、型の強制ができない古い環境を想定しているなど、色々な事情があるのだとは思います。
しかし、以下のような致命的な脆弱性3は、もっとモダンな設計なら、きっと発生しなかったと思います。
1-2.オートローディングの仕組みがない
WordPress では、依存関係にあるものをオートロードする仕組みが、本体に備わっていません。
例えば、デザイナさんが、プラグインやテーマを新規にインストールした後、サーバーのログへ undefined XXX...
(XXX が定義されてませんよ)というエラーが記録される事が時々あります。
これは、プラグインやテーマ作者の想定外の条件において、読み込まれていると思っているファイルが読まれていないといった理由によるものです。
しかし、PHP には 15 年近く前から、特定のルールを定めれば、必要になった時だけ必要なクラス(を定義したファイル)を自動的に読み込んでくれる、超素敵な機能が備わっていました。
//-- PHP5初期の頃の書き方
function __autoload($class)
{
$path = dirname(__FILE__) . '/' . strtolower($class) . '.class.php';
if (is_file($path)) { require $path; }
}
//-- ↑の書き方では、定義の追加や優先順位付けができないため、
//-- しばらく後、↓のように書けるようになりました。
spl_autoload_register(
function ($class) {
$path = __DIR__ . '/' . strtolower($class) . '.class.php';
if (is_file($path)) { require $path; }
}
);
Composer 導入環境でいちいち require
などを書かなくても良いのは、この仕組みのお陰ですが、これ自体は Composer の登場よりも遥か昔から使えていたわけです。4
しかし、WordPress は、それよりも更に昔の PHP4 時代からの遺産を引きずった(であろう)設計となっているため、設計をゼロから見直さない限り、WordPress 本体がこの仕組みを完全サポートするのは、まず無理だと思われます。
面倒な依存関係はバグの温床になりますし、把握するには学習コストもかかります。
1-3.テンプレートエンジンを使っていない
WordPress のテーマは、このようなコードで書かれています。
<html <?php language_attributes(); ?>>
<meta charset="<?php bloginfo( 'charset' ); ?>" >
<?php if ( is_front_page() ) { ?>
<h1 class="descr">
<?php bloginfo( 'description' ); ?>
</h1>
<?php } else { ?>
PHP のテンプレート言語としての性質をそのまま利用しているわけですが、可読性が落ちたり脆弱性が発生する原因となっています。5
テンプレートエンジンを使う事には、デザイナさんとの協業を楽にするという事以外に、セキュリティ面で楽ができるという側面もあります。
テンプレートエンジンを使えば、{{ $hoge }}
とするだけで、頭空っぽでもよしなにしてくれる事を、少しでも考えなければいけないのは、とても面倒です。6
テンプレートエンジンを使っていれば容易に防げるであろう、「今更嘘でしょ!?」と言いたくなるような低レベルな XSS も、度々報告されています。
頭の良い人達が生み出した素敵な仕組みを通せば、楽をしながらセキュアなシステムを効率良く作れる…それが理想ですが、残念ながら WordPress はそうではないため、プラグインやテーマで、脆弱性が生まれる要因になっていると思います。
1-4.後方互換は難しい問題
私は Firefox ユーザーでしたが、「Tab Mix Plus」が使えなくなった辺りで見切りを付け、今では Chromium ブラウザを使っています。
私と同じような方も少なくないと思います。実際、Firefox のシェアは、プラグインの仕様が変わった頃を機に、どんどん落ちていきました。
WordPress が人気な理由の 1 つが、豊富なプラグインやテーマの存在です。安易に後方互換を捨てれば、きっと Firefox の二の舞になるでしょう。
また、古い Windows OS がいつまでも使われているのと同じように、古い PHP 環境もまだまだたくさん残っています。多くの初心者が、そういった環境で WordPress を動かしています。
そこをどう切り捨てていくかは非常に難しい問題で、あの Microsoft ですら、OS のバージョンアップを無料にしても思うようにいかなかった事を、ボランティアの有志で成り立っている CMS に求めすぎるのは、酷な話だとも思います。
2.プラグインやテーマがフリーダム
WordPress 本体が、つい最近まで PHP5.2.4 をサポートしていたのは書いた通りですが、プラグインやテーマの中には、古いバージョンをサポートしていないものも多くあります。
逆に、WooCommerce のような著名なプラグインでも、PHP7.2 以降の新しいバージョンでの動作保証が遅れたりしています。(WordPress 本体は PHP7.3 を推奨しています。)
ところが、サポートしないバージョンで動作させた際の処理に、明確な基準が無いようで7、実装方法がフリーダムなため、WordPress 本体は動くのにプラグインやテーマは動かない…最悪、本体まで巻き込んで動かなくなる…といった事が、しばしば発生します。
知識のある方であれば、ログを見ればすぐに原因は分かるでしょう。
しかし、初心者の方では、「真っ白な画面になって意味不明」「動かないから仕方ない」と、脆弱性を含んだ古いバージョンの本体・プラグイン・テーマを使い続けてしまう事にもなると思います。
2-1.Nginx を考慮してない Apache 前提のものは要注意
WordPress のプラグインには、Apache 環境で動かす事を前提として作られているものも、多くあります。
特に、.htaccess
を使って、何らかの制御や、大事な設定ファイルのアクセス制限などをしているプラグインには、注意が必要です。
Nginx では .htaccess
は使えませんので、プラグイン作者が想定していない問題が発生する場合もあります。
2-2.両立は難しい問題
PHP が書ければ、何かに縛られずに自由に機能拡張できるという点は、大きなメリットでもあります。
第三者の機能拡張に対し、自由さと堅牢さとを両立するのは、とても難しい話で、ウェブブラウザのアドオン開発現場などでも、よく議論される事です。
3.全てのファイルが公開ディレクトリに置かれる
例えば、wp-config.php
は、DB 接続するための情報なども書かれた、重要な「設定ファイル」です。
何かを出力したり、外部からのリクエストをトリガーにして何かを処理したりするファイルではありませんので、ウェブブラウザからアクセスできる必要はありません。
サーバー管理者であれば、このようなファイルが公開ディレクトリに置かれる事には、強い違和感を覚えると思います。
WordPress では、ウェブブラウザから直接アクセスして欲しくない PHP ファイルに…
if (!defined('ABSPATH')) {
exit;
}
…と書くのが一種のお作法となっているようですが、そのようなファイルは、公開ディレクトリに置かないのが理想です。
WordPress は、zip ファイルをダウンロード ⇒ 解凍して FTP でアップロードのような、昔ながらの(初心者でも扱いやすい)使い方を想定しているため、今のようなファイル構成になっているのは、仕方のない事だとは思います。
ただ、誰でも簡単にファイル構成を変更できるような作りにはなっておらず、多くの人がデフォルトの構成のまま、全てのファイルを公開ディレクトリに置いているのですから、悪意のある者からすればヨダレの出る環境です。
3-1.弊害の例-1
例えば、プラグインによっては、独自に何らかの設定ファイルを作る場合があります。
http://○○○/wp-content/plugins/△△△/config.ini
このファイルも、公開ディレクトリ内にありますので、ウェブブラウザなどから config.ini
にアクセスされ、中に書かれた大事な情報を盗まれてしまう危険性はあるわけです。
例えば、akismet のように、自身のディレクトリ内(△△△)を .htaccess
で対処しているものもありますが、そういった対処はプラグインによってまちまちです。
メジャーなプラグインでは、流石にこの例のような事は無いとは思います8 が、何でも公開ディレクトリに置かれるというのは、大きなリスクです。
3-2.弊害の例-2
【WordPress】ハッキング候補をググる(Google Dorks) として別記事にまとめましたので、注意喚起の 1 つとして参考にしていただければ幸いです。
3-3.ファイル構成の基本
ウェブブラウザからアクセスできる必要のないファイルは、非公開ディレクトリへ置くというのが基本です。
例えば、以下のように、全てを公開ディレクトリに置くのではなく…
ServerName example.com
DocumentRoot /path/to/example.com
# example.com(公開) ┬ index.php
# ├ img ┬ 111.jpg
# │ └ 222.png
# └ data ┬ aaa.ini
# └ bbb.log
ブラウザからアクセスできる必要があるものだけを公開ディレクトリに置けば、わざわざ .htaccess
などでアクセス制限したりする必要はありません。
ServerName example.com
DocumentRoot /path/to/example.com/www
# example.com ┬ www(公開) ┬ index.php
# │ └ img ┬ 111.jpg
# │ └ 222.png
# └ _data(非公開) ┬ aaa.ini
# └ bbb.log
4.ユーザーが多い
WordPress は、世界で一番使われている CMS です。
誰でも簡単に使えると謳われる事も多いためか、その中には、セキュリティ意識をほとんど持たない人も数多くいます。
その結果、バージョンアップ放置 ≒ 脆弱性放置 ⇒ サイト改ざん ⇒ 攻撃の踏み台 ⇒ 脆弱性を持つ別の WordPress を改ざん… という負の連鎖も発生しています。
実際、サーバーのログを元に攻撃元を辿ると、改ざん被害を受けた WordPress が踏み台にされている事がよくあります。
酷い時は、同じサーバー内の WordPress で動いているドメイン全てが、改ざんされていたりします。
4-1.例
以下は、私が管理しているサーバーに不正リクエストを送りまくっていた、改ざん被害を受けた WordPress の HTML ソースの一例です。
※コードがウイルス対策ソフトに引っかからないよう、大半を省略したり伏せ字にした上で、一部整形しています。
<!-- eval()がある時点で悪い予感しかしません -->
<head>
<script>eval(String.fromCharCode(○, ○, ○, ...略</script>
<script async src='https://○agle○.x○z/ds.js&'></script>
<script async src='https://○ome○page.com/○○?frm=script&_cid=○'></script>
このサイトは、WordPress 4.5.2 とバージョンアップを放置していた事に加え、深刻な脆弱性が報告されていたプラグインも使用していました。9
いくら不正リクエストを受けても、きちんと対策していれば、サーバーのログが多少汚れる程度で済みます。
しかし、もし WordPress のバージョンアップやプラグインの脆弱性などを放置していたら、不正リクエストを受けた WordPress もまた、改ざん被害にあったりするわけです。
4-2.メリットでもあるが…
ユーザーが多い = 情報も多いという事です。
困った時に少しググればたくさん情報が出てくる事が、メリットとして紹介されている事も多いです。
しかし、PHP 界隈の情報(特に古いもの)はカオスです。
動いた(ように見えた)らOK!という感覚で書かれたであろう、問題のあるコードや、臭いものに蓋をするだけのその場凌ぎの対処法などが、あたかもベストの対応であるかのように紹介され、更にそれがコピペコピペで広まってしまっている事もあります。
情報が多いという事は、必ずしもメリットだけではなく、何が正しくて何が間違っているのか、特に初心者にはその判断が付かないというデメリットも含んでいるという事は、知っておいて欲しいなと思います。とりわけ、古い情報には要注意です。
いち PHPer として、この状況はとても悲しい事です。
私も、初心者向けにコピペで使える簡単なコードを載せる事が多いので、この辺りは重々気をつけようと思います。
5.ソースコードが公開されている
WordPress は、オープンソースで開発されています。
そのコードは、世界中の優れた技術者にも公開されているわけですから、バグは即座に報告され迅速に対応される事が大半です。
これは、非常に大きなメリットであり、今のウェブサービスを支える技術の多くが、オープンソースで開発されています。
しかし、それは同時に悪意のある者でもコードを自由に読めるという事であり、せっかくコードが修正されても、運用者がバージョンアップを怠れば、デメリットの方が大きくなります。
6.世界一攻撃を受けやすい CMS
以上のような理由から、悪意のある者にとっては、WordPress は格好のターゲットだという事になります。
実際、ウイルス対策ソフトが「危険」と警告した URL の HTML ソースを見てみると、大抵は上記 4-1 で紹介したような、改ざん被害にあった WordPress だったりします。
6-1.運用方法を見直そう
メリットと言われている事でも、運用者によっては大きなデメリットになり得えます。
- サーバーの知識はなく、レンタルサーバーしか使えない
- WordPress に特化しているわけではない、一般的なレンタルサーバーを使っている
- セットアップは、zip ファイルをダウンロード ⇒ FTP でアップロードという方法で行った
- バージョンアップは、基本的に WordPress 管理画面から手動
以上全てに当てはまる方は、WordPress を使わない方が良いとまでは言いません。
上手にググれば、チューニングやセキュリティ対策が施された、WordPress 運用に特化したレンタルサービスを提供しているところが、幾つか見つかる筈です。
そういったサービスでは、ウェブブラウザからの簡単な操作だけで、WordPress の問題点を解決する事ができたりもしますので、まずは運用環境から見直す事をオススメします。
また、リスクやデメリットを説明する事なく安易に WordPress を勧めてくる業者にも、注意して欲しいなと思います。
7.重い
WordPress は、とても重い CMS です。
動的にコンテンツを生成するためには当然コストがかかりますが、WordPress は様々な処理をフックできるようになっている事もあり10、プラグインが増えるに連れ、目に見えて重くなる事もあります。
重いという事は、表示速度も遅いという事ですし、過負荷にも弱いという事になります。
7-1.簡単なベンチマーク
Apache がインストールされた環境では、ab
というコマンド(Apache Bench)を使うと、とても手軽に簡易的なベンチマークができます。11
- Apache 2.4.39
- MariaDB 10.3.15
- PHP 7.3.6
- WordPress 5.2.1
某 VPS の最安プランへ、上記の環境をビルドして、なるべく素に近い状態で実験してみました。
WordPress は、最低限のセットアップだけ実行した、「Hello world!」が表示される状態(プラグインやテーマなどはデフォルトのまま)です。
$ /path/to/apache/bin/ab -c 10 -n 100 http://...
#-- yumなどでインストールしたパスの通った環境なら ab だけで使えます
# $ ab -c 10 -n 100 http://...
#-- Window 環境でもコマンドプロンプトから簡単に使えます
# C:\path\to\apache\bin\ab -c 10 -n 100 http://...
7-2.結果
Requests per second
(1 秒間に何リクエスト捌けたか)が分かりやすいと思いますので、そこに絞って、幾つかのサーバーから何度か試した結果から、3 つだけ抜粋しました。
7-2-1.WordPress
Requests per second: 2.90 [#/sec] (mean)
Requests per second: 2.18 [#/sec] (mean)
Requests per second: 1.28 [#/sec] (mean)
7-2-2.素の HTML
WordPress と同じ内容を出力する HTML です。
Requests per second: 489.61 [#/sec] (mean)
Requests per second: 474.17 [#/sec] (mean)
Requests per second: 339.36 [#/sec] (mean)
7-2-3.素の PHP
//-- ↓のようなコードでは、素のHTMLとほぼ同じ結果でした
echo <<<'__HTML__'
WordPressが出力するものと同じHTML
__HTML__;
全く何のチューニングもしていない状態とはいえ、予想していた以上の遅さでした(汗)
7-3.キャッシュを活用しよう
特にブログでは、DB の更新処理(ブログの更新)よりも、DB からデータを読み込んで HTML を生成する処理(ブログの表示)の方が、圧倒的に多いです。
生成された HTML は、ブログの内容が更新されなければ、毎回同じです。
であれば、生成結果をキャッシュして表示する方が、速くなりますよね。逆に、プログラムや DB を通せば、その分だけ遅くなります。特に DB 周りはボトルネックとなりやすいです。12
速度面では、CDN の活用も含め、キャッシュの仕組みを積極的に導入すれば、劇的な効果が得られます。
WordPress デフォルトではそのような仕組みになっていないのが、残念なところです。
7-4.KUSANAGI
様々なチューニングが施された WordPress 実行環境として、KUSANAGI というものもあります。
興味がある方は、導入を検討してみてください。
※以下は、本題からはそれる内容です。
8.甘い儲け話にはご注意を
「WordPress でブログを作れば誰でも簡単に儲かる!」と謳うものがよくあるようですが、アフィリエイトで月に 1 万円稼げる人は、全体の数%未満とも言われています。
儲けるための情報を、わざわざ見ず知らずの赤の他人に教える人はいません。では、何のために情報を公開するのか、よく考えた方が良いと思います。
くれぐれも情報商材などに騙されないよう、ご注意ください。
9.SEO について
WordPress は SEO に強いと言われますが、半分正しく、半分間違っていると思います。
確かに WordPress は、「検索クローラーに対してはこう情報を伝えるのがベター」という部分を、難しい事を考えなくとも、強力にサポートしてくれます。
特に初心者にとって、それが大きなアドバンテージである事は間違いありません。
9-1.特別な事ではない
しかし、それは「テクニカル SEO」と呼ばれる「こういうルールを守ろうね」という部分であって、決して「WordPress にしかできない特別な事」ではありません。
SEO に強い証拠として、Google の Matt Cutts 氏が、WordPress を褒め称えた事を取り上げている古い記事がよくあります。
氏が褒めていたのは、あくまでも、「Google のクローラーにはこういうルールで情報を伝えてね!」というところを、WordPress が忠実に守っていた点です。
SEO に「強い」という表現は、一種の誤解を与える表現だと私は感じます。
専門的な知識を持つ人なら、とっくの昔から当たり前に守っている事ですので、そこは勘違いしてはダメだと思います。
9-2.検索エンジンが何を目指しているか
検索エンジンの使命は、「人間にとって有用な情報を見つけやすくする」事です。そうしなければ、誰も検索エンジンを使ってくれなくなりますので。
ですから、かなり前から「情報の質」や「ページを快適に安全に閲覧できる事」が重視されるようになっているのは、至極当たり前の事です。
検索エンジンのアルゴリズムが多少変化しても、この根源的な部分は変わりません。
WordPress で構築された大した中身もないアフィブログを、見たいと思うでしょうか? 検索エンジンも、人間と同じように判断するよう進化し続けています。
SEO(特にテクニカルな部分)には、一種の宗教のような側面もあると感じます。
SEO と称してかけているその時間やお金は、もっと質の高いコンテンツを提供する事に費やした方が有意義なのではないか、よく考えてみてください。
それは別に、WordPress 以外でもできる事なの「かも」しれません。
-
2019 年 4 月にやっと PHP5.6 が必須要件となりました。 ↩
-
といっても、
namespace
やクロージャが使えるようになってから、既に約 10 年経ってますが。 ↩ -
WordPress 史上最悪の脆弱性とも言われており、150 万以上のサイトが、改ざん被害に遭ったと言われています。 ↩
-
ですから、
require_once
が連呼されているのを見た瞬間に、嫌な予感しかしない PHP 開発者も多いと思います(笑) ↩ -
ロジックとデザインとの分離ができていないコードが多く出回っているのも、そこに拍車をかけていると思います。 ↩
-
今でも「PHP 自体がテンプレートエンジンなのだからテンプレートエンジンは不要だ」という意見はあります。その意見をどう捉えるかは、自分次第だと思います。 ↩
-
実際はあるのに守ってないだけなのかもしれませんが、エラーを例外処理してくれれば「まとも」な方で、致命的エラーで終わるものも多いです。 ↩
-
フラグ(笑) ↩
-
こういう WordPress のあるサーバーでは、WordPress のバージョンやどういうプラグインを使っているかを、第三者でも簡単に調べられる事が多いです。 ↩
-
古い設計の中でそれを実装するための、涙ぐましい努力の跡も垣間見えます。 ↩
-
Windows や Macintosh 環境でも使えます。 ↩
-
その分、チューニングにより大きな効果を得られる箇所でもあります。 ↩