I’m just about finished with the ApexNinja blogging platform (v2) that I plan on releasing together with all the sources somewhere next week. Fortunately I met up with security experts Tim and Nathan from Recx (http://www.recx.co.uk/) during the UKOUG APEX SIG Meeting in London, where I did a presentation on APEX Printing Techniques (http://www.ukoug.org/events/5642-apex-sig-meeting/). And these guys, being really friendly and awesome, offered to use their APEX security analysis tool to check out my blog platform, before I release it on the wild and cause all its potential users some serious harm.
Long story short, after they sent me the security report, I realized there are some security best practices for developing APEX applications that I haven’t really followed and generated some vulnerabilities in my applications. And also understood why a tool like ApexSec is a must-have for every APEX development team, no matter how experienced it (thinks it) is.
First of all, you can find all the details about the ApexSec Security Console here: https://secure.recx.co.uk/apexsec/index.jsp. Although this is not a free application, Recx does offer free analysis by uploading the sources of your APEX app to Recx’s online interface here: https://secure.recx.co.uk/apexsec/upload.jsp. You will get back an HTML report together with an XML project, that you can upload and drill down more easily in the security report, by downloading the free version of the Apex Security Console, here: https://secure.recx.co.uk/apexsec/download.jsp?code=free. For paid subscriptions, you don’t need to submit your precious apps to Recx, instead the tool can connect directly to your database and generate the security reports from there.
Just to give you an idea on how the application looks like, here’s a screenshot:
What security issues I found and had to fix:
1. Direct APEX URL
In the blog admin interface I work with images a lot by opening popup windows for quick uploading and management. A typical way to do this is in a Report, by having a link column set as Standard Report display type:
A secure way to create a link column is by using the APEX_UTIL.PREPARE_URL function: http://apex.oracle.com/i/doc/AEAPI/apex_util074.htm
So the query below would become:
2. Substitution variables
,'<li><a href=”&F100_SITE_DAD_BASE.f?p=&APP_ID.:1:’||:APP_SESSION||’::::P1_ARTICLE:’ ||ARTICLE_ID||decode(nvl(ARTICLE_ID,-10),nvl(:P1_ARTICLE,-10),'” style=”text-transform: uppercase;font-weight:bold;”>’||TITLE,'”>’||TITLE)||'</a></li>’ TITLE
Notice how I’m using the application item &F100_SITE_DAD_BASE. as a substitution variable, to form a custom URL. This variable could be the entry point for a SQL Injection attack.
The first thing to do is make sure the F100_SITE_DAD_BASE item has Session State protection enabled, so that I cannot be modified from the URL. Then, remove the substitution variable by using the v() function:
v(:F100_SITE_DAD_BASE) instead of &F100_SITE_DAD_BASE.
The same for :APP_SESSION: v(‘SESSION’) instead of :APP_SESSION
And all together, create the URL by using the PREPARE_URL function described above.
3. Report column display type
Use HTF.ESCAPE_SC() function to replace characters that have special meaning in HTML with their escape sequences. This way, you won’t get malicious code in your blog search input item!
4. Authorization inconsistency
A rookie mistake, but I’ve done it! If you have a button that starts a page process, make sure both the button and the process use the same authorization scheme. Don’t put the authorization scheme only on the button, thinking the process won’t be executed anyway, because it’s trigger by the “secure” button. The button action can be replicated another way, having your page process executed.
5. Hidden and protected items
This is another security task that you might hear as being mandatory, but it really depends on how you use the items. A item that is hidden and protected cannot be manipulated when the page is posted. But if you use hidden items for storing filter values, like I do, there is no reason to protect these items, as there really isn’t a security flaw there. If you have hidden items that are set/unset by the browser, they shouldn’t be protected, but that should be the only exception (Thanks for the explanation Tim!). If you have hidden items set by APEX processes, always set them as protected!
6. Page autocomplete
The explanation is simple. With page autocomplete on, all the items values in a form will be cached, to be reused when you log in again. But what if you’re not not the one logging in again on that computer and within the same web browser? If autocompletion is needed, set it to item level.
7. Keep user grants to a minimum
This has nothing to do with ApexSec really, but it’s a best practice that must be followed always. Be careful about the grants a schema used by an APEX app has, as hacking an application and getting data is one thing, manipulating the data is another.
For example, the ApexNinjas blog platform consists of 2 applications: the blog and the administrative panel. The blog has no oracle objects of it’s own, it only uses synonyms to connect to views from the blog admin schema. It has only a read-only permission on those views and the only DML it does is comment posting, done also through a procedure from the blog admin schema. On the other hand, the blog admin uses VPD and Oracle Application Context for authentication and data separation, so it’s pretty hard to get access to all the data (hard, but not impossible).
Security is hard, take your time. The ideal way to use a tool like ApexSec is during development, not to just run a check at the end an start refactoring. This way, developers could know on a daily basis what they might have omitted, but also they would learn the security best practices while they are writing the code, not at the end. My personal goal is to release a free APEX blogging platform that has as little security flaws as possible, thanks to Recx. As APEX will soon be moving into the cloud, in the Oracle Database Cloud Service APEX store, security checks for APEX apps will be something mandatory, not just something we might or might not do.