Showing posts with label XSS. Show all posts
Showing posts with label XSS. Show all posts

Tuesday, 10 December 2019

Where would we be if we just believe?

As a science aficionado, there are certain phrases that ... catch the eye.

Recently on twitter there was an interesting thread that continued from Michelle Skamene's post on Top 15 Tuning Tips for APEX.  Michelle provided a wonderful follow-up post summarising the outcomes of the thread.

Point 9 suggests we avoid HTML in our queries, and use HTML expressions. This is undeniably good practice, but there was a question regarding how much performance is gained. Patrick Wolf summarises it well (sorting, XSS, context switching).

I've been curious about this for a while myself, and what better way to verify the truth than do some science ;p

I thought about the recent experimentation I did with interpreted code, and recent client work I've done with bind variables, so I thought I'd not only compare timings with a simple test harness I use, but see what v$sqlarea had to say.

When considering what SQL to compare, I decided to use the simple bit of SQL I used for my AskTOM Office Hours demo app. I saw how quickly the embedded HTML expanded to fit repeated business rules, and why not use something simple. If any difference was to be seen, let's see if it shows up with something basic, just like Juergen suggested.

The first query is just a simple query on scott.emp, with an extra expression to determine if the row is 'special'. This information is used declaratively within APEX, so these calculations are absent from this testing. The complexity has been transferred, but simplified. That's the reason it's best practice.
cursor c_1 is
select /*+ qb_name(c1) */ empno, ename, job, hiredate
  ,case
   when hiredate < date '2000-01-01'
     then 'special'
   end last_cent
from scott.emp
So, let's just concentrate on the differences in the SQL we can measure.

The second query has the HTML tags embedded, repeated on columns where I substituted the column into the class attribute in the previous example. The code required expands quickly, hence the argument to keep the SQL and presentation layer separate.
select /*+ qb_name(c2) */empno
  ,'<b>'||ename||'<b>' ename
  ,case when hiredate < date '2000-01-01'
    then '<span style="color:purple;font-weight:bold;">'
     ||'<span title="'||job||'">'||to_char(hiredate,'fmddth Mon YYYY')||'</span>'
   end ||'</span>'
   as hireDate
  ,case when hiredate < date '2000-01-01'
     then '<span style="color:purple;font-weight:bold;">'||job||'</span>'
   end job
from scott.emp
The third query introduces context switching to PL/SQL due to the inclusion of htf.bold and apex_escape.html. This protects the output we'd otherwise have escaped using the relevant property. Or you could mitigate usage by sanitising data on the way in.
cursor c_3 is
select /*+ qb_name(c3) */empno
  ,htf.bold(apex_escape.html(ename)) ename
  ,case when hiredate < date '2000-01-01'
    then '<span style="color:purple;font-weight:bold;">'
     ||'<span title="'||apex_escape.html(job)||'">'||to_char(hiredate,'fmddth Mon YYYY')||'</span>'
   end ||'</span>'
   as hireDate
  ,case when hiredate < date '2000-01-01'
     then '<span style="color:purple;font-weight:bold;">'||apex_escape.html(job)||'</span>'
   end job
from scott.emp;
If we just compare throughput, there is a clear loser. Context switching between SQL & PL/SQL is just too much, though I would like to think in recent versions of the database, those functions could be enhanced with such devices as the UDF pragma?
iterations:50000
     3.98 secs (.0000796 secs per iteration)
     5.16 secs (.0001032 secs per iteration)
    33.09 secs (.0006618 secs per iteration)
I just run these queries lots of times to measure throughput. Tom Kyte wrote a more enhanced test bed called runstats, if you want juicier details.
-- and start timing...
    l_start := dbms_utility.get_time;

    FOR i IN 1 ..c_iterations
    LOOP
     for x in c_1
     loop
        null;
     end loop;

    END LOOP;
    l_end := dbms_utility.get_time-l_start;
    dbms_output.put_line( TO_CHAR(l_end/100, '99990.00') 
                       || ' secs ('||(l_end/c_iterations/100) || ' secs per iteration)' );
What about v$sqlarea?
select substr(sql_text, 1, 22)sql, fetches, parse_calls, buffer_gets, sharable_mem
   ,persistent_mem, runtime_mem, user_io_wait_time
   ,plsql_exec_time, cpu_time, elapsed_time, physical_read_bytes 
from v$sqlarea  
where sql_text like 'SELECT%SCOTT.EMP%'
order by 1

v$sqlarea results

These statistics validate the timings, and I think also validates this as a performance tip that belongs in Michelle's list.
While performance difference with/without HTML may be marginal in this case, the supplementary benefits make it clear best practice.

Tuesday, 24 January 2017

Escape Special Characters APEX Demo

A few weeks ago I wrote more detail than expected regarding escaping of special characters.

I thought I'd add a simple demonstration, for reference.

Consider the following query, with variations of escaped column output.
with data as 
  (select q'[G'day,]'||chr(10)
           ||'Scott<strong>loves</strong>'
           ||'<br>APEX<script></script>' as string 
   from dual)
select 
 -- UI default
 string dflt
  -- where no tags expected
 ,apex_escape.html(string) protected
  -- good for most things
 ,apex_escape.html_whitelist(string) whitelisted 
  -- replace line feeds with HTML line break. Could use chr(13)
 ,replace(apex_escape.html_whitelist(string),chr(10),'<br>') protected_custom
 -- UI naughty
 ,string naughty
