Wednesday, May 21, 2014

ENFORCING CRUD-FLS Enforcements in Salesforce


ENFORCING CRUD-FLS Enforcements in Salesforce



Caution-Unauthorized-Entry-Prohibited-Sign-ES-0019_stake.gif
Security Authorizations are essential for every system in the universe.  Just like WBC cells in a human body which restricts access to foreign microbes or The Ozone layer in the atmosphere which inhibits the harmful radiations Entering inside,  Salesforce have something called CRUD FLS enforcement which prohibits the users to gain access to the records they don’t own. We were developing an app mostly with multiple visualforce pages and controllers. Usually all the standard pages in Salesforce are automatically enforce the CRUD and FLS settings. But when it comes for visualforce pages with Input text and Input text area  components  with lot of DML statements in their controllers. The system interprets the fields displayed in the visual force pages as the string values but  not as the fields from the Sobjects.

The damage done by this new evaluation procedure of Salesforce in our app took a huge toll on its release dates. When we submit the app for security review the app failed to pass due to the insufficient CRUD FLS enforcements checks. All we had his Salesforce’s own knowledge article and we started analyzing each and every classes we had with appropriate manual CRUD FLS checks. When the issue was finally resolved I thought of writing a blog on this which will help my fellow peers. Here is how we did this

In one of the security review findings related to CRUD FLS Enforcements Its given as “No manual CRUD enforcements on a DML event “ and the report document  listed the bunch of classes which needed modification.

For example if we instantiate a new record we have to make use of the statements such as Iscreateable(), IsUpdateable(), Isdeletable() appropriately to manually enforce the CRUD access something like this.   
  
 Cities__c city = new Cities__c__();  
   if(Schema.sObjectType.cities__c.fields.state__c.isCreateable()) city.state__c='American Samoa';
   if(Schema.sObjectType.cities__c.fields.name.isCreateable()) city.name ='Abeville';
   if(Schema.sObjectType.cities__c.isCreateable()) insert city;
But what if you want to implement the FLS settings for multiple fields like the example below,  It will take too much time to enforce the conditions


Job_Locations__c location = new Job_Locations__c();
  location.Account__c=a.id;
  location.City__c=city.id;
  location.Company__c='american textile';
  location.Description__c='testing';
  location.Employer_Wisdom__c='www.gmail.com';
  location.Latitude__c=3.5;
  location.Longtitude__c=3.5;
  location.Location_State__c='American Samoa';
  location.Region__c='south';

In this case you can iterate using a forloop and add the fields by adding all the field API names inside a string array and check the access if the object is Creatable, Updateable  or deletable refer the below example

Job_Locations__c location = new Job_Locations__c();
   String [] Job_LocationsFields = new String [] {'Account__c','City__c','Company__c','Description__c','Employer_Wisdom__c','Latitude__c','Longtitude__c','Location_State__c','Region__c'};
   Map<String,Schema.SObjectField> JLMap = Schema.SObjectType.Job_Locations__c.fields.getMap();
   Boolean isCreateable= true;
   for (String fieldToCheck : Job_LocationsFields ) {
   if (JLMap.get(fieldToCheck).getDescribe().isCreateable() == false) {
        isCreateable= false; break;   
        }}
        if (isCreateable== true){
   location.Account__c=a.id;
   location.City__c=city.id;
   location.Company__c='american textile';
   location.Description__c='testing';
   location.Employer_Wisdom__c='www.gmail.com';
   location.Latitude__c=3.5;
   location.Longtitude__c=3.5;
   location.Location_State__c='American Samoa';
   location.Region__c='south';   
   }
 if(Schema.sObjectType.Job_Locations__c.isCreateable()){
 insert location;
}
else{     
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,'Insufficient access'));
                return null;
}
This might be the easiest possible way to enforce the CRUD permission on DML statements.

External References:
Know more about permission settings and FLS settings in Salesforce
https://developer.salesforce.com/page/Testing_CRUD_and_FLS_Enforcement

Nirmal Christopher


Salesforce.com Technical Consultant
Global Tech and Resources Inc..,



Monday, May 19, 2014

SOQL INJECTION Attacks

What is SOQL Injection?

trojanhorseWe can compare the SOQL injection with the Trojan horse from Greek Mythology.  In Greek Mythology there is a tale about the Trojan War.  The Greeks used the selected soldiers and hide them into a giant wooden horse and pretended to leave the shores and people of Troy believed the horse as a war trophy and they brought it inside the city That night the Greek force crept out of the horse and opened the gates for the rest of the Greek army, which had sailed back under cover of night. The Greeks entered and destroyed the city of Troy, decisively ending the war. Here the beliefs of the people in the city of troy are used by the Greeks to bring down the city fortifications to ease the invading Greek Army.

Similarly if we don’t believe in validating  the user inputs in an Application there is a chance for the users might trick the application by providing the malicious inputs. So this is a serious security threat in an Application.

Just like SQL Injections Salesforce’s own query language SOQL also faces the similar problem.

Impact on Salesforce Database

Even though the database is different the attacks are similar just like SQL. Consider the SOQL query from one of my previous blogs How to Build a Simple Search Page Using Visualforce
String searchquery= 'SELECT Id FROM account WHERE ' +
'(IsDeleted = false and Name like \'%' + name + '%\')';
acc= Database.query(searchquery);
Here  the input for the query is not properly validated. Imagine if the user gives the malicious input something like this

User Input : test%') OR (Name LIKE '

Then query is modified something like this

String searchquery= 'SELECT Id FROM account WHERE ' +
'(IsDeleted = false and Name '%test%') OR (Name LIKE '%'))';

If you look in to the above line you can see the entire query is modified with three different where clauses.  Now the query will just not show the non deleted one’s  it will show all the accounts. This is a typical example for a SOQL injection.

Resolution

Usage of proper validations might solve the problem. All the user inputs in the UI have to be validated to check if the input contains special characters such as % ; ‘ etc…

Usage of static queries with dynamic binding of variable might also solve the issue. For example  the above query can be modified as follows

String searchquery = '%' + name + '%';
queryResult = [SELECT Id FROM account WHERE
(IsDeleted = false and Name like : searchquery)];

External References:

http://en.wikipedia.org/wiki/SQL_injection
https://www.salesforce.com/us/developer/docs/pages/Content/pages_security_tips_soql_injection.htm


Nirmal Christopher
Salesforce.com Technical Consultant
Global Tech and Resources Inc..,