
Tutor LMSでコース画像が小さくぼやける原因と画像サイズ変更の手順
Tutor LMSのコース一覧でサムネイル画像が小さくぼやける症状は、プラグインが登録した専用画像サイズ(約370×235px)をテンプレートが呼び出し、ブラウザ側で大きな容器に引き伸ばしているのが主な原因だ。子テーマでテンプレートを上書きするか、フィルターフックで画像サイズを変更すれば解決する。
Tutor LMSでコース画像がぼやける仕組みと原因

Tutor LMSはコース一覧ページを表示する際、専用の画像サイズを呼び出す。このサイズはプラグインがサーバー環境に登録したもので、コースカードのレイアウトに合わせて小さい寸法に設定されていることが多い。
問題は、テーマ側のスタイルシートがコースカードをより広い幅で表示しようとする場面だ。画像の実寸(約370×235px)に対して、実際の表示領域がそれを上回ると、ブラウザが画像を無理に拡大する。高解像度の元画像をアップロードしても、プラグインが生成した小さなサムネイルを参照している限り、ぼやけや文字の潰れは解消されない。
また、Tutor LMSのコースループ用テンプレートは標準の post_thumbnail_size フックを無視し、独自のサイズ指定を直接コード内に持っている。そのため、WordPressの標準設定から画像サイズを変更しても、コース一覧に反映されないという構造的な理由がある。
このデモは、Tutor LMSが小さいサムネイルを呼び出してからブラウザが拡大する流れと、修正後に高解像度画像を直接参照する流れを示している。
テンプレート上書きで画像サイズを変更する手順

最も確実な方法は、Tutor LMSのテンプレートファイルを子テーマにコピーし、画像サイズの指定を書き換えることだ。プラグイン本体のファイルを直接編集するとアップデートで上書きされるため、必ず子テーマを使う。
Tutor LMSのテンプレート構造を確認する
Tutor LMSのテンプレートは wp-content/plugins/tutor/templates/ ディレクトリ内に配置されている。コース一覧のカードを構成するテンプレートは、templates/course/loop/ または templates/loop/ 以下のファイル群だ。バージョンによって多少の違いはあるが、コースカードの表示を担当するファイルにサムネイル呼び出しが含まれている。
管理画面の「プラグイン」→「プラグインファイルエディター」からTutor LMSを選択し、templates/ フォルダを展開すると実ファイル名を確認できる。FTPで接続できるなら wp-content/plugins/tutor/templates/ を直接参照する方が速い。
子テーマにテンプレートをコピーする
対象のテンプレートファイルを子テーマ内の tutor/ ディレクトリにコピーする。Tutor LMSは子テーマの tutor/ フォルダを優先的に読み込む仕組みを持っている。コピー先のパスは wp-content/themes/子テーマ名/tutor/ だ。ディレクトリ構造を保ったままコピーする。
画像サイズの指定を変更する
コピーしたテンプレートファイル内の get_the_post_thumbnail() または tutor_course_loop_thumbnail() の呼び出し部分を探す。第二引数に指定されているサイズ名(例 'tutor-course-thumbnail')を 'full' または 'large' に変更する。
// 変更前
get_the_post_thumbnail($course_id, 'tutor-course-thumbnail');
// 変更後
get_the_post_thumbnail($course_id, 'full');テンプレート内に the_post_thumbnail() が直接記述されている場合は、同じくサイズ引数を 'full' に置き換える。
このデモは、テンプレート上書きの4つの手順を順番に示している。
フィルターフックで画像サイズを変更する方法

テンプレートを編集せずに済ませたい場合は、Tutor LMSが提供するフィルターフックを利用する。functions.php に数行追加するだけで、コースループで呼び出される画像サイズを変更できる。
functions.phpにフィルターを追加する
子テーマの functions.php に以下のコードを追加する。tutor_course_thumbnail_size フックは、コースループで使われるサムネイルサイズを差し替えるためのものだ。
add_filter('tutor_course_thumbnail_size', function($size) {
return 'full';
});このコードは、Tutor LMSがコースカードのサムネイルを出力する際に参照するサイズ名を full に上書きする。元画像が十分な解像度でアップロードされていれば、一覧表示でも鮮明になる。
なお、プラグインのバージョンや使用中のテーマによってフック名の実装が異なる場合がある。テンプレート上書きの方が確実に効くため、フィルターで変化が見られない場合はテンプレート上書きに切り替えるのが確実だ。
サムネイル再生成とキャッシュのクリア

