Serverless應用安全淺談


我是火線安全的曾垚,今天分享的議題是Serverless應用安全淺談,我們發現近年來主流的云廠商,或者是像K8S、CNCF生態出現了非常多的Serverless Faas的相關技術,像backend也是非常流行的。
整個Serverless產生或者是容器的產生,都是為了大幅度提高軟件的開發效率和降低后續的維護成本。
希望可以通過這次分享,可以讓相關Serverless開發者了解在Serverless應用開發過程中的安全風險。

整個議題分三個部分:
- Serverless相關的技術、簡要
- Serverless帶來的新工具場景
- Serverless需注意的安全事項
Serverless 簡介

什么是Serverless?不得不談到應用整體的技術架構變遷,最早開始要開發上線一個軟件,需要廠家提供硬件的服務器,需要運維對上面安裝的虛擬機或者操作系統,進行后續的維護和軟件部署,最后才是程序開發人員需要開發一個應用,在應用里面寫非常多不同的業務函數,再去做后續的部署。
在整個傳統環境,我們需要有各個不同職能的角色參與到軟件開發的過程中,再到后來的Vmware等等虛擬機,我們拋棄相關硬件上的東西,包括后續產生的虛擬機、ECS,我們不需要再去維護硬件上的事情,我們只需要選擇一個操作系統,在操作系統部署上我們的應用就可以了。
到現在像K8S,容器云的發展,在操作系統選擇上,是不需要自己選擇,我們給予Dockerfile或者是容器化的技術,我們只需要部署自己的應用,再用函數,后續只需要維護應用的穩定性和安全性就可以了。
目前我們已經進入到一個容器云的時代,大量的開發或者運維,都是以開發為優先,以Infrastructure as Code的方式去描述基礎架構或者網絡環境,或者應用部署的環境。
再下一個階段是Serverless新型技術,整個開發需要維護的事情就變得更少了,但我們現在還需要維護框架和軟件,后續在Serverless里面,我們只需要去維護我們真正的業務邏輯就可以了,有非常多的新型輸入源,或者是新型后端的技術函數,為我們Serverless生態提供非常多的便利。
整體技術變遷,我們可以看到軟件架構需要維護的程序是變得越來越少,但是我們整體的架構變得越復雜,總體來說都是為了軟件開發和后續的運維成本。

Serverless整個的運行機制也發生了變化,傳統的我們作為一個用戶終端,是直接通過各種方式訪問我們的ECS或者容器,通過容器或者ECS把流量傳遞到應用,再傳遞到框架組件,再傳到有業務屬性的函數,最終存儲到我們的數據庫,或者中間態的消息隊列。
在Serverless的整個架構上,我們把Serverless的應用分為兩部分,一部分是Function as Service,函數即服務,還有一部分是Backend as Service,后端即服務。
這里面有什么區別呢?Faas里面更多是通過一個函數塊去定義整個業務的運行流程,Backend as Service更多的是封裝好的標準控件,我們直接去調用它,這里面涉及到很多的技術,包括存儲技術、包括可以使用OSS或者S3 Bucket的服務,或者使用RDS原生的存儲數據庫,或者是我們可以調用API Getway去做事情,甚至我們可以調用非業務處理邏輯上的,像AI算法、數據分析,甚至像區塊鏈相關鏈技術,也提供相對的API接口,可以使我們直接調用下面的接口在區塊鏈上產生運算或者記錄。
從傳統意義上,我們應用的主要的數據還是來源于外部的HTTP數據引流,或者是RPC應用相關的外部控制變量,在Serverless里面,整個的數據來源變得更多了,我們統計了一下,在騰訊云上,整個Serverless數據來源的Event事件,有上百種的事件,這里面有非常多包括我們可以Serverless的函數,我們可以訂閱像Kafka、OSS、APIGetway,哪怕是一個在云平臺登錄的日志,或者是我們SNS的一個消息,或者是郵件的消息,我們都可以作為Serverless Faas函數的輸入。
從開發視角上,整個的軟件是變得更簡單,我們可以有更多的輸入去產生更多復雜的邏輯,但從安全來看,我們整個攻擊面變得更多了。

