Skip to Main Content

Integration

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Yes, Oracle API Gateway Can Protect Your Web Application, Too

Bob Rhubart-OracleJan 29 2015 — edited May 29 2015

This article by Marcelo Parisi examines basic concepts of web application security using Oracle API Gateway, using an XSS Injection issue and an SQL Injection issue to demonstrate how Oracle API Gateway can bring value to these scenarios.


The topic of Web application security never gets old. Some of the main associated challenges are related to detection and prevention of XSS Injection and SQL Injection. Such vulnerabilities are usually exploited through web application url parameters or user input fields in HTML forms.

While Oracle API Gateway has been used mainly to protect Web Services, RESTFul APIs and other kinds of services, its filtering and hardening mechanisms make it a powerful tool in a web application protection scenario.

In this article we’ll examine some basic concepts of web application security using Oracle API Gateway. We’ll work on an XSS Injection issue and on a SQL Injection issue to demonstrate how Oracle API Gateway can bring value to these scenarios.

The applications used here to demonstrate the issues were custom made for this article and are deployed in an Oracle WebLogic Server 12c environment with no clustering. The SQL Injection demonstration application uses a datasource connected to an Oracle Database 11gR2. The application reads data from the database’s simple three-column table and prints in the screen. The XSS Injection application prints only the user form input field value in the screen. These applications have no real-life use and are only some code samples for demonstration purposes.

We’ll not be covering infrastructure installation in this article. We’ll be using two servers, one with Oracle API Gateway installed on it, and the other one with the application running on Oracle WebLogic Server 12c.

Infrastructure

As mentioned before, building the infrastructure is out of this document’s scope. In this section we’ll just see what the infrastructure used to demonstrate the concepts looks like.

The infrastructure is built on top of two virtual machines (VMs), as in Figure 1 below:

image001.png

Figure 1

The Oracle API Gateway VM runs Oracle Enterprise Linux 5.6, and the Oracle WebLogic Server 12c VM runs Oracle Enterprise Linux 6.4. The network will use fully qualified domain names, so the names and ports will be:

image002.png

Figure 2

To demonstrate the problems, we’ll acess the application directly on WebLogic Server 12c Managed Server running on vmwls01. After that, we’ll secure the application on Oracle API Gateway, and will access it through the vmoag01 public port.

XSS Injection

The first demonstration we’ll see is XSS Injection. The application used for this demonstration is called XSSTest, and the context-root for it is /XSSTest. When we open it, it presents a form like the one shown in Figure 3:

image003.jpg

Figure 3

If we enter our name, we’ll get a result as shown in Figure 4, below:

image004.jpg

Figure 4

If we click on the link, we’ll go to the Oracle website:

image005.jpg

Figure 5

As we can see, the application is pretty straightforward. Here’s the code snippet that interests us:

image006.jpg

Figure 6

As we can see in Figure 6, the submitted form data is not processed at all. The application simply prints information on the screen. To demonstrate that this is dangerous, let’s go back to the application form, and input the following string on the form: Marcelo<script>alert('GOT YOU!')</script>

Figure 7 shows the form that is going to be submitted:

image007.jpg

Figure 7

Click submit to get the result shown in Figure 8, below:

image008.jpg

Figure 8

A JavaScript alert window—which can be harmless, but is also the first sign that the application may have security problems. Printing an alert window may not be dangerous, but what if we input something like: Marcelo<script>window.onload = function() {var link=document.getElementsByTagName("a");link[0].href="[http://www.google.com/](http://www.google.com/)";}</script>in the form?

As we can see in Figure 9 below, everything seems normal:

image009.jpg

Figure 9

Now, pay attention to the status of the window in Figure 9. The link is not directing to the Oracle website anymore. If we try to click on the link that was supposed to take us to the Oracle website, we´ll get to a different website, as in Figure 10, below:

image010.jpg

Figure 10

In other words, if this were an input form to a database or a url parameter, we could trick it very easily to steal user or admin data, or point someone to a malicious file, because users would be acessing a trusted site and would trust the links and information presented there.

