|
|||
Pay-For-Download System
Hallo.
Ich bitte euch mein Pay-For-Download System in punkto Security, Usability und Effizienz zu beurteilen: Ein User kann eine herunterzuladende Ware wie gewöhnliche Produkte in meinem (einfach gestrickten) Online-Shop kaufen. Ich verzichte auf eine direkte Bezahlmöglichkeit wie die Paypal API - grösstenteils aus Sicherheitsbedenken. Bis vor einigen Jahren wurden die übertragenen Variablen ohne Verifikation an Paypal übertragen, das heisst man konnte mittels "Tamper Data" & Co Werte beliebig ändern. Ich hatte damals Paypal und einige Shops die dieses System benutzten darauf aufmerksam gemacht, von Paypal habe ich nie eine Antwort erhalten, aber inzwischen werden die Daten immerhin tamperproof übertragen. Dennoch bin ich bei Paypal in Punkto Security einfach skeptisch und biete es dem User deshalb nur an, direkt die Summe zu überweisen. Nach dem Eingang des Geldes bekommt der User eine URL der Form: .../dl.php?file=$file&id=$id&token=$token Wobei $file der URL-encoded Dateiname des zu herunterladenden Files ist. $id ist die ID (aufsteigende Zahl) und $token ein SHA-256 HMAC über ID und Dateiname. Beispiel: http://www.falsemirror.de/dl.php?fil...e64dfbb0508d71 Dieser Token ist einen Monat lang gültig (zum Testen). Umgesetzt ist das ganze in PHP (auch wenn ich die Sprache absolut hässlich finde ist man manchmal einfach drauf angewiesen). Die Vorgehensweise ist wie folgt: 1. Einlesen der Parameter, urldecode() auf $file. 2. Überprüfen, ob alle Parameter vorhanden. 3. Überprüfen, ob die Länge aller Parameter stimmt (mittels strlen()). 4. Überprüfen, ob alle Parameter entsprechenden regulären Ausdrücken entsprechen. 5. Verifikation des HMACs. 6. Existenzprüfung der Datei. 7. Prüfen ob in der DB ein entsprechender Eintrag vorhanden ist. 8. Prüfen ob die Zeitdauer des Tokens gültig ist. 9. Falls bis dahin alle Tests erfolgreich: Ausliefern der Datei mittels readfile(). Die Datei befindet sich in einem mittels .htaccess geschützten Verzeichnis. Schritt 7. und 8 sind in einer SQL-Query zusammengefasst um die Anzahl von DB-Anfragen zu minimieren. Einige mögliche denkbare Angriffe: Erzeugen eines gültigen Tokens zu einer bekannten Datei: Aufgrund der Sicherheit der SHA-2 Hashes nicht effizient möglich. Möglicher Schaden: gering, da ja auch ein gültiger DB-Eintrag vorhanden sein müsste. SQL-Injection beim Zusammensetzen der Query: Mittels Regex-Checks und der Verwendung von mysql_real_escape_string() relativ abgesichert, dennoch nie vollkommen auszuschliessen. Möglicher Schaden: groß, Verlust der DB Buffer Overflow bei strlen(), urldecode() und den regexp funktionen: Wäre fatal wenn hier Buffer Overflows möglich wären, auszuschliessen ist es natürlich nie. User gibt URL weiter: Schaden wäre dass andere User den Download unberechtigterweise durchführen können. Allerdings ist der Zeitraum des Schadens zeitlich begrenzt (auf die Gültigkeit des Tokens). Mögliche Abhilfe wäre die Anzahl der Downloads zu begrenzen (im Optimalfall auf 1), was ich jedoch bislang aus Usability Gründen nicht tue. Eavesdropping der ungesichert per E-Mail übertragenen URL: Ist natürlich immer möglich, der Schaden ist jedoch nicht grösser als wenn der User die URL weitergibt. Ausspähen des Inhalts des gesicherten Verzeichnis. Ist ohne den HMAC check zu umgehen nicht möglich, da der Datei-Existenzcheck erst nach der HMAC Validierung durchgeführt wird. |
Sponsored Links |
Sponsored Links |
|
|||
Vielen Dank für die Antwort.
Zitat:
Die Sicherheit wäre auch nur bedingt erhöht. Klar würde SSL mir verschlüsselte Kommunikation zwischen User/Server ermöglichen und die Unsicherheit von E-Mail beheben, allerdings müsste ich dann im Optimalfall auch ein Zertifikat besitzen das von einer Root-CA signiert wurde, ansonsten wären SSL-Man-In-The-Middle Angriffe eine Leichtigkeit (falsches Zert ausstellen, in Kommunikation einklinken, Daten abfangen). Der Login und die User-DB würde eine weitere mögliche Schwachstelle darstellen. Weitergabe der URLs ist i.d.R. nicht erwünscht, siehe oben. Geändert von False Mirror (01.12.2009 um 15:48 Uhr) |
|
||||
Zitat:
über einen timestamp in der URI erfolgen). Ich vermute, Du schaust in der Datenbank nach ob der Hashwert ok ist. Dann kann man den Wert aber recht einfach überprüfen (Du weißt ja, welche Zeichen im Hashwert vorkommen dürfen). In der Datenbank reicht es eigentlich, dort den Zahlungseingang einzutragen (das ist aber ein rein interner Vorgang). Der Zahlungseingang gibt dann die Übertragung frei. |
|
|||
Zitat:
Thx. Ich wollte die Timestamps aus der URL raushalten damit 1. die URLs kürzer bleiben. 2. Ich die Zeit bei Bedarf noch ändern kann. Die query sieht so aus: "SELECT count(id) FROM downloadtokens WHERE id='".mysql_real_escape_string($id)."' AND token='".mysql_real_escape_string($token)."' AND file='".mysql_real_escape_string($filename)."' AND ((leasehours='0') OR (requesttime + 3600 * leasehours >= ".time()." ))"; Alle Werte werden gegen Regex Patterns gematcht: filename: [a-zA-Z0-9_-]+ id: [0-9]+ token: [a-f0-9]+ Die mysql_real_escape_string sind im Grunde deshalb auch überflüssig, stellen aber einfach nochmal ne Sicherheitsstufe ggü. SQL-Injections dar. Den Hashwert prüfe ich im Grunde 2mal. 1. Bei der HMAC Berechnung/Abgleich mit dem Token 2. Beim Eintrag in der Datenbank. Zweiteres ist im Grunde auch nur eine zusätzliche Sicherheitsstufe, da der DB-Eintrag ja schon über die ID aufgefunden werden kann. Aufgrund der Kollisionsunwahrscheinlichkeit (zwei gleiche Hashes) hätte ich statt der IDs auch direkt die Hashes verwenden können und die Zeit in die URL und somit auch in den HMAC packen können. Hat natürlich beides seine Vor- und Nachteile. Zahlungseingang & Co werden übrigens an ganz anderer Stelle verwaltet und haben nichts mit dem Token-Download-System zu tun. Edit: Habe time() noch mit einem mysql_real_escape_string übergeben, schliesslich könnte es theoretisch möglich sein, dass jemand den time() Funktionsaufruf umbiegt und somit eine Injection generiert - unwahrscheinlich, aber theoretisch möglich. Geändert von False Mirror (01.12.2009 um 20:25 Uhr) |
|
||||
Sorry, ich kenne PHP nur sehr rudimentär (dh ich weiß wie man es schreibt ).
Bei meinem Archiv arbeite ich mit einem timestamp (es sind gerade mal 8 Byte time() als Hexzahl). Bei der Überprüfung des timestamps vergleiche ich den Aufruf mit der aktuellen Zeit. Weicht die zu stark ab oder ist älter als die letzte Aktion, fliegt der User raus (dadurch funktionieren auch keine herauskopierten Links). Im Grunde recht ähnlich ... Teilweise verwende ich auch SQL (SQLite), bei relevanten Sachen hacke ich den String sobald ein ";" auftaucht ab ... Alles ist über einen MD5 "verhasht. Es würde mit ziemlicher Sicherheit auffallen. Bei der Prüfung der CGI-Parameter verwerfe ich die Anfrage wenn einer der Parameter eine bestimmte Länge überschreitet, komplett. Auch wenn nicht vorgesehen Namen von CGI-Variablen auftauchen. Seit den 5 Jahren wo das Archiv Online ist, ist noch keiner durchgekommen. Einige Versuche gab es schon Mir fehlt noch das Grundvertrauen in SQL. Mal sehen, das mit SQLite läuft erst seit einem Jahr. |
|
|||
MD5 ist nicht mehr als stark kollisionsresistent zu betrachten.
MD5 - Wikipedia, the free encyclopedia Ich würde stattdessen zu einer Hashfunktion aus der SHA-2 Familie greifen (SHA-1 ist inzwischen ebenfalls unsicher). |
|
|||
Numerische Werte kannst Du doch einfach mit (int) casten, statt darauf Regexp und escapen anzuwenden. Ansonsten ist der Query sicher.
__________________
... Meine Meinung |
Sponsored Links |
|
|||
Zitat:
Alternativ könnte ich natürlich noch den Betrag nehmen o.ä., aber indem ich generell alle Werte auf RegEx Patterns abgleiche ist es auch einfacher wenn ich mal ein Format ändern sollte, z.B. hexadezimale IDs o.ä. |
Sponsored Links |
Stichwörter |
download, shop, token |
|
|
Ähnliche Themen | ||||
Thema | Autor | Forum | Antworten | Letzter Beitrag |
960 Grid System - Problem | ceville | CSS | 1 | 17.09.2009 11:18 |
Schriftart welche auf jedem System vertreten ist? | Korasu | CSS | 4 | 05.10.2008 15:19 |
Ändert sich die Breite von System zu System? | Steakfred | CSS | 3 | 26.11.2007 21:37 |
Hängung bei verschachtelten Listen mit Nummerierung im System "1.1.1" | AndreasB | CSS | 2 | 05.11.2006 00:33 |
Nicht valieder Code von Map24 | sveniboy | (X)HTML | 7 | 06.11.2005 19:19 |