Sunday, June 10, 2012

Zwei-Faktor-Authentifizierung für das TYPO3 Backend

Wenn ein TYPO3 Backend Login erst mal geknackt ist, hat es ein Angreifer nicht mehr allzu schwer sich Zugang zu Daten (z.B. Userdaten) oder sogar zum Webserver zu verschaffen. Glücklicherweise kann man TYPO3 auch um eigene Authentifizierungs-Dienste erweitern, sodass ein Angreifer mit gestohlenen Benutzerdaten nicht automatisch Zugriff auf das TYPO3 Backend bekommt.

So einen Authentifizierungs-Dienst habe ich mir vor ein paar Jahren mal programmiert, nachdem ein Arbeitskollege mir einen YubiKey zur Verfügung gestellt hat. Der YubiKey ist ist Token, welchen man an einen USB Port seines Rechners anschließt und welcher dann per Knopfdruck ein OTP (one time password) generiert. Das OTP kann dann von einen Cloud Authentifizierungs-Cluster des Herstellers oder auch durch einen eigenen Authentifizierungs-Server verifiziert werden. Ganz simpel und vor allem Plattform-Unabhängig, denn der USB Token funktioniert unter jedem Betriebssystem gleich.

Die Veröffentlichung meiner Extension scheiterte seinerzeit an der Erstellung der Dokumentation, da ich keine Lust hatte mir meinen Windows Rechner mit OpenOffice vollzumüllen. Nun, wo ich komplett auf Linux umgestiegen bin, habe ich wohl keine Entschuldigung mehr und habe mich nun endlich mal hingesetzt und eine Dokumentation erstellt und die Extension sf_yubikey heute veröffentlicht.

Was macht die Extension sf_yubikey?

Die Extension erweitert das TYPO3 Backend Login um ein zusätzliches Feld, wo der User beim Backend Login neben seinen Userdaten auch ein OTP eingeben muss. Da der YubiKey USB Token auf Knopfdruck das OTP "eingibt", ist der neue Login-Prozess nicht sonderlich komplizierter geworden.


Der Backend Loginprozess erhält somit eine Zwei-Faktor-Authentifizierung, wo ein Angreifer nun neben den Benutzernamen und das dazugehörige Passwort auch das YubiKey USB Token das User braucht, um sich erfolgreich am TYPO3 Backend anzumelden.

Die Zwei-Faktor-Authentifizierung kann im Backend von TYPO3 pro User festgelegt werden.

Voraussetzungen für den Gebrauch von sf_yubikey

Die Extension funktioniert leider nicht out-of-the-box. Zum einen muss der Webserver über CURL und PEAR verfügen. Das sollte heutzutage aber eigentlich zum Standard gehörten. Zum anderen muss man die PHP Klasse Auth_Yubico installiert haben, welche aber dank PEAR recht einfach zu installieren ist. Die PHP Klasse erhält man hier.

Neben den Server-Voraussetzungen braucht man natürlich auch einen YubiKey sowie einen Yubico API Key, welchen man hier kostenlos erstellen lassen kann.

Feedback erwünscht

Ich habe die Extension wie erwähnt heute veröffentlicht und bin gespannt, ob ich auch Feedback erhalten werden und ob sie überhaupt jemand nutzt. Im TYPO3 Forge habe ich für Feedback und Bugreports ein entsprechendes Projekt eingerichtet.

Sichere Userpasswörter für TYPO3

In den letzten Tagen häufen sich in der Presse Berichte über Datenlecks bei Anbietern großer Portale wie z.B. LinkedIn, Last.fm oder eHarmony. Besonders erschreckend finde ich die Tatsache, dass solch große Portale die User-Passwörter per MD5 "verschlüsseln". Das ein MD5-Hash alleine alles andere als sicher ist sollte mittlerweile jeder Entwickler wissen, der sich schon mal mit dem Thema Sicherheit beschäftigt hat.

Ab TYPO3 4.6 sind deshalb auch die Extensions rsaauth und saltedpasswords per default installiert, damit ein Abgreifen der Userpasswörter nicht gleich zu dem Erfolg führt, dass der Angreifer sich recht simpel die Userpasswörter per Rainbow-Tables zugänglich machen kann. Ohnehin empfehle ich an dieser Stelle jedem TYPO3 Admin, die beiden erwähnten Extensions zu installieren und sowohl für die Backend als auch für die Frontend-Anmeldung zu aktivieren. Somit wären die Userpasswörter dann schon mal deutlich sicherer gegen Angriffe als vorher.

Die Extension saltedpasswords sorgt dafür, dass die Userpasswörter nicht mehr als MD5-Hash, sondern als gesalzener Hash in der TYPO3 Datenbank abgespeichert werden. Durch das "salzen" der Passwort-Hashes ergibt ein und dasselbe Passwort nun nicht mehr den gleichen Hash-Wert, wie es z.B. für ungesalzene Passwörter der Fall ist.

Tuesday, June 5, 2012

Zugriff auf eigene Extension Konfiguration aus Extbase Scheduler Task

In einem Projekt wollte ich aus einem Extbase Scheduler Task heraus E-Mails versenden. Der Body dieser E-Mails sollte über Fluid Templates gerendert werden. In diesem Zusammenhang hatte ich auch schon einen entsprechenden Artikel im Wiki zu Extbase gefunden.

http://forge.typo3.org/projects/typo3v4-mvc/wiki/How_to_use_the_Fluid_Standalone_view_to_render_template_based_emails

