├── .gitignore ├── CHANGELOG.md ├── pages ├── index.php ├── main.php └── config.php ├── .travis.yml ├── package.yml ├── install.php ├── LICENSE ├── README.md └── boot.php /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .DS_Store? 3 | ._* 4 | .Spotlight-V100 5 | .Trashes 6 | ehthumbs.db 7 | Thumbs.db 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # HTTP_HEADERS 2 | 3 | ### Changelog 4 | 5 | ##### 26.10.2020 6 | 7 | - add Changelog 8 | - rename package 9 | 10 | -------------------------------------------------------------------------------- /pages/index.php: -------------------------------------------------------------------------------- 1 | setVar('title', $this->i18n('main_title'), false); 7 | $fragment->setVar('body', $content, false); 8 | echo $fragment->parse('core/page/section.php'); 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - '7.1' 5 | 6 | cache: 7 | directories: 8 | - $HOME/.composer/cache 9 | 10 | before_install: 11 | - phpenv config-rm xdebug.ini || echo "xdebug not available" 12 | 13 | script: 14 | - composer require --dev friendsofredaxo/linter 15 | - vendor/bin/rexlint 16 | -------------------------------------------------------------------------------- /package.yml: -------------------------------------------------------------------------------- 1 | package: http_headers 2 | version: '0.0.5-beta' 3 | title: 'HTTP Headers' 4 | author: Friends Of REDAXO 5 | supportpage: https://github.com/FriendsOfREDAXO/http_headers 6 | 7 | page: 8 | title: 'HTTP Headers' 9 | perm: admin 10 | icon: rex-icon fa-exclamation-triangle 11 | 12 | subpages: 13 | config: 14 | title: 'Einstellungen' 15 | icon: rex-icon fa-wrench 16 | help: 17 | title: 'Info' 18 | subPath: README.md 19 | icon: rex-icon fa-book 20 | 21 | requires: 22 | redaxo: '^5.2' 23 | php: 24 | version: '^7.0' 25 | -------------------------------------------------------------------------------- /install.php: -------------------------------------------------------------------------------- 1 | hasConfig()) { 6 | $addon->setConfig('x-frame-options_fb', 1); 7 | $addon->setConfig('x-frame-options', 'deny'); 8 | $addon->setConfig('x-powered-by_fb', 1); 9 | $addon->setConfig('x-powered-by-always-unset', 1); 10 | $addon->setConfig('referrerpolicy_fb', 1); 11 | $addon->setConfig('referrerpolicy', 'no-referrer-when-downgrade'); 12 | } 13 | 14 | $somethingIsWrong = false; 15 | if ($somethingIsWrong) { 16 | throw new rex_functional_exception('Something is wrong'); 17 | } 18 | 19 | // Alternativ kann ähnlich wie in R4 mit den Properties "install" und "installmsg" die Installation als nicht erfolgreich markiert werden. 20 | // Im Gegensatz zu R4 muss für eine erfolgreiche Installation keine Property mehr gesetzt werden. 21 | if ($somethingIsWrong) { 22 | $this->setProperty('installmsg', 'Something is wrong'); 23 | $this->setProperty('install', false); 24 | } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Friends Of REDAXO 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Projekt eingestellt 2 | 3 | Es wurde ein neues Addon entwickelt welches bald hoffentlich auch bei den FOR zu finden ist: https://github.com/iceman-fx/httpheader 4 | 5 | --- 6 | 7 | ## Wichtige Info 8 | 9 | * **Mit den falschen Einstellungen kann es passieren, dass die Webseite nachhaltig nicht mehr wie gewünscht funktioniert!!** 10 | * Nicht alle Header werden von allen Browsern berücksichtigt. Wenn Du mehr wissen möchtest musst du googlen :-) 11 | * Nach der Aktivierung des AddOns und jeder Änderung muß unbedingt die Webseite auf Ihre Funktion geprüft werden! 12 | * Nicht übertreiben. Nicht immer ist es überall sinnvoll bei jedem test 100% zu erreichen! Nachdenken hilft. 13 | 14 | ## Header testen 15 | 16 | * https://siwecos.de 17 | * https://securityheaders.com 18 | * https://observatory.mozilla.org 19 | * https://cspvalidator.org 20 | * https://www.whatsmyip.org/http-headers/ 21 | 22 | ## Browser Plugins 23 | 24 | ### Chrome 25 | 26 | CSP Evaluator 27 | * https://chrome.google.com/webstore/detail/csp-evaluator/fjohamlofnakbnbfjkohkbdigoodcejf?hl=de 28 | 29 | CSP Mitigator 30 | * https://chrome.google.com/webstore/detail/csp-mitigator/gijlobangojajlbodabkpjpheeeokhfa?hl=de 31 | 32 | CSP Tester 33 | * https://chrome.google.com/webstore/detail/csp-tester/ehmipebdmhlmikaopdfoinmcjhhfadlf?hl=de 34 | 35 | Google Chrome Extension for 4ARMED's Content Security Policy Generator 36 | * https://github.com/4armed/csp-generator-extension 37 | 38 | 39 | ### Firefox 40 | 41 | Laboratory (Content Security Policy / CSP Toolkit) 42 | * https://addons.mozilla.org/en-US/firefox/addon/laboratory-by-mozilla/ 43 | 44 | 45 | ## Infoseiten (unsortiert und unvollständig) 46 | 47 | * https://developer.mozilla.org/de/docs/Web/HTTP/Headers 48 | * https://www.cspisawesome.com 49 | * https://content-security-policy.com 50 | * https://www.codingblatt.de/http-security-header-website-sicherheit-erhoehen 51 | * https://www.scip.ch/?labs.20190214 52 | * https://www.globalsign.com/de-de/blog/was-ist-hsts-wie-fuehren-sie-es-ein 53 | * https://www.sgalinski.de/typo3-agentur/technik/security-header 54 | * https://zinoui.com/blog/security-http-headers 55 | * https://zinoui.com/blog/http-headers-for-wordpress 56 | * https://8020webdesign.ch/hsts-http-security-headers 57 | * https://www.selbstaendig-im-netz.de/webdesign/7-http-security-header-website-sicherheit/ 58 | * https://spacehost.de/10-apache-header-eintraege-webseite-sicher-machen/ 59 | * https://www.scip.ch/?labs.20180308 60 | 61 | weitere Seiten folgen 62 | 63 | ## HSTS preload list 64 | 65 | * https://hstspreload.org 66 | Beachte, dass die Aufnahme in die Preload-Liste nicht einfach rückgängig gemacht werden kann! 67 | 68 | ## ToDo 69 | 70 | - CSS auslagern 71 | - Funktionen erweitern 72 | - Readme ergänzen 73 | - Texarea für eigene Header angaben bereitstellen 74 | - Prüfen ob Header schon gesetzt wurden 75 | 76 | ## Autor 77 | 78 | **Friends Of REDAXO** 79 | 80 | * http://www.redaxo.org 81 | * https://github.com/FriendsOfREDAXO 82 | 83 | **Projekt-Lead** 84 | 85 | [getaweb / Oliver Kreischer](https://getaweb.de) 86 | 87 | -------------------------------------------------------------------------------- /boot.php: -------------------------------------------------------------------------------- 1 | getConfig('x-frame-options') != '') { 13 | 14 | $url = ''; 15 | $error = 0; 16 | 17 | if ($addon->getConfig('x-frame-options') == 'allow-from') { 18 | if ($addon->getConfig('xframeurl') != '') { 19 | $url = ' ' . $addon->getConfig('xframeurl'); 20 | } else { 21 | $error = 1; 22 | } 23 | } 24 | 25 | if (!$error) { 26 | if($addon->getConfig('x-content-type-options-nosniff_fb') == 1) { 27 | rex_response::setHeader('X-Frame-Options', '' . $addon->getConfig('x-frame-options') . $url . ''); 28 | } else { 29 | if (rex::isFrontend()) { 30 | rex_response::setHeader('X-Frame-Options', '' . $addon->getConfig('x-frame-options') . $url . ''); 31 | } 32 | } 33 | } 34 | } 35 | 36 | 37 | 38 | // -------- 39 | // -------- X-Content-Type-Options 40 | // -------- 41 | if($addon->getConfig('x-content-type-options-nosniff') != '') { 42 | if($addon->getConfig('x-content-type-options-nosniff_fb') == 1) { 43 | rex_response::setHeader('X-Content-Type-Options', 'nosniff'); 44 | } else { 45 | if (rex::isFrontend()) { 46 | rex_response::setHeader('X-Content-Type-Options', 'nosniff'); 47 | } 48 | } 49 | } 50 | 51 | 52 | 53 | 54 | // -------- 55 | // -------- X-Powered-By 56 | // -------- 57 | if($addon->getConfig('x-powered-by-always-unset') != '') { 58 | if($addon->getConfig('x-powered-by_fb') == 1) { 59 | rex_response::setHeader('X-Powered-By', 'always unset'); 60 | } else { 61 | if (rex::isFrontend()) { 62 | rex_response::setHeader('X-Powered-By', 'always unset'); 63 | } 64 | } 65 | } 66 | 67 | 68 | 69 | // -------- 70 | // -------- X-Powered-By 71 | // -------- 72 | if($addon->getConfig('referrerpolicy') != '') { 73 | if($addon->getConfig('referrerpolicy_fb') == 1) { 74 | rex_response::setHeader('Referrer-Policy', ''.$addon->getConfig('referrerpolicy').''); 75 | } else { 76 | if (rex::isFrontend()) { 77 | rex_response::setHeader('Referrer-Policy', ''.$addon->getConfig('referrerpolicy').''); 78 | } 79 | } 80 | } 81 | 82 | 83 | /* 84 | 85 | rex_response::setHeader('Server', 'always unset'); 86 | rex_response::setHeader('Strict-Transport-Security', 'max-age=31536000'); 87 | rex_response::setHeader('Content-Security-Policy', 'connect-src "self"'); 88 | 89 | rex_response::setHeader('Feature-Policy', "geolocation 'none'; midi 'none'; camera 'none'; usb 'none'; magnetometer 'none'; accelerometer 'none'; vr 'none'; speaker 'none'; ambient-light-sensor 'none'; gyroscope 'none'; microphone 'none'"); 90 | */ 91 | 92 | 93 | -------------------------------------------------------------------------------- /pages/config.php: -------------------------------------------------------------------------------- 1 | get(3)); 8 | 9 | $addon = rex_addon::get('http_header'); 10 | 11 | $func = rex_request('func', 'string'); 12 | 13 | if ($func == 'update') { 14 | 15 | $this->setConfig(rex_post('config', [ 16 | ['x-frame-options_fb', 'int'], 17 | ['x-frame-options', 'string'], 18 | ['xframeurl', 'string'], 19 | ['referrerpolicy_fb', 'int'], 20 | ['referrerpolicy', 'string'], 21 | ['strict-transport-security_lifetime', 'int'], 22 | ['strict-transport-security_subdomain', 'string'], 23 | ['strict-transport-security_preload', 'int'], 24 | ['x-powered-by_fb', 'int'], 25 | ['x-powered-by-always-unset', 'int'], 26 | ['x-content-type-options-nosniff_fb', 'int'], 27 | ['x-content-type-options-nosniff', 'int'], 28 | 29 | ])); 30 | 31 | echo rex_view::success('Die Einstellungen wurden gespeichert'); 32 | } 33 | 34 | // -------- 35 | // -------- X-Frame-Options 36 | // -------- 37 | $content .= '
'; 38 | $content .= '
'; 39 | $content .= 'X-Frame-Options'; 40 | $content .= 'Mehr Informationen'; 41 | $content .= ''; 42 | 43 | $content .= '
'; 44 | $formElements = []; 45 | $n = []; 46 | $n['label'] = ''; 47 | $n['field'] = 'getConfig('x-frame-options_fb')) && $this->getConfig('x-frame-options_fb') == '1' ? ' checked="checked"' : '') . ' value="1" />'; 48 | $formElements[] = $n; 49 | 50 | $fragment = new rex_fragment(); 51 | $fragment->setVar('elements', $formElements, false); 52 | $content .= $fragment->parse('core/form/checkbox.php'); 53 | $content .= '
'; 54 | 55 | $formElements = []; 56 | $n = []; 57 | $n['label'] = ''; 58 | $select = new rex_select(); 59 | $select->setId('xframeselect'); 60 | $select->setAttribute('class', 'form-control'); 61 | $select->setName('config[x-frame-options]'); 62 | $select->addOption('-', ''); 63 | $select->addOption('deny', 'deny'); 64 | $select->addOption('sameorigin', 'sameorigin'); 65 | $select->addOption('allow-from uri', 'allow-from'); 66 | $select->setSelected($this->getConfig('x-frame-options')); 67 | $n['field'] = $select->get(); 68 | $formElements[] = $n; 69 | 70 | $fragment = new rex_fragment(); 71 | $fragment->setVar('elements', $formElements, false); 72 | $content .= $fragment->parse('core/form/form.php'); 73 | 74 | $content .= '
'; 75 | $formElements = []; 76 | $n = []; 77 | $n['label'] = ''; 78 | $n['field'] = ''; 79 | $formElements[] = $n; 80 | 81 | $fragment = new rex_fragment(); 82 | $fragment->setVar('elements', $formElements, false); 83 | $content .= $fragment->parse('core/form/form.php'); 84 | $content .= '
'; 85 | 86 | if ($addon->getConfig('x-frame-options') == 'allow-from' AND $addon->getConfig('xframeurl') == '') { 87 | $content .= '

