mcpField
T
typo3-security

typo3-security

github.com/dirnbauerセキュリティ3377 回インストール13 週間前に更新
リポジトリ

typo3-security について

TYPO3 v14プロジェクト向けのセキュリティ強化スキルです。設定、ファイルシステム、アカウントアクセス、一般的なWeb脆弱性への対策を、サイトの開発者や管理者に案内します。

主な機能

  1. 01TYPO3 v14のセキュリティ設定案内
  2. 02ホストとファイルアクセスの制限
  3. 03Install Toolとバックエンドアカウントの強化
  4. 04CSP、SQLインジェクション、XSS対策
  5. 05CSRF対策の実践

活用シーン

  1. 01公開前のTYPO3設定の確認
  2. 02Install Toolへのネットワークアクセス制限
  3. 03バックエンドアカウントへのMFA設定
  4. 04拡張機能のクエリとテンプレートの監査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/dirnbauer/webconsulting-skills --skill typo3-security

インストール後、Claude Code で/typo3-securityを入力して読み込まれたか確認します。

同梱ファイルreferences/checklists.mdreferences/v14-notes.md

詳細

TYPO3 のセキュリティ強化

出典:https://github.com/dirnbauer/webconsulting-skills

互換性: TYPO3 v14.x このスキルのすべてのセキュリティ設定は、TYPO3 v14 で動作します。

TYPO3 API を最優先: カスタム実装を作成する前に、常に TYPO3 の組み込み API、コア機能、確立された規約を使用してください。TYPO3 がすでに提供しているものを再発明しないでください。使用する API とメソッドが TYPO3 v14 に存在し、非推奨ではないことを、必ず TYPO3 の公式ドキュメントで確認してください。

1. 重要な設定

config/system/settings.php(TYPO3 v14)
<?php
return [
    'BE' => [
        // Disable debug in production
        'debug' => false,
        
        // Session security (example hardening values — tune for proxies/load balancers)
        'lockIP' => 4,                    // Example: bind backend sessions to the full IPv4 address
        'lockIPv6' => 8,                  // Lock to IPv6 prefix
        'sessionTimeout' => 3600,         // 1 hour session timeout
        'lockSSL' => true,                // Example: require HTTPS for backend requests
        
        // Password policy (TYPO3 v14)
        'passwordHashing' => [
            'className' => \TYPO3\CMS\Core\Crypto\PasswordHashing\Argon2idPasswordHash::class,
            'options' => [],
        ],
    ],
    
    'FE' => [
        'debug' => false,
        'lockIP' => 0,                    // Common for frontend sessions; mobile users / proxies often change IPs
        'sessionTimeout' => 86400,
        // `lockSSL` is BE-only (there is no `FE.lockSSL`) — enforce HTTPS for the frontend at the **web server / proxy** and send **HSTS** (`Strict-Transport-Security: max-age=31536000; includeSubDomains`) for production hosts
        'passwordHashing' => [
            'className' => \TYPO3\CMS\Core\Crypto\PasswordHashing\Argon2idPasswordHash::class,
            'options' => [],
        ],
    ],
    
    'SYS' => [
        // NEVER display errors in production
        'displayErrors' => 0,
        'devIPmask' => '',                // No dev IPs in production
        'errorHandlerErrors' => E_ALL & ~E_NOTICE & ~E_DEPRECATED,
        'exceptionalErrors' => E_ALL & ~E_NOTICE & ~E_WARNING & ~E_DEPRECATED,
        
        // Encryption key (generate unique per installation)
        'encryptionKey' => 'generate-unique-key-per-installation',
        
        // Trusted hosts pattern (CRITICAL) — Core wraps the pattern in `/^...$/`; omit `^` and `$`. Avoid `.*example\\.com` (without `\\.` before `example` — matches `evil-example.com`). Note: `.*\\.example\\.com` requires a subdomain and won't match bare `example.com`.
        'trustedHostsPattern' => '(www\\.)?example\\.com',
        
        // File handling security
        'textfile_ext' => 'txt,html,htm,css,js,tmpl,ts,typoscript,xml,svg',
        'mediafile_ext' => 'gif,jpg,jpeg,png,webp,svg,pdf,mp3,mp4,webm',
        
        // Security feature toggles — names and availability differ by minor release; confirm in Core docs for your exact version
        'features' => [
            'security.backend.enforceReferrer' => true,
            // Frontend CSP toggles (names stable from v12+; confirm in reference for your minor)
            'security.frontend.enforceContentSecurityPolicy' => false,
            'security.frontend.reportContentSecurityPolicy' => false,
        ],
    ],
    
    'LOG' => [
        'writerConfiguration' => [
            \Psr\Log\LogLevel::WARNING => [
                \TYPO3\CMS\Core\Log\Writer\FileWriter::class => [
                    'logFile' => 'var/log/typo3-warning.log',
                ],
            ],
            \Psr\Log\LogLevel::ERROR => [
                \TYPO3\CMS\Core\Log\Writer\FileWriter::class => [
                    'logFile' => 'var/log/typo3-error.log',
                ],
                \TYPO3\CMS\Core\Log\Writer\SyslogWriter::class => [],
            ],
        ],
    ],
];

