Salesforce的數據安全防護措施

通過Salesforce,我們可以配置或開發出功能強大的網路應用。與此同時,無論作為管理員還是開發者,我們都要面對數據安全的問題。

常見的數據安全隱患有:

  • SQL注入
  • 跨站腳本攻擊
  • 跨站請求偽造
  • 點擊劫持
  • 重定向攻擊

本文將闡述在Salesforce中對於上述隱患的基本防護措施。

SOQL注入

SQL注入是一種常見的攻擊方式。Salesforce中使用了類似於SQL的資料庫查詢語言SOQL,同樣存在注入攻擊的風險。

實例

假設系統提供給用戶的功能是查詢所有金額少於某個數值的記錄,用戶可以輸入數值進行查詢。

當用戶輸入數值之後,系統會用類似於下面的SOQL進行查詢。

SELECT Id, Name, AmountnFROM Certain_Object__cnWHERE Amount < 1000 n

其中的1000就是直接來源於用戶的輸入。

那麼當用戶輸入「1000 LIMIT 1」的時候,查詢語句將變為:

SELECT Id, Name, AmountnFROM Certain_Object__cnWHERE Amount < 1000 LIMIT 1 n

此時,系統總是只能返回一個結果,功能被破壞了。

防護方法

Salesforce提供了多種方法來過濾用戶的輸入,避免SOQL注入攻擊的情況出現。它們多用於Apex代碼中。

靜態查詢和參數綁定

如果在代碼中預先設定好了SOQL的語句,並且將之與用戶輸入拼接形成最終的查詢語句,使用靜態查詢和參數綁定的方法可以避免注入攻擊。

比如:

String query = SELECT Id, Name FROM Account WHERE Name = + userInputString + ;nresult = Database.execute(query); n

這段查詢代碼信任了用戶的輸入,從而有了被注入攻擊的風險。

比如用戶輸入是:「test LIMIT 1」,「test」後面的單引號就將查詢語句里的WHERE部分結束,而將LIMIT部分加入了查詢。注入攻擊的結果就是每次返回的記錄只有一條。

使用靜態查詢和參數綁定,改寫上面的代碼:

result = [SELECT Id, Name FROM Account WHERE Name = :userInputString]; n

這段代碼將用戶的輸入作為參數綁定到查詢語句中。當用戶輸入包含惡意代碼時,它並不會拼接到前面的查詢中,而是作為用戶輸入的一部分進行正常查詢。

當用戶輸入是「test LIMIT 1」時,系統會將其看作一個整體,單引號不會將WHERE部分結束,後面的LIMIT的部分也不會被執行了。

數據類型轉換

Salesforce提供了幾種數據類型轉換函數,可以安全的將用戶輸入轉換為相應的數據類型。

比如:

result = string.valueOf(userInputString) n

可以將用戶輸入userInputString變為一個字元串,以便放入查詢語句中使用。

過濾單引號

Salesforce提供了一個函數將字元串中的單引號全部過濾。

result = string.escapeSingleQuotes(userInputString) n

這個函數的返回結果是將用戶輸入userInputString中的所有單引號前面都加上轉義符「」,保證查詢語句的安全。

跨站腳本攻擊(XSS)

跨站腳本攻擊全稱Cross-site scripting。攻擊者將惡意代碼注入網頁,當用戶瀏覽網站時,惡意代碼就會自動執行。攻擊成功後,攻擊者將可能獲得更高的許可權、可以查看session、cookie或其他私密內容。

XSS的惡意代碼多數是由於網頁上對於用戶的輸入不加檢查而導致。比如攻擊者將惡意代碼輸入表單,在未經檢查的情況下被保存到資料庫中,等待其他頁面讀取它,然後執行。

XSS的基本防護措施

XSS的基本防護措施分為兩方面:

  • 輸入過濾:一般的編程語言都有相應的函數來過濾用戶的輸入,將可能存在的惡意代碼轉化為普通字元串,從而使其在被讀取的時候無法執行
  • 輸出編碼:輸出編碼的目的是防止已經存在於系統中的惡意代碼無法被執行。當網頁需要輸出內容時,已經存在的惡意代碼會經過編碼轉化為普通的字元串,從而無法執行

Salesforce中XSS的防護措施

為了避免將用戶的某些輸入錯誤的過濾掉,Salesforce默認對於用戶的輸入不會進行輸入過濾,而在做輸出時,總是會執行輸出編碼用來避免XSS攻擊。

HTML自動編碼機制

Visualforce中「apex」命名空間下的標籤在執行輸出時,會將輸出的字元串自動進行HTML編碼。比如:

<apex:outputText value="{!$CurrentPage.parameters.name}" /> n

如果調用這個元素的URL中加入了帶有「<」和「>」的「script」標籤(可能造成JavaScript代碼注入),那麼Salesforce頁面的輸出則是:

<script> n

而其HTML源碼則是:

<script> n

在這種情況下,HTML的標籤起止符「<」和「>」被替換成了「<」和「>」,從而避免了注入的JavaScript代碼的執行。

apex:outputText相關知識

在Visualforce頁面中,「apex:outputText」標籤可以將其中的內容使用一個「span」標籤包括起來,並且對HTML編碼進行自動轉換。這樣就可以對XSS進行防護。

另外,<apex:outputText>中也可以接受參數。比如:

<apex:outputText value="This is {0} text with {1}">n <apex:param value="the" />n <apex:param value="parameters" />n</apex:outputText> n

使用的規則是:

  1. 在「apex:outputText」標籤中的value屬性中使用大括弧和數字來對參數進行佔位
  2. 使用「apex:param」標籤來定義參數的值,多個參數按照順序替換value屬性中的佔位符

上面的代碼內容當顯示在頁面中時,其後台的HTML源碼是:

<span>This is the text with parameters.</span> n

關於「apex:outputText」更詳細的講解可以參考官方文檔

關閉HTML自動編碼機制

有時頁面中需要輸出原始的HTML內容,那麼在「apex:outputText」元素中將「escape」屬性設置為「false」即可。

<apex:outputText escape="false">n {!$CurrentPage.parameters.htmlStringToOutput}n</apex:outputText> n

當然,此時必須有其他對於XSS的防護措施來確保輸出的原始HTML內容是安全的。

非HTML內容的防護

Salesforce對於非HTML內容並沒有默認的編碼機制。比如在JavaScript代碼中使用用戶輸入的數據時,該數據不會被編碼。

<script>n var x = {!$CurrentPage.parameters.stringFromUser};n</script> n

在上面的代碼中,用戶輸入的字元串「stringFromUser」不會被自動編碼,從而形成了一個安全漏洞。

Visualforce提供的編碼函數

對於非HTML的內容,Visualforce提供了一些編碼函數來幫助開發者防止XSS攻擊,主要包括:

  • JSENCODE()
  • HTMLENCODE()
  • JSINHTMLENCODE()

JSENCODE()

JSENCODE()函數主要用於JavaScript代碼中。它的主要功能是在特殊字元的前面加上轉義符「」。

<script>n var x = {!JSENCODE($CurrentPage.parameters.stringFromUser)};n</script> n

在上面的代碼中,用戶輸入的字元串「stringFromUser」會被自動編碼,避免了惡意代碼的自動執行。

假設用戶輸入的字元串「stringFromUser」是:

dummy;alert("dummy text"); n

如果不用JSENCODE(),alert函數會被自動執行。

HTMLENCODE()

HTMLENCODE()主要用於將HTML內容編碼,用於當Salesforce自動的HTML編碼機制被「escape」屬性關掉時。

<apex:outputText escape="false">n {!HTMLENCODE($CurrentPage.parameters.htmlStringToOutput)}n</apex:outputText> n

在上面的代碼中,字元串「htmlStringToOutput」是有可能造成攻擊的,需要使用HTMLENCODE()來避免。

JSINHTMLENCODE()

HTMLENCODE()和JSENCODE()可以組合使用,HTMLENCODE(JSENCODE())。這等價於另一個函數:JSINHTMLENCODE()。

當需要同時對HTML和JavaScript編碼時,可以使用任意一種方式。

Apex中的編碼

Salesforce並不鼓勵在Apex代碼中對數據內容進行編碼,因為數據數據的輸入輸出應該交由前端來處理,Apex代碼並不需要關心數據內容本身。

跨站請求偽造

跨站請求偽造(Cross-site request forgery),簡稱CSRF或XSRF,是一種挾制用戶在當前已登錄的Web應用程序上執行非本意的操作的攻擊方法。

摘自維基百科:

跨站請求攻擊,簡單地說,是攻擊者通過一些技術手段欺騙用戶的瀏覽器去訪問一個自己曾經認證過的網站並執行一些操作(如發郵件,發消息,甚至財產操作如轉賬和購買商品)。由於瀏覽器曾經認證過,所以被訪問的網站會認為是真正的用戶操作而去執行。這利用了web中用戶身份驗證的一個漏洞:簡單的身份驗證只能保證請求發自某個用戶的瀏覽器,卻不能保證請求本身是用戶自願發出的。攻擊者並不能通過CSRF攻擊來直接獲取用戶的賬戶控制權,也不能直接竊取用戶的任何信息。他們能做到的,是欺騙用戶瀏覽器,讓其以用戶的名義執行操作。

舉個例子:

假如一個銀行網站轉賬請求的URL地址是:(URL-1)

https://www.example.com/transfer?username=alice&amount=1000&to=bob

那麼攻擊者可以在網上放置這樣偽造的URL地址:(URL-2)

https://www.example.com/transfer?username=alice&amount=1000&to=charlie

當一個用戶登錄了銀行網站,其用戶名是alice,在尚未登出時訪問了攻擊者的站點,點擊了偽造的URL鏈接(URL-2),那麼其銀行賬戶會自動轉賬1000給用戶名為charlie的用戶。

基本防護方法

CSRF的一般防護方法是在URL的參數中加入一個口令(token),口令的值是很長的字元串,並且隨著每次請求隨機生成。伺服器在接受請求時也會驗證口令。這樣的話攻擊者就無法猜到準確的URL,也就無法利用偽造的URL地址來攻擊了。

Salesforce中的設置功能自帶了關於CSRF攻擊的防護設置。在設置界面的「會話設置」連接中,可以進入「會話設置」的界面。在其中可以設置多種安全保護措施。在「跨站請求偽造 (CSRF) 保護」一欄,可以設置是否啟用CSRF保護。

在Apex和Visualforce中防護跨站請求偽造

在Visualforce頁面中,有一種情況是Salesforce中CSRF防護設置無法保護的,比如下面的Visualforce頁面(以下稱作「頁面1」):

<apex:page controller="ExampleController" action="{!initFunction}">n <!-- ... -->n</apex:page> n

與之對應的Apex類:

public class ExampleController {n public void initFunction() {n String id = ApexPages.currentPage().getParameters().get(UserId);nn // 使用UserId發送請求n }n} n

頁面1的功能是直接讀取URL中的UserId參數,然後利用該參數發送請求。當在另一個Visualforce頁面(以下稱作「頁面2」)中使用「outputLink」鏈接到頁面1時:

<apex:outputLink value="/apex/Example?UserId={!person.Id}">n Clickn</apex:outputLink> n

因為函數「initFunction()」是定義在頁面1的「apex:page」標籤的「action」屬性中的,所以該函數會在頁面1載入瀏覽器之前就執行,所以它會跳過在設置界面中設置的CSRF防護措施。

要讓CSRF防護措施執行,需要將頁面2中的「outputLink」鏈接變為「commandLink」,即:

<apex:commandLink value="Click" action="{!alternativeInitFunction}">n <apex:param name="uId" value="{!person.Id}" assignTo="{!curUserId}" />n</apex:commandLink> n

將頁面1中的「initFunction」的功能挪到「commandLink」定義的「alternativeInitFunction()」函數中,並傳入相應的參數。然後將頁面1中的「apex:page」標籤中的「action」屬性去掉。

這樣做的結果是:本來在頁面1中剛開始就要執行的功能和請求被放在了頁面2的「commandLink」鏈接中,而後者因為頁面2肯定已經被載入了,所以在執行功能和發送請求時,會調用Salesforce中設置的CSRF防護措施。

這兩種流程總結對比一下:

  • 使用outputLink:先重定向到新的頁面,在頁面載入之前執行outputLink的action屬性中定義的函數,在函數中會發送請求,發送的請求無法使用CSRF防護措施,函數執行完畢後才載入頁面
  • 使用commandLink:先用Ajax非同步執行commandLink的action屬性中定義的函數,此時因為當前頁面時已經載入了,所以可以使用CSRF防護措施,然後通過鏈接重定向到新的頁面並載入

點擊劫持

維基百科上對「點擊劫持」是這樣定義的:

點擊劫持(clickjacking)是一種在網頁中將惡意代碼等隱藏在看似無害的內容(如按鈕)之下,並誘使用戶點擊的手段。

舉個例子:在網頁上,攻擊者將一個包含惡意鏈接或其他惡意內容的iframe元素設置透明度為0,並顯示在網頁正常內容的上方。由於iframe的透明度為0,用戶無法看到其中的惡意內容,只能看到網頁上的正常內容。當用戶在看似正常的內容上面點擊時,實際上點擊的是包含惡意內容的iframe元素,從而被攻擊者利用,遭受損失。

在Salesforce的設置頁面中,進入「會話設置」的界面。在其中可以設置是否啟用「Clickjack 保護」。

重定向攻擊

在瀏覽網站時,用戶需要頁面重定向功能。重定向功能往往體現在URL的參數中,比如

https://www.example.com?returnURL=https://www.exampleWebsite.com

當用戶使用此URL時,頁面會自動重定向到「https://www.exampleWebsite.com」中。

當攻擊者將重定向的鏈接改為了惡意網頁,則該URL便成為了網路攻擊的工具。

Salesforce中的頁面重定向功能

在Salesforce中,提供了標準的頁面重定向參數:

  • startURL:當頁面被載入時重定向到指定的URL
  • retURL:當用戶點擊「後退」按鈕時重定向到指定的URL
  • saveURL:當用戶點擊「保存」按鈕時重定向到指定的URL
  • cancelURL:當用戶點擊「取消」按鈕時重定向到指定的URL

當這些參數的值可以被攻擊者利用時,比如參數的值從用戶輸入中得到,那麼Salesforce的網頁就存在被攻擊的風險。

重定向攻擊防護

在Salesforce中,可以採取以下幾種方法進行重定向攻擊防護:

對重定向進行硬編碼(Hardcode)

通過對重定向進行硬編碼,可以完全防止用戶更改重定向鏈接。但是這會損失靈活性。

只重定向到本地

另一種方法是強迫所有重定向鏈接只能重定向到同一個域名下,比如只能重定向到「xxx.salesforce.com」下,這樣的話可以保證無論用戶如何更改重定向鏈接,被重定向的鏈接總是處於開發者的控制下。

假設在一個Visualforce頁面中包含一個「urlToRedirect」參數,它來源於用戶的輸入,然後該頁面會重定向到「urlToRedirect」。那麼我們可以用以下代碼強制用戶的輸入重定向到當前的域名下:

PageReference finalPage;nn// 得到用戶的輸入nString urlToRedirect = ApexPages.currentPage().getParameters().get(urlToRedirect);nn// 清除用戶輸入開頭的「/」符號nif(urlToRedirect.startsWith(/) {n urlToRedirect = urlToRedirect.replaceFirst(/, );n})nn// 將頁面的重定向設定到當前域名下,保證用戶轉到的頁面是當前網站下的某一個頁面(或不存在的頁面)nfinalPage = new PageReference(/ + urlToRedirect);nfinalPage.setRedirect(true); n

設定域名白名單

如果開發的過程中的確需要重定向到外部網站,則可以在代碼中手動建立一個字元串列表,作為可信的域名白名單。當用戶的輸入包含白名單中的域名時,允許頁面重定向到外部網站。

Salesforce中沒有預設此類功能或函數,需要開發者自己實現。

總結

以上介紹了在Salesforce中對於常見網路攻擊的防護措施,並側重於在Apex和Visualforce中的實現。

隨著技術的發展,這些防護措施可能會過時。所以,追蹤數據安全的最新動態、養成時刻考慮數據安全的習慣更加重要。

如果想對數據安全(不光是Salesforce)進行更多的學習和了解,在此推薦OWASP組織的網站。

推薦閱讀:

想系統學習web安全...做了個計劃求大神幫忙看看?
常見web攻擊
保證網上購買的爐石戰網賬號不被盜?
在這場人機「黑客大戰」中,人類戰勝了機器,不過可能是最後一次了
現在的 SSL 加密技術,預計多少年以後會被輕易破解?

TAG:Salesforce | 数据安全 | 网络安全 |