Alexander (HH): Spielmannszugshomepage

Beitrag lesen

Moin Moin!

Leider hat der Jugendwart seine Kamera vergessen bei den letzten Aktionen. :(

Pssst, großes Geheimnis: Wenn Du keine aktuellen Bilder hast, dann schreib wenigstens kein altes Datum dran! ;-)

* Unter der Navigation klebt irgendwelcher unleserlicher Fliegendreck.
Die Sinnlosigkeit davon ist mir nun auch klar geworden -> entfernt.

Die Sinnlosigkeit der Links vielleicht. Warum setzt Du überhaupt Text in Fliegendreck-Größe auf die Seite? (Das frage ich mich übrigens bei immer mehr Sites ...)

Ich binde die Kopf- und Fußdatei per PHP require() ein.

Das geht auch per Server Side Includes. Oder noch besser offline. Im Rahmen einer so kleinen Website kann man das noch komplett mit einem kleinen Shellscript (wahlweise Batch-Datei) und cat (bzw. type) erschlagen. Oder mit irgendeiner anderen Script-Sprache, sei es Perl, awk, oder notfalls Basic.

Ich dachte, dass <b> und <em> deprecated wären?!

<b> ja, wie auch alles andere in Physische Auszeichnungen im Text ist das Design und damit Job von CSS.

<em> ist Emphasis, sprich: Betonung. Das ist Semantik und Job von HTML, wie auch alles andere in Logische Auszeichnungen im Text. Diese Betonung irgendwie sichtbar zu machen ist Job von CSS.

<span> und <div> sind nichtssagend wie ein leeres Blatt Papier, ohne jede Aussage. Mit <div>s kann man im Notfall irgendwie zusammengehörende Elemente zusammenpacken, wenn es kein besser geeignetes Element gibt. Und <span> kann ein Stück Text mit einer in HTML nicht anders ausdrückbaren Betonung versehen.

Beim Scripten des Gästebuchs war ich wohl im Abkürzungswahn :-/

"Wir haben keine Zeit für Konzepte, wir müssen handeln!" sprach einst einer meiner weniger beliebten Profs, um sich dann völlig planlos in eine so nicht zu gewinnende Schlacht zu stürzen.

Was sagt eigentlich Dein Auftraggeber dazu, dass Du die von ihm bezahlte(?) Arbeit verschenkst?
Die Bilder

Ich rede nicht von den Bildern. Du versprichst, die kompletten Sources herauszurücken.

werden mir von anderen Mitgliedern - auch ich bin Mitglied und verwalte die Homepage ehrenamtlich - zugespielt.

"Zugespielt"? Ist Dir die Bedeutung dieses Begriffes geläufig? Reportern werden vertrauliche Informationen "zugespielt", um Mißstände aufzudecken. Ist das die Absicht der Website?

Ja, eventuell sollte ich hierfür thumbnails einsetzen.

Ersetze "eventuell sollte ich" durch "ich werde".

* Medien-Seiten: Mit Javascript werden die Bilder in der Seite angezeigt, ohne Javascript ersetzt das Bild die Seite nach einem Klick. Warum packst Du das Bild nicht über eine (generierte) Seite exakt dort hin, wo es auch mit JS stehen würde? PHP steht Dir ja offenbar auf dem Server zur Verfügung, und selbst wenn nicht könnte man das 100% vorberechnen.
Wie kann ich dies mit HTML Strict verwirklichen?

Was verwirklichen?

Eine Bildseite?

Nimm das Gerüst der Seite, setze dort, wo das Javascript-Zeug dynamisch ein <img src="grosses-bild.jpg" alt="blabla"> einbaut, statisch das selbe hin. Ändere die Links der Vorschau-Bilder so, dass sie auf die einzelnen Bildseiten verweisen und nicht direkt auf das Bild.

Wenn Du PHP einsetzt, nimmst Du ein Template pro Galerie oder sogar ein Template für alle Galerien. Die Information, welche Bild-URL du jeweils einsetzen mußt, kannst Du locker über URL-Parameter übergeben, idealerweise nur einen Index, nicht die URL selbst, sonst baust Du eine Injection-Schwachstelle ein.

Das Javascript-Zeug verläßt sich vermutlich darauf, die Bild-URL aus dem href-Attribut des <a>-Elements fischen zu können, das wird dann nicht mehr so einfach gehen. Wenn Du überhaupt noch auf die albernen Überblend-Effekte bestehst, mußt Du dafür einen anderen Weg finden. Zum Beispiel, indem Du ein ungenutztes Attribut wie rel mißbrauchst, oder indem Du aus der Thumbnail-URL oder der Link-URL die URL des großen Bildes berechnest.