Sofern bei der Auswahl allow-from uri ausgewählt wurde muß zwingend eine URL angegeben werden.

'; 88 | } 89 | 90 | $content .= '
'; 91 | $content .= ' 92 | 111 | '; 112 | 113 | $content .= '
'; 114 | 115 | 116 | // -------- 117 | // -------- X-Powered-By 118 | // -------- 119 | 120 | $content .= '
'; 121 | $content .= '
'; 122 | $content .= 'X-Powered-By'; 123 | $content .= 'Mehr Informationen.'; 124 | $content .= ''; 125 | 126 | 127 | $content .= '
'; 128 | $formElements = []; 129 | $n = []; 130 | $n['label'] = ''; 131 | $n['field'] = 'getConfig('x-powered-by_fb')) && $this->getConfig('x-powered-by_fb') == '1' ? ' checked="checked"' : '') . ' value="1" />'; 132 | $formElements[] = $n; 133 | 134 | $fragment = new rex_fragment(); 135 | $fragment->setVar('elements', $formElements, false); 136 | $content .= $fragment->parse('core/form/checkbox.php'); 137 | $content .= '
'; 138 | 139 | 140 | $formElements = []; 141 | $n = []; 142 | $n['label'] = ''; 143 | $n['field'] = 'getConfig('x-powered-by-always-unset')) && $this->getConfig('x-powered-by-always-unset') == '1' ? ' checked="checked"' : '') . ' value="1" />'; 144 | $formElements[] = $n; 145 | $fragment = new rex_fragment(); 146 | $fragment->setVar('elements', $formElements, false); 147 | $content .= $fragment->parse('core/form/checkbox.php'); 148 | $content .= '
'; 149 | 150 | $content .= ' 151 | 165 | '; 166 | 167 | $content .= '
'; 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | // -------- 176 | // -------- Referrer-Policy 177 | // -------- 178 | 179 | $content .= '
'; 180 | $content .= '
'; 181 | $content .= 'Referrer-Policy'; 182 | $content .= 'Mehr Informationen.'; 183 | $content .= ''; 184 | 185 | $content .= '
'; 186 | $formElements = []; 187 | $n = []; 188 | $n['label'] = ''; 189 | $n['field'] = 'getConfig('referrerpolicy_fb')) && $this->getConfig('referrerpolicy_fb') == '1' ? ' checked="checked"' : '') . ' value="1" />'; 190 | $formElements[] = $n; 191 | 192 | $fragment = new rex_fragment(); 193 | $fragment->setVar('elements', $formElements, false); 194 | $content .= $fragment->parse('core/form/checkbox.php'); 195 | $content .= '
'; 196 | 197 | $formElements = []; 198 | $n = []; 199 | $n['label'] = ''; 200 | $select = new rex_select(); 201 | $select->setId('referrerpolicy'); 202 | $select->setAttribute('class', 'form-control'); 203 | $select->setName('config[referrerpolicy]'); 204 | $select->addOption('-', ''); 205 | $select->addOption('no-referrer', 'no-referrer'); 206 | $select->addOption('no-referrer-when-downgrade', 'no-referrer-when-downgrade'); 207 | $select->addOption('same-origin', 'same-origin'); 208 | $select->addOption('origin', 'origin'); 209 | $select->addOption('strict-origin', 'strict-origin'); 210 | $select->addOption('origin-when-cross-origin', 'origin-when-cross-origin'); 211 | $select->addOption('strict-origin-when-cross-origin', 'strict-origin-when-cross-origin'); 212 | $select->addOption('unsafe-url', 'unsafe-url'); 213 | $select->setSelected($this->getConfig('referrerpolicy')); 214 | $n['field'] = $select->get(); 215 | $formElements[] = $n; 216 | 217 | $fragment = new rex_fragment(); 218 | $fragment->setVar('elements', $formElements, false); 219 | $content .= $fragment->parse('core/form/form.php'); 220 | 221 | $content .= '
'; 222 | 223 | $content .= ' 224 | 266 | '; 267 | 268 | $content .= '
'; 269 | 270 | 271 | 272 | // -------- 273 | // -------- X-Content-Type-Options 274 | // -------- 275 | 276 | $content .= '
'; 277 | $content .= '
'; 278 | $content .= 'X-Content-Type-Options'; 279 | $content .= 'Mehr Informationen.'; 280 | $content .= ''; 281 | 282 | 283 | $content .= '
'; 284 | $formElements = []; 285 | $n = []; 286 | $n['label'] = ''; 287 | $n['field'] = 'getConfig('x-content-type-options-nosniff_fb')) && $this->getConfig('x-content-type-options-nosniff_fb') == '1' ? ' checked="checked"' : '') . ' value="1" />'; 288 | $formElements[] = $n; 289 | 290 | $fragment = new rex_fragment(); 291 | $fragment->setVar('elements', $formElements, false); 292 | $content .= $fragment->parse('core/form/checkbox.php'); 293 | $content .= '
'; 294 | 295 | 296 | $formElements = []; 297 | $n = []; 298 | $n['label'] = ''; 299 | $n['field'] = 'getConfig('x-content-type-options-nosniff')) && $this->getConfig('x-content-type-options-nosniff') == '1' ? ' checked="checked"' : '') . ' value="1" />'; 300 | $formElements[] = $n; 301 | $fragment = new rex_fragment(); 302 | $fragment->setVar('elements', $formElements, false); 303 | $content .= $fragment->parse('core/form/checkbox.php'); 304 | $content .= '
'; 305 | 306 | $content .= ' 307 | 321 | '; 322 | 323 | $content .= '
'; 324 | 325 | /* 326 | // -------- 327 | // -------- Strict-Transport-Security 328 | // -------- 329 | 330 | $content .= '
'; 331 | $content .= '
'; 332 | $content .= 'Strict-Transport-Security (** noch ohne Funktion **)'; 333 | $content .= 'Wichtige Informationen. Unbedingt lesen!'; 334 | $content .= ''; 335 | 336 | $formElements = []; 337 | $n = []; 338 | $n['label'] = ''; 339 | $n['field'] = ''; 340 | $formElements[] = $n; 341 | $fragment = new rex_fragment(); 342 | $fragment->setVar('elements', $formElements, false); 343 | $content .= $fragment->parse('core/form/form.php'); 344 | 345 | 346 | $formElements = []; 347 | $n = []; 348 | $n['label'] = ''; 349 | $n['field'] = 'getConfig('strict-transport-security_subdomain')) && $this->getConfig('strict-transport-security_subdomain') == '1' ? ' checked="checked"' : '') . ' value="1" />'; 350 | $formElements[] = $n; 351 | 352 | $fragment = new rex_fragment(); 353 | $fragment->setVar('elements', $formElements, false); 354 | $content .= $fragment->parse('core/form/checkbox.php'); 355 | 356 | 357 | $formElements = []; 358 | $n = []; 359 | $n['label'] = ''; 360 | $n['field'] = 'getConfig('strict-transport-security_preload')) && $this->getConfig('strict-transport-security_preload') == '1' ? ' checked="checked"' : '') . ' value="1" />'; 361 | $formElements[] = $n; 362 | $fragment = new rex_fragment(); 363 | $fragment->setVar('elements', $formElements, false); 364 | $content .= $fragment->parse('core/form/checkbox.php'); 365 | 366 | if (($addon->getConfig('strict-transport-security_subdomain') == '1' OR $addon->getConfig('strict-transport-security_preload') == '1') AND $addon->getConfig('strict-transport-security_lifetime') == '') { 367 | $content .= '