画像サイズの指定を変更した後は、既存の画像に対して新しいサイズのサムネイルが生成されていない場合がある。特に full サイズを使う場合は元画像そのものを参照するため再生成は不要だが、large や独自サイズを使う場合は再生成が必要になる。
サムネイル再生成で古いサイズを更新する
「Regenerate Thumbnails」などの再生成プラグインを使うと、WordPressに登録されている全画像サイズを一括で作り直せる。再生成の所要時間は画像点数に依存するが、数百枚程度なら数分で完了する。
サイトキャッシュとブラウザキャッシュを削除する
変更後に表示が古いままの場合は、キャッシュ系プラグインの全削除と、ブラウザのキャッシュクリアを行う。CDNを利用している場合は、CDN側のキャッシュもパージする。これで新しい画像サイズがサーバーから配信される。
このデモは、画像サイズ変更後に確認すべき作業の流れを示している。
よくある質問
Tutor LMSのコース画像サイズはどこで登録されているのか?
Tutor LMSはプラグインのコード内で add_image_size() 関数を使って専用サイズを登録している。登録名は tutor-course-thumbnail などで、コースループ用テンプレートがこのサイズを参照する。標準のWordPress設定画面からは変更できない。
子テーマを作っていない場合はどうすればよいか?
まず子テーマを作成する。WordPress公式ドキュメントに従い、style.css と functions.php を含むフォルダを作成すればよい。親テーマを直接編集するとアップデートで変更が消えるため、子テーマ運用が安全だ。
画像を変更しても古いサイズのまま表示されるのはなぜか?
ブラウザキャッシュやサイトキャッシュが古い画像を保持している可能性が高い。キャッシュ系プラグインの全削除と、ブラウザのキャッシュクリアを行う。CDNを使っているならCDN側のパージも必要だ。
フィルターフックが効かない場合はどうする?
プラグインのバージョンやテーマの構造によって、特定のフックが実装されていない場合がある。その場合はテンプレート上書き方式に切り替える。テンプレートファイル内のサイズ指定を直接書き換えれば、フックの有無に関係なく確実に反映される。
CSSだけで画像を鮮明にできるか?
できない。CSSで image-rendering プロパティを調整しても、元の画像データが小さい限り拡大によるぼやけは残る。根本的な解決には、テンプレートやフィルターで大きなサイズの画像を呼び出す必要がある。
この記事のポイント
- Tutor LMSのコース画像ぼやけは小さい専用サイズの参照が原因
- 子テーマへのテンプレート上書きで確実に修正できる
- フィルターフックでもサイズ変更が可能
- サイズ変更後は再生成とキャッシュ削除が必須
- CSSだけでは根本解決にならない

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

Yoast SEOとLearnDashの競合でコースが表示されないときの解決策
LearnDash 5.1.8 と Yoast SEO を同じサイトで動かすと、コースやレッスンの本文領域が空白になり、マークアップも生成されなくなる問題は、Yoast SEO の解析エンジンが LearnDash のコンテンツ出力に干渉しているのが原因だ。Yoast SEO 側の設定で特定の投稿タイプの解析を無効化するか、LearnDash を最新バージョンに更新すれば回避できる。
なぜ Yoast SEO と LearnDash で本文が消えるのか

この不具合は、両プラグインが吐き出す HTML の構造やフックの衝突に起因する。Yoast SEO はコンテンツ解析のために内部で出力バッファを操作し、記事本文の前後に独自の HTML コメントや隠し div を挿入する。一方 LearnDash はコースやレッスンを表示する際に、独自のテンプレート階層とコンテンツフィルターを使って本文を組み立てる。この組み合わせで、Yoast SEO の解析プロセスが LearnDash のメインコンテンツ領域のレンダリングを途中で止めてしまい、結果的に空の div だけが出力される状態になる。
多くのケースでは、PHP のエラーログにもブラウザのコンソールにもエラーは出力されない。この「痕跡のない空白」がトラブルシューティングを難しくしている。問題が表面化するのは、LearnDash が 5.1.8 にアップデートされ、かつ Yoast SEO がバージョン 21 系や 22 系など新しいエンジンを搭載した組み合わせだ。同様の競合は LearnDash のサポートフォーラムでも複数報告されており、開発チームも認識している。
上図は典型的な症状の遷移を表している。次項から実際の修正手順を説明する。
設定変更で競合を解消する 3 つの手順