Die Kopfdatei ist wie gesagt  statisch und wird auf jeder Seite eingebunden - leider weiß ich nicht, wie ich Mootools und das Javascript dynamisch einbinden kann.

Indem Du den Inhalt des grob kugelförmigen Gebildes oberhalb des Halses mit etwas mehr als nur den minimalen 20 Watt chemischer Energie versorgst. Du weißt, welche Seiten das Javascript-Zeug brauchen. Sorge dafür, dass diese Information vom Seiten-Skelett zum eingebundenen Header weitergereicht und dort in einem if-Block verarbeitet wird.

An einem effektiven und barrierefreiem Spam-Schutz arbeite ich zurzeit.

Und wie gehst Du mit den Leuten um, die für ein paar Euro wie blöd Müll in Kommentare posten? Die hebeln locker jeden rein maschinellen Spamschutz aus. Du könntest natürlich Prüfungsfragen aus der Quantenphysik stellen, damit wirst Du Du diese armen Spam-Sklaven loswerden -- und den großen Rest der Weltbevölkerung gleich mit. ;-)

offenbar validierst Du die vom Broser kommenden Daten nicht ausreichend.

$_GET['s'] wird per mysql_real_escape_string() umgewandelt - reicht das nicht?

Nein, das ist Quoting, keine Validierung. Mit dem Effekt, dass Informationen aus der Website herauslecken, die Du einem Angreifer besser nicht zur Verfügung stellst.

Validierung fängt damit an, dass Du generell jedem einzelnen Aspekt der Programm-Eingabe (bei PHP-Webseiten also mindestens allen Headern, allen Parametern, allen GET- und POST-Daten; bei Kommandozeilenprogrammen erst einmal STDIN, Environment, Kommandozeilenparameter; generell alle Inhalte von allen Dateien, die Du verarbeitest) erst einmal unterstellst, ein böswilliger Angriff zu sein.

Wirklich jedem. Sprich mir nach: "Alle Eingaben sind böse. Alle Eingaben sind böse. Alle Eingaben sind böse."

Diejenigen Eingaben, die Du nicht brauchst, kannst Du ignorieren. Den Rest mußt Du überprüfen. Jede Eingabe einzeln, ohne Ausnahmen. Stimmt auch nur eine Eingabe nicht, brichst Du ab. Keine Reparaturversuche! Es gibt diverse Angriffe, die genau auf gut gemeinte (merke: gut gemeint ist das Gegenteil von gut gemacht) Reparaturversuche abzielen, um Schadcode an den Prüfungen vorbei zu mogeln. Nur gnadenloses Abbrechen schützt Dich davor.

Zunächst einmal mußt Du ganz grob feststellen, ob die Eingabe überhaupt den richigen Typ hat. Weil PHP nicht so wirklich zwischen String und Zahl unterscheidet, ist das hier nicht sonderlich schwierig. Du kannst eine Whitelist der erlaubten Zeichen benutzen, oder eine Blacklist der verbotenen Zeichen. Die Whitelist ist in aller Regel günstiger, nicht nur, weil sie in aller Regel kürzer ist, Du wirst auch nicht von Zeichen überrascht, die Du in der Blacklist vergessen hast.

Du willst eine positive Zahl übergeben bekommen. Dein erster Test ist also, ob der Parameter s ausschließlich Ziffern enthält. Vermutlich willst Du Dich nicht mit Ziffern aus anderen Sprachen, die im Unicode enthalten sind, herumschlagen, sondern nur stumpf die 10 arabischen Ziffern haben, die schon im ASCII definiert sind.

Naiverwewise bastelst Du eine Schleife, die über alle Zeichen im String läuft und prüft, ob das n-te Zeichen eine 0, eine 1, eine 2, ... oder eine 9 ist. Wenn nicht, brichst Du mit einer Fehlermeldung ab.

Schneller und einfacher ist ein regulärer Ausdruck. Auf Deutsch: Vom Stringanfang bis zum Stringende nur arabische Ziffern, mindestens eine, beliebig viele. Als PCRE: [1]{1,}$ oder kürzer [2]{1,}$ oder noch kürzer [3]+$. Paßt dieser reguläre Ausdruck, arbeitest Du weiter, sonst brichst Du mit einer Fehlermeldung ab.