Es muß eine Lebensdauer angegeben werden!

'; 368 | } 369 | 370 | $content .= '
'; 371 | 372 | $content .= ' 373 | 387 | '; 388 | 389 | $content .= '
'; 390 | 391 | 392 | 393 | */ 394 | 395 | 396 | 397 | 398 | // -------- Buttons 399 | 400 | $formElements = []; 401 | $n = []; 402 | $n['field'] = 'Abbrechen'; 403 | $formElements[] = $n; 404 | 405 | $n = []; 406 | $n['field'] = ''; 407 | $formElements[] = $n; 408 | 409 | $fragment = new rex_fragment(); 410 | $fragment->setVar('elements', $formElements, false); 411 | $buttons = $fragment->parse('core/form/submit.php'); 412 | 413 | 414 | // -------- generate Page 415 | 416 | $fragment = new rex_fragment(); 417 | $fragment->setVar('class', 'edit'); 418 | $fragment->setVar('title','Einstellungen'); 419 | $fragment->setVar('body', $content, false); 420 | $fragment->setVar('buttons', $buttons, false); 421 | $content = $fragment->parse('core/page/section.php'); 422 | 423 | $content = ' 424 |
425 | 426 | ' . $content . ' 427 |
'; 428 | 429 | echo $content; 430 | 431 | ?> 432 | 433 | 451 | 452 | 571 | --------------------------------------------------------------------------------