+ Start a Discussion
colemabcolemab 

Secure public visual force page / site in the controller extension?

Hello,

 

I have created a VF page that will go on a public site that is meant for user to enter data into the system.  This is working fine but I noticed that URL hacking is possible (read only due to FLS on the public user profile for the site) if a user appends the id to the url (for example, VFPage?id=00AB0000001abcD).

 

Ideally, I would like to simply set FLS to edit with no view.  Since create FLS requires view FLS, how can one prevent url hacking in this manner?   How can we prevent the controller extension from processing data from the url?

 

Thanks,

 

Tony

Best Answer chosen by Admin (Salesforce Developers) 
Brian SobyBrian Soby

VF pages put on Sites are intended for public consumption. If you have a public page that's exposing private records based only on knowledge of the SFDC object ID (which is trivial to brute force), it's an app design problem. If all of your records available to the Sites user were intended to be public, "url hacking" wouldn't be relevant since that wouldn't expose any private information.

 

You have a couple of options:

 

1) Use portals to do record-level separation. Portals supports the concept of user logins and is the intended way to enforce access control in these types of environments.

2) If you're looking a simple page for data to go into the system (e.g. web2lead), you don't actually need to give the Sites portal user any CRUD, FLS, or sharing access. Create your VF page in such a way where it ignores the user's CRUD/FLS (e.g. using apex:inputText instead of apex:inputField) and have the controller create and insert the object.

 

 

On the lead sharing statement, you can use Apex Managed Sharing to share leads based on arbitrary logic.

 

Thanks

-Brian Soby

 

All Answers

Brian SobyBrian Soby

Hi Tony,

 

Are you trying to give them create-only access or update-only access?

 

-Brian Soby

 

 

colemabcolemab

Brian,

 

Thanks for taking the time to read and reply.   I would like for them to have create only access and not edit or view.  

 

Ideally, I would like my controller extension to not accept any options passed to it in the URL (such as id).

 

Thanks,

 

Tony

colemabcolemab

No one has addressed this issue?  So all web 2 lead VF pages that use controller extensions are non-secure and can be URL hacked if you can determine the SFID?

BrendanOCBrendanOC

By default, you cannot just specify an object ID in the query string on VF page and get to data.  So no, all VF pages do not allow URL hacking.

 

If you can post your code, I could comment further.

 

If this is a Public Sites page (user context is the Sites guest user), set your Lead sharing model to Private and give the sites user only the Create permission to the Lead object.  Visualforce will enforce CRUD/FLS as part of <apex:outputField />.

 

If your Apex is running without sharing and in System Mode, you can obviously hack around this, because System Mode gives Apex the View All Data permission.  Check out the Force.com ESAPI to make this simple.

http://code.google.com/p/force-dot-com-esapi/

 

In particular, look at the insertAsUser() and getCreatableFields() methods.

colemabcolemab

“By default, you cannot just specify an object ID in the query string on VF page and get to data.  So no, all VF pages do not allow URL hacking."

 

I said "VF pages that use controller extensions” - not just controllers or all pages, those using controller extensions.   This is a public site and the profile for that public site only has Read and Create permissions.  

 

This is due to the fact that read is required for create and on a public site profile the other options (delete, edit, etc) are simply not available (probably good security reasons). 

 

It would be great if SF would enable a create only (i.e. no view) option for public sites.  Also, the class does have with sharing turned on.

 

The Organization-Wide default access setting was set to the default (i.e. not private).  However, upon changing it to private (and waiting for the setting to take effect – which were probably delayed by caching of the VF page server side), this did result in getting the “Authorization required” page instead of the URL hacking working as before.

 

Thank you for this information – it was very helpful and did resolve my issue.

 

It is nice to know that “Any salesforce instance running the default Organization Wide Default Access settings that have a public VF page that uses a controller extension is vulnerable to (read only) URL hacking for those objects set to anything other than private.

 

You would think that this either wouldn’t be the default or that they would have a view setting under the public access profile that would require you explicitly enable view access on a public page.



colemabcolemab

I thought that I would also mention that you can't share leads by criteria (like say record type; which you can do on opportunities) but instead must share them by Group, Role, Role and subordinate, or manually.  

 

This makes the private setting all that much more hassle from an administrative stand point.  

 

Insert safe harbor statement here ......

 

Brian SobyBrian Soby

VF pages put on Sites are intended for public consumption. If you have a public page that's exposing private records based only on knowledge of the SFDC object ID (which is trivial to brute force), it's an app design problem. If all of your records available to the Sites user were intended to be public, "url hacking" wouldn't be relevant since that wouldn't expose any private information.

 

You have a couple of options:

 

1) Use portals to do record-level separation. Portals supports the concept of user logins and is the intended way to enforce access control in these types of environments.

2) If you're looking a simple page for data to go into the system (e.g. web2lead), you don't actually need to give the Sites portal user any CRUD, FLS, or sharing access. Create your VF page in such a way where it ignores the user's CRUD/FLS (e.g. using apex:inputText instead of apex:inputField) and have the controller create and insert the object.

 

 

On the lead sharing statement, you can use Apex Managed Sharing to share leads based on arbitrary logic.

 

Thanks

-Brian Soby

 

This was selected as the best answer
colemabcolemab

You are correct that the app design is flawed.  The (Certified) cookbook receipe for this is also flawed (when used with default or public settings) for everyone to copy.  I wonder how many people have copied this without knowing the information that is being made public.

 

Some how the name "Organization Wide Default Access" doesn't imply to me that it would include 'public' websites since they are outside of the organization.   Maybe that name should be changed.

 

Thank you very much for your timley and informative replies.

Ian SidleIan Sidle
As a workaround, you can add the argument rendered="{!Id=null}" to the apex:page tag and that will prevent this issue. 

Modifiying the above example:
<apex:page standardController="Lead" extensions="myWeb2LeadExtension" title="Contact Us" showHeader="false" standardStylesheets="true" rendered="{!Id=null}">

Thus, if an id is manually entered the page will result in a blank page, instead of returning any valid data. 
Since the processing is done server side, even the source code of the page is empty (except for the header).