Skip to content

Recent Articles

27
Jan

Spamer, Webspell und Stopforumspam.com

Das CMS Webspell hat, wie so ziemlich jedes andere CMS auch, mit Spammern zu kämpfen. Der Clan myRevenge e.V. setzt Webspell ein und hat mich um Hilfe mit ihrem Spam Problem gebeten. Trotz Captcha und Bestätigungslink schaffen es Spammer immer wieder sich anzumelden oder als Gast zu spammen. Nach einer erfolgreichen Anmeldung wird im zweiten Schritt auch in Bereichen gespmamt, in denen Gäste keine Schreibrechte haben.

Um den Spam einzudämmen, bietet sich eine Überprüfung an, wer so schreibt. Dabei macht man sich zu Nutze, dass Spammer wiederkehrende E-Mail Adressen und Usernamen verwenden.

Im ersten Schritt werden unerwünschte Top Level Domains und Domainendungen in 2 Arrays übergeben und überprüft, ob die verwendete E-Mail einen dieser Kriterien entspricht. Weil Spammer sehr flexibel sind, stellt diese Maßnahme lediglich einen Tropfen auf den heißen Stein dar.

Wesentlich effizienter ist der zweite Schritt. Hier wird die API von stopforumspam.com kontaktiert und gefragt, ob Name, oder E-Mail bereits als Spammer bekannt sind. Stopforumspam.com ist eine Seite, die bekannte Spammer sammelt und nicht kommerziellen Nutzern eine API zu der Datenbank anbietet.
Nur wenn die API antwortet, dass der Datensatz unbekannt ist, darf der User sich anmelden, bzw. einen Kommentar schreiben.

Die beschriebenen Ergänzungen werden in den Dateien register.php und comments.php vorgenommen.
Read moreRead more

27
Jan

2-Klick-Empfehlungsbutton

In den Nachrichten und Kommentaren wird das Thema Datenschutz im Zusammenhang mit Social Media schon länger diskutiert.
Trotz mancher Bedenken möchte man aus verschiedenen Gründen Social Media Buttons einfügen.

Als die Diskussion aufflammte hat heise.de eine 2-Klick Lösung entwickelt, um Social Media Buttons mit dem Datenschutz unter einen Hut zu bringen. Bei dieser Methode wird erst nach ausdrücklicher Aufforderung durch den Benutzer der externe Code von Facebook und Co. angefordert und eingebunden.

Wegen der großen Nachfrage wurde der Code zu der 2-Klick Lösung unter der MIT Lizenz veröffentlicht.

Diese 2-Klick Lösung habe ich in meinem Blog eingebaut. Sie kann von nun an beim Aufruf der einzelnen Beiträge am Ende genutzt werden.

Nachtrag:
Ich habe die Einbindung erweitert. Nun kann man die Buttons auch in der Übersicht benutzen.

23
Jan

Umstellung der Textausrichtung

Ich habe gerade die Textausrichtung des Blogs von Linksbündig auf Blocksatz umgeändert. Dazu musste ich im Stylesheet lediglich die Einstellungen zu den einzelnen Posts um die Angabe “text-align:justify;” erweitern.

Ich hoffe, dass diese Änderung die Texte etwas lesbarer machen wird.

23
Jan

CSS Layout: Header, 3 Reihen (Fixed-Fluid-Fixed), Footer

Ein 3 Spalten Layout, dass einen Header und Footer hat, kann man mit HTML und CSS auf unterschiedliche Weise gestalten. Die beiden meist genutzten Varianten sollten Divs und Tabellen sein.

Mit Tabellen ist die gleichmäßige Höhen- und Breitengestaltung sehr einfach. Die Höhe und Breite aller Spalten richtet sich an den Maximalwerten der anderen Elemente aus. Eine einfache Tabelle sieht so aus:

<table>
    <tr>
        <td colspan="3">Header</td>
    </tr>
    <tr>
        <td>Linkes Menu</td>
        <td>Inhalt</td>
        <td>Rechtes Menu</td>
    </tr>
    <tr>
       <td colspan="3">Footer</td>
    </tr>
