BadSamba - Exploiting Windows Startup Scripts Using a Malicious SMB Server

Windows Group Policy can be used to configure startup scripts that will execute each time the operating system starts up. These scripts execute with a high-level of privilege, the NT AUTHORITY\SYSTEM account, per the TechNet documentation:

“Startup scripts are run under the Local System account, and they have the full rights that are associated with being able to run under the Local System account.”

The scenario for this post includes a startup script running from a remote server using an SMB share. Typically it is not possible for an attacker to control the SMB share—if that were the case this post wouldn’t exist! But if an attacker is able to perform any form of man-in-the-middle attack or traffic redirection, such as DNS spoofing, it is possible to host a SMB server that will serve up malicious files in order to gain remote command execution as NT AUTHORITY\SYSTEM.

Finding Local Startup Scripts

As part of any post-exploitation process or host review, all startup scripts should be reviewed to determine the possibility for an elevation of privilege. One technique is to use the autoruns utility, part of the Sysinternals suite. This will also display Group Policy startup scripts which is our focus here.

In the lab setup, we have a Windows 7 (SP1, x86) machine that has a startup script, startup.vbs that is run each time the system boots. As part of this demonstration no DNS spoofing will be performed (for simplicity) so the script will point directly to a remote SMB share located at, a Kali Linux machine.

In the image below, we can see that the startup script is configured to run from a remote network share. Note that even though it indicates “File not found”, the system will still attempt to run the script when Windows starts. 

Introducing BadSamba

After seeing a similar scenario wherein a script was being run from a remote SMB share, this got me thinking… Would it be possible to spoof the SMB server? If the client asks for startup.vbs could I then send it evil.vbs of my choosing? Could I then further accept any form of authentication in order to trick the Windows system?

From this idea the concept of BadSamba was born, a simple malicious proof-of-concept SMB server that is built to exploit this very scenario in order to gain remote command execution as SYSTEM.

BadSamba has the following two requirements:

  • Accept any form of authentication - anonymous, domain, blank password, non-existent accounts. It will allow any user to connect to the SMB server and access any share.

  • File spoofing - serve the same file regardless of what file was originally requested, and regardless of which SMB share the client is connected to. If the user requests foo.vbs we will send them evil.vbs instead.

With these requirements, I have created an auxiliary Metasploit module to demonstrate this proof-of-concept that allows for any authentication, connection to arbitrary SMB shares, and reading files from the SMB server.


