Framework, Framework, Framework. Wenn diese 3 Worte, die übrigens dieselben sind (ha, da war der Trick), Verwirrung bei Ihnen auslösen –> oben rechts kann man den Browser schließen - oder aber Sie lesen das hier trotzdem und protzen morgen bei Ihren Arbeitskollegen mit dem neu erworbenen Wissen.
Vorab: In diesem Artikel wird auf das Schema von Application Frameworks eingegangen.
Die letzten Tage habe ich mich mal wieder intensiver mit Sicherheit im Netz beschäftigt. Und es stellt sich wie eh und je die Frage was ein “sicherer Login” ist. Ist eine IP ein Identifikationsfaktor?
if ip==127.0.0.1 ? true : false;
Und was ist, wenn die IP plötzlich jemand anders hat, weil’s keine static ist? Dann bin ich sofort ausgeloggt, ok, das ist nicht unsicher, aber sicher unpraktisch.
Doch wie stehts um das typische Username+Password-Geflecht, gespeichert in Cookies? Die Methode ist relativ einfach: Username und verschlüsseltes Passwort werden gespeichert und bei Seitenbesuch ausgelesen –> gibt es Übereinstimmungen ist / wird man eingeloggt. Wenn jedoch jemand durch geschicktes XSS-Cracking die Cookies ausliest kann sich dieser einloggen und das Passwort abändern und schon ist der Account übernommen.
Wiederholt steh ich also vor der Frage: Was ist ein sicherer Login?
Nach 3 Tagen Bedenkzeit stellte ich es fest - es gibt keinen sicheren Login. Es gibt ein nettes Sprichwort hierfür, das sich in meinen Versuchen eigentlich bestätigt hat: Der Aufwand für einen Cracker muss wesentlich geringer sein, als das Ergebnis seines Versuchs, da ansonsten ein Verlust entsteht, zeitlich und praktisch betrachtet (abgesehen von sgn. Script-Kiddies).
Man kann einen Login demnach so sicher wie möglich machen, solange es aber durch verschiedene Techniken möglich ist an Daten eines Users ranzukommen wird es prinzipiell immer möglich sein, einen Account zu hacken und zu cracken. Ein IP-Binding ist aber der falsche Versuch, da er mehr Frust als Sicherheit bringt bei dynamischen IPs. Eine leicht Umgehung dieses Problems stellt das Splitting einer IP dar. Statt 123.123.123.123 betrachtet man einfach nur noch 123.123.123.% (%=Platzhalter). Dann vergleicht man jeweils nur noch die ersten 3 Sub-IPs. Richtig lustig wird das aber, sobald sich IPv6 richtig durchsetzt, deswegen neige ich mittlerweile von dieser Methode ab.
Sehr sinnvoll ist dagegen eher die Speicherung von USER_AGENT, ACCEPT_LANGUAGE, etc., also festen Konstanten, in eine Datenbank. Dort steht auch ein sogenannter Cookie-Hash, den der entsprechende in einem seiner Cookies zusammen mit Username und verschl. Passwort hat.
In PHP geschrieben hätten wir also sowas:
$_COOKIE['uname'] = 'myusername'; $_COOKIE['crypted_pass'] = 'dsf34§1ayYdfe$/2assdf'; $_COOKIE['cookie_hash'] = 'any_cookie_hash_in_here_34837121';
Wenn der User nun unsere Seite besucht werden die gespeicherten Daten und die Cookie-Daten verglichen. Wenn der Browser und die Sprache immernoch dieselbe ist, ist es umso wahrscheinlicher, dass es tatsächlich derselbe User ist wie zuvor. Wenn mehrere solcher fester Werte verknüpft werden kann man eine bestmögliche Sicherheit garantieren. Hier kommt wieder der Hacking-Aufwand in’s Spiel. Der Hacker muss nun auch noch einige andere Sachen wissen, bevor er tatsächlich einbrechen kann.
Im Endeffekt bringt natürlich Aufklärung direkt beim User am meisten, aber das hilft wahrscheinlich genausoviel wie IE6-Usern dazu verführen zu wollen, doch bitte den IE7,IE8 oder den Firefox zu benutzen.
Mit der folgenden Funktion wird es ganz einfach zu verhindern, dass die eigene Seite geframed wird. Der wesentliche Grund, warum man dies tun sollte, ist wohl, dass XSS-Angriffe dadurch minimiert werden können. Ausserdem können andere Seiten nicht mehr unerwünscht die eigenen Inhalte aufrufen.
1 2 3 4 | function AntiFrame(){ if(top!=self) top.location.href = window.location.href; } |
1 | <body onload="AntiFrame()"> |
Natürlich funktioniert das nur, wenn JavaScript aktiviert ist. Wenn nicht wird es jedoch gleichzeitig schwerer einen XSS-Angriff auszuführen. Da XSS also ausschliesslich mit JavaScript-Gefrickel gemacht wird, ergänzt sich das Ganze.
Achtung:
Bitte verwendet diese Version von ISPEM nicht (mehr)!
Hier ist ein Fehler unterlaufen, der Dank P.B. enthüllt wurde.
Bitte verwendet folgenden Link um eine korrekte sichere ISPEM-Funktion zu bekommen: ISPEM Sicherheitsupdate
Individual Secure Password Encryption Method, das ist ISPEM. Dahinter steckt nicht viel Innovatives, aber Nützliches. Auch heute sieht man, wenn man in den Quellcode schaut, bei vielen Programmen noch die MD5-Verschlüsselung.
Passwörter werden MD5-verschlüsselt in die DB eingetragen und verglichen. Um eingeloggt zu bleiben muss das verschlüsselte Passwort aber im Cookie gespeichert werden und hier beginnt das Risiko von normaler MD5-Verschlüsselung: Wird das Cookie durch XSS oder auch auf andere Weise gestohlen lässt man entweder Bruteforce, oder noch viel einfacher, einen Decryptor drüberlaufen. Denn viele wissen nicht, dass es offen zugängliche MD5-Datenbanken gibt, die jede Verschlüsselung speichern und demnach auch reversibel funktionieren.
Die Lösung ist ISPEM. ISPEM ist die Verknüpfung verschiedener Methoden mit MD5.
define('ISPEM_FCONST_SPL','your_unknown_value1',true); define('ISPEM_SCONST_SPL','your_unknown_value2',true); function ISPEM_encrypt($clear_password){ $p = str_rot13($clear_password); $p = base64_encode($p); $S1 = md5(ISPEM_FCONST_SPL,true); $S2 = md5(ISPEM_SCONST_SPL,false); $SC = md5(strlen($p).$S1,false); $p = substr(($S2.$SC),0,45); return $p; //liefert einen 45 zeichenlangen Encrypted String, unknackbar }
Dadurch, dass der String abgeschnitten ist ist es prinzipiell unmöglich, dass wahre Passwort rauszufinden.
Wäre die kodierte konstante an hinterer Stelle, wäre es einfacher, da man dann nach Abzug von 13 Zeichen “nur” noch den SC-String hätte.
Bei ISPEM fehlt dem Cracker aber ein wichtiger Teil des SC-Strings, den er nicht “schätzen” kann, da er das Passwort nicht kennt.
Mit ISPEM ist man in Sachen Verschlüsselung auf der richtigen Seite. Natürlich gibt es keine ISPEM_decode, da es nicht reversibel ist.
ISPEM steht natürlich völlig frei zur Nutzung.
Nachtrag (So, 19. Juli 2009):
Das substr() kann natürlich auch variieren. Eine Idee wäre z.B. statt einfach nur substr($str,0,45) ein mehrteilig abgeschnittenes Crypting zu nutzen, durch substr($str, 4, 49);.
Das vaib-eigene Framework ist momentan im Einsatz in einer großen Projektentwicklung - Senso heißt das Framework übrigens. Die Template-Engine von Senso wurde inzwischen erweitert und interpretiert nun auch das erste Kommando:
Senso.insertTemplate(’template-datei.html’);
Der Befehl kann direkt in die Templates eingebettet werden, was viel Arbeit erspart und vor allem Übersicht im Template schafft. Anstatt Variablen zu hinterlegen, die vom PHP-Programm gefüllt werden müssen, kann man also direkt Templates in Templates einbinden.
Da die Klasse sich selbst wieder aufruft ist Rekursion gegeben. Das bedeutet, dass durch den obigen Befehl inkludierte Templates ebenfalls wieder Kommandos beinhalten können und ausgeführt werden.
Das insertTemplate-Kommando wird in alle Frameworks, die von Senso abgeleitet sind, eingebunden. Vereinzelt wird auch ein sprachbedingtes Kommando Einzug halten:
Senso.translateWord(word_code,lang_code);
Dieses Kommando wird aber nicht im original Framework verfügbar sein, da die Vorbedingungen, primär das Sprachpaket, fehlen.
PHP Lanquitch ist ist eine PHP-Klasse die bei sprachbasierten Webseiten helfen soll die korrekte Sprache des Nutzers herauszufiltern. Lanquitch ist eine kleine und ultra-einfach zu bedienende Sprache-Klasse für PHP. Lanquitch darf jedoch nur für private Zwecke kostenlos genutzt werden. Für kommerzielle Zwecke wird eine Gebühr von 25,00 EUR erhoben (pro Unternehmen / Person). Jegliche integrierte Fehlermeldungen werden aus globalen Gründen in Englisch ausgeworfen.
Für mehr Sprachen, einfach Kommentare schreiben, sie werden dann ergänzt. Natürlich hätte man eine komplette Tabelle nehmen können, aber das würde unnötig Code verbrauchen.
Bei der Erstellung des neuen Sensory Frameworks für das nanumCMS System brauchte ich unbedingt einen sehr guten E-Mail-Check, den man getrost in einen SecurityLayer einbauen kann. Die Suche im Internet brachte da eher sich um das Problem drehende Konstrukte, wie etwa:
1 | $RegExp = '/([a-z0-9\.\-]+)@([a-z0-9\.\-]+)\.([a-z]+)/'; |
Bei solchen Regexp sollte man aber bedenken, dass unlogische E-Mail-Konstrukte wie folgende möglich sind:
-hallo-.W-@.elt..de
.-hallo.@.Welt.-.de
Das ist nicht wirklich ein E-Mail-Check, das könnte man sogar genauso schlecht mit substr() und Co. lösen. Die einzig perfekte Lösung hatte ich nach 15min selbst erstellt. Die Bedingungen sind einfach:
Die fertige RegExp sieht dann so aus:
1 | $RegExp = '/^([a-z\d]+)([\-]{1}[a-z\d]+)*([\.]{1}[a-z\d]+)*\@([a-z\d]+)([\-]{1}[a-z\d]+)*([\.]{1}[a-z\d]+)*\.([a-z]{2,6})$/'; |
Die fertige Funktion könnte dann so aussehen (entschuldigt für das Englisch, aber ich teile gern global
):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /** * Checks if email is valid (RegExp-Test) * @return boolean * @param string $mail */ function checkEmailValidity($email){ $r = '/([a-z\d]+)([\-]{1}[a-z\d]+)*([\.]{1}[a-z\d]+)*\@([a-z\d]+)([\-]{1}[a-z\d]+)*([\.]{1}[a-z\d]+)*\.([a-z]{2,6})/'; if(preg_match($r,$email,$subPatterns)){ //email is valid return true; } return false; //only called when if-construction fails } |
Wer jetzt noch eine Liste mit allen möglichen Domainendungen hat, kann die Domainendung der Mail, die im $subPatterns-Array gespeichert ist mit einer entsprechenden Datenbank abgleichen und der E-Mail-Check ist perfekt!
Ich mag neue Technologien. Vor allem Ideen aus den Mozilla Labs schaue ich mir gerne mal an. Als inoffizielles Konkurrenzprodukt in den frühen Alpha-Phasen gegenüber Adobe AIR, soll Prism ebenfalls Web und PC verbinden. Als interessierter Entwickler habe ich mir Prism auf Ubuntu installiert und vor dem Start erst einmal nach einer Programmierdokumentation geschaut - vergebens. Das liegt daran, dass es nicht wirklich eine gibt. Alles was man können muss ist das, was man eigentlich schon vorher konnte: Websprachen.
Als ich Prism nämlich startete hat sich schnell großes Ernüchtern eingestellt. Mozilla Prism ist entweder der schlechteste Browser der Welt, oder einfach nur ein Kinderspielzeug. Natürlich ist Prism noch in den frühen Entwicklungsphasen, aber von Innovation ist keine Spur. Prism ist ein minimalistischer Browser, der nicht einmal eine Adressleiste hat, sondern lediglich den Browserinhalt anzeigt. URL’s können jeweils nur einmalig eingegeben werden. Man doppelklickt auf Prism, gibt beispielsweise http://google.com/ ein und man bekommt ein Google.com Icon auf den Desktop. Das ist nichts anderes als eine Verknüpfung die Prism öffnet und dann http://google.com/ lädt.
Das bedeutet, dass sich der eigentliche Sinn von Prism darin beschreibt, dass man oft besuchte Seiten per Verknüpfung auf den Desktop legt und dann mit einem Browser ohne Funktionen surft. Für den Entwickler ist der Sinn von Prism und die damit verbundene Arbeit nicht in einem geordneten Verhältnis:
Der Entwickler muss die Daten des Browsers auslesen und prüfen, ob man mit Prism surft. Wenn ja, dann passt man vorerst per JavaScript die Fenstergröße von Prism an, sodass die eigene Webapplikation, die mit Prism perfekt laufen soll, sich wie gewünscht auf dem Desktop einschmiegt. Dann gestaltet man die Webapplikation so, dass man sie ohne jegliche weitere Browserfunktionen problemlos bedienen kann, d.h. alles muss zwingend in einem Fenster zu bearbeiten sein.
Prism ist momentan nicht mehr als ein Spielzeug für Entwickler, das aber nach einigen Minuten langweilig wird. Ich warte immernoch darauf, dass sich in Prism, genau wie in Adobe AIR, eine eigene Sprache erschließt mit riesigem Funktionsumfang und Zusammenspiel mit dem eigenen lokalen Computer.
Beim durchsuchen des globalen Webs bin ich von der “kein CSS”-Aktion urplötzlich auf HTML5 gestoßen, ich weiß nicht mehr wie, aber der vergessenen gedankliche Zwischenschritt sei mir vergessen. Als ich mir die neue Spezifikation angeschaut habe war ich erstaunt. Weiterlesen »
Gegenüber dem iPhone und dem iPod Touch hat’s mich beim Android erwischt - der AppMarket ist beim mobilen Google-Betriebssystem Android wesentlich entwicklerfreundlicher. Sowohl Linux wie Windows, als auch Mac werden unterstützt. Das Entwicklerplugin gibt es direkt für Eclipse. Einfach die Quelle hinzufügen und installieren lassen (funktioniert noch nicht mit Aptana Studio). Anfreunden muss man sich aber als Nicht-Java-Programmierer erstmal mit dem Aufbau und der Funktion eines Apps. Im Grunde genommen sind die auf GoogleCode genannten Dinge einleuchtend. Trotzdem muss ich mir die Frage stellen, ob das heute noch so im Sinn der Entwickler ist. Wenn ich heute ein System programmierte, so würde ich ein entsprechend schnelles Framework bereitstellen.
Selbstverständlich ist es gut, dem Programmierer die Möglichkeiten der Art der Programmierung offen zu lassen, aber ein Framework für schnellere Zugriffe auf gängige Methoden wäre angebracht gewesen.
Um ein Textlabel zu erzeugen braucht man 3 Zeilen Code:
TextView tv = new TextView(this); tv.setText("Hello, Android"); setContentView(tv);
Ein relativ überladenes Vorhaben, wenn man es mal hochrechnet. Hier hätte es gereicht, wenn es eine MAIN-Klasse mit einer writeIntoContext(string, context) Methode gegeben hätte. Alles in allem ist die API aber doch ziemlich gut und auf den ersten Blick auch sehr mächtig, was die Funktionsvielfalt betrifft und demnach die App-Vielfalt. Zum Testen der eigenen Programme wird der Emulator gleich mitgeliefert, für echtes Android-Flair. In ein bis zwei Monaten wird auch eine Android-Applikation aus vaib hervorgehen, man darf gespannt sein.