# ------------------------------------------------------------------------
# OWASP ModSecurity Core Rule Set ver.3.3.9
# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved.
# Copyright (c) 2021-2026 Core Rule Set project. All rights reserved.
#
# The OWASP ModSecurity Core Rule Set is distributed under
# Apache Software License (ASL) version 2
# Please see the enclosed LICENSE file for full details.
# ------------------------------------------------------------------------

# These exclusions remedy false positives in a default XenForo install.
# The exclusions are only active if crs_exclusions_xenforo=1 is set.
# See rule 900130 in crs-setup.conf.example for instructions.

SecRule &TX:crs_exclusions_xenforo|TX:crs_exclusions_xenforo "@eq 0" \
    "id:9006000,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    ver:'OWASP_CRS/3.3.9',\
    skipAfter:END-XENFORO"

SecRule &TX:crs_exclusions_xenforo|TX:crs_exclusions_xenforo "@eq 0" \
    "id:9006001,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ver:'OWASP_CRS/3.3.9',\
    skipAfter:END-XENFORO"


#
# -=[ XenForo Front-End ]=-
#

# Proxy for images and remote content embedded in forum posts
# GET /xf/proxy.php?image=https://example.com/some.jpg&hash=foo
# GET /xf/proxy.php?link=https://example.com&hash=foo
# POST /xf/proxy.php, body: referrer=...
SecRule REQUEST_FILENAME "@endsWith /proxy.php" \
    "id:9006100,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:image,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:link,\
    ctl:ruleRemoveTargetById=931130;ARGS:referrer,\
    ctl:ruleRemoveTargetById=942230;ARGS:referrer,\
    ver:'OWASP_CRS/3.3.9'"

# Store drafts for private message, forum post, thread reply
# POST /xf/conversations/draft
# POST /xf/conversations/convo-title.12345/draft
# POST /xf/forums/forum-title.12345/draft
# POST /xf/threads/thread-title-%E2%98%85.12345/draft
#
# attachment_hash_combined example:
# {"type":"post","context":{"post_id":12345},"hash":"0123456789abcdef..."}
SecRule REQUEST_FILENAME "@rx /(?:conversations|(?:conversations|forums|threads)/.*)/draft$" \
    "id:9006110,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetById=931130;ARGS:href,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:title,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message_html,\
    ctl:ruleRemoveTargetById=942200;ARGS:attachment_hash_combined,\
    ctl:ruleRemoveTargetById=942260;ARGS:attachment_hash_combined,\
    ctl:ruleRemoveTargetById=942340;ARGS:attachment_hash_combined,\
    ctl:ruleRemoveTargetById=942370;ARGS:attachment_hash_combined,\
    ver:'OWASP_CRS/3.3.9'"

# Send PM, edit post, create thread, reply to thread
# POST /xf/conversations/add
# POST /xf/conversations/add-preview
# POST /xf/conversations/messages/1463947/edit
# POST /xf/posts/12345/edit
# POST /xf/posts/12345/preview
# POST /xf/conversations/convo-title.12345/add-reply
# POST /xf/threads/thread-title.12345/add-reply
# POST /xf/threads/thread-title.12345/reply-preview
# POST /xf/forums/forum-title.12345/post-thread
# POST /xf/forums/blogs/post-thread
# POST /xf/forums/forum-title.12345/thread-preview
SecRule REQUEST_FILENAME "@rx /(?:conversations/add(?:-preview)?|conversations/messages/\d+/edit|posts/\d+/(?:edit|preview)|(?:conversations|threads)/.*\.\d+/(?:add-reply|reply-preview)|forums/.*/(?:post-thread|thread-preview))$" \
    "id:9006120,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:title,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message_html,\
    ctl:ruleRemoveTargetById=942200;ARGS:attachment_hash_combined,\
    ctl:ruleRemoveTargetById=942260;ARGS:attachment_hash_combined,\
    ctl:ruleRemoveTargetById=942340;ARGS:attachment_hash_combined,\
    ctl:ruleRemoveTargetById=942370;ARGS:attachment_hash_combined,\
    ver:'OWASP_CRS/3.3.9'"

# Quote
# POST /xf/posts/12345/quote
SecRule REQUEST_FILENAME "@rx /posts/\d+/quote$" \
    "id:9006130,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:quoteHtml,\
    ver:'OWASP_CRS/3.3.9'"

# Multi quote
# POST /xf/conversations/convo-title.12345/multi-quote
# POST /xf/threads/thread-title.12345/multi-quote
# quotes={"12345":["quote-html"]}
SecRule REQUEST_FILENAME "@rx /(?:conversations|threads)/.*\.\d+/multi-quote$" \
    "id:9006140,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:quotes,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[0][value],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[1][value],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[2][value],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[3][value],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[4][value],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[5][value],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[6][value],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[7][value],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[8][value],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[9][value],\
    ver:'OWASP_CRS/3.3.9'"