Oracle API Gateway can help us protect our application from these kinds of injections with the Threatening Content filter. To demonstrate it, we’ll connect to our Oracle API Gateway Node Manager with OAG Policy Studio.

Now we’ll create a Policy Container for our policies, as in Figure 11:

image012.jpg

Figure 11

After that, we’ll create a new policy (“XSS Policy”) inside our container:

image012.jpg

Figure 12

Now we’ll drag a Threatening Content filter to our policy. Because we are trying to avoid a JavaScript injection, we’ll need to make sure we select the filter’s “JavaScript Insertion Attack” option, as shown in Figure 13 below:

image013.jpg

Figure 13

The created filter must be set as a start point for our policy. Now we’ll drag a Set Message filter to our policy. Its configuration should resemble Figure 14, below:

image014.jpg

Figure 14

After creating the filter, we need to create a Failure Path going from the Threatening Content filter to the Set Message filter. So far, our policy looks like Figure 15:

image015.png

Figure 15

Now we’ll drag a Reflect Message filter to our policy, configured like this:

image016.jpg

Figure 16

We’ll now create a success path from our Set Message filter to this Reflect Message filter. So far, our policy looks like Figure 17 below:

image017.png

Figure 17

Now we’ll drag the last filter on our error path: a Set Response Status filter.

image018.jpg

Figure 18

And to finish our error path in this policy, we’ll create a success path going from our Reflect Message filter to the Set Response Status filter so that our policy looks like Figure 19:

image019.png

Figure 19

After that, we’ll start building the success path of our policy. To do it, we’ll start by dragging a Static Router filter to our policy, and we’ll set it up to connect to our Oracle WebLogic Server 12c managed server, as in Figure 20:

image020.jpg

Figure 20

Now we’ll drag a Connection filter to our policy and accept its defaults:

image021.jpg

Figure 21

After that, we’ll need to create a Success Path going from Threatening Content to Static Router and another Success Path going from Static Router to Connection. Our policy will resemble Figure 22 below:

image022.png

Figure 22

The last step before deploying the configuration is creating the path. In order to do it, we’ll go to Paths on the Oracle API Gateway tree, inside Default Services, and click Add, as in Figure 23, below:

image023.jpg

Figure 23

The path that we’re going to create is a Relative Path, and its configuration should resemble Figure 24, below:

image024.jpg

Figure 24

Note that in Path Specific Policy we need to select the policy we’ve just created. After that, we just need to deploy the configuration.

Now, using Oracle API Gateway url, let’s try again, as shown in Figure 25, below:

image025.jpg

Figure 25

And after hitting submit, the result we get is just like the one in Figure 26:

image026.jpg

Figure 26

Now using the script that changes the link, as in Figure 27 below:

image027.jpg

Figure 27

And again, as we can see in Figure 28 below, the attack was blocked:

image028.jpg

Figure 28

Now, if we try a normal input, as in Figure 29, below…

image029.jpg

Figure 29

It’ll succeed!

image030.jpg

Figure 30

SQL Injection

The next demonstration we’ll see is SQL Injection. In this section, we’ll see how information can be leaked from the database when the application is not correctly coded. The application used for this demonstration is called a SQLTest, and the context-root for it is /SQLTest. This application has a form used to input the username and it will return the full name and SSN of that user. This information comes from a table in the database, just like in Figure 31, below:

image031.jpg

Figure 31

When we open the application, we see this form:

image032.jpg

Figure 32

If we enter user1in the form, we’ll get the information just like Figure 33 below:

image033.jpg

Figure 33

As we can see, the application returns all the three fields from the table. The code snippet that interests us in this case, is the one in Figure 34 below:

image034.jpg

Figure 34

The problem here is that the username variable is not being processed at all. So if we input user1' or '1'='1 in the form, we’ll get a result similar to Figure 35, below:

image035.jpg

Figure 35

As seen in Figure 35, we have the first sign of information leakage because of bad coding on our application. But it doesn’t stop here. We know that we are getting three fields as result of the query, so we can, for example, play with some unions like user1' union select owner,table_name,tablespace_name from all_tables where table_name like '%; as we can see in Figure 36, we can get a lot of table information from the database:

