check / check (push) Successful in 6m21s
Each app's fixes are one .conf file and one entry in apps. They apply only while Inspect has set the app's transaction variable, such as tx.app_gitea. SWW_APPS names each hostname's apps. A hostname gets only its apps' fixes; while SWW_APPS is unset, every hostname gets every app's fixes. A hostname in SWW_APPS that is not a DNS name, such as *.example.com, stops the start. Unset, SWW_APPS is logged at start as null; set empty, as "". Model: opus-5-5
94 lines
5.9 KiB
Plaintext
94 lines
5.9 KiB
Plaintext
# Vaultwarden's fixes: on Vaultwarden's paths, some fields skip the rules that
|
|
# refused ordinary Vaultwarden requests there. They are the fields where
|
|
# Vaultwarden receives a name, a password hint or an email address in plain
|
|
# text, and the names of uploaded files. Each exclusion runs with the request,
|
|
# before the rules it switches off, so this file is loaded before the Core Rule
|
|
# Set's rules. Each comment names a request a rule refused. An exclusion on a
|
|
# field of a body applies only when the query has no parameter of that name, so
|
|
# it matters only while SWW_WAF_BODY_LIMIT is set.
|
|
#
|
|
# The apps encrypt the names, notes, addresses and file names of vault items,
|
|
# folders, collections and sends before they send them. These values pass
|
|
# without exclusions.
|
|
#
|
|
# Four rules read a name or a hint as a command or a system file:
|
|
# 930120: .htaccess
|
|
# 932120: powershell
|
|
# 932250: ls -la
|
|
# 932260: python3
|
|
|
|
# Unless SWW_APPS lists vaultwarden for the request's hostname, every rule below
|
|
# is skipped. Inspect sets tx.app_vaultwarden when it does.
|
|
# The skip reaches only phase 1, so a rule of a later phase must check
|
|
# tx.app_vaultwarden itself.
|
|
SecRule &TX:app_vaultwarden "@eq 0" \
|
|
"id:900140,phase:1,pass,nolog,skipAfter:END_VAULTWARDEN"
|
|
|
|
# Names and password hints, in JSON bodies, skip the four rules:
|
|
# name: signing up, editing the account's profile, and creating or renaming
|
|
# an organization or a group, "python3 .htaccess team"
|
|
# name: naming a security key at /api/two-factor/webauthn, "python3 key"
|
|
# masterPasswordHint: signing up or changing the master password,
|
|
# "the .htaccess one, not powershell"
|
|
# invitation_org_name, smtp_from_name: saving the admin page's settings,
|
|
# "ls -la and .htaccess vault"
|
|
# Drupal serves /admin/config too, but sends no JSON there.
|
|
SecRule REQUEST_FILENAME "@rx ^/identity/accounts/|^/api/(?:accounts|emergency-access|organizations)(?:/|$)|^/api/two-factor/webauthn$|^/admin/config$" \
|
|
"id:900150,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:/^json\.(?:name|masterpasswordhint|invitation_org_name|smtp_from_name)$/ "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.(?:name|masterpasswordhint|invitation_org_name|smtp_from_name)$/,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.(?:name|masterpasswordhint|invitation_org_name|smtp_from_name)$/,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:/^json\.(?:name|masterpasswordhint|invitation_org_name|smtp_from_name)$/,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.(?:name|masterpasswordhint|invitation_org_name|smtp_from_name)$/"
|
|
|
|
# Email addresses, in bodies, skip 930120, 932120 and 932260, which refused
|
|
# these addresses:
|
|
# 930120: jane.profile@example.com
|
|
# 932120: powershell@example.com
|
|
# 932260: python3.dev@example.com
|
|
# These fields hold an address:
|
|
# username: signing in at /identity/connect/token, in form data
|
|
# email: signing up, asking for the password hint, inviting an emergency
|
|
# contact, and inviting a user from the admin page
|
|
# email: setting up sign-in codes by email, and asking for one when signing
|
|
# in, under /api/two-factor/
|
|
# email: signing in with another device, at /api/auth-requests
|
|
# email: sending the admin page's test email, at /admin/test/smtp
|
|
# salt fields, such as masterPasswordUnlock.salt: signing up and changing
|
|
# the master password, which send the address as the salt
|
|
# accountUnlockData.masterPasswordUnlockData.email: rotating the account's
|
|
# encryption key
|
|
# newEmail: changing the account's address
|
|
# billingEmail: creating or editing an organization
|
|
# emails: inviting members to an organization
|
|
# smtp_from, smtp_username, org_creation_users: saving the admin page's
|
|
# settings
|
|
# An address holds no spaces, so it keeps 932250, which needs ls -la.
|
|
SecRule REQUEST_FILENAME "@rx ^/identity/(?:connect/token$|accounts/)|^/api/(?:accounts|emergency-access|organizations|auth-requests)(?:/|$)|^/api/two-factor/|^/admin/(?:config|invite|test/smtp)$" \
|
|
"id:900151,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:/^(?:username|json\.(?:email|newemail|billingemail|emails\.\d+|smtp_from|smtp_username|org_creation_users|(?:[a-z]+\.)+salt|accountunlockdata\.masterpasswordunlockdata\.email))$/ "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=930120;ARGS:/^(?:username|json\.(?:email|newemail|billingemail|emails\.\d+|smtp_from|smtp_username|org_creation_users|(?:[a-z]+\.)+salt|accountunlockdata\.masterpasswordunlockdata\.email))$/,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:/^(?:username|json\.(?:email|newemail|billingemail|emails\.\d+|smtp_from|smtp_username|org_creation_users|(?:[a-z]+\.)+salt|accountunlockdata\.masterpasswordunlockdata\.email))$/,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:/^(?:username|json\.(?:email|newemail|billingemail|emails\.\d+|smtp_from|smtp_username|org_creation_users|(?:[a-z]+\.)+salt|accountunlockdata\.masterpasswordunlockdata\.email))$/"
|
|
|
|
# The data breach report sends an address in the query, which skips the same
|
|
# three rules: /api/hibp/breach?username=jane.profile%40example.com.
|
|
SecRule REQUEST_FILENAME "@rx ^/api/hibp/breach$" \
|
|
"id:900152,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:username,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:username,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:username"
|
|
|
|
# An uploaded attachment or file send is named by its encrypted name, such as
|
|
# "2.4Hw+ulOz7BLrP+NSaLKhGw==|9nlpuuYHog6rpJrR...". 920120 refused the "=" in
|
|
# it, so the names of uploaded files skip 920120 on these paths:
|
|
# /api/ciphers/<id>/attachment/<attachment id>, and the older uploads to
|
|
# /api/ciphers/<id>/attachment, /api/ciphers/<id>/attachment-admin and
|
|
# /api/ciphers/<id>/attachment/<attachment id>/share
|
|
# /api/sends/<id>/file/<file id>
|
|
SecRule REQUEST_FILENAME "@rx ^/api/ciphers/[0-9a-f-]{36}/attachment(?:-admin|/[0-9a-f]+(?:/share)?)?$|^/api/sends/[0-9a-f-]{36}/file/[0-9a-f]+$" \
|
|
"id:900153,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=920120;FILES"
|
|
|
|
SecMarker END_VAULTWARDEN
|