2. 信頼済みホストパターン

重要: ホストヘッダーインジェクションを防ぐため、必ず trustedHostsPattern を設定してください。

// ❌ DANGEROUS - Allows any host
'trustedHostsPattern' => '.*',

// ✅ SECURE - Explicit host list (Core adds `/^...$/` around the pattern)
'trustedHostsPattern' => '(?:example\\.com|www\\.example\\.com)',

// ✅ SECURE - Regex for subdomains (tie to your registrable domain)
'trustedHostsPattern' => '(.*\\.)?example\\.com',

// Development with DDEV
'trustedHostsPattern' => '(?:(?:.*\\.)?example\\.com|.*\\.ddev\\.site)',

3. ファイルシステムのセキュリティ

fileDenyPattern(アップロード/公開ファイルへのアクセス)

コアの拒否リストは厳格なままにし、リスクを理解している場合にのみ拡張してください。

警告: fileDenyPattern を設定すると、コアのデフォルトパターンが完全に置き換えられます。必ず v14 のデフォルト(\\.(php[3-8]?|phpsh|phtml|pht|phar|shtml|cgi)(\\..*)?$|\\.pl$|^\\.htaccess$)をベースに追加してください。pht、phpsh、shtml、^\.htaccess$ は決して削除しないでください。

// Example: keep Core's v14 default and append extra executable extensions (adjust to your policy)
$GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern'] = '\\.(php[3-8]?|phpsh|phtml|pht|phar|shtml|cgi|sh|bash|py|asp|aspx|jsp)(\\..*)?$|\\.pl$|^\\.htaccess$';
ディレクトリの権限
# Set correct ownership (adjust www-data to your web user)
chown -R www-data:www-data /var/www/html

# Directories: 2775 (group sticky)
find /var/www/html -type d -exec chmod 2775 {} \;

# Files: 664
find /var/www/html -type f -exec chmod 664 {} \;

# Configuration files: more restrictive
chmod 660 config/system/settings.php
chmod 660 config/system/additional.php

# var directory (writable)
chmod -R 2775 var/

# public/fileadmin (writable for uploads)
chmod -R 2775 public/fileadmin/
chmod -R 2775 public/typo3temp/
保護すべき重要なファイル

これらを public/ で公開しないでください。

❌ var/log/
❌ config/
❌ .env
❌ composer.json
❌ composer.lock
❌ .git/
❌ vendor/ (should be outside public)
.htaccess のセキュリティ(Apache)
# public/.htaccess additions

# Block access to hidden files
<FilesMatch "^\.">
    Require all denied
</FilesMatch>

# Block access to sensitive file types
<FilesMatch "\.(sql|sqlite|bak|backup|log|sh)$">
    Require all denied
</FilesMatch>

# Block PHP execution in upload directories
<Directory "fileadmin">
    <FilesMatch "\.php$">
        Require all denied
    </FilesMatch>
</Directory>

# Security headers
<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</IfModule>
Nginx のセキュリティ
# Block hidden files
location ~ /\. {
    deny all;
}

# Block sensitive directories
location ~ ^/(config|var|vendor)/ {
    deny all;
}