Bei Scheduler Tasks aus Extbase muss man nun jedoch den Kontext bedenken, unter dem der Scheduler Task läuft. In diesem Fall läuft der eingerichtete Scheduler Task im Kontext der Extbase Extension, was zur Folge hat, dass der ConfigurationManager mit folgendem Code das Typoscript Setup der Extension Extbase zurückliefert.

$extbaseFrameworkConfiguration = $this->configurationManager->getConfiguration(Tx_Extbase_Configuration_ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
Um nun im Scheduler Task auf die Konfiguration seiner eigenen Extension zugreifen zu können, muss man wir folgt vorgehen.

Man holt sich die komplette Typoscript Konfiguration der TYPO3 Installation.

$extbaseFrameworkConfiguration = $this->configurationManager->getConfiguration(Tx_Extbase_Configuration_ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT);
Danach kann man aus dem Typoscript (welches ja nur ein großes Array ist) die Konfiguration seiner Extension auslesen.

$config = $extbaseFrameworkConfiguration['plugin.']['tx_helloworld.']['irgendeine_einstellung']
Wichtig ist, dass man die Punkte jeweils nach "plugin" und dem Extensionnamen beachtet. Im Zweifel kann man sich auch einfach das ganze Typoscript Array ausgeben und schauen, wo genau im Array sich die gewünschten Einstellungen befinden.

Sunday, June 3, 2012

Zugriff auf Frontend User Tabelle aus Extbase

Extbase bindet die TYPO3 fe_users Tabelle schon automatisch mit ein und stellt entsprechende Objekte bereit. Man muss jedoch ein paar Dinge beachten, damit man auch auf diese Daten zugreifen kann.

Als erstes muss man in seiner Klasse das Users-Repository per Dependency Injection zu Verfügung stellen.

/**
 * @var Tx_Extbase_Domain_Repository_FrontendUserRepository
 */
protected $userRepository;    

/**
 * Inject the user repository
 *
 * @param Tx_Extbase_Domain_Repository_FrontendUserRepository $userRepository
 * @return void
 */
public function injectFrontendUserRepository(Tx_Extbase_Domain_Repository_FrontendUserRepository $userRepository) {
    $this->userRepository = $userRepository;
}  

Somit hat man dann Zugriff auf das Repository. Kennt man nun z.B. die UID des FE Users, kann man wie folgt die Userdaten über das Repository auslesen.

$user = $this->userRepository->findByUid($uid);

Wer sich nun wundert, warum die Variable $user leer ist, obwohl sie einen User enthalten müsste, der muss folgendes beachten.

Extbase stellt die Daten zwar per default zur Verfügung, geht aber davon aus, dass alle FE User auch einen Record Type zugewiesen haben.

config.tx_extbase.persistence.classes {
 Tx_Extbase_Domain_Model_FrontendUser {
  mapping.recordType = Tx_Extbase_Domain_Model_FrontendUser
 }
}

Beim installieren von Extbase wird sowohl die Tabelle fe_users als auch fe_groups um genau dieses Feld (tx_extbase_type) erweitert. Existierende als auch neue User haben natürlich keinen recordType zugewiesen (siehe Bild), sodass das UserRepository demzufolge auch nichts zurückliefern kann.







Nun gibt es zwei Möglichkeiten mit diesem "Problem" umzugehen. Entweder man setzt in allen FE Usern den Record Type, oder man hebt das von Extbase vorgegebene mapping wie folgt auf.

config.tx_extbase.persistence.classes {
 Tx_Extbase_Domain_Model_FrontendUser {
  mapping.recordType >
 }
}

Ich würde aber ganz klar dazu raten, die User entsprechend richtig anzulegen (sprich das Feld Record Type gleich bei Anlage des/der FE User zu setzen). Damit man das nicht manuell machen muss, kann man die Felder schon vorbelegen. Dazu einfach folgendes TS ins PageTS der Root-Seite einfügen.

TCAdefaults.fe_users.tx_extbase_type = Tx_Extbase_Domain_Model_FrontendUser
TCAdefaults.fe_groups.tx_extbase_type = Tx_Extbase_Domain_Model_FrontendUserGroup

So kann man übrigens auch beliebige Felder bei Neuanlage von Datensätzen vorbelegen.

Saturday, June 2, 2012

TYPO3 Scheduler Task mit ExtBase 4.7

Seit Extbase 4.7 kann man TYPO3 Scheduler Tasks direkt als Command Controller registrieren. Anbei eine kurze Step-By-Step Anleitung, wie das funktioniert.

Als erstes muss man einen CommandController erstellen.

Classes/Command/HelloWorldCommandController.php
/**
 * Description of HelloWorldCommandController
 */
class Tx_HelloWorld_Command_HelloWorldCommandController extends Tx_Extbase_MVC_Controller_CommandController {
    
    /**
     * Simple Hello World Command
     * 
     * @param string $name 
     * @return void
     */
    public function HelloWorldCommand($name) {
        echo 'Hello ' . $name;
    }
}

Danach wird der CommandController registriert.

ext_localconf.php
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['extbase']['commandControllers'][] = 'Tx_HelloWorld_Command_HelloWorldCommandController';

Als nächstes erstellt man über den TYPO3 Scheduler einen neuen Task und wählt als Klasse den "Extbase CommandController Task (extbase)"

Beim CommandController wählt man den HelloWorld CommandController aus und speichert den Task ab. Um die Optionen für den Task einzustellen, muss man den Task wieder öffnen und dann die entsprechenden Optionen ausfüllen.

Update - 02.06.2012 19:24
Leider gibt es noch einen Bug für denn Fall dass man einen Task ohne Parameter anlegt:
http://forge.typo3.org/issues/37563

Ein Workaround steht im Issue beschrieben.