| • schlechter Code |
| • Fehlermeldungen |
| • besserer Code |
| • Code kopieren |
| • Fortress ?? |
| • weitere Schmankerl |
| • phpNuke 7.5 |
Fortress
Fortress is a unique application that provides a multi-faceted approach to security
and alert notifications. Fortress is a live work in progress and will be updated
when milestones are met, and if any patches are released.
Fortress is the first in its class that doesn't interface with PHP-Nuke. Fortress
protects itself on sites using REGISTER_GLOBALS, and it takes on a truly intelligent
operation where users do not know of its existence. Silent operation ensures
all suspects continue leaving more proof and evidence that they are being malicious.
This information arms you in whatever path you take for action.
Union Tap Code (UTC)
UTC catches not just UNION SQL Injections, but also any attempts to fool current
filtering technologies against C-Like comments. UTC monitors any attempts on
both the plaintext and base64 injections.
Nuke Cops
An Official PHP-Nuke Development Website working hard to promote positive PHP-Nuke
enhancement and security for a global community of webmasters, admins, and users."
Grosse Worte, aber....
Mit einfachen Worten: das Tool prüft ob dem script per GET (Browserzeile) das Wort UNION oder ein Sternchen * übergeben wird. Ist dies der Fall, wird dem Webmaster ein Mail mit einer diesbezüglichen Meldung geschickt und der weitere Scriptablauf abgebrochen, bzw. auf die Startseite umgeleitet.
Um dies zu sehen werden wir mal den Code etwas genauer ansehen.
Nachfolgend der Code, der sich in 2 Teile splittet. Einmal der Codeschnippsel,
der in die mainfile.php eingefügt werden soll, weiterhin der Code der in der
fortress.php enthalten ist. In der linken Spalte befindet sich der eigentliche
Code, in der Mitte eine kurze Erläuterung was in dieser Codezeile geschieht
und rechts davon meine Bemerkungen dazu. Die Reihenfolge der Codeschnippsel
entspricht ungefähr dem Scriptablauf.
Fortress Beta 1 by Nuke Cops, Zhen-Xjell
http://nukecops.com - Computer Cops, LLC
Copyright 2004, All Rights Reserved
Hier beginnt der Code, der in der mainfile.php integriert wird.. |
|||
| // Union Tap Code (UTC) - Fortress Integrated |
|
ohne Worte... |
|
| // Copyright Zhen-Xjell 2004 http://nukecops.com |
|||
| // Beta 4b Code to prevent UNION SQL Injections |
|||
| // GNU GPL License 2 |
|||
| // The following catches C-like comment code within all SQL Injections, not just Union. |
|||
| // White paper available here: http://www.securiteam.com/securityreviews/5FP0O0KCKM.html |
|||
| // Also caught are plaintext and base64 version of the Union SQL Injection code. |
|||
| define('ZERO', true); |
Die Konstante, die in der fortress.php gecheckt wird, um zu verhindern, dass diese direkt aufgerufen wird. |
Einfacher wäre es, den code in die fortress.php einzubinden und nur diese zu includen | |
| include('fortress.php'); |
Die fortress.php includen |
||
Der Inhalt der fortress.php |
|||
| /* Start Configuration Section */ |
|||
| // You Must Configure This Section |
|||
| $sitename = "Nuke Cops"; // Enter your website name here. |
Verschiedene Variablen für den eMailversand deklarieren. |
Eigentlich in phpNuke überflüssig, wenn man
vorher die config.php includet. In der config.php werden Variablen mit
sinngemäss gleichem inhalt bereits deklariert. |
|
| $domain = "http://nukecops.com"; // Enter your full website URL here. Include "http://". Do not include a trailing "/". |
|||
| $to = "zx@nukecops.com"; // Enter the email address Alerts should be sent to. |
|||
| $realname = "Zhen-Xjell"; // Enter the full name such that email Alerts may be properly titled. |
|||
| $subject = "Fortress Alarm @ $sitename"; // You may change the Subject here (optional). |
Der Betreff für das eMail |
||
| /* End Configuration Section */ |
|||
| /* Do Not Edit Settings Below */ |
|||
| $ver = "Beta 1.01"; // Internal variable for Fortress version. |
Versionsnummer, auch für das eMail |
||
| if (defined('ZERO')) { |
Dies verhindert, dass der nachfolgende Code nicht ausgeführt wird, wenn die fortress.php direkt aufgerufen wird |
||
| // Protecting against possible Register_Global attacks |
Das soll verhindern, dass bei register_globals = ON, dem script bestimmte Variablen untergeschoben werden |
Völliger Schwachsinn, weil in den anschliessenden Zeilen, genau diese Variablen expliziet deklariert werden. Zudem werden diese Variablen ausser $loc nur für das zu versendende eMail benötigt. |
|
| unset($matches); |
|||
| unset($rawloc); |
|||
| unset($loc); |
|||
| unset($addr); |
|||
| unset($refer); |
|||
| unset($agents); |
|||
| unset($method); |
|||
| unset($cookies); |
|||
| unset($authors); |
|||
| unset($uri); |
|||
| unset($rawuri); |
|||
| unset($port); |
|||
| unset($host); |
|||
| $server=$_SERVER["SERVER_NAME"]; |
Versch. Variablen für die eMail belegen |
||
| $rawloc=$_SERVER["QUERY_STRING"]; |
|||
| $loc=rawurldecode($_SERVER["QUERY_STRING"]); |
Alle dem script per GET übergebenen Variablen in einem gemeinsamen String, inkl. den Variablennamen. |
ACHTUNG: Die Möglichkeit der Variablenübergabe per POST und COOKIE wird hier nicht beachtet! |
|
| $addr=$_SERVER["REMOTE_ADDR"]; |
Weitere Variablen für die eMail belegen. |
Beachte: Sämtliche Variablen werden im globalen Scope abgelegt, obwohl fast alle, nur für die eMail benötigt werden, wenn ein Fehler detektiert wird. Da die Namen recht allgemein gehalten sind, kann es passieren, dass manche Module nicht funktionieren, weil sie die gleichen Variablennamen als Übergabeparameter erwarten, die hier aber überschrieben werden. Eigentlich sind sämtliche Variablen überflüssig, da sie ausnahmslos, aus sowieso vorhandenen, globalen, Variablen generiert werden und dadurch direkt im Mail bzw. als "Prüfstring" verwendet werden können. |
|
| $refer=$_SERVER["HTTP_REFERER"]; |
|||
| $agents=$_SERVER["HTTP_USER_AGENT"]; |
|||
| $cookiess=explode(":", base64_decode($_COOKIE["user"])); |
|||
| $authorss=explode(":", base64_decode($_COOKIE["admin"])); |
|||
| $rawuri=$_SERVER["REQUEST_URI"]; |
|||
| $uri=rawurldecode($_SERVER["REQUEST_URI"]); |
|||
| $port=$_SERVER["REMOTE_PORT"]; |
|||
| $host=$_SERVER["REMOTE_HOST"]; |
|||
| } else { Header("Location: index.php"); } |
Wenn fortress.php direkt aufgerufen wird, zur index.php umleiten |
||
| function AlertMail($method) { |
Funktion zum Senden der eMail |
||
| global $server, $rawloc, $loc, $addr, $refer, $agents, $sitename, $domain, $to, $realname, $ver, $matches, $method, $subject, $cookies, $authors, $uri, $rawuri, $port, $host; |
Hier werden die für das eMail benötigten Variablen aus dem globalen Scope importiert. |
Wie oben schon angemerkt, völlig unsinnig. Die Variablen können direkt in dieser Funktion deklariert werden. |
|
| if ($method == "CLIKE") { $matches[1] = "A C-Like Comment Code Entry"; } |
Je nachdem ob ein * oder das Wort UNION im Querystring vorkommt, wird der Funktion die Variable $method übergeben und daraus eine Meldung für das mail generiert |
Warum erst ausserhalb der Funktion die Varible $method mit dem String "CLIKE" belegen, wenn der Wert hier wieder geändert und als $matches[1] weiterverwendet wird | |
| $body = "Fortress Alarm!\r\n" |
Aus den verschiedenen Variablen den Mailtext generieren. |
||
| ."---------------\r\n" |
|||
| ."\r\n" |
|||
| ."An attack on $server has triggered Fortress to send a high-priority email to you." |
|||
| ." Other methods may be included in this attack, but it only takes one to trigger an Alert." |
|||
| ." It is that trigger which is reported below:\r\n\r\n" |
|||
| ."Timestamp: " . date("l dS of F Y h:i:s A") ."\r\n" |
|||
| ."Attack: $matches[1]\r\n" |
|||
| ."Query: $loc\r\n" |
|||
| ."Raw Query: $rawloc\r\n" |
|||
| ."Method: $domain" . "$uri\r\n" |
|||
| ."Raw Method: $domain" . "$rawuri\r\n" |
|||
| ."Suspect Host: $host\r\n" |
|||
| ."Suspect IP: $addr\r\n" |
|||
| ."Remote Port: $port\r\n" |
|||
| ."Suspect Agents: $agents\r\n" |
|||
| ."User Cookie: $cookies[1]\r\n" |
|||
| ."Admin Cookie: $authors[0]\r\n" |
|||
| ."Referred: $refer\r\n" |
|||
| ."\r\n\r\n" |
|||
| ."---\r\n" |
|||
| ."Fortress $ver\r\n" |
|||
| ."Brought to you exclusively by http://nukecops.com. Keep it secure!\r\n"; |
|||
| $to = $realname . " <$to>"; |
Empfänger des mails |
||
| $headers = "From: Fortress\r\n" |
Aus den verschiedenen Variablen den Header für das eMail generieren. |
die versteckte Werbung für nukecops ist recht penetrant... | |
| ."Priority: urgent\r\n" |
|||
| ."Importance: High\r\n" |
|||
| ."Precedence: special-delivery\r\n" |
|||
| ."Organization: $sitename\r\n" |
|||
| ."MIME-Version: 1.0\r\n" |
|||
| ."Content-Type: text/plain\r\n" |
|||
| ."Content-Transfer-Encoding: 8bit\r\n" |
|||
| ."X-Priority: 1\r\n" |
|||
| ."X-MSMail-Priority: High\r\n" |
|||
| ."X-Mailer: PHP/" . phpversion() ."\r\n" |
|||
| ."X-Fortress: $ver by http://nukecops.com\r\n"; |
|||
| mail($to, $subject, $body, $headers); |
Mail absenden |
||
| Header("Location: index.php"); |
Weiterleiten zur Startseite. |
Das Script wird dadurch normalerweise beendet. Allerdings nicht, wenn durch einen unvorhergesehenen Fehler bereits eine Textausgabe erfolgt ist. Dann kann der header nicht gesendet werden und das script läuft weiter. Dies kann dazu führen, dass die sql_injection trotzdem ausgeführt wird. |
|
| } |
|||
| function ReleaseVars() { |
Diese Funktion soll vermutlich bewirken, dass, wenn keine injection erkannt wurde, die vielen, für das mail generierten Variablen, aus dem globalen Scope entfernt werden. |
Das funktioniert so aber nicht, weil diese Variablen innerhalb der Funktion überhaupt nicht existieren, also auch nicht gelöscht werden können. Die Variablen bleiben weiter im globalen Scope verfügbar. Wie oben geschrieben, sind die Variablen sowieso unnötig. |
|
| unset($matches); |
|||
| unset($rawloc); |
|||
| unset($loc); |
|||
| unset($addr); |
|||
| unset($refer); |
|||
| unset($agents); |
|||
| unset($method); |
|||
| unset($cookies); |
|||
| unset($authors); |
|||
| unset($uri); |
|||
| unset($rawuri); |
|||
| unset($port); |
|||
| unset($host); |
|||
| unset($subject); |
|||
| unset($sitename); |
|||
| unset($domain); |
|||
| unset($to); |
|||
| unset($realname); |
|||
| } |
|||
Hier geht der Code in der mainfile.php weiter |
|||
| if (strstr($loc,"*")) { |
Die Variable $loc wird in der fortress.php deklariert. Sie enthält den dem script per GET übergebenen Querystring. |
Unsinn |
|
| $method = "CLIKE"; |
Die "Hack-Methode" für das eMail bestimmen |
unnötig, den String "CLIKE" kann man der Funktion dirk übergeben | |
| AlertMail($method); |
EMail absenden und Script abbrechen. |
Weiteres dazu siehe bei dieser Funktion... |
|
| } |
|||
| if (preg_match("/([OdWo5NIbpuU4V2iJT0n]{5}) /", $loc, $matches)) { |
Prüfen, ob in der Variable $loc (der querystring) das Wort "Union", gefolgt von einem "normalen" Leerzeichen enthalten ist. |
Unsinn und funktioniert nicht In Mysql werden als Leerzeichen aber auch andere Sonderzeichen, wie Tabulator, Zeilenumbruch usw. (Spaces) anerkannt. So kann man weiterhin das Wort Union einschleusen indem man anstatt dem Leerzeichen z.B. einenTabulator (%09) verwendet. Der Ausdruck ist somit wirkungslos. Umgekehrt, stellt man sich einen Übergabeparameter vor, in dem das Wort "Onion" (engl. Zwiebel) vorkommt, findet der Ausdruck einen Angriffsversuch.... |
|
| $method = "UNION"; |
Die "Hack-Methode" für das eMail bestimmen |
unnötig, den String "UNION" kann man der Funktion dirk übergeben | |
| AlertMail($method); |
EMail absenden und Script abbrechen. |
Weiteres dazu siehe bei dieser Funktion... |
|
| } |
|||
| ReleaseVars(); |
Versuch, die unnötigen Variablen zu löschen |
weiteres dazu siehe bei dieser Funktion... |
|
Das Tool kann primitive Atacken durch scriptkiddies abfangen, berücksichtigt dabei aber nur sql_injection über mySql-Union-Select. Dieser Hack ist eigentlich nur interessant, um Passwort-Hash's aus der User oder Admintabelle auszulesen. Leider hat hier phpNuke ein grundsätzliches Sicherheitsloch, da es mit einem kleinen Trick möglich ist, sich auch mit solch einem Passwort-Hash als Administrator einzuloggen. Eine direkte Datenmanipulation per Union ist nicht möglich. Andere, teils viel gefährlichere Angriffe, wie mit dem Verweis auf das Whitepaper versprochen, werden aber nicht abgefangen.
Es wird nicht berücksichtigt, dass Scriptvariablen auch per POST oder Cookies eingeschleust werden können. Ein ernsthafter Hacker bastelt sich in wenigen Minuten ein HTML-Formular und schickt die Variablen per POST an das script.
Weiterhin sind durch die primitive Abfrage der Variablen, Fehlfunktionen nicht auszuschliessen [beispiel]
In phpNuke 7.3 wurde von FB der mainfile-code 1:1 übernommen....