image036.jpg

Figure 36

Another example, is getting database software, operating system version information and patchset using user1' union select banner,'','' from v$version where banner like '%. Again, we get all database information as in Figure 37:

image037.jpg

Figure 37

Now we know that the database is running in a Linux environment, on a 64bit platform, and it is an Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 in Production mode. This is some serious information leakage and should not happen. Depending on the user privileges that the datasource uses to connect to the database, a malicious user could see even more information, like session information, database users, etc.

To prevent this kind of leakage, we’re going to create a policy just like the one we created for XSS Injection. This policy, called SQL Policy, will be put inside the policy container (WEB-APP Policies) that we created in the last example. We’ll create it just like the one we’ve created for XSS Test.

image022.png

Figure 38

Our Threatening Content filter should have the options highlighted in Figure 39, below:

image038.jpg

Figure 39

After that, we need to create the Path for our SQLTest application, just like we did for the XSSTest application. First we need to click Add, then select Relative Path:

image039.jpg

Figure 40

The new path configuration should resemble Figure 41, below:

image040.jpg

Figure 41

Next, we need to deploy and test our configuration.

The first test we’ll execute is using user1’ or ‘1’=’1as a input string. As we can see in Figure 42, below, the policy is working and has prevented information leakage.

image041.jpg

Figure 42

However, if we try user1' union select banner,'','' from v$version where banner like '% the policy won’t work, as Figure 43 below resembles:

image042.jpg

Figure 43

This is happening because the default expressions for SQL Attacks on our Threatening Content filter matches only specific cases of ORs, INSERTs, UPDATEs, DELETEs and DROPs. Our case here is a little bit different, and we’ll need to customize the filter a little bit, by adding another expression to it. To do so, we’ll click Add, as in Figure 44, below:

image043.jpg

Figure 44

Now we’ll add an expression that matches a ‘ + any number of blank spaces + the word “union” + any number of blank spaces + the word “select”. This way, we’ll be able to match expressions like ' union select or 'union select, for example. The expression should look like Figure 45 below:

image044.png

Figure 45

We now need to make sure we select the expression we’ve just created, as in Figure 46:

image045.jpg

Figure 46

Now, after we deploy and retry with the same expression again, the result should be like Figure 47, below:

image046.jpg

Figure 47

Our new expression is now matching the input we’re using on the form. If we try with a normal input, it should work fine, as Figure 48 shows:

**image047.jpg
**

Figure 48

Conclusion

Injection issues in Web Applications are among the most exploited security issues. In this article we saw how Oracle API Gateway can bring value to these kind of scenarios by using the Threating Content filter. Oracle API Gateway can also bring value to file upload scenarios by using Antivirus filters, as explained, for example, in another article entitled: Virus-Proofing Oracle WebCenter Content 11g with Oracle API Gateway 11g.

It is important that Threatening Content expressions be created with a lot of care. An incorrect expression can break a web application’s functionality, so it is important to test with multiple scenarios to make sure no functionality has been broken in the application.

The policies created in this article are specific policies for the examples that we’ve seen here, and are not for general use.

Note: This document is not an Oracle official documentation and is not intended to replace any of product’s official documentation. This document is intended to be a simple guideline on Web Application security practices. Offical product documentation should always be reviewed.

About the Author

Marcelo Parisi is an Oracle IT Architecture Certified Specialist working as a Senior Consultant for Oracle Consulting Services in Brazil, where he is a member of the Tech Infrastructure team, with a focus on Oracle Fusion Middleware. His work includes includes architecture design, and implementation and performance tuning of FMW infrastructure. Marcelo's fields of expertise include Oracle Reference Architecture, Oracle WebLogic Server, Oracle SOA Suite and Oracle WebCenter.

Twitter: @feitnomore

LinkedIn: https://www.linkedin.com/in/marceloparisi

Facebook: Marcelo F. Parisi

Comments

xkb

I dug a little deeper on this by comment/tagging differently my queries in table and mview objects (as they are *not* in sync within SDDM)

so respectively :

SELECT -- sddm rel table qry

(...)

