Thursday, May 14, 2009

Enhancing APEX Security - Explanation

I recently posted an entry called Enhancing APEX Security. I may have jumped the gun and not given a full explanation as to what problem this was trying to solving and the logic behind this solution. Here's the full explanation to the problem and a high level overview of the proposed solution.

In APEX, Session State Protection (SSP) can help secure your applications by preventing users to set session state value of items. Developers should be aware that it has 2 issues regarding it. First, it prevents items from being set using AJAX. If I try to set using AJAX I get the following error (using Firebug):



Second, when a user is on a page, they can alter the value before it is submitted to try to access data they aren't allowed to. For example, let's say users are only allowed to see information about people within their own department. So my LOV is something like:


SELECT e.ename d,
e.empno r
FROM emp e
WHERE job = 'CLERK'


Using Firebug I can see that this is what my option list looks like



Now what if I were to modify the select list and change the value for "SMITH" from 7369 to 7839 (This is "KING" / President) then submit the page? It still works and sets the value in session state:



Notice how the value in session is set to 7839, which we really shouldn't have access to? If you're not careful in your application this can lead to serious security holes.

Now on to the proposed solution. When you have a Select List, use a hashed value for the IDs so that users can't alter the select list values (well they can but they'll require the hash value as well). Instead of P1_EMPNO being a select list, set it as a Hidden and Protected item and enable SSP for it. This allows your application to still reference P1_EMPNO as it normally would. Create a new item, P1_EMPNO_SEC, which will be a select list with the altered LOV code (i.e. the return value has a hash associated to it). So if the value is 7369, it will actually be 7369@J92388502378540C (i.e. VALUE[DELIMITER][HASH]). The code (in my example) handles the rest so that when a user submits a page, it will take the submitted value from the secure item and then set the "regular" item with the unhashed value. If someone were to try to alter the select list, they'd be unsuccessful since the unhashing method returns NULL when an invalid hash value is present.

The reason why I create 2 items is I don't want to have to alter any existing code. So all code referencing P1_EMPNO will remain the same. If users need to pass P1_EMPNO in via the URL they can (provided they pass in the checksum since it has SSP enabled).

5 comments:

  1. Martin, nice work there. As a different approach to this problem, what do you think about the idea of a new declarative validation type that compares the submitted value of an item with the LOV it should have been selected from?

    Scott

    ReplyDelete
  2. Hi Scott,

    Comparing the item to the LOV is an excellent idea. For basic (and most) cases this can work, however you may take a small hit in performance if your LOV takes a while to generate. I'd also have to look at cascading LOVs.

    Adding a validation will prevent users from altering the LOVs however it still won't resolve the AJAX issue (i.e. you wouldn't be able to set the value in session state very securely, yes you can use x01..x10 but it still requires that you check that x01 is a valid value).

    Thoughts?

    Thanks for your feedback,

    Martin

    ReplyDelete
  3. Martin - Can you explain more about the AJAX issue and how your solution deals with that? Also, I don't understand the x01..x10 problem. Don't you need an application process that takes the x values and assigns them to particular items in session state? And if so, that would be up to the developer to control. What I mean is that this isn't a generic method that hackers can use to arbitrarily set session state (unless I missed something).

    Scott

    ReplyDelete
  4. Hi Scott,

    Here's the example for the AJAX issue:

    Let's say we have 2 tables TCUSTOMER and TSERVICE, where a customer has multiple services. On P1 you have 2 items and a report region. Items: P1_CUSTOMER_ID and P1_SERVICE_ID. Region: Report displaying all the service information. When the user selects the customer, an AJAX call is made (using get.add()) and generates the service list. The user then clicks submit and the report region displays with all the service information. Your suggestion of adding a validation against the LOV would be the final check developers would need to add to ensure a user didn't P1_SERVICE_ID.

    Other pages also reference the same page and pass in the CUSTOMER_ID and SERVICE_ID so I'd like to enable SSP on these items. I'd have to alter my JS call and my Application Process (AP) to deal with the SSP on these items. My new Application Process (AP), called AP_P1_SERVICE_ID, would take in x01. AP_P1_SERVICE_ID has to validate that x01 is a valid service_id and the user is allowed to see it. Once validations are passed I can set P1_CUSTOMER_ID in session state and return the select list for P1_SERVICE_ID.

    If I turn on SSP (and add a LOV validation like you suggested), this would work. Creating individual APs for each page would not be practical since we're going to have over 300 pages in our application. Instead, I'd have to create a generic AP to validate items against their LOVs which may take longer to run (I explored this option a while ago but things got a bit messy along the way so I put it on hold for now)

    This is where my solution may resolve the issue. It would still allow users to set values using get.add(); and not have to alter any of their AJAX calls. Developers would still be required to do an extra step (i.e. add "secure" and "non-secure" items instead of 1 item) and alter their LOV slightly. They wouldn't be required to add the LOV validation.

    Of course if this functionality were added as a new Item Type in APEX ("Select List and Protected" for example) they wouldn't need to do change anything but the type of Select List, Check box, etc.

    Your proposed solution of adding an extra validation process and my solution get the same results, they just do validations at different points in the application and would require different types of AJAX / APs

    I hope this makes a bit more sense.

    Thank you,

    Martin

    ReplyDelete
  5. Martin - It certainly does make more sense. I wonder if we could converse by phone at your convenience. If it's okay with you, please email your contact number to me with a time (weekend or weekday) when you would be available to discuss this, I'll call.

    Thanks,
    Scott

    ReplyDelete