WordPress Plugin Shopping Cart (alias wp-commerce) e-downloads knackbar?

Das Plugin WP-Commerce scheint mir echt gefähtlich für Datei-Downloads zum im eigenen Webshop zu sein.

Das gefährliche Problem
Bis zur aktuellen Version WP e-Commerce 3.5.2 RC4 (UND der teuren “gold” edition!) ist der Download gekaufter digitaler Dateien mit einer URL á la http://meinshop.de/?downloadid=3 verbunden. Immerhin geht der Link dann auch genau nur einmal – und zwar so lange, bis wieder einer was “downloadbares” kauft – dann ist es eben /?downloadid=4 und wer zuerst kommt mahlt zuerst.

Mindestens genau so schlimm ist, dass die geheimen Dateien in einem öffentlichen Verzeichnis liegen (/wp-content/plugins/wp-shopping-cart/files/) und zwar als SHA1 Hash. Nur ist der SHA1 Hash IMMER gleich der ID der Datei!!! Also 1, 2, 3 usw. encrypted!

D. h. in JEDEM WP-Commerce gibt es in dem Verzeichnis eine Datei namens
356a192b7913b04c54574d18c28d46e6395428ab (nämlich sha1(“1″)) und
da4b9237bacccdf19c0760cab7aec4a8359010b0 (sha1(“2″))

und so weiter. Natürlich hat das Verzeichnis dann auch noch 755 CHMOD Rechte (also für jeden lesbar). Was ist denn das für ein Scheiss? Wer auch immer dieses Plugin benutzt – ich muss ja nur die URL oben eingeben und kann eine geheime Datei nach der anderen runterladen. Im Forum des Betreibers hat sich auch noch keiner drüber beschwert (nur ein Einziger hat erwähnt, dass er das im live-system umprogrammieren musste, weil er die sicherheitslücke bemerkte – wer rechnet denn auch damit?)

Lösung
Das “files”-Verzeichnis natürlich erstmal auf CHMOD 700 setzen.

Im Folgenden nur mein Lösungsansatz (der bei mir wunderbar klappt!!!) und nicht jeder Schritt im Detail:

  • Man fügt in seine wp_download_status Tabelle ein VARCHAR(45) Feld mit Namen “hash” ein.
  • In der submit_checkout_function.php Zeile 165 erweitert man den INSERT INTO um dieses Feld und füllt es mit z. B. sha1(‘xyz’.$product_data['file'].$log_id.’blabla’). Also etwas was in jeder Zeile der Tabelle anders aussehen dürfte. Oder sha1(time()) ist auch sicher gut.
  • In der transaction_result_functions.php wird der Download-Link für die Bestätigungs-Email erstellt. Zeile 101 muss dann um den hash z. B. so “erweitert” werden:

    $link = $siteurl.”?downloadid=”.$download_data['id'].”&code=”.$download_data['hash'];

  • Als letztes muss in der wp-shopping-cart.php Zeile 1189 geprüft werden, ob der code ebenfalls übergeben wurde:

    if(is_numeric($_GET['downloadid']) && $_GET['code'] != null)

    Nur vier Zeilen tiefer wird dass dann mit der Datenbank abgeglichen:

    $code = $_GET['code']; # < Diese Zeile wird hinzugefügt die nächste abgeändert
    if($download_data != null && $code == $download_data['datehash'])