# Delete thread
# POST /xf/threads/thread-title.12345/delete
SecRule REQUEST_FILENAME "@rx /threads/.*\.\d+/delete$" \
    "id:9006150,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetById=942130;ARGS:starter_alert_reason,\
    ver:'OWASP_CRS/3.3.9'"

# Feature thread
# POST /xf/threads/thread-title.12345/feature-edit
SecRule REQUEST_FILENAME "@rx /threads/.*\.\d+/feature-edit$" \
    "id:9006155,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:feature[feature_excerpt]"

# Inline moderate thread
# POST /xf/inline-mod/
SecRule REQUEST_FILENAME "@endsWith /inline-mod/" \
    "id:9006160,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:author_alert_reason,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message,\
    ver:'OWASP_CRS/3.3.9'"

# Warn member
# POST /xf/members/name.12345/warn
# POST /xf/posts/12345/warn
SecRule REQUEST_FILENAME "@rx /(?:members/.*\.\d+|posts/\d+)/warn$" \
    "id:9006170,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:conversation_message,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:notes,\
    ver:'OWASP_CRS/3.3.9'"

# Editor
SecRule REQUEST_URI "@endsWith /index.php?editor/to-html" \
    "id:9006200,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:bb_code,\
    ctl:ruleRemoveTargetById=942200;ARGS:attachment_hash_combined,\
    ctl:ruleRemoveTargetById=942260;ARGS:attachment_hash_combined,\
    ctl:ruleRemoveTargetById=942340;ARGS:attachment_hash_combined,\
    ctl:ruleRemoveTargetById=942370;ARGS:attachment_hash_combined,\
    ver:'OWASP_CRS/3.3.9'"

# Editor
SecRule REQUEST_URI "@endsWith /index.php?editor/to-bb-code" \
    "id:9006210,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:html,\
    ver:'OWASP_CRS/3.3.9'"

# Post attachment
# POST /xf/account/avatar
# POST /xf/attachments/upload?type=post&context[thread_id]=12345&hash=foo
SecRule REQUEST_FILENAME "@rx /(?:account/avatar|attachments/upload)$" \
    "id:9006220,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveById=200003,\
    ctl:ruleRemoveTargetById=942220;ARGS:flowChunkSize,\
    ctl:ruleRemoveTargetById=942440;ARGS:flowIdentifier,\
    ctl:ruleRemoveTargetById=942440;ARGS:flowFilename,\
    ctl:ruleRemoveTargetById=942440;ARGS:flowRelativePath,\
    ver:'OWASP_CRS/3.3.9'"

# Media
# POST /xf/index.php?editor/media
SecRule REQUEST_URI "@endsWith /index.php?editor/media" \
    "id:9006230,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetById=931130;ARGS:url,\
    ctl:ruleRemoveTargetById=942130;ARGS:url,\
    ver:'OWASP_CRS/3.3.9'"

# Emoji
# GET /xf/index.php?misc/find-emoji&q=(%0A%0A
SecRule REQUEST_URI "@rx /index\.php\?misc/find-emoji&q=" \
    "id:9006240,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetById=921151;ARGS:q,\
    ver:'OWASP_CRS/3.3.9'"

# Login
# POST /xf/login/login
SecRule REQUEST_FILENAME "@endsWith /login/login" \
    "id:9006300,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:password,\
    ver:'OWASP_CRS/3.3.9'"

# Register account
# POST /xf/register/register
# The password is passed in a variable-name form parameter. We don't
# want to exclude all parameters completely as this would cause an
# unacceptable bypass. So, we exclude only commonly hit rules.
SecRule REQUEST_FILENAME "@endsWith /register/register" \
    "id:9006310,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetById=942130;ARGS,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:reg_key,\
    ver:'OWASP_CRS/3.3.9'"

# Confirm account
# GET /xf/account-confirmation/name.12345/email?c=foo
SecRule REQUEST_FILENAME "@rx /account-confirmation/.*\.\d+/email$" \
    "id:9006315,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:c"

# Edit account
# POST /xf/account/account-details
SecRule REQUEST_FILENAME "@endsWith /account/account-details" \
    "id:9006320,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetById=931130;ARGS:custom_fields[picture],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:about_html,\
    ver:'OWASP_CRS/3.3.9'"

