Trackbacks, also das Senden von Rückverweisen von einem Blog zu einem Artikel eines anderen, wurde vor ein paar Jahren von Six Apart für das Weblog-System Movable Type eingeführt und erfreut sich recht großer Beliebtheit, auch wenn der große Hype inzwischen wieder vorbei ist. Grund hierfür sind auch die Möglichkeiten, die sich Spammern bieten das Web auf diesem Wege mit nutzlosen Angeboten zu überschwemmen. In der Regel dauert es nur ein paar Tage und in einem neuen Blog tauchen die ersten Spam-Trackbacks auf, wenn der Webmaster dies nicht entsprechend zu verhindern weiß.
Fast alle Blog-System bieten inzwischen Mechanismen, um Trackback-Spam zu verhindern, allerdings basieren diese entweder auf externen Black-Listen wie Akismet oder sie bedürfen einer manuellen Nachsorge der meist als Kommentare eingestellten Trackbacks. Ad absurdum geführt wird das Ganze allerdings oftmals wieder durch den Einsatz von Pingbacks, der automatischen Trackback-Variante.
In diesem Artikel möchte ich eine Implementierung für ASP.NET und Javascript vorstellen, die ich für zerbit.de entwickelt habe und die meines Erachtens einen größmöglichen Schutz gegen Trackback-Spam bietet, da hier gleich mehrere Schutzmechanismen dafür sorgen, es den Spammern möglichst schwer zu machen. In den 12 Wochen, die das neue zerbit.de-Web online ist, hat es bislang noch keiner geschafft mir ein Viagra-Angebot oder eine Penis-Verlängerung unterzuschieben.
Der Trackback-Handler
Kommen wir zunächst zum eigentlichen Zweck, dem Verarbeiten eines eingehenden Trackbacks. Um eine gewisse Flexibilität zu wahren, bietet es sich an, diesen nicht über eine ASPX-Seite abzuarbeiten, sondern über einen HTTPHandler, da dann der Name der aufzurufenden "Datei" jederzeit über die web.config geändert werden kann.
<httpHandlers>
<add verb="POST" path="trackback.axd" type="TrackbackHandler" />
</httpHandlers>
Ein Trackback ist ein Post-Request mit der Übergabe der Trackback-Daten, wie Titel, Excerpt (Text) und der URL des verlinkenden Artikels. Meist speichert die aufgerufene Seite den Trackback als Kommentar ab und liefert ein standardisiertes Stück XML zurück.
Um Trackback-Spam in dieser Phase zu vermeiden, ist es wichtig sicherzustellen, daß im Markup des verlinkenden Artikels auch der eigene Artikel erwähnt wird. Dazu sollte man unbedingt vor dem Speichern des Trackbacks den HTML-Code der übergebenden URL abrufen und auf das Vorhandensein der eigenen URL prüfen. Eine sehr schöne Implementierung für VB.NET gibt es auf wwwcoder.com, die auch als Grundlage für meinen Trackback-Handler diente (Download am Ende des Artikels).
Die sichere Trackback-URL
Aktuell würde die URL zum Artikel No. 1 zum Beispiel so aussehen:
http://www.mydomain.de/trackback.axd?id=1
Die weitere Absicherung basiert nun zunächst auf der Verschleierung der URL des Trackback-Handlers, denn es wäre leichtfertig die statische URL des Handlers zu verwenden. Besser ist es sie dynamisch zu halten und ständig zu wechseln, zum Beispiel stündlich, täglich oder wöchentlich, wobei man den Intervall des Wechsels nicht zu kurz halten sollte, um einem echten Trackback-User die Zeit zu geben, ihn senden zu können. Dies geschieht durch die Übergabe eines Sicherheitsparameters, der serverseitig überprüft werden kann.
Beispiel: http://www.mydomain.de/trackback.axd?id=1&check=12Januar2008
Damit die Spammer die Struktur des dynamischen Teils der Url (zum Beispiel das aktuelle Datum) nicht gleich erraten können, ist es sinnvoll ihn mit einem beliebigen String zu ergänzen (Seed) und anschließend mittels MD5 in einen Hash zu verwandeln. Der Seed wird dabei, ebendso wie das Format des Datums-Strings, zentral in der web.config abgelegt, um ihn jederzeit ändern zu können.
Private Function GetCheckHash() As String
'Erzeugung des Prüf-Hash's mittels des Datumsformat-Strings und des
'Hash-Seeds aus der web.config
Dim strHashSeed As String = AppSettings("TrackbackHashSeed")
Dim strHashDateFormat As String = AppSettings("TrackbackHashDateFormat")
Dim strHash As String = Format(Now(), strHashDateFormat) & strHashSeed
Return System.Web.Security.FormsAuthentication. _
HashPasswordForStoringInConfigFile(strHash, "md5")
End Function
Unterstützt durch obige Methode sieht die URL dann folgendermaßen aus:
http://www.mydomain.de/trackback.axd?id=1&check=56D08713ED768F2B43ADEB2FF47F52D9
Diese URL ist bereits gut gegen Spam-Versuche abgesichert, ist aber für meinen Geschmack wegen der Parameter für den Einsatz noch nicht handlich genug und bietet einen weiteren Ansatz zur Absicherung. Um die Parameter in die URL zu integrieren und den Pfad zum Trackback-Handler dynamisch und konfigurierbar zu halten, eignet sich das sogenannte URL-Rewriting bestens. Ziel dabei ist es, eine virtuelle URL auf eine vorhandene, in unserem Fall die des Trackback-Handlers, weiterzuleiten.
In unserem Fall setzt sich die virtuelle URL aus einem in der web.config konfigurierbaren Pfad und einem Dateinamen zusammen, in der der Hash und die ID enthalten sind:
Beispiel: http://www.mydomain.de/trackback/56D08713ED768F2B43ADEB2FF47F52D9.1.aspx
In ASP.NET lässt sich das URL-Rewriting mit einem HttpModule bewerkstelligen. Ein solches Modul ist eine eigenständige Klasse und wird in der web.config konfiguriert. Sie schaltet sich quasi als programmierte Erweiterung der global.asax in die Request-Pipeline ein.
Die Klasse implementiert die Schnittstelle IHttpModule und damit unter anderem die Methode Init, in der ein Ereignishandler für die Methode BeginRequest registriert werden kann. In diesem Ereignishandler wird der Name der angeforderten Datei und deren Pfad analysiert. Wenn der Pfad mit dem virtuellen Trackbackpfad übereinstimmt, werden aus dem Dateinamen die beiden Parameter extrahiert und der Request mittels RewritePath auf den eigentlichen Trackback-Handler umgeleitet. (Download am Ende des Artikels)
Abrufen und Anzeigen der Trackback-URL
Die virtuelle Trackback-URL ist nach dem Laden einer Artikelseite im Markup nicht enthalten, sondern wird mittels Javascript auf Anforderung erzeugt und dargestellt. Hierzu dient zunächst eine ASPX, die mit Übergabe der Artikel-ID als Parameter ein Stück JSON-Code zurückliefert, der die aktuell gültige Trackback-URL enthält.
<%@ Page
Language="VB"
AutoEventWireup="false"
CodeFile="GetTrackbackUrl.aspx.vb"
Inherits="GetTrackbackUrl" %>
<% Response.Write(pstrResponse)%>
Im Code-Behind der Seite wird im Load-Event zunächst die notwendige Artikel-ID aus der anfordernden URL ermittelt und ein gültiger Hash erzeugt. Mit diesen Informationen und dem virtuellen Pfad aus der web.config wird dann die Trackback-URL zusammengestellt und in einem JSON-Konstrukt verpackt, das an den Client-Code ausgeliefert wird.
Protected Sub Page_Load( _
ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
'Erzeugen eines JSON-Strings mit der virtuellen Trackback-URL
'des Artikels
'---------------------------------------------------------------
'{'trackbackinfo':
' {'url':'http://www.mydomain.de/trackback/<HASH>.<ID>.aspx'}}
'---------------------------------------------------------------
Dim lngArticleID As Long = 0
Dim strURL As String = ""
Dim stbResponse As New StringBuilder("")
'Request auswerten
Dim strValue As String = Request.QueryString("id")
If strValue.Length <> 0 Then
If IsNumeric(strValue) Then
lngArticleID = CType(strValue, Long)
End If
End If
'virtuelle URL zusammenbauen
If lngArticleID > 0 Then
Dim strVirtualPath As String = AppSettings("VirtualTrackbackPath")
Dim strHash As String = GetCheckHash()
strURL = "http://www.mydomain.de/" & _
strVirtualPath & "/" & strHash & "." & lngArticleID & ".aspx"
End If
'JSON-String eröffnen
stbResponse.Append("{")
stbResponse.Append("'trackbackinfo':{")
stbResponse.Append("'url':'" & strURL & "'")
stbResponse.Append("}")
'JSON-String abschließen
stbResponse.Append("}")
pstrResponse = stbResponse.ToString
End Sub
Der folgende Javascript-Code verwendet das Javascript-Framework jQuery, das das Abholen des JSON-Codes vom Server übernimmt und das Einstellen der URL in eine Textarea gegenüber normalem Javascript deutlich reduziert:
function showTrackbackUrl(lID) {
//URL für den Abruf zusammenstellen
var sURL = "http://www.mydomain.de/GetTrackbackUrl.aspx?id=" + String(lID);
//JSON-Code vom Server holen
$.getJSON(sURL, function(json){
//einzufügendes HTML erstellen...
var sHTML = '<div>Trackback-URL:</div>'
sHTML += '<div><textarea id="TrackbackField" rows="1" cols="20" '
sHTML += ' readonly="readonly" onclick="this.select(); this.focus();">'
sHTML += json.trackbackinfo.url + '</textarea></div>'
//...und in dafür vorgesehenes DIV-Element einfügen
$('#ShowTrackbackContainer').append(sHTML)
//Focus auf die neue Textarea setzen
$('#TrackbackField').focus();
});
}
Die Javascript-Methode wird über einen Link oder einen Button aufgerufen, der sich, wie die Textarea die die URL anzeigen soll, im Markup eines jeden Artikels befindet.
Zusammenfassung
Das in diesem Artikel beschriebene Vorgehen beinhaltet eine Vielzahl an Sicherungsmechanismen, um die Trackback-Funktion der eigenen ASP.NET-Homepage gegen Spammer abzusichern.
Neben der Darstellung der Trackback-URL erst auf Anforderung, was zumindest die Spam-Bots fernhält, die mit Javascript nicht zurecht kommen, ist es sehr effektiv eine permanent wechselnde URL inklusive der Übergabe eines Sicherheits-Hashs zu verwenden. Sollte es doch einmal ein Spammer schaffen einen unerwünschten Trackback-Kommentar zu platzieren, gibt es insgesamt 6 Konfigurationsmöglichkeiten, um die URL schnell wieder abzusichern, ohne den Code anzufassen zu müssen.
Downloads
Spam-sichere_Trackbacks.zip