常見的Serverless的服務,最早是AWS推出的 lambda,后續谷歌和微軟也推出了自己的Functions函數,國內的話,我們在之前C2隱藏上用過騰訊云函數,阿里也推出了相關Serverless的服務,包括一些開源的生態,也推出了相關開源的Serverless的項目,包括K8s推出的Kubeless的相關服務。
右側是我們一個Golang寫的Serverless的Functions的示例,里面需要訂閱兩個東西,一個是Context,還有一個Event,基本上所有的函數,都需要傳入這兩個參數,后續函數里面的業務邏輯就是處理我們所針對的這些事件,再對他進行解包和數據的處理,Event它在AWS里面,是支持更多的Event事件。
阿里云也支持安全掃描的記錄,像安騎士的記錄等等,它是非常豐富的,跟云廠商的提供的服務有關系,如果是Kubeless,他更多是提供容器層的日志,或者是容器層API網關的Event事件都是它封裝好的。
Serverless 攻擊面
在Serverless里面可以看到整個業務的處理流程發生了較大變化,整個數據源也增加了非常多種不同協議或不同種類的Event事件的類型,我們的后端也發生了比較大的變化。

這張圖總結了Serverless攻擊面。
第一部分:看右側是我們整個函數事件產生的注入攻擊,這里面跟傳統外部上的攻擊是沒有太大的差別,主要還是在比如說像SQL注入、命令執行、外部實體注入、XSS等等常見的外部攻擊,但它相比于我們的外部應用來看,它觸發的源不只是HTTP請求,更多還有它內部云服務或者是LaaS服務自帶的事件型或者日志型的服務,所以我們整個插入的源會變得更多。
第二部分:最終畢竟還是應用,雖然我們不需要維護服務器、硬件服務器、操作系統容器,但是對整個應用的開發里面,還是會涉及到非常多的開源軟件供應鏈的組件,里面包括我們提供Serverless Function的函數里面 ,它會自己封裝框架,同時我們在寫Function的時候,也會依賴很多的開源組件,開源組件的安全性也是非常重要的。
第三部分:權限控制的錯誤。到Serverless層面,我們可以通過Serverless的yaml文件去描述我們整個Serverless所需要運行的環境,所需要對后端服務的訪問權限,大概是怎樣的?所以我們整體的權限控制是由yaml文件去控制,很多開發同學在開發過程中,為了方便把權限設置的非常大,我們就可以利用Serverless的權限去對其他的應用進行橫向的攻擊。
第四部分:敏感信息的泄露。我們可以發現Serverless的應用,很多程序開發比較喜歡從環境變量里面去取東西,包括Serverless本身的框架里面,也會在環境變量存儲非常多敏感的AK/SK信息,還有臨時的數據也會存在TMP臨時目錄下的數據,因為Serverless的服務基本上只會允許Serverless用在臨時目錄下寫些東西,我們在臨時目錄下也會產生非常敏感的數據。
整體的Serverless的服務,相比于傳統的企業架構,在日志審計上是缺乏比較完善的日志系統,雖然Serverless里面,服務里面也提供了比較簡單的日志的收集和日志log的系統,像Serverless,他整個的生命周期比容器會更短,但經過測試發現,整個Serverless應用最多也就十來分鐘的一個生命周期,有可能他會更短,這可以去設置的。
我們整個日志產生也只能產生在log的目錄下,對日志收集的難度來說,變得更大的。所以我們在Serverless如果發生攻擊之后,我們去回溯整個攻擊事件,也是缺乏審計的手段。

從攻擊面來看,我們的輸入源變得更多,除了傳統的HTTP的數據源以外,我們還增加了OSS、Kafka、SNS、RDS,還有互聯網的MQ的協議。
從運行環境來看,我們用Serverless都是用公有云的方式函數,或者是用K8S,在一個標準環境運行,它會遇到一些問題,他是個臨時的環境,需要接入這些網絡,還有一個特權的話,你還需要對我們后端的Backend as Service的數據庫,或者是計算服務,有一些數據上的交互,在運行環境上也會存在環境控制不當的問題。
從應用本身來看,也會存在注入攻擊、業務邏輯攻擊等等應用層的問題,還有軟件供應鏈上的問題。