# Block PHP in upload directories
location ~ ^/fileadmin/.*\.php$ {
    deny all;
}

# Security headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

4. Install Tool のセキュリティ

Install Tool を無効化する
# Remove enable file after installation
# Composer-based TYPO3 v14: file is in var/transient/
rm var/transient/ENABLE_INSTALL_TOOL
Install Tool のパスワードを保護する

強力なパスワードを生成し、安全に保管してください。

# Generate random password
openssl rand -base64 32

Install Tool または環境固有の config/system/additional.php を使用してハッシュ化済みパスワードを設定してください。プレースホルダーや空文字列をコミットしないでください。

Install Tool の IP 制限

Web サーバーレベルで、Install Tool のエントリーポイント(Composer ベースの v14 では /typo3/install.php)へのアクセスを信頼済み IP に制限してください。

# Apache: in the vhost or .htaccess
<LocationMatch "^/typo3/install\.php">
    Require ip 203.0.113.0/24
    Require ip 198.51.100.42
</LocationMatch>
# Nginx
location = /typo3/install.php {
    allow 203.0.113.0/24;
    allow 198.51.100.42;
    deny  all;
    # ...existing fastcgi_pass / include snippet...
}

注:$GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask'] が制御するのは、開発/デバッグツール(管理パネルやデバッグ出力など)の公開範囲のみです。Install Tool の制限や認証には使用されません。強力な installToolPassword を設定するだけでなく、上記のように Web サーバーで Install Tool をロックダウンしてください。

5. バックエンドユーザーのセキュリティ

強力なパスワードポリシー(TYPO3 v14)
<?php
// ext_localconf.php of site extension
$GLOBALS['TYPO3_CONF_VARS']['BE']['passwordPolicy'] = 'default'; // policy *name* only
$GLOBALS['TYPO3_CONF_VARS']['SYS']['passwordPolicies']['default'] = [
    'validators' => [
        \TYPO3\CMS\Core\PasswordPolicy\Validator\CorePasswordValidator::class => [
            'options' => [
                'minimumLength' => 12,
                'upperCaseCharacterRequired' => true,
                'lowerCaseCharacterRequired' => true,
                'digitCharacterRequired' => true,
                'specialCharacterRequired' => true,
            ],
        ],
        \TYPO3\CMS\Core\PasswordPolicy\Validator\NotCurrentPasswordValidator::class => [],
    ],
];
多要素認証(TYPO3 v14)

MFA は TYPO3 v14 に組み込まれています。ユーザーは次の場所で設定できます。 ユーザー設定 > アカウントのセキュリティ

対応プロバイダー:

  • TOTP(時間ベースのワンタイムパスワード)
  • リカバリーコード

config/system/settings.php で $GLOBALS['TYPO3_CONF_VARS']['BE']['requireMfa'] を使用して MFA の必須化を設定します。値は 0 が無効、1 が全ユーザー、2 が非管理者、3 が管理者のみ、4 がシステムメンテナーのみです(正確な意味は、使用するマイナーバージョンのコアドキュメントで確認してください)。または、ユーザー TSconfig の auth.mfa.required を使用して、ユーザー/グループごとに設定します。

# User or group TSconfig — require MFA for those accounts (overrides global when set)
auth.mfa.required = 1

多要素認証を参照してください。

バックエンドアクセスのログ記録
// Log all backend logins
$GLOBALS['TYPO3_CONF_VARS']['LOG']['TYPO3']['CMS']['Backend']['Authentication']['writerConfiguration'] = [
    \Psr\Log\LogLevel::INFO => [
        \TYPO3\CMS\Core\Log\Writer\FileWriter::class => [
            'logFile' => 'var/log/backend-auth.log',
        ],
    ],
];

6. コンテンツセキュリティポリシー(CSP)

組み込み CSP(TYPO3 v14)

TYPO3 v14 には CSP のサポートが組み込まれています。有効化してください。

