|
1 | | -.. include:: /Includes.rst.txt |
2 | | -.. index:: |
3 | | - Security guidelines; Restrict file access |
4 | | - Security guidelines; Web servers |
5 | | -.. _security-restrict-access-server-level: |
6 | | - |
7 | | -========================================== |
8 | | -Restrict access to files on a server-level |
9 | | -========================================== |
10 | | - |
11 | | -This is a controversial topic: Some experts recommend to restrict the |
12 | | -access to specific files on a server-level by using Apache's |
13 | | -`FilesMatch` directive for example. Such files could be files with the |
14 | | -endings :file:`.bak`, :file:`.tmp`, :file:`.sql`, :file:`.old`, etc. in their |
15 | | -file names. The purpose of this restriction is, that even if backup files or |
16 | | -database dump files are accidentally stored in the DocRoot directory of the |
17 | | -web server, they cannot be downloaded. |
18 | | - |
19 | | -The downside of this measure is, that this is not the solution of the |
20 | | -problem but a workaround only. The right recommendation would be not |
21 | | -to store sensitive files (such as backups, etc.) in the DocRoot |
22 | | -directory at all – instead of trying to address the issue by |
23 | | -restricting the access to certain file names (keep in mind that you |
24 | | -cannot predict which file names could occur in the future). |
25 | | - |
26 | | - |
27 | | -Verification of access restrictions |
28 | | -=================================== |
29 | | - |
30 | | -Administrators should *test and verify* file access to these files are actually denied. |
31 | | -The following list provides some files as an example that should not be retrievable |
32 | | -directly by using HTTP requests: |
33 | | - |
34 | | -* :samp:`https://example.org/.git/index` |
35 | | -* :samp:`https://example.org/INSTALL.md` |
36 | | -* :samp:`https://example.org/INSTALL.txt` |
37 | | -* :samp:`https://example.org/ChangeLog` |
38 | | -* :samp:`https://example.org/composer.json` |
39 | | -* :samp:`https://example.org/composer.lock` |
40 | | -* :samp:`https://example.org/vendor/autoload.php` |
41 | | -* :samp:`https://example.org/typo3_src/Build/package.json` |
42 | | -* :samp:`https://example.org/typo3_src/bin/typo3` |
43 | | -* :samp:`https://example.org/typo3_src/INSTALL.md` |
44 | | -* :samp:`https://example.org/typo3_src/INSTALL.txt` |
45 | | -* :samp:`https://example.org/typo3_src/ChangeLog` |
46 | | -* :samp:`https://example.org/typo3_src/vendor/autoload.php` |
47 | | -* :samp:`https://example.org/typo3conf/system/settings.php` |
48 | | -* :samp:`https://example.org/typo3conf/system/additional.php` |
49 | | -* :samp:`https://example.org/typo3temp/var/log/` |
50 | | -* :samp:`https://example.org/typo3temp/var/session/` |
51 | | -* :samp:`https://example.org/typo3temp/var/tests/` |
52 | | -* :samp:`https://example.org/typo3/sysext/core/composer.json` |
53 | | -* :samp:`https://example.org/typo3/sysext/core/ext_tables.sql` |
54 | | -* :samp:`https://example.org/typo3/sysext/core/Configuration/Services.yaml` |
55 | | -* :samp:`https://example.org/typo3/sysext/extbase/ext_typoscript_setup.txt` |
56 | | -* :samp:`https://example.org/typo3/sysext/extbase/ext_typoscript_setup.typoscript` |
57 | | -* :samp:`https://example.org/typo3/sysext/felogin/Configuration/FlexForms/Login.xml` |
58 | | -* :samp:`https://example.org/typo3/sysext/backend/Resources/Private/Language/locallang.xlf` |
59 | | -* :samp:`https://example.org/typo3/sysext/backend/Tests/Unit/Utility/Fixtures/clear.gif` |
60 | | -* :samp:`https://example.org/typo3/sysext/belog/Configuration/TypoScript/setup.txt` |
61 | | -* :samp:`https://example.org/typo3/sysext/belog/Configuration/TypoScript/setup.typoscript` |
62 | | - |
63 | | -The list above is probably not complete. However, if general deny rules are in place links |
64 | | -provided above should not be accessible anymore and result in a HTTP `403` error response. |
65 | | - |
| 1 | +:navigation-title: Restrict File Access |
| 2 | + |
| 3 | +.. include:: /Includes.rst.txt |
| 4 | +.. _security-restrict-access-server-level: |
| 5 | + |
| 6 | +============================================ |
| 7 | +Restrict access to files at the server level |
| 8 | +============================================ |
| 9 | + |
| 10 | +TYPO3 installations can either use a classic mode (non-Composer) or a |
| 11 | +Composer-based approach. File access and web server configuration differ |
| 12 | +significantly between these setups. This chapter outlines recommendations |
| 13 | +for both cases. |
| 14 | + |
| 15 | +.. contents:: Table of contents |
| 16 | + |
| 17 | +.. _security-restrict-access-server-level-composer: |
| 18 | + |
| 19 | +Composer-based installations |
| 20 | +============================ |
| 21 | + |
| 22 | +For Composer-based TYPO3 installations, the public document root is typically |
| 23 | +the :file:`public/` directory. All web-accessible files are |
| 24 | +placed in this folder, while all sensitive and internal application files |
| 25 | +(e.g., :file:`vendor/`, :file:`.git/`, configuration files) are stored outside |
| 26 | +the document root by default. |
| 27 | + |
| 28 | +This layout significantly reduces the risk of accidental exposure of |
| 29 | +sensitive files, eliminating the need for complex blacklisting rules. |
| 30 | + |
| 31 | +**Recommendations for Composer-based installations:** |
| 32 | + |
| 33 | +- Ensure the web server document root points to the :file:`public/` |
| 34 | + directory only. |
| 35 | +- Verify that all non-public files (e.g., :file:`composer.json`, :file:`.env`, |
| 36 | + :file:`vendor/`, :file:`config/`) are outside of this directory. |
| 37 | +- Keep your :file:`public/.htaccess` (Apache) or server config (NGINX/IIS) |
| 38 | + files updated to deny access to any critical files inside the public folder. |
| 39 | +- Store downloadable files that are only intended for authenticated users in |
| 40 | + `File storage <https://docs.typo3.org/permalink/t3coreapi:fal-administration-storages>`_ |
| 41 | + located outside the document root. Deliver them programmatically to |
| 42 | + authenticated users, for example using extensions like |
| 43 | + :composer:`leuchtfeuer/secure-downloads`. |
| 44 | + |
| 45 | +.. _security-restrict-access-server-level-classic: |
| 46 | + |
| 47 | +Classic-mode installations |
| 48 | +========================== |
| 49 | + |
| 50 | +In classic TYPO3 installations (without Composer), all files are contained in the |
| 51 | +web root directory. This increases the risk of accidental exposure of internal |
| 52 | +files. For example, temporary files such as backups or logs may become |
| 53 | +accessible unless explicitly protected. |
| 54 | + |
| 55 | +**Restricting access to sensitive files** |
| 56 | + |
| 57 | +Some experts recommend denying access to certain file types (e.g., |
| 58 | +:file:`.bak`, :file:`.tmp`, :file:`.sql`, :file:`.old`) using web server rules |
| 59 | +like Apache's `FilesMatch` directive. This helps prevent downloads of |
| 60 | +sensitive files that have accidentally been placed in the document root. |
| 61 | + |
| 62 | +However, this is a workaround — not a real solution. The proper approach is to |
| 63 | +ensure sensitive files are never stored in the web root at all. Blocking access |
| 64 | +by file name patterns is unreliable, as future file names cannot be predicted. |
| 65 | + |
| 66 | +.. _security-restrict-access-server-level-verification: |
| 67 | + |
| 68 | +Verification of access restrictions in Classic-mode installations |
| 69 | +----------------------------------------------------------------- |
| 70 | + |
| 71 | +Administrators must *verify* that access to sensitive files is properly denied. |
| 72 | +Attempting to access any of the following files should result in an HTTP `403` |
| 73 | +error: |
| 74 | + |
| 75 | +* :samp:`https://example.org/.git/index` |
| 76 | +* :samp:`https://example.org/INSTALL.md` |
| 77 | +* :samp:`https://example.org/INSTALL.txt` |
| 78 | +* :samp:`https://example.org/ChangeLog` |
| 79 | +* :samp:`https://example.org/composer.json` |
| 80 | +* :samp:`https://example.org/composer.lock` |
| 81 | +* :samp:`https://example.org/vendor/autoload.php` |
| 82 | +* :samp:`https://example.org/typo3_src/Build/package.json` |
| 83 | +* :samp:`https://example.org/typo3_src/bin/typo3` |
| 84 | +* :samp:`https://example.org/typo3_src/INSTALL.md` |
| 85 | +* :samp:`https://example.org/typo3_src/INSTALL.txt` |
| 86 | +* :samp:`https://example.org/typo3_src/ChangeLog` |
| 87 | +* :samp:`https://example.org/typo3_src/vendor/autoload.php` |
| 88 | +* :samp:`https://example.org/typo3conf/system/settings.php` |
| 89 | +* :samp:`https://example.org/typo3conf/system/additional.php` |
| 90 | +* :samp:`https://example.org/typo3temp/var/log/` |
| 91 | +* :samp:`https://example.org/typo3temp/var/session/` |
| 92 | +* :samp:`https://example.org/typo3temp/var/tests/` |
| 93 | +* :samp:`https://example.org/typo3/sysext/core/composer.json` |
| 94 | +* :samp:`https://example.org/typo3/sysext/core/ext_tables.sql` |
| 95 | +* :samp:`https://example.org/typo3/sysext/core/Configuration/Services.yaml` |
| 96 | +* :samp:`https://example.org/typo3/sysext/extbase/ext_typoscript_setup.txt` |
| 97 | +* :samp:`https://example.org/typo3/sysext/extbase/ext_typoscript_setup.typoscript` |
| 98 | +* :samp:`https://example.org/typo3/sysext/felogin/Configuration/FlexForms/Login.xml` |
| 99 | +* :samp:`https://example.org/typo3/sysext/backend/Resources/Private/Language/locallang.xlf` |
| 100 | +* :samp:`https://example.org/typo3/sysext/backend/Tests/Unit/Utility/Fixtures/clear.gif` |
| 101 | +* :samp:`https://example.org/typo3/sysext/belog/Configuration/TypoScript/setup.txt` |
| 102 | +* :samp:`https://example.org/typo3/sysext/belog/Configuration/TypoScript/setup.typoscript` |
| 103 | + |
| 104 | + |
| 105 | +.. _security-restrict-access-server-level-htaccess: |
66 | 106 |
|
67 | 107 | Apache and Microsoft IIS web servers |
68 | | -==================================== |
69 | | - |
70 | | -To increase protection of TYPO3 instances, the Core Team however decided to |
71 | | -install default web server configuration files under certain |
72 | | -circumstances: If an Apache web server is detected by the web based installation |
73 | | -procedure, a default :file:`.htaccess` file is written to the document root, and if |
74 | | -a Microsoft IIS web server is detected, a default :file:`web.config` file is written |
75 | | -to the document root. These files contain web server configurations to deny direct web |
76 | | -access to a series of common file types and directories, for instance version control system |
77 | | -directories like :file:`.git/`, all private template directories like :file:`Resources/Private/` |
78 | | -and common package files like :file:`composer.json <extension-composer-json>`. |
79 | | - |
80 | | - |
81 | | -This "black list" approach needs maintenance: The Core Team tries to keep the template files |
82 | | -:file:`.htaccess` and :file:`web.config` updated. If running Apache or IIS, administrators |
83 | | -should compare their specific version with the reference files found at |
84 | | -:t3src:`install/Resources/Private/FolderStructureTemplateFiles/root-htaccess` |
85 | | -and :t3src:`install/Resources/Private/FolderStructureTemplateFiles/root-web-config` |
86 | | -and adapt or update local versions if needed. |
87 | | - |
88 | | -See :ref:`<maintain-htaccess>` for details on maintaining the file after a major |
89 | | -version upgrade. |
90 | | - |
91 | | - |
92 | | -NGINX web servers |
93 | | -================= |
94 | | - |
95 | | -Administrators running the popular web server `NGINX <https://www.nginx.com/>`_ need to |
96 | | -take additional measures: NGINX does not support an approach like Apache or IIS to configure |
97 | | -access by putting files into the web document directories - the TYPO3 install procedure can |
98 | | -not install good default files and administrators must merge deny patterns into the web |
99 | | -servers virtual host configuration. A typical example looks like this: |
100 | | - |
101 | | -.. code-block:: nginx |
102 | | -
|
103 | | - server { |
104 | | -
|
105 | | - # ... |
106 | | -
|
107 | | - # Prevent clients from accessing hidden files (starting with a dot) |
108 | | - # This is particularly important if you store .htpasswd files in the site hierarchy |
109 | | - # Access to `/.well-known/` is allowed. |
110 | | - # https://www.mnot.net/blog/2010/04/07/well-known |
111 | | - # https://tools.ietf.org/html/rfc5785 |
112 | | - location ~* /\.(?!well-known\/) { |
113 | | - deny all; |
114 | | - } |
115 | | -
|
116 | | - # Prevent clients from accessing to backup/config/source files |
117 | | - location ~* (?:\.(?:bak|conf|dist|fla|in[ci]|log|psd|sh|sql|sw[op])|~)$ { |
118 | | - deny all; |
119 | | - } |
120 | | -
|
121 | | - # TYPO3 - Block access to Composer files |
122 | | - location ~* composer\.(?:json|lock) { |
123 | | - deny all; |
124 | | - } |
125 | | -
|
126 | | - # TYPO3 - Block access to flexform files |
127 | | - location ~* flexform[^.]*\.xml { |
128 | | - deny all; |
129 | | - } |
130 | | -
|
131 | | - # TYPO3 - Block access to language files |
132 | | - location ~* locallang[^.]*\.xlf { |
133 | | - deny all; |
134 | | - } |
135 | | -
|
136 | | - # TYPO3 - Block access to static typoscript files |
137 | | - location ~* ext_conf_template\.txt|ext_typoscript_constants\.(?:txt|typoscript)|ext_typoscript_setup\.(?:txt|typoscript) { |
138 | | - deny all; |
139 | | - } |
140 | | -
|
141 | | - # TYPO3 - Block access to miscellaneous protected files |
142 | | - location ~* /.*\.(?:bak|co?nf|cfg|ya?ml|ts|typoscript|dist|fla|in[ci]|log|sh|sql)$ { |
143 | | - deny all; |
144 | | - } |
145 | | -
|
146 | | - # TYPO3 - Block access to recycler and temporary directories |
147 | | - location ~ _(?:recycler|temp)_/ { |
148 | | - deny all; |
149 | | - } |
150 | | -
|
151 | | - # TYPO3 - Block access to configuration files stored in fileadmin |
152 | | - location ~ fileadmin/(?:templates)/.*\.(?:txt|ts|typoscript)$ { |
153 | | - deny all; |
154 | | - } |
155 | | -
|
156 | | - # TYPO3 - Block access to libraries, source and temporary compiled data |
157 | | - location ~ ^(?:vendor|typo3_src|typo3temp/var) { |
158 | | - deny all; |
159 | | - } |
160 | | -
|
161 | | - # TYPO3 - Block access to protected extension directories |
162 | | - location ~ (?:typo3conf/ext|typo3/sysext|typo3/ext)/[^/]+/(?:Configuration|Resources/Private|Tests?|Documentation|docs?)/ { |
163 | | - deny all; |
164 | | - } |
165 | | -
|
166 | | - # ... |
167 | | -
|
168 | | - } |
169 | | -
|
170 | | -The config example above has been taken from `ddev |
171 | | -<https://github.com/drud/ddev/blob/f2171f390a3af8d4a85954105e8aa68b8bcab5ac/containers/ddev-webserver/files/etc/nginx/nginx-site-typo3.conf>`_. |
| 108 | +------------------------------------ |
| 109 | + |
| 110 | +In classic mode, TYPO3 automatically creates default web server config files |
| 111 | +(:file:`.htaccess` for Apache, :file:`web.config` for IIS) to deny access to |
| 112 | +common sensitive files and directories. |
| 113 | + |
| 114 | +These blacklist-style rules require ongoing maintenance. Administrators should |
| 115 | +regularly compare their config files with the TYPO3 reference templates: |
| 116 | + |
| 117 | +* :t3src:`install/Resources/Private/FolderStructureTemplateFiles/root-htaccess` |
| 118 | +* :t3src:`install/Resources/Private/FolderStructureTemplateFiles/root-web-config` |
| 119 | + |
| 120 | +See :ref:`<maintain-htaccess>` for updating config files after major version |
| 121 | +upgrades. |
| 122 | + |
| 123 | +.. _security-restrict-access-server-level-nginx: |
| 124 | + |
| 125 | +NGINX Web Servers configuration (both installation modes) |
| 126 | +========================================================= |
| 127 | + |
| 128 | +NGINX does not support `.htaccess` or similar per-directory configuration |
| 129 | +so TYPO3 cannot install default protection automatically. Instead, administrators |
| 130 | +must include appropriate deny rules in the virtual host configuration. |
| 131 | + |
| 132 | +A sample configuration is provided by DDEV: |
| 133 | + |
| 134 | +.. literalinclude:: _codesnippets/_nginx.config |
| 135 | + :language: plaintext |
| 136 | + :caption: nginx-site-typo3.conf |
| 137 | + |
| 138 | +This example is taken from `DDEV webserver config |
| 139 | +<https://github.com/ddev/ddev/blob/6a7655c178f5961666bb9c9efd10442314f6749c/pkg/ddevapp/webserver_config_assets/nginx-site-typo3.conf>`_. |
0 commit comments