注入攻擊漏洞
這是一個注入攻擊的Demo,右側我們可以看到整個業務邏輯,就是一個函數,我們到時候是部署在AWS上的應用,這個里面是SNS的消息,這個實踐為例,這個業務代碼邏輯,我們把郵件里面的簡歷的PDF附件處理,把里面的PDF的內容處理成一個輸出文本的內容的函數。
我們可以看到它從event里面去接受一個SNS的一個Message,最后通過Email的一個函數,把郵件里面的附件提取出來,對附件進行調用的一個PDF to text的命令,去對PDF進行處理,但是他整個的過程中,他沒有對我們的PDF可控的Filename進行檢查,所以導致了一個命令注入的漏洞。
后半部分的原理上, 跟傳統的原理是一致的,從但是從輸入源上是有比較不同的點,傳統輸入更多是從HTTP的包里面去做輸入,這里面我們可以看到,它是依賴于云服務里面一個郵件服務,他收到郵件之后,產生了Event事件,產生的漏洞攻擊。
我們從漏洞攻擊上來看,我們如果能找到個他所訂閱的收件箱,我們只需要對他的收件箱,發送一個附件,為Payload的一個文件,我們就可以產生攻擊。
除了這個郵件Event事件,我們可以看到阿里云里面也有多達100多項的觸發器,這里面包括他的Laas的產品,也包括日志審計、登錄日志等東西。
整個的在 Serverless Function層面的,我們遇到的攻擊面比之前要變的更大,隨著公有云提供的服務種類變多,我們的Serverless的整個的Function支持的Event事件種類也會越來越多。
所以這也是后續大家在做Serverless開發的時候也需要關注的一個點,我們需要對所有的不同來源的Event事件的內容也需要做判斷。

依賴組件漏洞
Serverless依然會面臨依賴組件的漏洞攻擊。我們可以看到主流的Serverless,都會提供Java、Python、NodeJS、Golang等主流語言的開發支持。這是我們在騰訊云上創建了一個Function函數,我們可以看到里面也會涉及到requirements包的引入。
據統計,我們在整體應用開發過程中,有80%以上的代碼都來源于第三方的開源或者是商業的組件包,但是50%以上的開源組件多少會存在漏洞。
從去年開始,像Log4j2,我們分析完發現影響了整個開源生態四萬多個開源項目,影響了全球50%以上的Java應用的在線業務系統;前兩天還爆發了Fastjson系統,通過資產測繪的基礎,我們發現影響到20萬多臺在線的生產業務的安全性。
除了開源組件的安全性以外, 我們發現在2018年, aws-lambda官方提供的函數框架里面, 也存在ReDoS漏洞, 可以對整個應用產生拒絕服務攻擊。
一個是開源軟件,我們自己內部編碼所依賴組件包,還有我們所使用的Serverless的方式的框架是否有問題。我們發現aws-lambda、國外提供 Serverless服務的安全廠商基本上也爆出過框架本身漏洞, 影響我們整個應用的安全性。

權限控制不當
可能會存在權限控制不當的問題。我自己從GitHub上對所有的Serverless的配置的yaml文件做了分析,來源于一個真實的樣例,這里面可以看到,它在statement這里面有一個Action,Action是對目標資源的一個權限,他設置的是S3:*,用來表示完整的S3所有的控制權限,包括修改、查看、刪除等等操作,對Resoure的描述也是用*號來表示,所以我就可以對所有的S3對象進行控制, 整個權限是非常非常大的。
我們可以在開源的項目里面可以看到有非常多這樣的案例存在,這會過多的分配Serverless應用對其他的Faas服務的控制權限,我們就可以拿到GetObject、PutObject等,能控制S3的權限。
如果我們通過剛才的注入攻擊或者是其他的手法,拿到Serverless的臨時控制權限,我們可以通過他的AK/SK對其所依賴的第三方的Faas服務進行橫向攻擊。

敏感信息泄露
這個是截圖了某個云廠商Serverless的一個環境變量,他把非常多生產環境的K8S,這個K8S不是租戶的K8S,是Serverless本身提供服務的K8S,一些相關的信息,還有所對應的非常敏感的Key,都寫到環境變量里面, 我們很容易就可以拿到這些環境變量進行一些攻擊,并且由于Serverless服務他是部署在公網上的,我們只要拿到AK/SK,不需要網絡訪問權限,我們直接就可以通過API或者是命令終端,直接可以通過AK/SK獲得相應服務的控制權。
Serverless環境變量信息,它可以通過幾種方式去獲取。
開發模式
我們發現也提供Django的框架,我們可以看到Django的服務, 默認是開啟了Debug的模式, 我們可以通過一些報錯就可以直接拿到環境變量的信息。
異常報錯
非常多的程序在業務代碼開發中,把過多異常通過信息報道出來,方便程序員去做bug的處理,但程序如果拋出了過多的信息,也會導致信息的泄露。
獲取Serverless權限后橫向攻擊提供便利
我們通過一些漏洞攻擊,獲取到Serverless一個橫向的權限之后,可以通過環境變量里面泄露的AK/SK或者是代碼里面硬編碼這些AK/SK,對其他依賴的服務進行橫向的攻擊。
整個Serverless從攻擊上來看, 它的生命周期變得更短了,所以我們整個Serverless的攻擊, 相比原來的滲透測試會有比較大的區別, 我們一定是自動化的。
因為傳統的滲透測試,拿個機器,只要在管理員發現之前,是有無限長的時間對目標進行詳細的分析,但Serverless里面,你對Serverless進行請求,本身就有非常短的生命周期,所以一切的攻擊都是需要自動化的。
我們發現前年已經有相關的蠕蟲的病毒,就是針對Serverless應用進行攻擊的,基本上也都是拿到權限之后去讀env變量,通過env變量的AK/SK進一步的擴展,去控制其他在線的系統。
從整個的橫向,滲透測試的角度來看,攻擊面或者攻擊手法在新的場景下都發生了比較大的變化。

Serverless有這么多攻擊面,在安全檢測上也遇到了比較多的挑戰。
傳統黑白盒技術無法檢測
我們發現傳統的黑白盒技術已經無法檢測Serverless場景漏洞,主要原因有幾個原因。
一個是黑盒技術,它是需要應用運行時的一個技術,但在 Serverless里面,應用本身就不會有特別長的生命周期,所以不會讓你一直掃描,并且他整個Event事件源也非常多,你無法通過傳統的HTTP請求對Serverless應用進行掃描。
白盒也遇到一樣的問題,Serverless整個的應用架構,原生是個微服務架構,一個完整的應用它是由幾十個或者上百個Serverless函數進行構成的,本來是一個分布式,而且里面支持的協議也不是傳統的RPC或者是標準協議,它更多是通過Backend后端服務進行交互,所以在這種場景下,在白盒里面檢測非常難的,白盒是無法適配這么多的Event事件的來源,白盒基本上只能做常見的接口、協議或者HTTP協議的 污點追蹤,但是白盒到現在也沒有解決,跨服務、跨應用、跨語言之間的漏洞檢測的問題。
無法部署WAF、防火墻
目前在整個函數應用層面是沒有辦法部署在線的WAF或者防火墻,但是我們也看到國外已經有相關的技術,可以通過插件的方式,在Serverless運行時部署Serverless臨時的WAF、防火墻,但是這個技術相對比較早。
無應用函數架構復雜
整個的Serverless函數架構是無比的復雜的,我們之前攻擊的應用,他可能是部署在一起,或者是很容易梳理關系,但在Serverless整個應用里面, 是由非常多無數的函數和無數的后端服務構成的,所以我們很難梳理出整個的架構的情況。
無法進行統一鑒權
在公有云上使用,Serverless服務默認就會生成一個很長的地址,基本上我們很難去對地址進行鑒權,除非我們使用云廠商自己統一的鑒權方式,無法去對每一個函數進行統一鑒權,除非從開發設計一開始就考慮這個問題,如果后續去做的話, 是難度非常大。
Serverless 安全建議

安全編碼規范,防止注入攻擊
需要注意編碼規范,防止外部注入攻擊,或者是由于異常導致企業信息泄露。
三方供應鏈軟件檢查
我們需要去注重三方的開源組件的安全檢查,或者是我們所依賴的商業的SDK,或者是我們所使用的Serverless框架,他本身是不是也會存在問題。
IAM/Baas等最小權限運行
運行環境的問題,我們所運行的Serverless應用,賦值的權限是否是最小的權限,因為我們需要依賴非常多的后端的服務去做業務的處置。
Serverless服務統一鑒權
Serverless默認是沒有鑒權的,我們只要拿到地址就可以對這個應用進行攻擊, 我們需要做統一的鑒權。
KMS密鑰安全管理
我們發現非常多的 Serverless的一種,是整個密鑰都非常粗暴的管理,都是在環境變量進行管理,我們可以依賴于像K8S密鑰管理的系統,對密鑰進行統一的管理。
及時銷毀運行時臨時敏感數據
Serverless是一個生命周期非常短的服務,所以它會有非常多臨時的敏感數據存在我們的臨時目錄下,我們需要在對數據進行處理完之后,進行及時的銷毀。
資源網絡隔離
Serverless整個的網絡默認如果是你跟VPC連通的話, 是會存在一個被橫向的風險。
Serverless技術在國內外都是非常前沿、早期的技術,但相對是比較確定的技術方向,是一個非常好的技術。
大家從技術本身或者是安全上,還是有非常多可做的事情,包括如果你現在使用Serverless,目前對Serverless的安全上的關注還是比較少的。