config/system/settings.php/Install Tool で CSP を有効にします。フロントエンドの切り替え設定(名前は変更される場合があるため、使用するマイナーバージョンのコアドキュメントで確認してください)には、一般に次のものがあります。 $GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['security.frontend.enforceContentSecurityPolicy'] と security.frontend.reportContentSecurityPolicy。バックエンドの CSP は v13 以降、デフォルトで強制されます。 バックエンドにはフロントエンドと同等の切り替え設定はありません。

イベントを使った CSP の設定(TYPO3 v14)
<?php
declare(strict_types=1);

namespace Vendor\Extension\EventListener;

use TYPO3\CMS\Core\Attribute\AsEventListener;
use TYPO3\CMS\Core\Security\ContentSecurityPolicy\Directive;
use TYPO3\CMS\Core\Security\ContentSecurityPolicy\Event\PolicyMutatedEvent;
use TYPO3\CMS\Core\Security\ContentSecurityPolicy\UriValue;

#[AsEventListener(identifier: 'vendor-extension/csp-modification')]
final class ContentSecurityPolicyListener
{
    public function __invoke(PolicyMutatedEvent $event): void
    {
        if (!$event->scope->type->isFrontend()) {
            return;
        }

        $policy = $event->getCurrentPolicy()
            ->extend(Directive::ScriptSrc, new UriValue('https://cdn.example.com'))
            ->extend(Directive::StyleSrc, new UriValue('https://fonts.googleapis.com'));

        $event->setCurrentPolicy($policy);
    }
}
TypoScript の CSP ヘッダー(代替方法)
config.additionalHeaders {
    10.header = Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://www.googletagmanager.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; frame-ancestors 'self';
}

7. SQL インジェクションの防止

常に QueryBuilder を使用する
<?php
declare(strict_types=1);

// ❌ VULNERABLE - Never do this
$result = $connection->executeQuery(
    "SELECT * FROM pages WHERE uid = " . $_GET['id']
);

// ✅ SECURE - Use QueryBuilder with prepared statements
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('pages');
$result = $queryBuilder
    ->select('*')
    ->from('pages')
    ->where(
        $queryBuilder->expr()->eq(
            'uid',
            $queryBuilder->createNamedParameter($id, \TYPO3\CMS\Core\Database\Connection::PARAM_INT)
        )
    )
    ->executeQuery();
Extbase リポジトリの安全性
<?php
declare(strict_types=1);

// Extbase automatically escapes parameters
$query = $this->createQuery();
$query->matching(
    $query->equals('uid', $id)  // Safe - auto-escaped
);

8. XSS の防止

Fluid テンプレート

{variable}


{variable -> f:format.raw()}


{variable -> f:format.htmlspecialchars()}


<f:format.html>{bodytext}</f:format.html>
バックエンドフォーム

TCA はエスケープを自動的に処理します。カスタムフィールドの場合:

'config' => [
    'type' => 'input',
    'max' => 255,
    // Input is automatically escaped
],

9. CSRF 保護

バックエンドリクエスト(TYPO3 v14)

TYPO3 バックエンドには CSRF トークンが自動的に含まれます。カスタム AJAX の場合:

<?php
declare(strict_types=1);

use TYPO3\CMS\Core\FormProtection\FormProtectionFactory;

final class MyController
{
    public function __construct(
        private readonly FormProtectionFactory $formProtectionFactory,
    ) {}

    public function generateToken(): string
    {
        $formProtection = $this->formProtectionFactory->createFromRequest($this->request);
        return $formProtection->generateToken('myFormIdentifier');
    }

    public function validateToken(string $token): bool
    {
        $formProtection = $this->formProtectionFactory->createFromRequest($this->request);
        return $formProtection->validateToken($token, 'myFormIdentifier');
    }
}
フロントエンドフォーム(Extbase)

<f:form action="submit" controller="Contact" method="post">
    
    <f:form.hidden name="__trustedProperties" value="{trustedProperties}" />
</f:form>

付録

TYPO3 v14 固有のセキュリティ強化に関する注意事項と関連スキルへのリンクについては、references/v14-notes.md を参照してください。公開開始チェックリスト、レート制限、残りの v14 セキュリティに関する注意事項については、references/checklists.md を参照してください。


謝辞とクレジット

出典:https://github.com/dirnbauer/webconsulting-skills

コメント