Уязвимость в Kohana?

в 5:09, , рубрики: Kohana, Веб-разработка, информационная безопасность

Вчера наш портал, написанный на Kohana, подвергся успешной атаке. Мысль, что грешить надо именно на уважаемый фреймворк, безопасность в котором далеко не на последнем месте, сначала даже не обсуждалась. Программке, которой сканировали наш сайт, потребовалось порядка 95 тысяч запросов и 5 часов времени, чтобы найти эту уязвимость.Взгляните внимательно на эти две функции из ядра Коханы версии 3.2:

public function redirect($url = '', $code = 302)
{
    $referrer = $this->uri();
    $protocol = ($this->secure()) ? 'https' : TRUE;
 
    if (strpos($referrer, '://') === FALSE)
    {
        $referrer = URL::site($referrer, $protocol, ! empty(Kohana::$index_file));
    }
 
    if (strpos($url, '://') === FALSE)
    {
        // Make the URI into a URL
        $url = URL::site($url, TRUE, ! empty(Kohana::$index_file));
    }
 
    if (($response = $this->response()) === NULL)
    {
        $response = $this->create_response();
    }
 
    echo $response->status($code)
        ->headers('Location', $url)
        ->headers('Referer', $referrer)
        ->send_headers()
        ->body();
 
    // Stop execution
    exit;
}
public static function site($uri = '', $protocol = NULL, $index = TRUE)
{
    // Chop off possible scheme, host, port, user and pass parts
    $path = preg_replace('~^[-a-z0-9+.]++://[^/]++/?~', '', trim($uri, '/'));
 
    if ( ! UTF8::is_ascii($path))
    {
        // Encode all non-ASCII characters, as per RFC 1738
        $path = preg_replace('~([^/]+)~e', 'rawurlencode("$1")', $path);
    }
 
    // Concat the URL
    return URL::base($protocol, $index).$path;
}

Как видно, при использовании функции редиректа у реквеста к текущему uri применяется функция URL::site, в которой используется preg_replace с модификатором исполнения «e»: к каждому сегменту урла применяется rawurlencode, причем сегмент передается в двойных кавычках, что позволяет передать туда что-нибудь вроде (${@ phpinfo()}), и оно отработает. Таким образом, если у нас по ссылке http://site/path/param1 производится редирект, то дописав в param1 выражение вроде (${@ phpinfo()}), можно выполнить какой-нибудь код. В нашем случае, после того как уязвимость была найдена ботом, за дело взялся человек, и спустя некоторое время нехитрыми манипуляциями смог залить шелл через эту дырку. Неоценимую помощь в этом оказал еще такой момент. Кохановский обработчик исключений имеет такой кусочек:


public static function handler(Exception $e)
{
// ..... //
        if (Request::$current !== NULL AND Request::current()->is_ajax() === TRUE)
        {
            // Just display the text of the exception
            echo "n{$error}n";
 
            exit(1);
        }
// ..... //
}

Запрос имеет заголовок X-Requested-With равным XMLHttpRequest? Держите сообщение об ошибке!Интересно ваше мнение по поводу этих нюансов.

Автор: Grusho

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js