# Lost password
# POST /xf/lost-password/user-name.12345/confirm?c=foo
SecRule REQUEST_FILENAME "@rx /lost-password/.*\.\d+/confirm$" \
    "id:9006330,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:c,\
    ver:'OWASP_CRS/3.3.9'"

# Set forum signature
# POST /xf/account/signature
SecRule REQUEST_FILENAME "@endsWith /account/signature" \
    "id:9006340,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:signature_html,\
    ver:'OWASP_CRS/3.3.9'"

# Search
# POST /xf/search/search
SecRule REQUEST_FILENAME "@endsWith /search/search" \
    "id:9006400,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:keywords,\
    ctl:ruleRemoveTargetById=942200;ARGS:constraints,\
    ctl:ruleRemoveTargetById=942260;ARGS:constraints,\
    ctl:ruleRemoveTargetById=942340;ARGS:constraints,\
    ctl:ruleRemoveTargetById=942370;ARGS:constraints,\
    ver:'OWASP_CRS/3.3.9'"

# Search within thread
# GET /xf/threads/foo.12345/page12?highlight=foo
SecRule REQUEST_FILENAME "@rx /threads/.*\.\d+/(?:page\d+)?$" \
    "id:9006410,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:highlight,\
    ver:'OWASP_CRS/3.3.9'"

# Search within search result
# GET /xf/search/12345/?q=foo
SecRule REQUEST_FILENAME "@rx /search/\d+/$" \
    "id:9006420,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:q,\
    ver:'OWASP_CRS/3.3.9'"

# Contact form
# POST /xf/misc/contact
SecRule REQUEST_FILENAME "@endsWith /misc/contact" \
    "id:9006500,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:subject,\
    ver:'OWASP_CRS/3.3.9'"

# Report post
# POST /xf/posts/12345/report
SecRule REQUEST_FILENAME "@rx /posts/\d+/report$" \
    "id:9006510,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message,\
    ver:'OWASP_CRS/3.3.9'"

# Alternate thread view route
# /xf/index.php?threads/title-having-some-sql.12345/
#
# Especially threads with the HAVING sql keyword are FP prone.
# This rule has some chains to narrow down the exclusion,
# making it harder for an attacker to abuse the ARGS_NAMES
# exclusion on other endpoints.
SecRule REQUEST_FILENAME "@endsWith /index.php" \
    "id:9006600,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    ver:'OWASP_CRS/3.3.9',\
    chain"
    SecRule REQUEST_METHOD "@streq GET" \
        "t:none,\
        chain"
        SecRule &ARGS "@eq 1" \
            "t:none,\
            chain"
            SecRule REQUEST_URI "@rx /index\.php\?threads/.*\.\d+/$" \
                "t:none,\
                ctl:ruleRemoveTargetById=942100;ARGS_NAMES,\
                ctl:ruleRemoveTargetById=942230;ARGS_NAMES"

# Browser fingerprint (DBTech security extension)
# May Contain various javascript/XSS false positives
SecRule REQUEST_URI "@endsWith /index.php?dbtech-security/fingerprint" \
    "id:9006700,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:components[14][value],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:components[15][value],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:components[16][value],\
    ver:'OWASP_CRS/3.3.9'"

# Get location info
SecRule REQUEST_FILENAME "@endsWith /misc/location-info" \
    "id:9006710,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:location,\
    ver:'OWASP_CRS/3.3.9'"

#
# -=[ XenForo Global Exclusions ]=-
#

# _xfRedirect, _xfRequestUri can appear on various endpoints.
# Cookies can appear on all endpoints.

SecAction \
    "id:9006800,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetById=931120;ARGS:_xfRedirect,\
    ctl:ruleRemoveTargetById=941150;ARGS:_xfRedirect,\
    ctl:ruleRemoveTargetById=942230;ARGS:_xfRedirect,\
    ctl:ruleRemoveTargetById=942260;ARGS:_xfRedirect,\
    ctl:ruleRemoveTargetById=931120;ARGS:_xfRequestUri,\
    ctl:ruleRemoveTargetById=941150;ARGS:_xfRequestUri,\
    ctl:ruleRemoveTargetById=942130;ARGS:_xfRequestUri,\
    ctl:ruleRemoveTargetById=942230;ARGS:_xfRequestUri,\
    ctl:ruleRemoveTargetById=942260;ARGS:_xfRequestUri,\
    ctl:ruleRemoveTargetById=942100;REQUEST_COOKIES:xf_csrf,\
    ctl:ruleRemoveTargetById=942210;REQUEST_COOKIES:xf_csrf,\
    ctl:ruleRemoveTargetById=942440;REQUEST_COOKIES:xf_csrf,\
    ctl:ruleRemoveTargetById=942100;REQUEST_COOKIES:xf_emoji_usage,\
    ctl:ruleRemoveTargetById=942150;REQUEST_COOKIES:xf_emoji_usage,\
    ctl:ruleRemoveTargetById=942410;REQUEST_COOKIES:xf_emoji_usage,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;REQUEST_COOKIES:xf_ls,\
    ctl:ruleRemoveTargetById=942100;REQUEST_COOKIES:xf_session,\
    ctl:ruleRemoveTargetById=942100;REQUEST_COOKIES:xf_user,\
    ver:'OWASP_CRS/3.3.9'"

