Security Advice – Remove the Unused Function mdlaux.externalcommand from BIOVIA Direct

Background

BIOVIA Direct includes the auxiliary function mdlaux.externalcommand which allows a user to execute commands on the Oracle server that BIOVIA Direct is installed on. Following BIOVIA's recommendation to run BIOVIA Direct through a secure extproc listener, i.e. run the listener from a non-privileged account with limited permissions in the system, the mdlaux.externalcommand function has only limited access to the system. However, as the mdlaux.externalcommand function is no longer used in any currently supported version of BIOVIA Direct, BIOVIA recommends removing this function from BIOVIA Direct to avoid any security risks that it might present.

Starting with version 2022, BIOVIA Direct will no longer include the mdlaux.externalcommand function. To remove the function from previous BIOVIA Direct versions, follow the instructions as discussed in the Solution section. The instructions apply to BIOVIA Direct version 2017 and higher, and are valid for any supported operating system.


Solution

You can remove the mdlaux.externalcommand function while performing a new BIOVIA Direct installation or when a BIOVIA Direct version is already installed.

Removing the mdlaux.externalcommand function while performing a new installation of BIOVIA Direct

1. During the standard installation process of BIOVIA Direct, and right after you unpacked the BIOVIA Direct application files to their final installation directory, make a backup copy of the mdlauxop.sql file that is located in the sql subdirectory of the BIOVIA Direct installation directory.

2. Open the mdlauxop.sql file in an editor and make the following changes:

Locate and comment out the declaration for the ExternalCommand function within the CREATE PACKAGE statement.

/*    FUNCTION ExternalCommand(command IN VARCHAR2,
                            inputClob IN CLOB,
                            args IN VARCHAR2,
                            binaryOutput IN BOOLEAN,
                            outputClob OUT CLOB,
                            outputBlob OUT BLOB,
                            stdout OUT VARCHAR2,
                            stderr OUT VARCHAR2)
   RETURN BOOLEAN; */

Locate and comment out the declaration for the ExternalCommandHelper function within the CREATE PACKAGE statement.

/*    FUNCTION ExternalCommand(command IN VARCHAR2,
                            inputClob IN CLOB,
                            args IN VARCHAR2,
                            binaryOutput IN BOOLEAN,
                            outputClob OUT CLOB,
                            outputBlob OUT BLOB,
                            stdout OUT VARCHAR2,
                            stderr OUT VARCHAR2)
   RETURN BOOLEAN; */

Locate and comment out the definition for the ExternalCommand function within the CREATE PACKAGE BODY statement.

/*    FUNCTION ExternalCommand(command IN VARCHAR2,
                            inputClob IN CLOB,
                            args IN VARCHAR2,
                            binaryOutput IN BOOLEAN,
                            outputClob OUT CLOB,
                            outputBlob OUT BLOB,
                            stdout OUT VARCHAR2,
                            stderr OUT VARCHAR2)
   RETURN BOOLEAN IS
      ret BOOLEAN;
      tmpOutputClob CLOB;
      tmpOutputBlob BLOB;
      bflag BINARY_INTEGER;
   BEGIN
   [... more code removed for better readabilty... ]
   END ExternalCommand; */

Locate and comment out the definition for the ExternalCommandHelper function within the CREATE PACKAGE BODY statement.

/*    FUNCTION ExternalCommandHelper(command IN VARCHAR2,
                                  inputClob IN CLOB,
                                  args IN VARCHAR2,
                                  binaryOutput IN BINARY_INTEGER,
                                  outputClob IN OUT CLOB,
                                  outputBlob IN OUT BLOB,
                                  stdout OUT VARCHAR2,
                                  stderr OUT VARCHAR2)
   RETURN BINARY_INTEGER
   IS LANGUAGE C
      NAME "MDLExternalCommand"
      LIBRARY mdldirect
      WITH CONTEXT
      PARAMETERS (CONTEXT,
                  command                STRING,
                  command      INDICATOR SHORT,
                  inputClob              OCILOBLOCATOR,
                  inputClob    INDICATOR SHORT,
                  args                   STRING,
                  args         INDICATOR SHORT,
                  binaryOutput           INT,
                  binaryOutput INDICATOR SHORT,
                  outputClob             OCILOBLOCATOR,
                  outputClob   INDICATOR SHORT,
                  outputBlob             OCILOBLOCATOR,
                  outputBlob   INDICATOR SHORT,
                  stdout                 STRING,
                  stdout       INDICATOR SHORT,
                  stdout          MAXLEN INT,
                  stderr                 STRING,
                  stderr       INDICATOR SHORT,
                  stderr          MAXLEN INT,
                  RETURN       INDICATOR SHORT,
                  RETURN                 INT);
 */

3. Save the edited file. Continue the BIOVIA Direct installation as directed in the BIOVIA Direct Installation and Configuration Guide.