from data
The major difference being unescaped output looks like
"G'day,
Scott <strong>loves</strong><br>APEX<script></script>"


While escaped output looks like
"G&#x27;day,
Scott &lt;strong&gt;loves&lt;&#x2F;strong&gt;&lt;br&gt;APEX&lt;script&gt;&lt;&#x2F;script&gt;"


It determines how the browser will interpret these tags and display them to the end user.

Note that the first field called "DFLT" is using the default setting, therefore escaping special characters.
All other four columns do no explicitly escape these characters, deferring protection to the SQL.

Colum Attributes across four columns

The output looks like the following. The first line may look similar to any time you attempt to use APEX_ITEM in a classic report without turning this flag off.

Sample output, using template: Value Attribute Pairs - Column

So depending on what you're trying to display, you might need a particular combination of code / settings.
  1. Default - default APEX behaviour, no column settings adjusted.
  2. Protected - uses apex_escape package to do the same job as declarative attribute
  3. Whitelisted - Certain markup tags are allowed, but all others are still escaped
  4. Protected custom - often I want to replace line feeds/carriage returns in data with HTML line breaks. This combination facilitates the best of both worlds
  5. Naughty - avoid unticking Escape Special Characters attribute without protecting data within SQL. This is enabled Cross Site Scripting (XSS)

The naughtiness can be demonstrated by adding alert("Hello universe") between the <script> tags. The unescaped column will mean the browser will render an alert when the page renders.

This is bad because instead of an alert, it could be some malicious JavaScript.

Further security tips can be found at Recx.
APEX-SERT is also 5.0 ready.

Wednesday, 4 January 2017

APEX attributes for Escaping Special Characters

A relatively common on the forums is regarding the escaping of special characters in reports, but it seems the developer isn't always sure what is actually happening and how to how to search for it.

It seems I've had this on my "to blog" list since April 2015, but now that 5.1 has been released, it seems more people are coming out to leave 4.x can't work out where the Standard Report Column option is.

APEX 4.x Display As attribute

This was required when HTML was present in the query, either to add tabular items manually using apex_item, or to style data (though you should use HTML Expression instead)

Example of special characters being escaped

For instance, if you've written a query like so

SELECT APEX_ITEM.CHECKBOX2(1, empno, 'CHECKED') chk, ename
FROM   emp
ORDER BY 1


And are only seeing the HTML code in your column output

<input type="checkbox" name="f01" value="7369" CHECKED />

Then you need to Escape Special Characters, now found in the Security section of the column properties as a Yes/No option.

APEX 5.0 Escape Special Characters attribute

This is defaulted to Yes to help protect from cross-site scripting (XSS), a common security concern in the web world where data entered by users is stored in the database, then when rendered it can be interpreted as HTML code.

Set to No to allow your data to be rendered as you may expect. 
Note that in the 5.0 component view this is still referenced as Display As - Standard Report Column.

The change in terminology is documented in the 5.0 release notes

Report column property naming differences
Please note that if setting this attribute to no, you should still make efforts to protect your applications by escaping data where possible. For example, if I wanted to replace all carriage returns with the HTML line break, you can still escape your data then add HTML content.

replace(apex_escape.html(card_title), chr(10), '<br>')

You could probably do a variation of this using apex_escape.html_whitelist

If you're combining two fields, separated by the line break:

apex_escape.html(phone)||'<br>'||apex_escape.html(email)

then you might as well use HTML Expression and keep your data/UI layers separate.

HTML Expression attribute

Check out the open source project APEX-SERT to help find potential security concerns with your Oracle APEX applications.

See escaping examples in APEX reports here
http://www.grassroots-oracle.com/2017/01/escape-special-characters-apex-demo.html

Tuesday, 10 May 2016

Difference between SQL Injection and Cross Site Scripting

I came across a tweet from a non-Oracle person I follow that should amuse many web developers:
One of the replies referred to "little bobby tables", eluding to a classic xkcd comic about SQL injection.

Of course I had to make the correction that this was in fact Cross Site Scripting (XSS), not SQL injection. This post summarises syntactical considerations within APEX, but in the spirit of #entrylevel content I'd like to summarise the conceptual difference. It's a little like flogging a dead horse, but security is everyone's concern so it won't hurt to mention it again!

Both concepts are about information being entered by a user within an application to do something nefarious, but they differ in where this malicious activity ends up happening.

SQL Injection is about information being entered in the browser, such as within a search field, which would impact the query being executed on the database. This could modify the statement to produces results you wouldn't normally have access to see, or even drop a table.

Don't try this on the road (Gizmodo)

Using bind variables instead of building dynamic queries usually mitigates SQL injection, but it doesn't stop bored programmers from finding susceptible examples in the wild.

Cross Site Scripting is also about information being entered in the browser, but instead of the malicious code impacting the database, it affects a user's machine when the information is redisplayed. Someone could enter JavaScript in a text area that when redisplayed as data, the code could actually execute.

It's never hard to find an example of XSS in the news, and it requires a little more proactive coding to minimise flaws.

Oracle APEX does a good job of 'escaping' information displayed in reports by default, so any code gets rendered as it looks, instead of being treated as if it's code. You may have already used the "Escape Special Characters" toggle to allow the use of the apex_item API within a report, but this should normally be used in conjunction with the apex_escape package. Another alternative is to use the HTML Expression attribute to construct your final code for output.

In the end this pizza store wins, since the person's "name" was rendered as entered instead of displaying an alert.

But they lose points for spelling "piza"