</table>

Der Einsatz von Tabellen zu diesem Zweck gilt aber als veraltet und damit nicht mehr zeitgemäß.

Zur Zeit verwendet man für die Layout Gestaltung überwiegend Divs. Dabei schreibt man die Positionsangaben zum DIV nicht in selbiges hinein, sondern weist diesem eine ID und oder Klasse zu. Die Eigenschaften der IDs und Klassen definiert man dann in einer extra *.css Datei.

Wenn man feste mit flexiblen Breiten- und Höhenangaben vermischt, wird man bei Divs auf Hürden und Hindernisse treffen.

Wenn man z.B. möchte, dass die Höhe des Layouts immer minimal 100% der Höhe des Browserfensters beträgt, umfasst man das eigentliche Layout mit einem Div. Dieses Div macht man dann zu einem Wrapper. In den Eigenschaften wird dann bestimmt, dass der Wrapper immer mindestens 100% der Seitenhöhe belegen soll. Die Divs, die das eigentliche Aussehen bestimmen sollen, werden in diesem Wrapper positioniert.

Bei einem Layout mit drei Spalten kann man diese mittels Float ausrichten. Bei dem Linken und Mittleren setzt man “float:left;”. Beim Rechten “float:right;”.
Ist die Höhe der Divs ein fester Wert, bekommt man keine Probleme. Soll aber zumindest eine Höhe flexibel sein, werden alle drei eine, an ihrem Inhalt bestimmte, unterschiedliche Höhe erhalten. Möchte man unterschiedliche Hintergründe verwenden, kann das Endergebnis sehr unsymmetrisch aussehen.

Eine Alternative ist es, die Position der 3 Spalten absolut (“position:absolute;”) zu bestimmen. Im Folgenden definiert man dann den Abstand der rechten und linken Spalte zum Rand mit 0. Die mittleren Spalte wird mit Margin nach Links und Rechts ausgerichtet. Als Werte für die Margin Angabe nimmt man die Spaltenbreite der äußeren beiden Spalten.
Im Ergebnis hat man 3 Spalten, bei denen für die beiden äußeren feste Pixelwerte verwendet werden können. Die Mittlere Spalte wird immer die restliche Breite für sich in Anspruch nehmen, egal wie Breit das Browserfenster des Users gerade ist.

Definiert man nun die minimale Höhe aller drei Spalten mit 100%, werden durch diese Höhenangabe alle Spalten gleichmäßig bis zum Ende des Wrappers getreckt.

Die farbliche Gestaltung der einzelnen Divs erfolgt ebenfalls mittels CSS. Im Beispiel habe ich die Farben Grün #0F0, Rot #0F0 und Blau #00F verwendet. Die Farben passen so sicher nicht zusammen und beißen sicher etwas in den Augen. Ich habe sie dennoch gewählt, um mittels des Kontrastes die gleichmäßige Höhe der Spalten besser darstellen zu können.

Eine Beispielseite, die den nachfolgenden Code verwendet, kann man hier ansehen: 3cols.html

Die CSS Angaben:
Read moreRead more

16
Jan

Mit PHP nach Inhalten in bestimmten Dateitypen suchen

Ich wurde heute von jemanden angeschrieben, bei dem über einen Exploit eine umfangreiche PHP Shell eingeschleust wurde. Das Einfallstor war ein Uploadskript, welches eigentlich für Zip Archive gedacht war. Dieses Skript hat leider nicht geschaut, was wirklich hochgeladen wird.

Dank strenger Chmods war der PHP User sehr eingeschränkt. Durch den Einsatz von disable_functions in der php.ini war es dem PHP User weder möglich, Systembefehle auszuführen, noch Sockets zu öffnen. Aus diesem Grund konnte nur Schaden bei der betroffenen Webseite selber angerichtet werden. Es war zum Beispiel möglich sämtliche Dateien auszulesen und zu manipuliert. Des Weiteren ist es sehr wahrscheinlich, dass der Inhalt der Datenbank sich in den Händen des Angreifers befindet.

