-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathboot.php
More file actions
216 lines (181 loc) · 8.2 KB
/
boot.php
File metadata and controls
216 lines (181 loc) · 8.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
<?php
/**
* Boot-Datei für das Upkeep AddOn
*/
use KLXM\Upkeep\Upkeep;
use KLXM\Upkeep\IntrusionPrevention;
use KLXM\Upkeep\MailSecurityFilter;
use KLXM\Upkeep\MailReporting;
// Falls Setup aktiv ist, nichts tun
if (rex::isSetup()) {
return;
}
// Intrusion Prevention System - ALLERERSTE Prüfung
IntrusionPrevention::checkRequest();
// Stellen Sie sicher, dass die Session immer verfügbar ist
if (!rex_backend_login::hasSession()) {
rex_login::startSession();
}
// Backend-Wartungsmodus-Prüfung DIREKT ausführen (nicht in Extension Point)
// Muss früh geschehen, aber nach Session-Initialisierung
if (rex::isBackend()) {
// Benutzer erstellen falls noch nicht vorhanden
rex_backend_login::createUser();
// Backend-Sperre prüfen wenn Benutzer existiert
if (rex::getUser()) {
Upkeep::checkBackend();
}
}
// Register Extension Point nach dem Laden aller Packages
rex_extension::register('PACKAGES_INCLUDED', static function () {
// Mail Reporting System initialisieren
MailReporting::init();
// Frontend-Wartungsmodus-Prüfung HIER ausführen (nachdem YRewrite geladen ist)
// Damit rex_yrewrite::getCurrentDomain() korrekt funktioniert
if (rex::isFrontend()) {
Upkeep::checkFrontend();
}
// Backend-spezifische Initialisierungen
if (rex::isBackend()) {
// Module-Konfiguration und Seitenausblendung
Upkeep::configureModulePages();
// Statusindikator im Backend-Menü setzen
Upkeep::setStatusIndicator();
// CSS für das Backend laden
rex_view::addCssFile(rex_addon::get('upkeep')->getAssetsUrl('css/upkeep.css'));
// Cronjob für IPS-Cleanup registrieren (nur wenn Cronjob-AddOn verfügbar)
if (rex_addon::get('cronjob')->isAvailable() && !rex::isSafeMode()) {
rex_cronjob_manager::registerType('rex_upkeep_ips_cleanup_cronjob');
}
}
// URL-Redirects (nur wenn kein Wartungsmodus aktiv war)
Upkeep::checkDomainMapping();
}, rex_extension::EARLY);
// Impersonate-Warnung über OUTPUT_FILTER: Inline-Info im Backend (einmal pro Session)
if (rex::isBackend()) {
rex_extension::register('OUTPUT_FILTER', static function (rex_extension_point $ep) {
$addon = rex_addon::get('upkeep');
// Nur wenn Backend-Wartungsmodus aktiv ist
if (!$addon->getConfig('backend_active', false)) {
return $ep->getSubject();
}
// Prüfen ob wir im Impersonate-Modus sind
$impersonator = rex::getImpersonator();
if (!$impersonator instanceof rex_user) {
return $ep->getSubject();
}
// Warnung nur anzeigen wenn der aktuelle Benutzer kein Admin ist
$currentUser = rex::getUser();
if ($currentUser instanceof rex_user && $currentUser->isAdmin()) {
return $ep->getSubject();
}
// Anzeige vorbereiten (sichere Übergabe der Texte an JS mittels json_encode)
$title = $addon->i18n('upkeep_impersonate_warning_title');
$userName = $currentUser instanceof rex_user ? ($currentUser->getName() ?: $currentUser->getLogin()) : 'Unknown User';
$message = $addon->i18n('upkeep_impersonate_warning_message', $userName);
// JSON-sichere Strings für JS (vermeidet manuelles Escaping)
$titleJson = json_encode($title, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT);
$messageJson = json_encode($message, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT);
$content = $ep->getSubject();
// Bootstrap 3 Modal für elegante Anzeige der Warnung
// Anzeige erfolgt nur einmal pro Browser-Session (sessionStorage).
$modalId = 'upkeep-impersonate-modal-' . uniqid();
$modalHtml = '
<!-- Upkeep Impersonate Warning Modal -->
<div class="modal fade" id="' . $modalId . '" tabindex="-1" role="dialog" aria-labelledby="' . $modalId . '-label">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header" style="background-color: #f0ad4e; color: white;">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="' . $modalId . '-label">
<i class="rex-icon rex-icon-warning"></i> ' . rex_escape($title) . '
</h4>
</div>
<div class="modal-body">
<p>' . rex_escape($message) . '</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">' . $addon->i18n('upkeep_impersonate_ok') . '</button>
</div>
</div>
</div>
</div>';
$warningScript = '
<script type="text/javascript" nonce="' . rex_response::getNonce() . '">
(function(){
try {
if (!sessionStorage.getItem("upkeep_impersonate_warning_shown")) {
jQuery(function($){
// Modal beim Laden der Seite anzeigen
$("#' . $modalId . '").modal({
backdrop: "static",
keyboard: false
});
// Session-Flag setzen wenn Modal geschlossen wird
$("#' . $modalId . '").on("hidden.bs.modal", function() {
sessionStorage.setItem("upkeep_impersonate_warning_shown", "1");
});
});
}
} catch(e) {
// Fallback: nichts tun
}
})();
</script>';
// Modal HTML und Script vor dem schließenden body-Tag einfügen
if (strpos($content, '</body>') !== false) {
$content = str_replace('</body>', $modalHtml . $warningScript . '</body>', $content);
}
return $content;
}, rex_extension::LATE);
}
// Mail Security Filter für PHPMailer registrieren
// Nur registrieren wenn PHPMailer-AddOn verfügbar ist
if (rex_addon::get('phpmailer')->isAvailable()) {
rex_extension::register('PHPMAILER_PRE_SEND', static function (rex_extension_point $ep) {
try {
// Mail Security soll nur im Frontend greifen.
if (!rex::isFrontend()) {
return $ep->getSubject();
}
return MailSecurityFilter::filterMail($ep);
} catch (Exception $e) {
// Log der Exception für Debugging
if (rex_addon::get('upkeep')->getConfig('mail_security_debug', false)) {
rex_logger::factory()->log('error', 'Mail Security Filter Error: ' . $e->getMessage());
}
// Exception weiterwerfen um E-Mail-Versand zu stoppen
throw $e;
}
});
}
// Security Advisor API Route registrieren (deprecated)
if (rex::isBackend() && rex_request::get('api') === 'security_advisor') {
include rex_addon::get('upkeep')->getPath('api/security_advisor.php');
exit;
}
// Content Security Policy für Backend - nach Security AddOn Vorbild
if (rex::isBackend() && rex_addon::get('upkeep')->getConfig('csp_enabled', false)) {
// CSP Header direkt in boot.php setzen wie das Security AddOn
$cspRules = [
'script-src' => ["'self'", "'unsafe-inline'", "'unsafe-eval'"],
'style-src' => ["'self'", "'unsafe-inline'"],
'base-uri' => ["'self'"],
'object-src' => ["'none'"],
'frame-ancestors' => ["'self'"],
'form-action' => ["'self'"],
'img-src' => ["'self'", 'data:', 'https:'],
'connect-src' => ["'self'"]
];
// CSP-String bauen
$cspValues = [];
foreach ($cspRules as $directive => $sources) {
$cspValues[] = $directive . ' ' . implode(' ', $sources);
}
$cspHeader = implode('; ', $cspValues);
rex_response::setHeader('Content-Security-Policy', $cspHeader);
rex_response::sendCacheControl('no-store');
rex_response::setHeader('Pragma', 'no-cache');
}