RCE and PCI Data Exfiltration in Oracle OPERA

Hotel Counter © 2010 Italy Travel Experience (CC BY-NC-SA 2.0)

tl;dr: I found bugs in Oracle's hotel management platform which can be used to escalate app privileges and gain access into the operating system and database. An attacker on the network starting from an unauthenticated standpoint could exploit them to exfiltrate stored cardholder data. The issues were reported to Oracle, quickly patched, and CVE IDs were issued.


Oracle OPERA (formerly MICROS OPERA) is a dominant property-management platform used by hotels worldwide. It’s the software you’d see staff use behind the counter at chains like the Hyatt and Hilton to manage reservations and process payments.


For the purpose of settling transactions, the application retains encrypted PANs (credit card numbers), expiry dates, and cardholder names in an Oracle SQL database. Three different ways to gain database access were discovered. Once an attacker has gained access, they could then develop the capability to extract and decrypt the stored cardholder data.

All of these issues were found in areas that wouldn’t have been part of any user stories and would not have been identified solely through black-box testing. But unlike in-house developed solutions, the wide deployment of vendor solutions makes it easier for motivated attackers to obtain and analyze the software (legally or illegally). Through static and dynamic analysis, an attacker could determine entry points that stray off the beaten path.



CVE-2016-5565: Session Hijacking via Exposed Logs

Login log

After a user logs into OPERA, they can choose which interface they want to interact with. For most users, this is typically the Property Management System (PMS) interface that’s circled above. The request to launch interfaces contains the user’s session token and parameters of the particular interface they want to launch.

launch request

Just one problem though… the session tokens and other parameters required to start a session were logged in a directory that can be accessed through the webserver… without authentication.

Login log

An attacker simply needs to wait for an administrative user to login and once they’re in, they can gain full privileges within the application. Administrators have access the the “Opera SQL” tool which allows them to submit raw queries to the database.

Opera SQL

The caveat with using this approach to extract cardholder data is that it’s too slow and not stealthy enough. Every query is logged at the application layer and using the Oracle Forms UI is much more sluggish than establishing a direct connection to the database server.

CVE-2016-5564: Exposure of Oracle SQL Database Credentials

If the attacker is on the same network as the database server, another approach would be to construct a database connection string. The database credentials and service name were returned in the HTML of a successful authentication response to launch Oracle Forms. The database server hostname was accessible in the response of an unauthenticated servlet.

Database credentials

With this, an attacker has what they need to connect with sqlplus using the “easy connect” syntax. They can also avoid the user-tied logging and sluggish behaviour in the “Opera SQL” tool.

sqlplus [Username]/[Password]@[Hostname]:[Port]/[Service Name]

Database connection

CVE-2016-5563: RCE via OS Command Injection and RFI

In circumstances where the attacker has access to only the application server (e.g. Internet exposure) or if inbound connections to the database server are restricted to only the application server, this remote code execution vulnerability could be exploited to their advantage. This is my favourite finding because it puts together seemingly unrelated elements toward a malicious purpose.

There was what appeared to be a diagnostic process information servlet that would return information given a PID. What may not be obvious in a black-box test is that the PID argument flows into a concatenated string for command execution. An attacker could, as shown below, modify the argument to run another command and send that output to another file accessible through the web server.

ProcessInfo flow

If it worked as expected, it should have returned the whoami output into the webtemp directory within web root. Instead what I got was an error message saying that a certain file was missing.

ProcessInfo error

Looking at the corresponding code for this servlet, we can see where the error occurs. The constructed command line contains the path of the pslist utility which is derived from a property file. The location of that file is hardcoded to D:\micros\opera\operaias\default.env but it doesn’t seem to exist there. This is why the function fails before getting to execute the pslist command.

ProcessInfo code

A couple things need to be done to fix this servlet:

  1. Find the value of the OPERA_HOME property.
  2. Save it to D:\micros\opera\operaias\default.env.

Coincidentally, there was another diagnostic servlet that exposed the OPERA_HOME property.


And yet another diagnostic servlet conveniently served as an RFI vector to upload to the target path:


Exploiting the ProcessInfo servlet again seemed to indicate that the fix worked. The whoami output indicated the application was running as SYSTEM.


Cardholder Data Decryption

Leveraging any combination of the findings detailed above, an attacker could gain authenticated access to the database starting from an unauthenticated standpoint. From there, they could retrieve cardholder data and decrypt them.

According to the OPERA knowledgebase, credit card numbers and expiration dates are stored in the database tables in encrypted (Triple DES) format. Of interest to an attacker would be the 3DES encryption keys. The DBMS_OBFUSCATION_TOOLKIT package is used by OPERA to perform 3DES encryption. That package does not store or maintain the keys. Instead, a separate package is created to store the keys and handle encryption function calls. The wrap utility of PL/SQL is used to obfuscate the code to prevent casual snooping. This package is regenerated every time the encryption keys are changed.

An example SQL query used to retrieve the package body is: SELECT NAME, TYPE, TEXT from USER_SOURCE WHERE NAME LIKE '%IFC_CRYPT_V4_%'.

As the package body is only obfuscated, it could be de-obfuscated or “unwrapped” to reveal the 3DES keys.

Now that the keys and algorithm are known, the next step for an attacker would be to find the tables where the encrypted data is stored. That information is conveniently available in the OPERA knowledgebase:

A select query performed on the NAME$_CREDIT_CARD table can yield names and encrypted card information. The ciphertexts can then be passed through a script to decrypt them to plaintext.

Responsible Disclosure Process

The disclosure process with Oracle was delightfully straightforward. I received a response within 24 hours of submitting the vulnerability report with their PGP public key. After supporting some clarification requests, the fixes were scheduled for the next Critical Patch Update.