Da es sich um einen angemieteten Webspace handelt, wäre es nun extrem aufwendig gewesen, alle Dateien per Hand nach Manipulationen zu durchsuchen. Ich wurde deswegen gebeten, ein PHP Skript zu schreiben, das diese Aufgabe für den Betroffenen erledigt.

Das Ergebnis sind diese beiden Functions:

<?php
// Function, die die einzelnen Dateien überprüft.
function checkfile($file) {
	// Der Inhalt dieser Dateitypen wird überprüft.
	$types=array('php', 'php4', 'php5', 'txt', 'html', 'htm');
	// Nach diesem Inhalt wird in den Dateien gesucht.
	$contents=array('Suchbegriff', 'Suchausdruck');
	$found=array();
	// Namen der ausführenden Datei und der zu durchsuchenden bestimmen.
	$thisfile=preg_split('/\//', $_SERVER['SCRIPT_FILENAME'], -1, PREG_SPLIT_NO_EMPTY);
	$filename=preg_split('/\//', $file, -1, PREG_SPLIT_NO_EMPTY);
	// Den Dateityp bestimmen.
	$filetype=preg_split('/\./', $file, -1, PREG_SPLIT_NO_EMPTY);
	// Wenn es sich nicht um die ausführende Datei handelt und der Typ in der Dateiliste ist, einen Filehandler für die Datei öffnen.
	if ($thisfile[count($thisfile)-1]!=$filename[count($filename)-1] and in_array($filetype[count($filetype)-1], $types)) {
		// Die Datei so lange auslesen, bis das Ende erreicht wurde.
		$fp= @fopen($file, 'r');
		// Wenn der Filehandler erfolgreich geöffnet werden konnte, die Datei durchsuchen.
		if ($fp) {
			while (!feof($fp)){
				// Alle Suchbegriffe durchgehen und wenn einer gefunden wurde, diesen Treffer dem Trefferarray hinzufügen.
				foreach ($contents as $content) {
					if(strpos(strtolower(fgets($fp)), strtolower($content)) !== false) $found[]=$content;
				}
			}
			// Dateihandler schließen
			fclose($fp);
		}
	}
	unset($fp);
	// Wenn Suchbegrife gefunden wurden, diese als String ausgeben. Anderenfalls mit false antworten.
	if (count($found) == 0) return false;
	else return implode(', ',$found);
}
// Das angegeben Verzeichnis und alle Unterverzeichnisse durchsuchen.
// Wenn kein Verzeichnis angegeben wird, dann im aktuellen beginnen.
function listcontent($dir='.') {
	// Wenn es sich um ein Verzeichnis handelt, den Inhalt listen.
	if (is_dir($dir)) {
		$dircontent=scandir($dir);
		// Den gesamten Inhalt des Verzeichnisses durchgehen.
		foreach ($dircontent as $c) {
			// Wenn es sich um ein Verzeichnis handelt, die Function listcontent() aufrufen;
			if ($c!='.' and $c!='..' and is_dir($dir.'/'.$c)) {
				listcontent($dir.'/'.$c);
			// Wenn es sich um eine Datei handelt und die checkfile() Function einen String zurückgibt, einen Suchtreffer ausgeben.
			} else if ($c!='.' and $c!='..' and checkfile($dir.'/'.$c)) {
				echo 'Found file: '.$dir.'/'.$c.' with content: '.checkfile($dir.'/'.$c).'<br />';
			}
		}
	// Wenn es sich um eine Datei handelt und die checkfile() Function einen String zurückgibt, einen Suchtreffer ausgeben.
	} else if (checkfile($dir.'/'.$c)) {
		echo 'Found potential bad file: '.$dir.'/'.$c.' with content: '.checkfile($dir.'/'.$c).'<br />';
	}
}
// Die Suche starten.
echo "Starting search<br />";
listcontent();
echo "Search finished<br />";
?>