SELECT -- sddm phy mview qry

(...)

Now the weird part is that, only one db object is to be imported in Data Dictionary Import Wizard (only Tables tab exist, no mview tab) but two will match in the Compare Model window (table and mview).

I tried to select both or only one but the actual deployed code is always that of the MVIEW (SELECT -- sddm phy mview qry)

...and even if I sync both, the actual code deployed through DDL "Preview" (well, more than a preview indeed : there is the generated code) is the physical mview query (SELECT -- sddm phy mview qry) but it is reprocessed (e.g. : blank lines are deleted)

It hence seems that Compare will eternally consider db objects as different from sddm ones...

...and thus endlessly generate them.

Any help is welcome.

Delta/differential/gap/incremental analysis & ddl generation is one the most powerful feature of a DM tool but here I feel it lacks, if not capability, maybe some up-to-date documentation (?)

Thanks

David Last-Oracle

Hi,

Normally the master version of the query is held in the Query property on the Table.  However if the Body property on the Materialized View is changed, this becomes the master.  It is this that will be used in generated DDL and when comparing properties for the Materialized View.

To sync the two up again, you should make sure the Query property on the Table contains the appropriate value, and then copy it to the Body property on the Materialized View.

Provided the value copied to the Body is different from its previous value, it should recognize that the new Body value is the same as the Table Query, and revert to using the Table's Query property.

David

Philip Stoyanov-Oracle

Hi,

thanks for reporting the problems. David logged a bug about no DDL when select statement is changed. Some remarks:

but it is reprocessed (e.g. : blank lines are deleted)

that is an option in preferences "Preferences>Data Modeler>DDL" - "Use SQL Developer formatter" - if it's not checked then select statement will appear as it is

Now the weird part is that, only one db object is to be imported in Data Dictionary Import Wizard

There is an easy way to do it - right click on table on diagram and select "Synchronize Data Dictionary" from pop-up menu (blue arrow at the bottom).

The same blue arrows you can find on relational model tool bar (next to "Generate DDL" icon) - you ca synchronize the whole model in both directions (connection also can be changed). Also if you put some objects (tables and views) in subview  you can find the same blue arrows on context menu for that subview and can synchronize only objects in subview.

Philip

xkb

Hi Philip,

First : thanks for your concern.

I unchecked the Formatter although I don't care that much if ddl code can finally be in sync and thus not detected as changed and regenerated.

Unfortunately, that's still what happens : I checked that all code is in sync :

- sddm relational table mview query

- sddm physical mview body

- db dictionary ddl code (between "create (...) as" and the final semi-colon)

- sddm swapped import ddl preview code (in the relevant section)

Nonetheless, when I import the table, select table and/or mview in sddm, and ask for ddl preview, it still generates the MView (with the very same code).

Are you able reproduce the problem ? (if you please)

BTW : Synchronize Data Dictionary does sync but with the intermediation of the db schema so if you want to sync only relational table mview query with physical mview body without impacting your db model, it doesn't fit

(but that's a nice nice-to-have anyhow)

I'm also encountering a similar detection problem with tables generating a sequence and trigger (Identity + auto increment) but I'll open another thread so to not pollute this one.

Thanks

Hi,

I'm not sure I understand the steps and the problem.

are you saying:

1) definitions in the model and database are equal, and

2) MV definition is still generated (recreated) when compare to database

Are those MVs in the same schema in model and database? There are options that have impact on that:

- "Preferences>Data Modeler>DDL>DDL/comparison" - "Use schema property in compare functionality"

- "Preferences>Data Modeler>Model>Relational"- check-boxes for "database synchronization" - "Use source schema"

Philip

xkb

Hi Philip,