手順の詳細は以下のとおりだ。この操作に FTP やコード編集は不要で、管理画面の中だけで完結する。
Yoast SEO の検索アピアランスを開く
WordPress 管理画面の左メニューから「Yoast SEO」→「検索アピアランス」へ進む。ここでサイト全体の表示設定と、カスタム投稿タイプごとの解析可否を管理できる。
コンテンツタイプタブで LearnDash 項目を無効化する
「検索アピアランス」画面の上部には「一般」「コンテンツタイプ」「メディア」「タクソノミー」「アーカイブ」などのタブが並んでいる。「コンテンツタイプ」をクリックすると、登録されているすべての投稿タイプが一覧表示される。ここで LearnDash に該当する Courses(sfwd-courses)、Lessons(sfwd-lessons)、Topics(sfwd-topic)、Quizzes(sfwd-quiz) などの項目を探す。各項目の右側にある「Yoast SEO の分析を有効にする」スイッチをすべてオフにする。また、すぐ下の「読みやすさの分析を有効にする」も同様にオフにする。
設定を保存してキャッシュをクリアする
画面下部の「変更を保存」ボタンをクリックする。保存後、サイトキャッシュやサーバーキャッシュを利用している場合は、念のため全キャッシュを削除する。管理画面から再度 LearnDash のコースページにアクセスし、本文が正しく表示されるようになっていれば完了だ。
LearnDash のバージョンアップで根本解決を図る

上記の設定変更は対症療法であり、Yoast SEO の解析機能を一部犠牲にする方法だ。根本的には、LearnDash 側で Yoast SEO との互換性を高めたバージョンがリリースされるのを待ち、アップデートするのが望ましい。実際、LearnDash 5.1.8 のリリース後に同様の競合が複数報告されており、開発チームが修正パッチを準備している可能性が高い。
LearnDash の最新バージョンを確認する
WordPress 管理画面の「ダッシュボード」→「更新」、あるいは「プラグイン」→「インストール済みプラグイン」で LearnDash に更新通知が出ていないかチェックする。5.1.9 以降のバージョンが利用可能であれば、適用してから Yoast SEO の解析を再度有効に戻してみるとよい。なお、更新前に必ずサイト全体のバックアップを取ることは大前提だ。
それでも改善しない場合の追加チェック
まれに、Yoast SEO の「カスタム投稿タイプごとの noindex 設定」が一部影響しているケースもある。先ほどの「検索アピアランス」→「コンテンツタイプ」で、LearnDash の投稿タイプを「検索エンジンに表示する(index)」に設定し直すと、内部のフラグがリセットされて競合が解消したという報告もある。設定をいったんデフォルトに戻してから再度解析をオフにする、という手順を試してみる価値はある。
よくある質問
Yoast SEO を無効化せずに済ませたいが他に方法はあるか
Yoast SEO 全体を無効化するより、上記のとおり LearnDash の投稿タイプだけ解析をオフにする方法が最も手軽で影響が小さい。コースやレッスンの SEO タイトルやメタディスクリプションは Yoast SEO の「検索アピアランス」とは別の編集画面から入力できるため、最低限の SEO 対策は維持できる。
LearnDash 以外の LMS プラグインでも同じことが起きるのか
LifterLMS や LearnPress など他の LMS でも、Yoast SEO の解析がカスタム投稿タイプのテンプレートと干渉する事例は報告されている。いずれも Yoast SEO のコンテンツタイプ設定から解析をオフにすることで対処可能だ。
コンソールやログに何も出ないのはなぜか
PHP の致命的エラーが発生しているわけではなく、Yoast SEO が出力バッファ内でコンテンツの一部を誤ってカットしているだけだからだ。そのため WordPress のエラーログやブラウザの開発者ツールにも痕跡が残らない。
設定を変えても直らない場合はどうすればよいか
テーマや他のプラグインとの三重競合も考えられる。一度すべてのプラグインを停止し、標準テーマ(Twenty Twenty-Five など)に切り替えて LearnDash と Yoast SEO だけを有効にして再現するか確認する。原因を特定したら、該当プラグインのサポートに問い合わせるか、LearnDash のバージョンダウンを検討する。
LearnDash をダウングレードするのは安全か
緊急避難として 5.1.7 以前に戻す方法もあるが、セキュリティや機能面で後退するリスクを伴う。どうしても表示をすぐに復旧させたい場合に限り、バックアップを取ったうえで実施する。長期運用には上記の設定変更と最新版へのアップデート待ちを推奨する。
この記事のポイント
- LearnDash 5.1.8 と Yoast SEO の組み合わせでコース本文が空白になる不具合は、Yoast SEO の解析エンジンが原因
- 管理画面の「Yoast SEO」→「検索アピアランス」→「コンテンツタイプ」で LearnDash の投稿タイプの解析をオフにすれば即座に解消
- PHP ログやコンソールにエラーが出ないため、見落としやすい
- 根本対応は LearnDash の最新バージョンへのアップデートだが、緊急時は上記の設定変更でしのぐ
- 他の LMS プラグインでも同様の競合が起きる可能性があるので、同じ手順で対処可能

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