Jetzt ist es doch etwas detailierter gewesen…
So! Jetzt kann man sein Shop-Plugin natürlich nicht mehr updaten :(

Egal, funktioniert jetzt erstmal! Noch ein Hinweis: downloadid habe ich so gelassen wie es ist und nicht NUR nach dem code in der Tabelle gesucht, weil es dann nicht mehr Injection-Safe wäre. downloadid muss ja numerisch sein und wenn die ID stimmt, wird der Code erst abgeglichen.

Ähnliche Posts:
» XML Sitemap Generator for Rails
» Funkenrailsdav: Webdav with Rails e.g. for ical
» Presenting: The Funkengallery Demo App
» Plugin: acts_as_list_in_tree und descendants in acts_as_tree

16 Responses to “WordPress Plugin Shopping Cart (alias wp-commerce) e-downloads knackbar?”


  • krass das hätte ich nicht gedacht…
    werd ich mal weiter geben…

  • Hat er auch :)
    Hab da trotzdem mal ne Frage: was ist, wenn man gar keine Downloads anbietet?
    Kann man trotzdem mit deiner oben beschriebenen Methode an Daten rankommen?

  • @Malte: Soweit ich das beurteilen kann, ist es SICHER, SOLANGE du KEINE DOWNLOAD Produkte hast (oder früher mal angeboten aber nicht wieder gelöscht hast, also die download-files immer noch im verzeichnis “files” liegen). :)

    Mit anderen Worten: Dann gibt es ja auch nichts zu klauen. Userdaten oder so sind ja sicher in der Datenbank und nicht klaubar mit einem “geheimen Link”.

  • Gut dann kann ich beruhigt schlafen :)
    Keiner meiner Kunden nutzt den Download
    Danke fuer die Info!

  • danke sehr für den beitrag – war gerade dabei an einem shop in wordpress mit diesem plugin zu arbeiten der downloads verkaufen soll.

  • Ich bin über diesen Artikel gestolpert nach meiner zweitägigen Suche irgendwie die Antwortemails des Shops mit korrekten Eurozeichen und
    den ä, und ö zu fixen.
    Ich weiss es hat nicht direkt mit dem Thema zu tun, aber ich bin
    verzweifelt.

  • Hi Mc. Vielleicht könntest du den Content-type der Mails irgendwie ändern. Ich weiss nicht, ob du als normale utf-8 Text-Mail jemals Umlaute rein bekommst.

    Als html-Mail:
    mail(mail_empfaenger, $betreff, $text,”from:$mail_absender\r\
    nContent-Type:text/html\r\nContent-Transfer-Encoding: 8bit\r\n”);

    Als ISO (umlaute…)
    mail(mail_empfaenger, $betreff, $text,”from:$mail_absender\r\
    nContent-Type:text/html; charset=iso-8859-1\r\nContent-Transfer-Encoding: 8bit\r\n”);

    http://www.phpbox.de/tipsundtricks/emailsumlaute.php

  • Ich danke Dir herzlich für Deine Hilfe, ich werd es damit mal versuchen.
    Tatsächlich habe ich zunächst die Hoffnung gehabt, das die Änderung der Kollationen in der Datenbank auf utf-8 etwas bringen würde.
    Aber leider Fehlanzeige. Ich muss tatsächlich an der Übergabe der Daten in die Email den Ansatz suchen.

    Übrigens nochmal Danke das du geantwortet hast.
    Gruß Mc

  • Hmmm, ich habe mit meinen begrenzent PHP Fähigkeiten versucht Deine Anregung umzusetzen. Mein Pech, hab den ganzen Blog abgeschossen.
    ;)
    Nachdem ich das Ding wieder neu aufgesetzt habe, wollte ich doch man nachfragen, wie Du den Code implementieren würdest.

    Ich denke es diese Stelle hier in der transaction_result_functions.php
    Datei.

    if(($email != ”) && ($purchase_log['email_sent'] != 1)) {
    mail($email, TXT_WPSC_PURCHASERECEIPT, $message, “From: “.get_option(‘return_email’).”");
    }

  • Probier’s mal so:

    if(($email != ”) && ($purchase_log['email_sent'] != 1)) {
    $headers = “From: “.get_option(‘return_email’).”\r\n”;
    $headers .= “Content-Type: text/plain; charset=\”iso-8859-1\”\n”;
    mail($email, TXT_WPSC_PURCHASERECEIPT, $message, $headers);
    }

    (Wenn ich mich jetzt nicht vertippt habe :)

  • PS: Wenn du hier runterscrollst findest du viele Beispiele:

    http://de.php.net/mail

  • Is This True???

    The use of hashes for filenames is to avoid filename conflicts and make it slightly harder to work out what the filenames are.

    Also, the download links are also somewhat more secure now.

    Anyhow, the files directory is normally locked off using a .htaccess file set to deny from all, (since about 3.6 this file will be created automatically if it is not already present).

    Is This True???

  • 1. Of course the hashes are there to avoid filename conflicts. This changes nothing on the fact that the hashes are predictable!

    2. What does he mean by “the download links are also somewhat more secure now” ? This can mean anything, I personally haven’t looked at the newest code now.

    3. It is true that the directory for downloads is secured with htaccess. But that was not the main point of my blog entry. My main point was, that you could fake the download-link (and usually not the URL directly to the file).

    To sum it up:
    If you use htaccess, that’s great. It’s a must. I don’t know what you mean by “somewhat more secure”, but it does not SOUND secure at least ;)

  • To Use or Not To Use?

    Marius… I would like to sell downloadable music with this cart, what would you say is the bottom line here???

    Is .htaccess adequate?

    “My main point was, that you could fake the download-link (and usually not the URL directly to the file).”
    Does this mean that the URL cannot be compromised and shared?

    And if the protection is poor, does this mean that anyone can do this? Or is it just for the more skilled?

    Is the asset (MP3) worth the effort?

    To Use or Not To Use? That Is The Question…

    Thanks…

  • You have to use .htaccess in any case or everybody can download everything.
    This is the security lack apart from that:

    If someone buys music, he gets a download-link like so:
    ……?downloadid=5

    Now if you are smart and you know that every day somebody buys music in your store, you just go through all the numbers:
    ……?downloadid=6
    ……?downloadid=7

    And those where a user bought something, but has not yet tried his link, you can download what he payed for. Note that I only checked version 3.5.2 RC4.

  • Hi !

    Ich sitze hier ebenfalls an einem eStore über den Musik zum Download angeboten werden soll.

    Gibt es von deiner Seite Tipps wie man trotzdem das aktuelle Plugin mit der WordPress 2.6 Version benutzen kann ?

    Du kannst mir ja per Email schreiben. Würde mich freuen.

    Gruß
    Frank

Leave a Reply