1/ & 2/ -> yes, you got me right (plus, I took care to align sddm mview & table sql query and checked ddl preview is also in sync with that, to make sure comparison doesn't occur with some other code than the one deployed)

I already had unchecked schema for DDL comparison.

I didn't know of data sync "Use source schema" check option (and I must confess although I found it in e57984 sddm 4.1 user manual, I have a hard time to consolidate all that may impact comparison and why).

Nevertheless, I unchecked it and DDL Preview still drops & recreates my MVIEW as if it weren't in sync with DB.

Do you experience a different behavior ?

Thanks

Hi,

probably something else is changed. Can you check what is reported as changed - when you step with the mouse on MV node in (comparing dialog) - details about changes are updated below (Details, Physical details, Storage details). Or you can generate a report.

So if tablespace is changed it'll try to recreate the MV with new tablespace.

Philip

xkb

As a matter of fact, the "Compare Models" dialog identifies a delta on Partitionning (no detail available) and Range Partitions (although init partition has already been deployed by the script ; for the record I use interval partitionning on this mview).

I had already unchecked all Storage/Physical properties in Compare Options, unchecked all properties in Range Partitions @ Properties Filter but it didn't change behavior.

From your previous reply I went to Prefs > Data Model > Model > Syncronization Physical > Oracle to also uncheck Import Options Partitions

...but the result is still that the MVIEW ddl is generated.

There's even the "Optional Import and Processing" / Partitions check I played with at Data Dictionary Import time (Wizard dialog) but it doesn't do much difference.

At the end, I'm a bit confused whether desactivating options in all places about physical & partitionning doesn't contribute to the phenomenon (like : oh it could be about the same here but since unchecked, just different -> generate !)

Do you have an idea of which options work together in order to skip the partitions comparison ?

(many thanks for your time)

David Last-Oracle
Answer

Interesting. It looks like you are right that it is the partitioning that is causing the problem.

In a model, partitioning information can be held on Physical Model objects for both Tables and Materialized Views.

In the usual case where a Table and a Materialized View are associated together (by the Implement as Materialized View property on the Physical Model Table), it is the partitioning information held on the Table that is relevant. The information on the Table is used when generating DDL. And in an import or synchronize, the partitioning information is added to the Table object.

I think what is probably happening in your case is your model has some partitioning details held on the Materialized View object.

The synchronize is associating the partition details from your database with the Table object in the model.

As it is not associating the partition details from your database with the Materialized View object in the model, the comparison shows a difference for the Materialized View:- not partitioned in database, but partitioned in your model. And this difference is causing the drop and recreate of your Materialized View in the DDL.

There are various options to get round this:

  1. You could remove the unnecessary Partitioning details held on the Materialized View object in your model.

  2. You could unset the check box for the entry for the Materialized View(s) in the tree in the Compare Models dialog before doing the DDL Preview. (But this also means that no DDL will be generated for any other differences in those Materialized Views.)

  3. You could use the Properties filter to filter out the relevant properties (e.g. Partitioned, Partitioning Columns and Subpart Columns for Materialized View objects) and then select the Refresh Trees button before doing the DDL Preview. (See screenshot below.)

pastedImage_1.png

David

Marked as Answer by xkb · Sep 27 2020
xkb

Hi David,

Thanks for your detailed answer :

2/ is not option because I DO want to catch differences

3/ is tedious because I would have to uncheck partitionning criteria each time I sync.

1/ is just FINE !

I had indeed partitionning information on the MVIEW

Deleting it is just a 1-shot work so it has my preference.

Many thanks !

(I'll be back soon with an equivalent issue around identity sequence/trigger generation and delta detection )

xkb

Hello,

I'm allowing myself to post here since the context is the very same :

Selecting Options > Properties Filter > Materialized Views > Comment in RDBMS causes SDDM to regenerate the entire MView plus comment although comment is fine and sync'ed between physical Model and db object (i.e. within db Dictionary).

I can toggle check box and Refresh Trees to alternate that behavior (without including Comment in RDBMS, MView is considered equal and not regenerated)

  1. Why SDDM won't sync comment only ? how can I do that ?
  2. Why anyway will it detect a difference once I have deployed diff ddl script with the right comment ?

(I thought it could be due to comparison with the underlying table comment but I can't comment even manually on it in db which issues ORA-12098: cannot comment on the materialized view, Issue a COMMENT ON MATERIALIZED VIEW statement instead)

Thanks

1 - 11

Post Details

Added on Jan 29 2015
2 comments
25,462 views