Removing the mdlaux.externalcommand function from an already existing BIOVIA Direct installation


1. Make a backup copy of the mdlauxop.sql file that is located in the sql subdirectory of the BIOVIA Direct installation directory.

2. Open the mdlauxop.sql file in an editor and make the following changes:

Locate and comment out the declaration for the ExternalCommand function within the CREATE PACKAGE statement.

/*    FUNCTION ExternalCommand(command IN VARCHAR2,
                            inputClob IN CLOB,
                            args IN VARCHAR2,
                            binaryOutput IN BOOLEAN,
                            outputClob OUT CLOB,
                            outputBlob OUT BLOB,
                            stdout OUT VARCHAR2,
                            stderr OUT VARCHAR2)
   RETURN BOOLEAN; */

Locate and comment out the declaration for the ExternalCommandHelper function within the CREATE PACKAGE statement.

/*    FUNCTION ExternalCommandHelper(command IN VARCHAR2,
                                  inputClob IN CLOB,
                                  args IN VARCHAR2,
                                  binaryOutput IN BINARY_INTEGER,
                                  outputClob IN OUT CLOB,
                                  outputBlob IN OUT BLOB,
                                  stdout OUT VARCHAR2,
                                  stderr OUT VARCHAR2)
   RETURN BINARY_INTEGER; */

Locate and comment out the definition for the ExternalCommand function within the CREATE PACKAGE BODY statement.

/*    FUNCTION ExternalCommand(command IN VARCHAR2,
                            inputClob IN CLOB,
                            args IN VARCHAR2,
                            binaryOutput IN BOOLEAN,
                            outputClob OUT CLOB,
                            outputBlob OUT BLOB,
                            stdout OUT VARCHAR2,
                            stderr OUT VARCHAR2)
   RETURN BOOLEAN IS
      ret BOOLEAN;
      tmpOutputClob CLOB;
      tmpOutputBlob BLOB;
      bflag BINARY_INTEGER;
   BEGIN
   [... more code removed for better readabilty... ]
   END ExternalCommand; */

Locate and comment out the definition for the ExternalCommandHelper function within the CREATE PACKAGE BODY statement.

/*    FUNCTION ExternalCommandHelper(command IN VARCHAR2,
                                  inputClob IN CLOB,
                                  args IN VARCHAR2,
                                  binaryOutput IN BINARY_INTEGER,
                                  outputClob IN OUT CLOB,
                                  outputBlob IN OUT BLOB,
                                  stdout OUT VARCHAR2,
                                  stderr OUT VARCHAR2)
   RETURN BINARY_INTEGER
   IS LANGUAGE C
      NAME "MDLExternalCommand"
      LIBRARY mdldirect
      WITH CONTEXT
      PARAMETERS (CONTEXT,
                  command                STRING,
                  command      INDICATOR SHORT,
                  inputClob              OCILOBLOCATOR,
                  inputClob    INDICATOR SHORT,
                  args                   STRING,
                  args         INDICATOR SHORT,
                  binaryOutput           INT,
                  binaryOutput INDICATOR SHORT,
                  outputClob             OCILOBLOCATOR,
                  outputClob   INDICATOR SHORT,
                  outputBlob             OCILOBLOCATOR,
                  outputBlob   INDICATOR SHORT,
                  stdout                 STRING,
                  stdout       INDICATOR SHORT,
                  stdout          MAXLEN INT,
                  stderr                 STRING,
                  stderr       INDICATOR SHORT,
                  stderr          MAXLEN INT,
                  RETURN       INDICATOR SHORT,
                  RETURN                 INT);
 */ 

Save the edited file.  

3. If required, notify users that BIOVIA Direct will be shortly unavailable for maintenance.

4. Login to the particular C\$DIRECTxxxx Oracle account that is the owner of your BIOVIA Direct installation, for instance C\$DIRECT2021 for BIOVIA Direct 2021.

5. Run the script mdlauxop_upgrade.sql that is located in the same sql subdirectory of the BIOVIA Direct installation directory as the mdlauxop.sql script. You can safely ignore the error ORA-04043: Objekt VCHAR30ARRAY_T does not exist.

6. (Optional) After running the mdlauxop_upgrade.sql script several objects in the C\$DIRECTxxxx schema will be marked as invalid as the script recreated their underlying base objects in the mdlauxop package. You can ignore this as these objects will recompile and become valid again on first use. If you however want to avoid e.g. alarms from monitoring tools you can enforce the immediate recompilation of all invalid objects by running the following command (replace C\$DIRECT2021 with your Direct version account):

EXEC DBMS_UTILITY.compile_schema(schema => 'C\$DIRECT2021', compile_all => false);

You can then confirm that the schema no longer has invalid objects:

SELECT object_name, status, object_type FROM user_objects WHERE NOT status = 'VALID' ORDER BY object_type;