KnowledgeDeliver脆弱性、ViewState攻撃の実態と対策まとめ
国内の教育機関や企業研修で広く使われるLMS(学習管理システム)のKnowledgeDeliverに、深刻な脆弱性が見つかった。サーバーに保存された共通の暗号鍵を悪用され、遠隔から不正なコードを実行される恐れがある。
Google Cloudの脅威インテリジェンスチームであるMandiantは、2025年後半に実際の攻撃を確認した。攻撃者はこの脆弱性を足がかりにWebシェルを設置し、サイト訪問者のPCにバックドアを感染させる手口を使っていた。本記事では、この脆弱性の仕組みと攻撃の流れ、具体的な検知方法と対策を整理する。
KnowledgeDeliverが見舞われた脆弱性の正体

共有されたマシンキーが招く全インストール共通の弱点
問題の発端は、ASP.NETアプリケーションの設定ファイル web.config に書き込まれた machineKey の値だ。このキーは、画面の状態情報を保持するViewStateデータの暗号化と署名に使われる。
本来、このキーはサーバーごとに個別のランダムな値を生成すべきものだ。しかし、2026年2月24日より前に配布されたKnowledgeDeliverのパッケージでは、開発元が用意したテンプレートの中に固定のキーが埋め込まれていた。その結果、別々の組織で稼働するすべてのインスタンスが、まったく同じマシンキーを共有する状態になった。
これは、すべての家の玄関に同じ鍵が付いているようなものだ。攻撃者が一つの鍵束を入手すれば、インターネット上に公開された他のすべてのKnowledgeDeliverサーバーに侵入できることを意味する。
ViewState Deserializationが悪用される仕組み
ASP.NETのViewStateは、ページの往復(ポストバック)の間、ユーザーが入力した値や画面の状態を維持するための仕組みだ。ブラウザとサーバーの間で、暗号化された文字列としてやり取りされる。
machineKey を知る攻撃者は、このViewStateの中に悪意あるコードを含んだ特殊なデータ(ペイロード)を埋め込める。サーバーは受け取ったViewStateを復号し、データをオブジェクトに戻す処理(デシリアライゼーション)を実行する。この過程で、埋め込まれたコードがサーバー上で実行されてしまう。
この手法は、以前にMandiantが報告したSitecoreのViewStateゼロデイ脆弱性や、Microsoftが警告したASP.NETマシンキーの悪用事例と同種のものだ。共通鍵を使う設計の危険性を、あらためて浮き彫りにしている。
攻撃者は侵入後に何をしたのか

メモリ内で動作するWebシェル「BLUEBEAM」の投入
Mandiantの調査によれば、攻撃者はまず.NETベースのWebシェル「BLUEBEAM」を展開した。このツールはGodzillaとも呼ばれ、Microsoftも以前に同種の活動を報告している。
BLUEBEAMの特徴は、ファイルとしてディスクに保存されず、IISのワーカープロセス(w3wp.exe)のメモリ空間上だけで動作する点だ。一般的なウイルス対策ソフトによるファイルスキャンをすり抜け、HTTP POSTリクエストのボディに暗号化したコマンドを忍ばせて、遠隔操作を受け付ける。
ファイル改ざんとCobalt Strikeによる端末感染
Webシェルを確保した攻撃者は、サーバー上のファイル権限を変更し、アプリケーションのJavaScriptファイルに細工を加えた。具体的には、次のような改ざんが確認されている。
- 「セキュリティ認証プラグイン」のインストールを促す偽の警告を表示するスクリプトの追加
- 攻撃者が管理する外部ドメインから、不正なスクリプトをひそかに読み込むコードの埋め込み
この偽警告に従って「プラグイン」をダウンロードしたユーザーのPCには、Cobalt StrikeのBEACONバックドアが仕込まれた。ペイロードの暗号化には、標的組織の名称が使われており、攻撃者が特定の組織を狙って準備を進めていたことがわかる。
侵害をいち早く検知するための調査ポイント