Verfeinerung: Du willst in aller Regel keine Zahlen erhalten, die größer sind als die Anzahl der Elementarteilchen im Universum. In aller Regel willst Du noch nicht einmal Zahlen sehen, die mehr als 64, 32 oder sogar nur 16 Bit belegen. Damit ergibt sich bei dezimaler Darstellung eine Obergrenze für die Ziffernanzahl. 16 Bit belegen höchstens 5 Ziffern, 32 Bit höchstens 10 Ziffern, 64 Bit höchstens 20 Ziffern. Das kann in den regulären Ausdruck mit einfließen. Ich gehe mal davon aus, dass Du nicht mehr als 2^32 Einträge im Gästebuch haben wirst: [4]{1,10}$ 9 999 999 999 hat zwar nur 10 Ziffern, ist aber trotzdem größer als 2^32 (= 4 294 967 296). Entweder arbeitest Du für die Prüfung mit einem 64 Bit Integer, oder aber du pfeifst auf die letzten paar Milliarden und begrenzt die Eingabe auf 9 Ziffern: [5]{1,9}$

Diverse String-zu-Zahl-Konvertierungsroutinen interpretieren Zahlen mit führender 0 als Oktal, Du willst also KEINE führenden Nullen haben. Praktischerweise willst Du auch nur positive Zahlen haben, nicht die Null selbst. Damit kannst Du die Aussage über den Parameter s noch präziser fassen. Bisher war die Aussage über s nur vom Stringanfang bis zum Strinende mindestens eine, höchstens 9 arabische Ziffern. Jetzt willst Du am Stringanfang eine der arabischen Ziffern von 1 bis 9, gefolgt von null bis acht arabischen Ziffern von 0 bis 9, gefolgt vom Stringende: [6][0-9]{0,8}$

Der nächste Test ist, ob der Wert inhaltlich paßt. Du willst nicht immer den gesamten möglichen Wertebereich ausschöpfen. Gerade wenn Du einen großen Integer-Typ für die Prüfung benutzen mußtest, mußt Du sicherstellen, dass der Wert auch in den kleineren Integer-Typ paßt, denn Du für die weitere Arbeit benutzt. (Das ist bei PHP nicht so ein riesiges Problem wie in C. Aber auch PHP hat eine Obergrenze für Integer.) Ist die Zahl zu groß (oder zu klein), brichst Du mit einer Fehlermeldung ab. Eine andere Obergrenze kann aus der Programmlogik selbst kommen, wenn es z.B. um durchnumerierte Sitzplätze geht.

Andere Typen brauchen natürlich andere Prüfungen, aber das Prinzip bleibt.

Notorisch problematisch sind E-Mail-Adressen. Der Teil vor dem letzten @ ist fast beliebig, er darf nur nicht leer sein. Danach sieht es ähnlich wild aus, nicht zuletzt durch den Wildwuchs neuer TLDs und der Internationalisierung des DNS, mit unterschiedlichen Definitonen erlaubter Zeichen abhängig von der Laune des jeweiligen NICs. Die einzig sicheren Aussagen dort sind eigentlich, dass rechts vom letzten @ mindestens ein Punkt vorkommen muß, dass die Punkte nicht direktt neben anderen Punkten oder dem @ erlaubt sind, und dass der abschließende Punkt optional ist. Entsprechend spartanisch wird ein regulärer Ausdruck aussehen müssen. Siehe auch Validierung von eMail-Adressen (Selfforumssieb).

Für Strings, die Du in die DB schreibst, ist die MINIMALE Prüfung, ob der String nicht zu lang für das DB-Feld ist. Oft mußt Du auch vermeiden, dass der String ASCII NUL enthält, weil die C-APIs dieses Zeichen als String-Ende verstehen. Effekt: Poison NULL byte.

Richtig übel wird es, wenn Du String-Eingaben für Dateinamen auf dem Server benutzt, nicht zuletzt, weil PHP bei vielen File-Funktionen auch URLs akzeptiert. In der Regel solltest Du es daher vermeiden, Dateinamen vom Browser anzunehmen. Wenn überhaupt, arbeitest Du mit einer sehr kurzen Whitelist, z.B. über den regulären Ausdruck [7]+.[A-Za-z0-9._-]+$

Namen enthalten in aller Regel keine ASCII-Steuerzeichen von 0-31 oder auch 127, auch sind Satzzeichen mit Ausnahme von Punkt und Bindestrich eher selten. Hier kann also eine Blacklist zum Einsatz kommen, die solche Zeichen gezielt verbietet.

Alexander

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".

  1. 0123456789 ↩︎

  2. 0-9 ↩︎

  3. 0-9 ↩︎

  4. 0-9 ↩︎

  5. 0-9 ↩︎

  6. 1-9 ↩︎

  7. A-Za-z0-9._- ↩︎