#
# -=[ XenForo Administration Back-End ]=-
#

# Skip this section for performance unless requested file is admin.php

SecRule REQUEST_FILENAME "!@endsWith /admin.php" \
    "id:9006900,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    ver:'OWASP_CRS/3.3.9',\
    skipAfter:END-XENFORO-ADMIN"

SecRule REQUEST_FILENAME "!@endsWith /admin.php" \
    "id:9006901,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ver:'OWASP_CRS/3.3.9',\
    skipAfter:END-XENFORO-ADMIN"

# Admin edit user
# POST /xf/admin.php?users/the-user-name.12345/edit
SecRule REQUEST_URI "@rx /admin\.php\?users/.*\.\d+/edit$" \
    "id:9006910,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:profile[about],\
    ctl:ruleRemoveTargetById=931130;ARGS:profile[website],\
    ver:'OWASP_CRS/3.3.9'"

# Admin save user
# POST /xf/admin.php?users/the-user-name.12345/save
# Runs in phase 1 to be able to remove rule 200003.
SecRule REQUEST_URI "@rx /admin\.php\?users/.*\.\d+/save$" \
    "id:9006920,\
    phase:1,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveById=200003,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:custom_fields[occupation],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:custom_fields[personal_quote],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:profile[about],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:profile[signature],\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:custom_fields[sexuality],\
    ctl:ruleRemoveTargetById=931130;ARGS:custom_fields[picture],\
    ctl:ruleRemoveTargetById=931130;ARGS:profile[website],\
    ver:'OWASP_CRS/3.3.9'"


# Admin edit forum notice
# POST /xf/admin.php?notices/0/save
# POST /xf/admin.php?notices/forum-name.12345/save
SecRule REQUEST_URI "@rx /admin\.php\?notices/(?:.*\.)?\d+/save$" \
    "id:9006930,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:title,\
    ver:'OWASP_CRS/3.3.9'"

# Admin batch thread update
# POST /xf/admin.php?threads/batch-update/action
SecRule REQUEST_URI "@rx /admin\.php\?(?:threads|users)/batch-update/action$" \
    "id:9006940,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetById=942200;ARGS:criteria,\
    ctl:ruleRemoveTargetById=942260;ARGS:criteria,\
    ctl:ruleRemoveTargetById=942330;ARGS:criteria,\
    ctl:ruleRemoveTargetById=942340;ARGS:criteria,\
    ctl:ruleRemoveTargetById=942370;ARGS:criteria,\
    ver:'OWASP_CRS/3.3.9'"

# Edit forum theme
# POST /xf/admin.php?styles/title.1234/style-properties/group&group=basic
SecRule REQUEST_URI "@rx /admin\.php\?styles/" \
    "id:9006950,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetById=942200;ARGS:json,\
    ctl:ruleRemoveTargetById=942260;ARGS:json,\
    ctl:ruleRemoveTargetById=942300;ARGS:json,\
    ctl:ruleRemoveTargetById=942330;ARGS:json,\
    ctl:ruleRemoveTargetById=942340;ARGS:json,\
    ctl:ruleRemoveTargetById=942370;ARGS:json,\
    ctl:ruleRemoveTargetById=942440;ARGS:json,\
    ver:'OWASP_CRS/3.3.9'"

# Set forum options
# POST /xf/admin.php?options/update
SecRule REQUEST_URI "@rx /admin\.php\?options/update" \
    "id:9006960,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:options[boardInactiveMessage],\
    ver:'OWASP_CRS/3.3.9'"

# Edit pages/templates
# POST /xf/admin.php?pages/0/save
# POST /xf/admin.php?pages/foo.12345/save
# POST /xf/admin.php?templates/foo.1234/save
SecRule REQUEST_URI "@rx /admin\.php\?(?:pages|templates)/.*/save" \
    "id:9006970,\
    phase:2,\
    pass,\
    t:none,\
    nolog,\
    ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:template,\
    ver:'OWASP_CRS/3.3.9'"

SecMarker "END-XENFORO-ADMIN"

SecMarker "END-XENFORO"