イベントログとプロセスの異常を監視する
ViewStateの悪用を試みた痕跡は、Windowsのアプリケーションログに記録される。ソースが ASP.NET 4.0.30319.0 で、イベントID 1316のメッセージに注目する。
- 整合性チェック失敗時は「
Viewstate verification failed. Reason: The viewstate supplied failed integrity check.」と出る。誤った鍵が使われた可能性がある。 - 整合性チェックを通過したものの、ペイロードが無効だった場合は「
Viewstate verification failed. Reason: Viewstate was invalid.」と記録される。この場合、復号は成功しており、コード実行までは至らずとも攻撃の試行があったとみなせる。
Mandiantは、実際にこのログからBLUEBEAMに関連するペイロード文字列を復元できたとしている。
また w3wp.exe を親プロセスとする不自然な子プロセスにも警戒が必要だ。cmd.exe /c ... whoami powershell.exe といったコマンドが実行されていないか、継続的にモニタリングする。
ファイルの改ざんと異常なUser-Agentをつかむ
Webサーバーの公開ディレクトリ内にある .js .aspx .config ファイルについて、想定外の変更が加えられていないか定期的に確認する。特に、外部ドメインへのスクリプト読み込みや、業務と無関係なコードの追加がないかを重点的に調べる。
さらに、Webサーバーのアクセスログに現れるUser-Agent文字列にも特徴がある。Mandiantの調査では、2つの異なるブラウザ識別子が連結された異常な文字列が確認された。以下はその一例だ。
Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.2 (KHTML, like Gecko) Chrome/22.0.1216.0 Safari/537.2 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36このような連結されたUser-Agentは、通常のブラウザでは生成されない。攻撃ツールによる通信の痕跡として、ログ監視の有効な指標になる。
再発を防ぐための具体的な対策

この脆弱性の根本原因は、全インストールで鍵を共有していたことにある。したがって、最も重要な対策は、マシンキーを一意の値に切り替えることだ。
- マシンキーの再生成:各KnowledgeDeliverインスタンスで、暗号的に安全なランダム値を生成し、設定ファイルに反映する。共通鍵を無効化するには、これ以外の方法はない。
- アクセス制限の見直し:LMSがインターネット全体に公開されている必要がなければ、社内ネットワークや特定のIPアドレス範囲からのみ接続を許可する。
- 徹底的なインシデント調査:ログ監視やファイル整合性チェックを実施し、少しでも疑わしい兆候があれば、外部の専門家も交えて深く調査する。
Vupointブログの分析でも指摘されているとおり、テンプレートに埋め込まれた共通シークレットは、一見すると設定の手間を省く便利な仕組みに見える。しかし、ひとたび鍵が流出すれば、世界中のすべてのサーバーが一瞬で危険にさらされる。利便性と引き換えに、きわめて大きなリスクを抱え込む設計だったわけだ。
今回の事例は、ASP.NETに限らず、あらゆるWebアプリケーションの展開時において「鍵や認証情報は必ず環境ごとにユニークに生成する」という原則を再認識させるものだ。テンプレートや初期設定のまま本番運用に臨むことの危うさを、開発者と運用者の双方が改めて肝に銘じる必要がある。
この記事のポイント
- KnowledgeDeliverの全インストール共通のASP.NETマシンキーが、ViewState Deserialization攻撃の原因になった
- 攻撃者はメモリ内WebシェルBLUEBEAMを使い、サイト改ざんとCobalt Strike感染を連鎖させた
- イベントログやプロセス監視、異常なUser-Agentの検出が有効な調査指標になる
- 最も重要な対策は、各サーバーでユニークなマシンキーを生成し、共通鍵の状態を完全に解消すること

・ 複数業界における17年間のデジタルビジネス開発経験
・ ウェブサイト開発のためのHTML、PHP、CSS、JavaScript等の実用的知識
・ 15ヶ国語対応の多言語SaaSの開発経験
・ 17年間にも及ぶ、Eコマース長期運営経験
・ 幅広い業界でのSEO最適化の豊富な経験