Within the Windows 7 system (, we have already identified that the startup.vbs script will execute from the remote SMB share when the operating system starts up.

Start Metasploit on Kali ( and load the BadSamba server, setting the FILE to notepad.vbs. This file simply executes notepad.exe in order to demonstrate that the commands being executed are in fact being run in the context of NT AUTHORITY\SYSTEM.

notepad.vbs file:

Dim oShell

Set oShell = WScript.CreateObject (“WScript.Shell”) “C:\windows\system32\notepad.exe”


After running the module and once the Windows 7 machine is restarted it successfully authenticates and connects to the malicious SMB share. A request for startup.vbs is then made, and we serve up our notepad.vbs. This is downloaded and executed by the target machine under the NT AUTHORITY\SYSTEM account as can be seen by inspecting the running tasks within the operating system.

Now that we have verified the module works, and that we can execute privileged commands, let’s create another VBScript file that will add a user account, also added to the Administrators group.

evil-user-add.vbs file:

Dim oShell

Set oShell = WScript.CreateObject (“WScript.Shell”) “cmd.exe /c net user hacker Password123 /ADD && net localgroup Administrators hacker /ADD”

Again we set the FILE setting to our malicious script, run the exploit server and restart the Windows 7 system.

As we can see the file was successfully downloaded by the target machine. Now to verify it executed successfully:

The hacker account has been created and added to the Administrators group!


  • BadSamba has been tested using .bat and .vbs remote script includes. The file extension does seem to matter, so if it’s requesting a .bat, serve up a .bat.

  • In the lab environment, testing has been against Windows 7 SP1 (English) for the proof-of-concept. Different versions of Windows may react differently, but the principal concepts should remain the same.

  • It’s not currently possible to “Browse” the files within the SMB share. This is due to the complexity of the SMB protocol, and adding this functionality would greatly increase the complexity of the module.

  • The protocol is quite noisy, and so it can be difficult to determine if the file was successfully downloaded or if it was download and executed.

  • Currently there is no exclusive lock on files being requested, and this allows for the file to be downloaded multiple times. In my experience, it only gets executed once, but it does make for noisy output within the module.

Lessons Learned & Tips

  • The SMB protocol is one of the noisiest protocols I’ve ever looked at. The number of requests required just to establish a connection to a share and download a file is much higher than I would have ever anticipated! This module requires 9 distinct request/responses, granted some of those are very simple such as an SMB ping.

  • When running multiple commands in VBScript, the most consistent way I have found is to execute cmd.exe and use the && operator instead of multiple .run commands.

  • When setting up an SMB server, pay special attention to the “capabilities” bits that are sent during the negotiation phase. For similar modules, I recommend:

0x0080000d # UNIX extensions; large files; unicode; raw mode

  • When working with SMB, use the Wireshark dissector to determine what is being parsed accurately. I’ve included resources for the protocol below, but Wireshark was essential to building this module.

  • Every version of Windows, and different tools or commands, use the SMB protocol differently. When testing with Windows XP, and Windows 7, even the “type” command of a remote share was different than using the Windows Run dialog, and even the Windows Explorer Address bar. Keep this in mind when playing with Windows SMB, as you have to target specific environments and functionality.

  • This almost goes without saying, but do try your scripts out on the local test environment before attempting to execute them remotely. VBScript and Batch don’t necessarily have the most intuitive syntax.

References & Resources

Source Code


Docker Secure Deployment Guidelines

Within today’s growing cloud-based IT market, there is a strong demand for virtualisation technologies. Unfortunately most virtualisation solutions are not flexible enough to meet developer requirements and the overhead implied by the use of full virtualisation solutions becomes a burden on the scalability of the infrastructure.

Docker reduces that overhead by allowing developers and system administrators to seamlessly deploy containers for applications and services required for business operations. However, because Docker leverages the same kernel as the host system to reduce the need for resources, containers can be exposed to significant security risks if not adequately configured. 

The GitHub repository referenced below aims at providing some deployment guidelines for Docker developers and system administrators alike, that can be used to improve the security posture of Linux containers within a Dockerized environment.


Hooking Non-Public Methods With the NDK - Using Mobile Substrate For Android Part 2

One day, you decide to put on the security ninja gloves, open your laptop, plug your android phone and take apart your dear Android application using Part 1 of our tutorial on Android Hooking using Mobile Substrate; and you realize there is something wrong – something is not working. Then you come to the realization that your hook can’t access non-public methods. This post will discuss an option for hooking non-public methods by utilizing Mobile Substrate from NDK code.

Getting Started

The application we will be using in this demonstration is a demo application called SuperMath and can be downloaded here. This application will perform various mathematical operations within private functions and display the results to the user. The focus of this post will be hooking into private functions of a class, accessing and modifying the function parameters, and viewing and modifying the function’s return values.

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:

You can also read the following documentation on how to download the Mobile Substrate APIs here:

Preparing NDK/JNI Support

After following steps “Setting Up the IDE” and “Adding Permissions to AndroidManifest.xml” from Part 1 of our tutorial, we need to make sure that we have installed and enabled NDK support for the ADT plugin and that the environment variables are set properly. To ensure that we have NDK support available, we will navigate to the ‘About Eclipse’ menu item, click the ‘Installation Details’ button and check for ‘Android Native Development Tools’ under ‘Installed Software’. If an entry for ‘Android Native Development Tools’ is missing then we are missing NDK support and NDK support can be installed from the ADT Plugin Update Site. 

Once the plugin has been installed successfully, ensure that SDK and NDK paths have been properly set in Eclipse Properties. This can be done as follows:

  • Navigate to the ‘Preferences’ menu item, select ‘Android’ preferences, and set SDK path
  • Navigate to the ‘Preferences’ menu item, expand ‘Android’ preferences, select ‘NDK’ preferences, and set NDK path

Adding NDK/JNI Support

Next, we will need to add support for NDK/JNI to our project. This will allow us to use NDK functions to interact with the Android system and applications. In order to add NDK/JNI support, Right Click on project, navigate to the ‘Android Tools’ context menu, and click ‘Add Native Support…’. Once you click the menu item, Eclipse will show you a dialog box and will ask you for the name of your library. You can specify whatever name that pleases you. However, it is a good practice to append suffix ‘.cy’ to help one identify it is a Cydia extension.





Once you click Finish, the ADT plugin will process the provided information and generate a new directory ‘jni’ under the project directory and create following two new files –

  •  <libName>.cpp: This file will contain the code for the Substrate hook
  • This is a Makefile file which contains make commands used to build our hook



Including Substrate Libraries

Next, we need to include the Substrate libraries. The easiest way to do this is to navigate to the ‘/sdk/extras/saurikit/cydia_substrate/’ directory and copy ‘substrate.h’ and navigate to the ‘/sdk/extras/saurikit/cydia_substrate/lib/<ARCH>/’ directory and copy ‘’ file into the jni folder of the project.



Finding Target Functions

The ‘SuperMath.apk’ contains a private method to perform multiplication (This can be identified by decompiling the application using a utility like Dex2Jar) :

private String mul(int a, int b){
  return "" + (a * b);


If we recall, the steps outlined in previous tutorial will not allow us to hook into non-public members of a class.  By creating our hooks using NDK code we will be able to overcome this limitation.

Coding a Substrate NDK Hook

We will start by including appropriate header files in the ’.cpp’ file, and calling the ‘MSConfig’ Substrate macro.

#include "substrate.h"
#include <android/log.h>

#define TAG "NDK_HOOK"

 * Decide where we would like to hook
MSConfig(MSFilterExecutable, "/system/bin/app_process") 


The first import statement imports substrate headers into the current program to provide us all Substrate functionality. The second import statement imports Android logging headers into the current program to provide us logging features, which will be used later in the program to log information to LogCat.

MSConfig is a Substrate macro that allows developers to configure and ask the Substrate runtime to allow our extension to hook into the application or the library of our choice. MSConfig takes two string constant arguments: the name of a configuration option and a string value.

Macro Signature: MSConfig(configOption, configOptionValueAsString)

Configuration Option



This tells the Substrate runtime that we would like to hook into an application. If this configuration option is specified as the first argument to the MSConfig macro, the second argument is a string value containing the fully qualified path to the process that we are trying to hook. Usually this argument is set to “/system/bin/app_process” as this process points to zygote but can be other processes as well.  For more information on why we wish to hook zygote, refer to the blogpost by David Ehringer on The Dalvik Virtual Machine Architecture. For this blogpost, we will hook into zygote.


This tells the Substrate runtime that we would like to hook into a library. If this configuration option is specified as the first argument to the MSConfig macro, the second argument is a string value containing the library that we are trying to hook. If we are trying to hook __android_log, the value of this argument will be “”.


Then we will call the MSInitialize macro in order for us to write the function definition used to initialize the hook. This is the primary entry point into the application and where we begin to write our hooks.

 * Substrate entry point
  // Let the user know that the extension has been
  // extension has been registered
  __android_log_print(ANDROID_LOG_ERROR, TAG,
      "Substrate initialized.");

// Hook into specified class and call OnClazzLoad // method when hooked MSJavaHookClassLoad(NULL, "me/rahilparikh/SuperMath/ShowMathOps", &OnClazzLoad); }


A call is made to the MSJavaHookClassLoad function, which is used to hook into the class specified by the second argument to the function.  A callback function is passed as the third argument which will be called once the ‘ShowMathOps’ object is loaded.

Method Signature: MSJavaHookClassLoad( jniPtr, classNameAsString, referenceToCallbackMethod)

The class name passed to MSJavaHookClassLoad follows the JNI naming convention. So, me.rahilparikh.SuperMath.ShowMathOps is written as me/rahilparikh/SuperMath/ShowMathOps. The OnClazzLoad callback function will now need to be defined as follows:

 * This method should be used to perform various operations
 *  within the class
static void OnClazzLoad(JNIEnv *jniPtr, jclass clazz,
    void *data) {

  // Let user know that the class has been hooked
  __android_log_print(ANDROID_LOG_ERROR, TAG,
      "Hooked into the application.");

  // Search for method
  jmethodID methodMul = jniPtr->GetMethodID(clazz, "mul",
  if (methodMul != NULL) {
    // Let user know that we have found the method
    __android_log_print(ANDROID_LOG_ERROR, TAG,
        "mul called.");
    // Hook into method
    MSJavaHookMethod(jniPtr, clazz, methodMul,
        &newMulMethod, &oldMulMethod);


The onClazzLoad callback function is invoked once the specified object is loaded by the Android device. The first parameter to this function is a JNI Pointer, which will provide us access to various JNI methods. The second parameter to this function is an instance of jclass, which will provide us access to the members of the class.

In onClazzLoad, we call the GetMethodId method to get a reference to the method that we are trying to hook into. Refer to JNI and JNI Types and Data Structures documents to for more information on how to use GetMethodId and other JNI methods. On the next line, we check if an instance of the returned methodId is null or not. If the instance is not null, a Java method that matches our signature was found and we will use MSJavaHookMethod to hook into our desired method.

The MSJavaHookMethod function is used to replace the implementation of the function at runtime. The third parameter contains the reference to the ‘methodId’ that was previously returned by the GetMethodID function. The fourth parameter contains the reference to the new implementation of the ‘mul’ method that will need to be defined within our Substrate code. The fifth parameter will contain a callback reference to the original ‘mul’ method. We will still need to the define a prototype for the function passed as the fifth parameter. Substrate will handle setting the appropriate values once the ‘mul’ method is hooked.

The following walks through how to create the function prototype to the ‘oldMulMethod’ and a definition for the new ‘newMulMethod’ method to include the code we want to execute within the hook.

 * Original method template
static jstring (*oldMulMethod)(JNIEnv *jni, jobject _this, ...);

 * Modified method
static jstring newMulMethod(JNIEnv *jni, jobject _this,
    jint param1, jint param2) {

  // Let user know that the method has been hooked
  __android_log_print(ANDROID_LOG_ERROR, TAG,
      "Hooked into mul.");

  // Print all original parameters
  __android_log_print(ANDROID_LOG_ERROR, TAG, "Param1 : %d",
  __android_log_print(ANDROID_LOG_ERROR, TAG, "Param2 : %d",

  // Call original method
  jstring originalRetVal = (*oldMulMethod)(jni, _this, param1,
  __android_log_print(ANDROID_LOG_ERROR, TAG,
      "Original Answer : %s",
      jni->GetStringUTFChars(originalRetVal, 0));

  // Modify return value of original method
  char *modifiedRetValC = (char*) malloc(3);
  strcpy(modifiedRetValC, "10");
  __android_log_print(ANDROID_LOG_ERROR, TAG,
      "Modified Answer : %s", modifiedRetValC);
  jstring modifiedRetValS = jni->NewStringUTF(

  // Be a nice kid, return what you've got

  // Return modified return value
  return modifiedRetValS;


The hook will simply log the values of the parameters that were passed by the application to the ‘mul’ method. This allows us to gain visbility into the values being passed at runtime without requiring a debugger. We then call the ‘oldMulMethod’ function which causes the original ‘mul’ method that was defined by the hooked application to be invoked. We could have modified the values for the param1 and param2 variables if we would have liked, but in this scenario we simply pass them to the original method. The return value of the original mul function is then logged as well. Lastly, we then decide to modify the expected return value of the ‘mul’ funtion so that the value of “10” will always be returned.


Once the hook has been created we need to update the Makefile to help the Android build system understand what we are trying to achieve and how it should compile our application. The Android system creates a make file with the following as default content –

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)



This would have allowed us to compile a simple ‘Hello World’ application but we will need to make some modifications to account for the Substrate library dependencies. The resulting Makefile should look similar to the following:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE:= substrate-dvm

include $(CLEAR_VARS)

LOCAL_LDLIBS += -L$(LOCAL_PATH) -lsubstrate-dvm



For more information on how to configure the file, refer to the NDK Programmer’s Guide, which is shipped with the NDK SDK.

Running our Substrate Hook

With the skeleton of the Substrate hook in place, running this code should allow us to hook into the desired class and method. The created Substrate hook can then be run using the instructions found in Part I - Using Mobile Substrate With Android Applications  After the screen flashes, we can run the SuperMath application and monitor the output of Logcat for the tag “NDKHook”. 


JNI does not suffer from the access restrictions that are imposed by Java to access various fields, methods and other members of an application. Therefore, writing hooks using the NDK Substrate APIs can give us low-level access to the application code and allows us to make changes to the existing code at runtime.

One should also remember that some of the method signatures provided here are simplified, minimal and essential for writing a hook. There are instances where these methods can take more arguments but are not specified here as they have been omitted to improve the understanding of the hook writing process and/or they are not required in most cases.

All of the code discussed within this blog post can be found on our Github page here.


References/Further Reading

Ehringer, D. (2010, March). The Dalvik Virtual Machine Architecture. Retrieved October 2014, from

Java Programming Tutorial – Java Native Interface (JNI) . (2014, February). Retrieved October 2014, from

JNI Functions. (n.d.). (Oracle Corp.) Retrieved Oct 2014, from Java SE Documentation:

JNI Types and Data Structures. (n.d.). (Oracle Corp.) Retrieved October 2014, from Java SE Documentation:

Kumar, A. (2012, October). Understanding Android: Zygote and DalvikVM. Retrieved October 2014, from StackOverflow:

NDK Programmer’s Guide. (n.d.). Retrieved October 2014, from /ndk/docs/Programmers_Guide/html/md_3__key__topics__building__chapter_1-section_8__android_8mk.html



A Java Web App's Attack Surface to Shellshock

Amongst the chaos of trying to patch and the whirlwind of information on the Shellshock vulnerability, several of our clients raised the question - what level of exposure, if any, do our enterprise Java web applications have to Shellshock?

In case you’ve been living under a shell, here are a few links to get up to speed on CVE-2014-6271, dubbed Shellshock. Various web-based software products were proven to be vulnerable. Custom web apps running on Apache using mod_cgi or mod_cgid where CGI scripts are either written in Bash, or spawning subshells are also easy targets (if a vulnerable version of Bash is still installed). Web apps written in PHP, Python, or Java could be vulnerable if they make calls to functions such as popen() or system(), as these are backed by calls to /bin/sh -c. Since it is common for systems to create symbolic links from /bin/sh to /bin/bash it could still lead to these applications being susceptible to the Shellshock vulnerability.  

Despite Java apps being implicated as potentially vulnerable, our gut reaction was the exposure for a typical Java web app would likely not be critical or systemic, but rather on a case by case basis. Further, we always advise our clients that any Java web app spawning external processes be closely audited and better more secure alternatives be considered irrespective of this Bash vulnerability. With that said, we still wanted to do a little bit of research to back this up and this blog post shares some of these results. On to the details …

Two main conditions must be met to exploit the Shellshock vulnerability :

  1. The system runs a vulnerable version of Bash shell
  2. An attacker injects a persistent or volatile malicious environment variable into directly or indirectly invoked Bash shell

Applications running Apache ‘mod_cgi’ are remotely vulnerable to Shellshock due to HTTP request headers (e.g. User-Agent header) being set as environment variables. During the request processing Apache receives an HTTP request header and sets the values as environment variables that are visible within the script handler provided by mod_cgi. The combination of user controllable environment variables through HTTP data and the behavior of command executions spawning shells creates a high potential for exploitable Shellshock scenarios within CGI applications to be a likely scenario.

However, Java web application containers like Apache Tomcat, handle the request parameters and headers without using the environment variables as a pipeline. To verify the previous statement GDS performed a set of tests on Apache Tomcat (v8.0.12,7.0.55) and JBoss Application Server (v7.4). The tests included using a python script that injects a Shellshock payload into HTTP request headers and query parameters on a selected endpoint. A simple JSP page was built to iterate through the environment variables to confirm that the request headers did not lead to an environment variable being tainted with user input. As expected, this was confirmed and significantly reduces the potential for Shellshock to be exploited in a Java web app via the typical HTTP header payloads


… snip …

Enumeration<String> HeaderName = request.getHeaderNames(); %>

<H1> Headers</h1>


 String headerName , headerValue  ;


  headerName  = HeaderName.nextElement();

  headerValue = request.getHeader(headerName);

  // Save Header

  headerMap.put(headerName, headerValue);

 %><H1> Env Variables </h1><%

for(Map.Entry<String,String>  entry : System.getenv().entrySet()){ %>

  <%=entry.getKey()%> <%=entry.getValue()%><br>


for(Map.Entry<String,String> headerEntry : headerMap.entrySet()){


  finding.put(entry.getKey(), headerEntry.getKey() +":"+ headerEntry.getValue());


// Register Logs

for(Map.Entry<String,String> entry : finding.entrySet()){



…snip … :

…snip …

def start:

request_headers =  {}

for header_key in INPUT.HEADERS:

for reuqest_method in INPUT.METHODS:

  request_headers = copy.copy(INPUT.HEADERS)

  request_headers[header_key] = INPUT.HEADERS[header_key]+INPUT.PAYLOAD

  self.__client.request( request_method,"/ POCs_Headers.jsp",headers=request_headers )


… snip …

Java’s ‘Runtime.exec’ method seemed like the most obvious place to start as a high-risk function that could work as a stepping stone for exploitable scenarios of Shellshock. ‘Runtime.exec’ uses the ProcessBuilder class to execute the command passed to it. The following outlines the function execution flow for executing the submitted command.

Runtime.exec function flow :

- > Runtime.exec(String command)

- > Runtime.exec(String command, String envp, File dir)

- > ProcessBuilder.start(String[] cmdArray, Map<String,String> env, String dir, …)

- > UnixProcess( final byte[] prog, …. )

- > forkAndExec( … )

Unlike command execution APIs found on PHP or Perl where a shell will be invoked regardless of the string passed in, Java’s Runtime.exec does not work in this manner. Runtime exec will perform an exec of the submitted string value and therefore a Shellshock vulnerability could only occur if Bash is invoked by the running process by calling ‘/bin/bash’, symbolic links to ‘/bin/bash’ or any executable that may invoke Bash at some point. 

In the event that an environment variable within the application server process is user controllable it would cause the application invoking the following code to be vulnerable to the Shellshock vulnerability (as discussed above, this is not the case for the application servers we looked at):

Runtime.getRuntime().exec( "/bin/bash" ) ;

Runtime.getRuntime().exec( "/" ) ; # Where uses !#/bin/bash 

Another exploitable scenario but also very unlikely would be if a malicious environment variable is passed as the second parameter within the ‘Runtime.exec’ method.


  new String[]{"/bin/bash"},

  new String[]{"P=() { :;}; echo 'vulnerable' > message"}



  new String[]{"/"},

  new String[]{"P=() { :;}; echo 'vulnerable' > message"}


What follows is a sample code snippet that if present in a web app would be remotely exploitable via Shellshock:

… snip …

Enumeration<String> HeaderName = request.getHeaderNames();

String headerName , headerValue ;



 if ( headerName.nextElement().equals(“HOST”)){

 headerValue = request.getHeader(headerName);


  new String[]{“/bin/bash”,”-c”,”/bin/process_host”}, new String[] {headerValue});



Although not impossible, it’s unlikely that a developer would pass the environment variable intentionally via a HTTP header.

In conclusion, while there are certain scenarios where a Java web app could be vulnerable to Shellshock, these are likely to be one off edge cases. This is primarily due to application servers not setting environment variables with HTTP request data and also the fact that Runtime.exec does not invoke a shell unless explicitly set by a developer or indireclty used by any invoked script. Organizations should ensure that Bash is patched to the latest version and not vulnerable to Shellshock. Additionally, identify if any of the following methods or functions are called using a shell (e.g. /bin/bash/, /bin/sh, shell scripts) and ensure user input is not passed in as any parameters unless it undergoes stringent input validation. 

  • Runtime.exec
  • ProcessBuilder.start

  • UnixProcess

  • forkAndExec

It is also recommended to pass in a empty String array as the environment to these functions in order to prevent the possibility of the application server’s environment being tainted with user input. By passing an empty array as the environment it will provide an extra layer of protection in the event the application server’s environment variables can be compromised


Auditing Scala for Insecure Code with FindBugs

Here at GDS we have noticed an increase in the use of the Scala programming language by our clients. We have been looking for good tools to perform static analysis of Scala to facilitate our code audits. Although there are static analysis tools for Scala, they are not capable of identifying security issues with their out of the box rule-sets. In this blog post we cover how FindBugs can be leveraged to scan Scala for the purposes of identifying insecure code patterns.

Why FindBugs?
FindBugs is an open source static analysis tool that detects bugs in Java applications. Unlike static analysis tools PMD or Jlint, FindBugs operates on bytecode rather than source code. Because Scala classes compile to Java bytecode, this means we can run FindBugs against them! Additionally, FindBugs exposes a plugin interface making it possible to write custom bug detectors to find vulnerabilities in Scala applications. It is possible to run FindBugs without custom detectors against a Scala code base, however there will certainly be false positives and false negatives since the bug detectors are tuned against javac compiler generated bytecode. To start finding security flaws we need to write Scala specific detectors. Finally, because FindBugs is a well-known open source project already common to developer toolchains, the learning curve for extending is potentially reduced and existing development workflows do not need to be altered. It is also worth mentioning that FindBugs is integrated into the enterprise security static analysis tool Fortify SCA, and so the approach we suggest here could be a low cost alternative for these organizations. 

Implementing Your First Security Detector
We will implement a very small ‘Hello World’ detector which does nothing more than to flag every time a dangerous MongoDB function is executed. We will be writing a rule targeting Casbah, the official MongoDB driver for Scala. The Casbah library has an ‘eval’ method which can lead to the execution of arbitrary Javascript code if unvalidated user input is passed in. We will walk through how to write a rule to identify potential insecure usage of the Casbah ‘eval’ method within Scala applications.

For an introductory tutorial on how to write custom detector for FindBugs have a look at For the rest of this blog post it will be assumed that you know the basics shown in the above link.

  • Since we are operating on bytecode we will extend the BytecodeScanningDetector
  • We will override the visit method, since it is called every time new code is executed.
  • When we find the ‘eval’ method we will log a bug using the standard FindBugs logging interface.

We start with extending the BytecodeScanningDetector so Findbugs knows what code we are interested in.

public class HelloworldRule extends BytecodeScanningDetector {

Next, we declare the function we are looking for. Invokevirtual means that a new function is being invoked.
private final String VULNERABLE_METHOD = "com.mongodb.casbah.MongoDB.eval";
private final String FUNCTION_DECLARATION = "invokevirtual";
BugReporter bugReporter;

We also need to define a constructor which will take in a ‘bugreporter’ object which is used to report back found bugs to FindBugs.
public HelloworldRule(BugReporter bugReporter) {
 this.bugReporter = bugReporter;

Next we chose to implement the visit function. The documentation around this method is a bit shorthanded but the returned object “represents a chunk of Java byte code contained in a method” according to the Javadocs. Using this method allows us to analyze a function line by line.
public void visit(Code someObj) {
 ByteSequence stream = new ByteSequence(someObj.getCode());
 while (stream.available() > 0) {
   String line = Utility.codeToString(stream, someObj.getConstantPool(), true);

 We use two helper functions to identify the function call. getCommand will give us the current instruction being executed. In this example we are mainly interested in the invokevirtual instruction mentioned above. 
String command = getCommand(line);

We also use getFunction to parse out a function signature. It might look like the following:
com.mongodb.casbah.MongoClient$.apply (Ljava/lang/String;I)Lcom/mongodb/casbah/MongoClient
The signature will always start with the full package name followed by the function name. For this example, this is all we need. For more involved rules, the function arguments could also be analyzed.
String function = getFunction(line);
 if(command.equals(FUNCTION_DECLARATION) &&   
   function.startsWith(VULNERABLE_METHOD)) {

If the function matches what we are looking for we will log a bug. We state that it’s a normal priority bug and we pass in an identifier which we will define below.
    BugInstance instance = new BugInstance("MONGO_INJECTION",

protected String getCommand(String line) {
 String[] parts = line.split("\\t");
 return (parts.length > 0) ? parts[0] : "";

protected String getFunction(String line) {
 String[] parts = line.split("\\t");
 return (parts.length > 1) ? parts[1] : "";

We also need to reference our new rule so FindBugs knows where to find it. Create a new folder in the project directory and name it “etc”. Create a new file called findbugs.xml in this folder. In here we can reference the rule by adding the following text:

  <Detector class="com.package.HelloworldRule" speed="fast" />

Lastly we need to give a short description of our plugin. Create a new file called messages.xml in that same folder. Put the following content in there:

  <Detector class="com.package.HelloworldRule">
      <p> A Simple Mongo Injection Detection Rule</p>

The plugin is now ready to go, let’s give it a test!

Running FindBugs is pretty simple, all you need to do is to download the Jar and specify the source to run against. Adding new plugins is simple as well. You can either supply the plugin jar as a command line argument or you can add it to the default plugins folder for FindBugs. For this example we’ll add it on the command line:

java -jar /path-to-findbugs/findbugs.jar -textui -pluginList /path-to-your-new-jar.jar -home . -auxclasspath /path-to-scala-installation/:casbah-alldep.jar /path-to-class-files/

It is important to specify the auxclasspath option since this is how we will specify the classpath to the Scala installation. If the auxclasspath is not set, running Findbugs on Scala code will result in various errors. Additionally we add the Casbah jar to the path since it is a dependency to our sample application. Any other dependencies to the application being scanned should be added to the auxclasspath option when running FindBugs. The sample output below shows how FindBugs will report usage of the Casbah eval function within a Scala application.

M S GDS: A Simple Mongo Injection Detection Rule.       At CasbahExample.scala:[line 18]

This is just a short introduction on how to leverage FindBugs to analyze Scala code. Hopefully this code can be used as a foundation to write more involved and more complex rules. Popular web frameworks such as Play and Vert.x run in Scala and FindBugs can certainly be used to evaluate them.

The code referenced in this blog post can be found on our GitHub page: