Mercurial > prosody-modules
comparison mod_http_upload_external/README.markdown @ 3358:e49660ba3161
mod_http_upload_external: Improve implementation docs, including v2 details
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Sun, 21 Oct 2018 14:54:19 +0100 |
parents | 57332ea0c1c7 |
children | 3d01ab6b1186 |
comparison
equal
deleted
inserted
replaced
3357:af824168729a | 3358:e49660ba3161 |
---|---|
95 GET https://example.com/upload/foo/bar.jpg | 95 GET https://example.com/upload/foo/bar.jpg |
96 ``` | 96 ``` |
97 | 97 |
98 The only tricky logic is in validation of the PUT request. Firstly, don't overwrite existing files (return 409 Conflict). | 98 The only tricky logic is in validation of the PUT request. Firstly, don't overwrite existing files (return 409 Conflict). |
99 | 99 |
100 Then you need to validate the auth token. This will be in the URL query parameter 'v'. If it is absent, fail with 403 Forbidden. | 100 Then you need to validate the auth token. |
101 | |
102 ### Validating the auth token | |
103 | |
104 | |
105 | Version | Supports | | |
106 |:--------|:--------------------------------------------------------------------------------------------------------| | |
107 | v | Validates only filename and size. Does not support file type restrictions by the XMPP server. | | |
108 | v2 | Validates the filename, size and MIME type. This allows the server to implement MIME type restrictions. | | |
109 | |
110 It is probable that a future v3 will be specified that allows carrying information about the uploader identity, allowing | |
111 the implementation of per-user quotas and limits. | |
112 | |
113 Implementations may implement one or more versions of the protocol simultaneously. The XMPP server generates the URLs and ultimately selects which version will be used. | |
114 | |
115 #### Version 1 (v) | |
116 | |
117 The token will be in the URL query parameter 'v'. If it is absent, fail with 403 Forbidden. | |
101 | 118 |
102 Calculate the expected auth token by reading the value of the Content-Length header of the PUT request. E.g. for a 1MB file | 119 Calculate the expected auth token by reading the value of the Content-Length header of the PUT request. E.g. for a 1MB file |
103 will have a Content-Length of '1048576'. Append this to the uploaded file name, separated by a space (0x20) character. | 120 will have a Content-Length of '1048576'. Append this to the uploaded file name, separated by a space (0x20) character. |
104 | 121 |
105 For the above example, you would end up with the following string: "foo/bar.jpg 1048576" | 122 For the above example, you would end up with the following string: "foo/bar.jpg 1048576" |
110 calculated_auth_token = hmac_sha256("foo/bar.jpg 1048576", "secret string") | 127 calculated_auth_token = hmac_sha256("foo/bar.jpg 1048576", "secret string") |
111 ``` | 128 ``` |
112 | 129 |
113 If this is not equal to the 'v' parameter provided in the upload URL, reject the upload with 403 Forbidden. | 130 If this is not equal to the 'v' parameter provided in the upload URL, reject the upload with 403 Forbidden. |
114 | 131 |
115 Note: your language/environment may provide a function for doing a constant-time comparison of these, to guard against | 132 **Security note:** When comparing `calculated_auth_token` with the token provided in the URL, you must use a constant-time string |
116 timing attacks that may be used to discover the secret key. | 133 comparison, otherwise an attacker may be able to discover your secret key. Most languages/environments provide such a function, such |
134 as `hash_equals()` in PHP, `hmac.compare_digest()` in Python, or `ConstantTimeCompare()` from `crypto/subtle` in Go. | |
135 | |
136 #### Version 2 (v2) | |
137 | |
138 The token will be in the URL query parameter 'v2'. If it is absent, fail with 403 Forbidden. | |
139 | |
140 | Input | Example |Read from | | |
141 |:--------------|:------------|:--------------------------------------------------------------------| | |
142 |`file_path` | foo/bar.jpg | The URL of the PUT request, with the service's base prefix removed. | | |
143 |`content_size` | 1048576 | Content-Size header | | |
144 |`content_type` | image/jpeg | Content-Type header | | |
145 | |
146 The parameters should be joined into a single string, separated by NUL bytes (`\0`): | |
147 | |
148 ``` | |
149 signed_string = ( file_path + '\0' + content_size + '\0' + content_type ) | |
150 ``` | |
151 | |
152 ``` | |
153 signed_string = "foo/bar.jpg\01048576\0image/jpeg" | |
154 ``` | |
155 | |
156 The expected auth token is the SHA256 HMAC of this string, using the configured secret key as the key. E.g.: | |
157 | |
158 ``` | |
159 calculated_auth_token = hmac_sha256(signed_string, "secret string") | |
160 ``` | |
161 | |
162 If this is not equal to the 'v2' parameter provided in the upload URL, reject the upload with 403 Forbidden. | |
163 | |
164 **Security note:** When comparing `calculated_auth_token` with the token provided in the URL, you must use a constant-time string | |
165 comparison, otherwise an attacker may be able to discover your secret key. Most languages/environments provide such a function, such | |
166 as `hash_equals()` in PHP, `hmac.compare_digest()` in Python, or `ConstantTimeCompare()` from `crypto/subtle` in Go. | |
167 | |
168 ### Security considerations | |
169 | |
170 #### HTTPS | |
171 | |
172 All uploads and downloads should only be over HTTPS. The security of the served content is protected only | |
173 by the uniqueness present in the URLs themselves, and not using HTTPS may leak the URLs and contents to third-parties. | |
174 | |
175 Implementations should consider including HSTS and HPKP headers, with consent of the administrator. | |
176 | |
177 #### MIME types | |
178 | |
179 If the upload Content-Type header matches any of the following MIME types, it MUST be preserved and included in the Content-Type | |
180 of any GET requests made to download the file: | |
181 | |
182 - `image/*` | |
183 - `video/*` | |
184 - `audio/*` | |
185 - `text/plain` | |
186 | |
187 It is recommended that other MIME types are preserved, but served with the addition of the following header: | |
188 | |
189 ``` | |
190 Content-Disposition: attachment | |
191 ``` | |
192 | |
193 This prevents the browser interpreting scripts and other resources that may potentially be malicious. | |
194 | |
195 Some browsers may also benefit from explicitly telling them not to try guessing the type of a file: | |
196 | |
197 ``` | |
198 X-Content-Type-Options "nosniff" | |
199 ``` | |
200 | |
201 #### Security headers | |
202 | |
203 The following headers should be included to provide additional sandboxing of resources, considering the uploaded | |
204 content is not understood or trusted by the upload service: | |
205 | |
206 ``` | |
207 Content-Security-Policy: "default-src 'none'" | |
208 X-Content-Security-Policy: "default-src 'none'" | |
209 X-WebKit-CSP: "default-src 'none'" | |
210 ``` |