404
"Moment, ich erledige das."
) auf die Platte geschrieben -> Webshell. // Bewusst nicht auf "pearcmd" als Keyword eingeschraenkt, da sich das Angriffsziel (jede per // Path Traversal erreichbare, includebare Datei) aendern kann -> generisch auf "../.." und "". $mc_waf_pearLang = isset($_GET['lang']) && is_string($_GET['lang']) ? $_GET['lang'] : ''; $mc_waf_pearQs = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : ''; if ( $mc_waf_pearLang !== '' && strpos($mc_waf_pearLang, '../..') !== false && ( strpos($mc_waf_pearQs, '') !== false || strpos(urldecode($mc_waf_pearQs), '') !== false ) ) { file_put_contents("/tmp/mc-microwaf.log", date('Y-m-d H:i:s') . " - CVE-2026-87902: Blocked pearcmd LFI/RCE attempt" . " from " . $_SERVER['REMOTE_ADDR'] . " (X-Forwarded-For: " . $mc_waf_xForwardedFor . ") " . "to " . $_SERVER['REQUEST_URI'] . "\n", FILE_APPEND | LOCK_EX); mc_waf_block('CVE-2026-87902'); } //StyleSmuggler: https://sansec.io/research/stylesmuggler // Portierung der nginx-/VCL-Regeln (accord_rce). // 1. Block "/paypal/transparent/response/" if (stripos($_SERVER['REQUEST_URI'], '/paypal/transparent/response/') !== false) { mc_waf_block('StyleSmuggler', 'VCL'); } // Layer 0/1: Query-String, routenunabhaengig. // Keine Admin-Ausnahme wie in der VCL, weil der Admin-Frontname pro Installation // individuell ist und sich nicht generisch erkennen laesst. $mc_waf_ssQs = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : ''; if ($mc_waf_ssQs !== '') { // drei Paesse kollabieren bis zu 3-fach-Encoding, qs2 dient als Rest-%-Detektor fuer >=4x $mc_waf_ssQs2 = urldecode(urldecode($mc_waf_ssQs)); $mc_waf_ssQs3 = urldecode($mc_waf_ssQs2); // Layer 0: PHP-Open-Tag im QS (Stage-1A File-Plant) if (strpos($mc_waf_ssQs3, '') !== false) { mc_waf_block('StyleSmuggler-L0', 'VCL'); } // Layer 1a: styles[] in jeder Encoding-Tiefe. // $_GET-Key deckt einfaches Encoding ab, weil PHP vor dem Klammer-Parsing dekodiert. if ( isset($_GET['styles']) || preg_match('@styles\s*\[@i', $mc_waf_ssQs3) || preg_match('@styles\s*%@i', $mc_waf_ssQs2) ) { mc_waf_block('StyleSmuggler-L1a', 'VCL'); } // Layer 1b: Template-Direktive in text-Parametern (text=, text[]=, text[0]=, ...) // [\s+]* statt \s*, weil ein Leerzeichen im QS als '+' ankommt if ( stripos($mc_waf_ssQs3, '{{') !== false && preg_match('@(^|[&;])text[^=&;]*=[^&;]*\{\{[\s+]*(block|widget|layout|config|template|store|trans|media|view|var|if|depend|inlinecss|css|customvar|for|protocol)\b@i', $mc_waf_ssQs3) ) { mc_waf_block('StyleSmuggler-L1b', 'VCL'); } } // Layer 2: Request-Body if ($_SERVER['REQUEST_METHOD'] === 'POST' || $_SERVER['REQUEST_METHOD'] === 'PUT') { $mc_waf_ssBody = $mc_waf_input; if ($mc_waf_ssBody === '' && !empty($_POST)) { // php://input ist bei multipart/form-data leer $mc_waf_ssBody = http_build_query($_POST); } // ohne ^-Anker: faengt Store-Code-Praefixe, /index.php/... und Unterverzeichnis-Installationen // zweite Alternative deckt JSON-Notation ab, auch mit escapten Quotes in verschachtelten Strings if ( preg_match('@(^|/)(graphql|paypal|rest|sales|multishipping|newsletter)(/|\?|$)@i', $_SERVER['REQUEST_URI']) && preg_match('@styles\s*(\[|%5b)|\\\\?"styles\\\\?"\s*:\s*\[@i', $mc_waf_ssBody) ) { mc_waf_block('StyleSmuggler-L2b', 'VCL'); } // engere Routenliste als bei L2b: /rest, /sales und /newsletter fuehren im Backend // legitim Direktiven im Body (CMS-API, Newsletter-Templates, Order-Comments) if ( preg_match('@(^|/)(graphql|paypal|multishipping)(/|\?|$)@i', $_SERVER['REQUEST_URI']) && stripos($mc_waf_ssBody, '{{') !== false && preg_match('@\{\{[\s+]*(block|widget|layout|config|template|store|trans|media|view|var|if|depend|inlinecss|css|customvar|for|protocol)\b@i', $mc_waf_ssBody) ) { mc_waf_block('StyleSmuggler-L2a', 'VCL'); } }