brendan o’connor salesforce
DESCRIPTION
Writing Secure Force.com Code. Brendan O’Connor salesforce.com. Trust means having the…. Page Response Times (ms). Quarterly Transactions (billions). ISO 27001 Certified SAS 70 Type 2 Audited SYSTRUST Certified Innovative Security Features. Highest Security. Highest Reliability. - PowerPoint PPT PresentationTRANSCRIPT
salesforce.com confidential – distribute under NDA only
Brendan O’Connorsalesforce.com
Writing SecureForce.com Code
salesforce.com confidential – distribute under NDA only
Page Response
Times (ms)
Quarterly Transactions(billions)
Highest Reliability
Highest Performance
Highest Security
ISO 27001 CertifiedSAS 70 Type 2 AuditedSYSTRUST Certified
Innovative Security Features
Trust means having the…
salesforce.com confidential – distribute under NDA only
Same Origin Policy
- Creates zones of trust in the browser• Boundaries between data and objects belonging to different domains• Prevents cross-domain access
- Content from the same origin has equal privileges in the browser• Can read and manipulate content• Can reference the DOM
o document.cookieo document.form
salesforce.com confidential – distribute under NDA only
Cross Site Scripting - XSS
Reflective XSS• Triggers off of a link• Interactive
Stored XSS• Persistent• Triggers when the exploited page is viewed
DOM XSS • Similar to Reflective XSS• Attack is not embedded in the page
Same origin policyXSS inherits the security context of the vulnerable site
salesforce.com confidential – distribute under NDA only
Cross Site Scripting - XSS
Location Location Location • XSS breaks out of data and in to code
http://www.domain.com/MyPage?foo=someValue <a href="/MyPage?foo=someValue">
<a href="/MyPage?foo=someValue" onclick=doBadStuff(); "">
salesforce.com confidential – distribute under NDA only
Cross Site Scripting - XSS
Reflective XSS
http://www.domain.com/MyPage?fname=John&lname=Doe"><script>alert('XSS');</script>// <form method="post" action="/MyPage"><input type="hidden" name="fname" value="John"><input type="hidden" name="lname" value="Doe"><script>alert('XSS');</script>//">
salesforce.com confidential – distribute under NDA only
Cross Site Scripting - XSS
DOM XSS
http://www.mysite.com/MyCalendar?Month=July&Date=4
<script>var querystring = window.location.search.substr(1);var values = querystring.split("&");var month = values[0].substr(6);var date = values[1].substr(5);document.write("Today's Date is " + month + " " + date);</script>
Date=4<script>alert('XSS!');</script>
salesforce.com confidential – distribute under NDA only
Cross Site Scripting - XSS
Visualforce has built in protections against XSS attacks
• Special characters are encoded to HTML safe equivalents• Context sensitive
o <apex:outputText> < becomes < " is not escapedo <apex:outputLink> < becomes %3C " becomes %22
Exceptions • Escape = false
o <apex:outputText escape="false" >• Javascript
o <script> var foo = ' {!foo.name} ' </script>o <apex:includeScript value =' some user input ' >
salesforce.com confidential – distribute under NDA only
Cross Site Scripting - XSS
Exceptions• on* events, such as onclick
<apex:inputText onclick="{!$CurrentPage.parameters.foo}"> • *Style parameters, such as Style, startStyle, and stopStyle
<apex:actionStatus Style="{!$CurrentPage.parameters.foo}"> • The Help parameter, such as sectionHeader help="{!foo} "
• Bare HTML without enclosing quotes, such as id={!foo}
<H1 id={!$CurrentPage.parameters.foo}> H1 </H1>
salesforce.com confidential – distribute under NDA only
Cross Site Scripting - XSS
Context Sensitive Encoding Functions • HTMLENCODE - escapes < and > characters to < and >
• JSENCODE - uses backslash \ to escape unsafe characters such as ' • JSINHTMLENCODE - escapes for Javascript and HTML characters
Javascript is never escaped by default, so you must call JSENCODE or JSINHTMLENCODE on user input. <script> var foo = ' {!foo.name} ' </script> should be:
<script> var foo = ' {!JSENCODE($foo.name)} ' </script>
salesforce.com confidential – distribute under NDA only
Cross Site Scripting - XSS
Conclusion:• Visualforce will perform automatic HTML escaping in almost every case
<apex: > is used. See the "Exceptions" slides for details. • Don't call escape="false" on untrusted input
• Javascript is not escaped automatically
• Use the Escape functions for the correct contexts
salesforce.com confidential – distribute under NDA only
Cross Site Request Forgery - CSRF
• Tricks your browser in to doing something you didn't intend.• Can perform actions with your privilege level is you are logged in.
salesforce.com confidential – distribute under NDA only
Cross Site Request Forgery - CSRF
https://na2.salesforce.com/ToDoList?Item=1&Action=Delete
public void init() { String Item = ApexPages.currentPage().getParameters().get('Item'); String Action = ApexPages.currentPage().getParameters().get('Action'); if (Action == 'Delete') { ToDoList__c list = [Select Item__c ,Description__c from ToDoList__c where Item__c = :Item];
delete list; return ; }}
salesforce.com confidential – distribute under NDA only
Cross Site Request Forgery - CSRF
https://na2.salesforce.com/ToDoList?Item=1&Action=Delete
<HTML>......<img src="https://na2.salesforce.com/ToDoList?Item=1&Action=Delete"><img src="https://na2.salesforce.com/ToDoList?Item=2&Action=Delete"><img src="https://na2.salesforce.com/ToDoList?Item=3&Action=Delete"> ......</HTML> • If the victim is logged in, their Session Cookie gets sent with the request• It looks like a legitimate request to the Web Application
salesforce.com confidential – distribute under NDA only
Cross Site Request Forgery - CSRF
VisualForce has automatic protection against CSRF• Hidden parameters in Viewstate have a CSRF Token• Token is tied to the user's session and VF page
There is no automatic protection for Get requests • Avoid DML operations based on the query string
salesforce.com confidential – distribute under NDA only
SQ(O)L Injection
• Similar to XSS, SQL Injection attacks break out fo the data portion of a statement and in to code.
string username = request.getParameter("username");string password = request.getParameter("password");
String bad_select = "SELECT user_name, user_id FROM UsersTable WHERE username = '" + username + "' AND password = '" + password + "'";
salesforce.com confidential – distribute under NDA only
SQ(O)L Injection
username = [email protected] = MyPassword123 SELECT user_name, user_id FROM UsersTable WHERE username = '[email protected]' AND password = 'MyPassword123'; username = [email protected] = ' OR 1=1 --
SELECT user_name, user_id FROM UsersTable WHERE username = '[email protected]' AND password = ' ' OR 1=1 -- ';
salesforce.com confidential – distribute under NDA only
SQ(O)L Injection
In traditional database platforms, attackers can do a lot of damage:• Use the UNION operator• Terminate a SQL statement with ; and write an arbitrary statement• Use comment characters to disregard the existing query• Call default stored procedures like xp_cmdshell and xp_regwrite
With the Force.com Platform, SOQL and SOSL syntax prevents many of these attacks.
salesforce.com confidential – distribute under NDA only
SOQL / SOSL Injection
• Attackers may be able to view or modify data• Escalation of privilege if Apex is running in System mode
public class SOQLController {
public String name { get { return name;} set { name = value;} } public PageReference query() { String qryString = 'SELECT Id FROM Contact WHERE (IsDeleted = false and Name like \'%' + name + '%\') ' ; queryResult = Database.query(qryString) ; return null; } }
salesforce.com confidential – distribute under NDA only
SOQL / SOSL Injection
name = Bob
queryString = SELECT Id FROM Contact WHERE (IsPrivate__c = false and Name like '%Bob%')
name = NoSuch%') or (Name like '
queryString = SELECT Id FROM Contact WHERE (IsPrivate__c = false and Name like '%NoSuch%') or (Name like '%') The SOQL language helps limit the damage of injection attacks
o No UNION operatoro No chaining of independent statementso No calls to default Stored Procedures
salesforce.com confidential – distribute under NDA only
SOQL / SOSL Injection
Using bind variables prevents SOQL injection attacks
name = BobqueryString = SELECT Id FROM Contact WHERE (IsPrivate__c = false and Name like '%Bob%') Should Be: name = Bob String queryName = '%' + name + '%' queryResult = [SELECT Id FROM Contact WHERE (IsPrivate__c = false and Name like :queryName)]If you must use dynamic queries, call escapeSingleQuotes()
salesforce.com confidential – distribute under NDA only
Access Control
With Sharing keywords• Inheritance - With Sharing does not apply to Inner Classes, unless you
specifically declare it.
Public with sharing Class MyController { ... With Sharing is Applied ...
Public Class MyInnerClass { ... With Sharing is not applied to this class ... }
}
salesforce.com confidential – distribute under NDA only
Access Control
CRUD/FLS on VisualForce Pages• If the object is on the VisualForce page, CRUD and FLS will be enforced
<apex:outputText>{!account.Name}</apex:outputText> //CRUD/FLS enforced • If a String is used instead of an SObject, CRUD and FLS will Not be
enforced
Public Class MyController { Public String myAccount { get; set; }...qryAccount = [SELECT Name FROM Account WHERE Name = :myAccount)];... }<apex:outputText>{!myAccount}</apex:outputText> //CRUD/FLS Not enforced
salesforce.com confidential – distribute under NDA only
Questions&
Discussion
salesforce.com confidential – distribute under NDA only
Questions&
Discussion