作者 | 阿里云容器安全專家,徐越(樂枕)
責編 | 屠敏
頭圖 | CSDN 下載自東方 IC
出品 | CSDN(ID:CSDNnews)
容器化帶來的安全隱患
過去的2019 年是企業容器化爆發的一年。據統計已經有超過 90% 的互聯網企業正在部署或使用容器,希望能通過更為敏捷的方式快速響應市場需求。
然而,伴隨著容器技術的快速發展,容器安全問題也逐漸成為企業所關注的話題,同時,開發和運維人員缺乏對容器的安全威脅和最佳實踐的認識也可能會使業務從一開始就埋下安全隱患。Tripwire的調研顯示,60%的受訪者所在公司在過去的一年中發生過至少一起容器安全事故。在部署規模超過100個容器的公司中,安全事故的比例上升到了75%,由此可見,快速擁抱容器化帶來的安全風險不容忽視。本文對云上容器ATT&CK矩陣做了詳細闡述,希望能幫助開發和運維人員了解容器的安全風險和落地安全實踐。
云上容器攻擊矩陣概覽
ATT&CK?框架(Reference ATTACK Matrix for Container on Cloud)是網絡攻擊中涉及的已知策略和技術的知識庫。為便于企業構建容器化應用安全體系,阿里云在傳統主機安全的基礎上,圍繞自建容器集群以及云原生容器服務場景,通過全面分析黑客攻擊Docker和K8s的過程和手段,推出容器安全ATT&CK矩陣,讓黑客無所遁形,助力企業全面提升容器安全能力水位。
云上容器ATT&CK矩陣詳解
1. Initial Access/初始訪問
1.1 云賬號AK泄露
云平臺安全是云服務(容器服務、VM服務)的基礎,如果業務代碼需要通過AccessKey的方式進行鑒權并與云服務通信,應至少為每個云服務創建子賬號并賦予需要的最小權限,同時推薦使用云平臺提供的角色(如阿里云RAM角色)進行認證和授權。在實踐中我們發現,存在部分管理員在進行代碼托管時,使用主賬號AK(擁有全部云資源控制權限)并不慎將其泄露到公開倉庫(如Github),進而導致其云服務遭受入侵的場景,針對這一風險點,需要企業在使用云原生服務及容器化應用的過程中時刻關注。
1.2 使用惡意鏡像
部分容器開發者會使用公開的鏡像源(如dockerhub)下載鏡像并在業務環境中運行,但如果不慎使用了存在漏洞的鏡像,會給業務帶來安全風險。此外,攻擊者時常會將惡意鏡像部署到dockerhub,并通過誘導安裝或鏈路劫持對企業進行供應鏈攻擊。
示例:一個在Dockerhub中偽裝成mysql的惡意鏡像,同時攜帶了挖礦程序:
1.3 K8sAPI Server 未授權訪問
K8s API Server作為K8s集群的管理入口,通常使用8080和6443端口,其中8080端口無需認證,6443端口需要認證且有TLS保護。
如果開發者使用8080端口,并將其暴露在公網上,攻擊者就可以通過該端口API,直接對集群下發指令,或訪問/ui進入K8s集群管理dashboard,操作K8s實施破壞。
1.4 K8s configfile 泄露
K8s configfile作為k8s集群的管理憑證,其中包含有關K8s集群的詳細信息,包括它們API Server的地址和登錄憑證。在購買托管容器服務時,云廠商會向用戶提供該文件以便于用戶可以通過kubectl對集群進行管理。如果攻擊者能夠訪問到此文件(如辦公網員工機器入侵、泄露到Github的代碼等),就可以直接通過API Server接管K8s集群,帶來風險隱患。
示例:阿里云容器服務K8s configfile:
1.5 Docker daemon公網暴露
Docker以client-server模式工作,其中docker daemon服務在后臺運行,負責管理容器的創建、運行和停止操作,并提供docker許多其他運行時功能。執行docker命令會調用一個客戶端,該客戶端通過Docker的REST API將命令發送到服務端(docker daemon)。
在Linux主機上,docker daemon監聽它在/var/run/docker.sock中創建的unix socket。為了使docker daemon可管理,可以通過配置TCP socket將其暴露在網絡中,一般情況下2375端口用于未認證的HTTP通信,2376用于可信的HTTPS通信。
如果管理員測試業務時配置不當導致docker.sock通過2375暴露在公網,攻擊者即可通過該API接管docker服務。
示例:Docker daemon的2375端口的暴露:
docker daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
1.6 容器內應用漏洞入侵
同主機安全一樣,容器中運行的應用側漏洞(如WEB應用RCE漏洞、Redis未授權訪問等)也會成為黑客的突破口,攻擊者可以利用這些漏洞進入容器內部并發起進一步攻擊。
1.7 Master節點SSH登錄憑證泄露
常見的容器集群管理方式是通過登錄Master節點或運維跳板機,然后再通過kubectl命令工具來控制k8s。在此情況下,前置節點的SSH憑證泄露或被攻破也會使K8s集群暴露在風險中。
1.8 私有鏡像庫暴露
在容器化應用場景中,公司使用鏡像來進行持續集成和自動化部署,這些鏡像往往通過專用的私有鏡像庫來管理。暴露在公網的私有鏡像庫極有可能遭受攻擊者入侵,并通過劫持供應鏈來滲透下游業務。
以Harbor為例,Harbor是一個用于存儲和分發Docker鏡像的企業級Registry開源服務器,集成了Docker Hub、Docker Registry、谷歌容器等。它提供了一個簡單的GUI,允許用戶根據自己的權限下載、上傳和掃描鏡像。在過去的數年里,Harbor逐漸受到人們的關注并成為CNCF的孵化項目,被企業廣泛應用。Harbor在2019年披露了一個嚴重漏洞CVE-2019-16097,該漏洞允許攻擊者通過發送惡意請求以管理員權限創建用戶,從而接管Harbor。該漏洞利用方式簡單,對暴露在公網的Harbor服務構成較大威脅。
2.Execution/執行
2.1 通過kubectl進入容器
Kubectl是一個管理k8s集群的命令行工具,kubectl在$HOME/.kube目錄中尋找一個名為config的文件并連接API Server進行鑒權操作。攻擊者可以通過kubectl exec指令在任意pod內部執行命令。
示例:kubectl exec進入pod內部執行指令:
xy@x-8 ~/D/t/K8s_demo> kubectl get pod
NAME READY STATUS RESTARTS AGE
app-1-wp-0 1/1 Running 0 182d
app-1-wp-1 1/1 Running 0 182d
myapp 1/1 Running 0 11d
myappnew 1/1 Running 0 11d
xy@x-8 ~/D/t/K8s_demo> kubectl exec -it myappnew /bin/bash
root@myappnew:/# whoami
root
2.2 創建后門容器
攻擊者可通過擁有pods權限的用戶創建基礎鏡像并利用其執行后續滲透操作。
示例:通過yaml文件創建pod,并將pod的根目錄/掛載到容器/mnt目錄下,操作宿主機文件:
xy@x-8 ~/D/test> cat mymaster.yaml
apiVersion: v1
kind: Pod
metadata:
name: myappnew
spec:
containers:
- image: nginx
name: container
volumeMounts:
- mountPath: /mnt
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /
xy@x-8 ~/D/test> kubectl create -f ~/Desktop/test/mymaster.yaml
pod/myappnew created
xy@x-8 ~/D/test> kubectl exec -it myappnew /bin/bash
root@myappnew:/# cd /mnt
root@myappnew:/mnt# ls
bin checkapp etc lib lost+found mnt proc run srv tmp var
boot dev home lib64 media opt root sbin sys usr
2.3 通過K8s控制器部署后門容器
Kubernetes中運行了一系列控制器(Controllers)來確保集群的當前狀態與期望狀態保持一致。例如,ReplicaSet控制器負責維護集群中運行的Pod數量;Node控制器負責監控節點的狀態,并在節點出現故障時及時做出響應。
攻擊者在擁有controllers權限情況下可以通過ReplicaSet/DaemonSet/Deplyment創建并維持后門容器。
示例:攻擊者通過controllers攻擊:
xy@x-8 ~/D/test> cat nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx-test
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: container
volumeMounts:
- mountPath: /mnt
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /
xy@x-8 ~/D/test> kubectl apply -f nginx-deploy.yaml
deployment.apps/nginx-deployment created
xy@x-8 ~/D/test> kubectl get pods
NAME READY STATUS RESTARTS AGE
app-1-wp-0 1/1 Running 0 183d
app-1-wp-1 1/1 Running 0 183d
myapp 1/1 Running 0 12d
myappnew 1/1 Running 0 38m
nginx-deployment-b676778d6-lcz4p 1/1 Running 0 55s
2.4 利用Service Account連接API Server執行指令
Kubernetes區分用戶和服務(Service Account)兩種賬戶,其中用戶賬戶便于管理員與集群交互,服務賬號用于Pod進程調用Kubernetes API或其他外部服務。
K8s pod中默認攜帶服務賬戶的訪問憑證,如果被入侵的pod存在高權限的用戶,則容器中可以直接通過service account向K8s下發指令。
示例:service account在容器內部的默認路徑:
cd /var/run/secrets/kubernetes.io/serviceaccount
示例:帶憑證訪問API server的方式:
curl -voa -s https://192.168.0.234:6443/version
# 以下命令相當于 kubectl get no
curl -s https://192.168.0.234:6443/api/v1/nodes?watch --header "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tOGprZmQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2DydmljZS1hY2NvdW50LnVpZCI6Ijg4Y2ZmNmYzLWY0NzktMTFlOS1iZmY1LTJlYzU3MmZlMWRjOCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.OU740qNcSf0Z__vAO1XJWUw9fvNNI2e4LxHypkpzREmnqrK9UZ-rrp9tG8Vxbc65FlPFj9efdpfWYExxjDDQwQTi-5Afmk4EA6EH-4vEs4V1r4gb0za8cyPVSAjzmEh7uIMgQHVo7y32V_BqUd8cmBoTdgnTY8Nx2QvMClvoYvEWvDKhbMnQjWH1x5Z6jK0iNg7btlK_WXnz8-yU2a0-jgoZFZ8D_qX16mZJ_ZoxEwPNTeNR8pP1l3ebZGVqBQA1PIFVG4HOlYomZya_DWGleMRYpulnECtBOTYyswzCwN8qJUVsdv6yWH1blWHKzYrkcoDmp2r6QhekaG1KFoX_YA" --cacert ca.crt
2.5 帶有SSH服務的容器
含有SSH服務的容器暴露了新的攻擊面,由于暴力破解或者登錄憑證泄露,攻擊者可以進入到容器內部執行指令進行惡意操作。這種情況多見于自建容器或K8s環境(一些運維人員將容器當做VM使用)。此外當攻擊者逃逸到node節點時可以通過添加賬號或寫入/.ssh/authorized_keys等方式利用SSH下發后續惡意指令。
2.6 通過云廠商CloudShell下發指令
針對VM和容器服務的管理,云服務商往往會提供沙箱化的便捷管理工具,在云賬號憑證泄露的情況下,攻擊者可以通過云廠商提供的API接管集群。此外云廠商沙箱本身的安全問題也會影響到用戶集群安全。
示例:通過Cloud Shell管理集群:
3.Persistence/持久化
3.1 部署遠控客戶端
(參考2.3部分通過K8s控制器部署后門容器)攻擊者通過K8s DaemonSet向每個Node中植入后門容器,這些容器可以設置為特權容器并通過掛載宿主機的文件空間來進一步向每個Node植入二進制并遠控客戶端,從而完成Node層持久化,且后續操作不會觸發K8s層的審計策略。
3.2 通過掛載目錄向宿主機寫入文件
一種常見的容器逃逸方法,如果容器/Pod啟動時將VM的核心目錄以寫權限掛載(如/root, /proc, /etc等),則攻擊者進入容器后可以修改敏感文件進行逃逸,如利用/etc/crontab執行定時任務、修改/root/.ssh/authorized_keys獲取SSH登錄權限、讀取其他進程空間內容等。
示例:不安全的目錄掛載:
docker run -it -v /root:/root ubuntu /bin/bash
寫入SSH憑證
(echo -e "\n\n";cat id_rsa_new.pub) >> /root/.ssh/authorized_keys
3.3 K8s cronjob持久化
Cronjob是K8s controller的一種,用于創建基于時間的調度任務(類似主機的/etc/crontab)。攻擊者在獲取controller create權限后可以創建cronjob實現持久化。
示例:cronjob持久化
xy@x-8 ~/D/test> cat cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: echotest
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: container
image: nginx
args:
- /bin/sh
- -c
- echo test
restartPolicy: OnFailure
xy@x-8 ~/D/test> kubectl create -f cronjob.yaml
cronjob.batch/echotest created
xy@x-8 ~/D/test> kubectl get cronjobs
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
echotest */1 * * * * False 3 26s 3m8s
3.4 在私有鏡像庫的鏡像中植入后門
(參考1.8私有鏡像庫暴露)攻擊者在接管企業私有鏡像庫之后,可以進行拉取私有鏡像竊取信息、刪除倉庫中的鏡像、替換倉庫中的鏡像、為已有鏡像添加后門、在鏡像服務中創建后門賬號等惡意操作。
一種持久化攻擊方式是在dockerfile中加入額外的惡意指令層來執行惡意代碼,同時該方法可以自動化并具有通用性。同時在Docker鏡像的分層存儲中,每一層的變化都將以文件的形式保留在image內部,一種更為隱蔽的持久化方式是直接編輯原始鏡像的文件層,將鏡像中原始的可執行文件或鏈接庫文件替換為精心構造的后門文件之后再次打包成新的鏡像,從而實現在正常情況下無行為,僅在特定場景下觸發的持久化工具。
3.5 修改核心組件訪問權限
攻擊者通過ConfigMap修改Kubelet使其關閉認證并允許匿名訪問,或暴露API Server的未授權HTTP接口,使其在后續滲透過程中擁有持續的后門命令通道。
4. Privilege Escalation/權限提升
4.1 利用特權容器逃逸
Docker允許特權容器訪問宿主機上的所有設備,同時修改AppArmor或SELinux的配置,使特權容器擁有與那些直接運行在宿主機上的進程幾乎相同的訪問權限。在這種情況下,攻擊者從特權容器逃逸是極其容易實現的。
示例:將系統盤掛載到容器內部,讀寫宿主機文件:
root@d000b330717d:/# fdisk -l
Disk /dev/vda: 40 GiB, 42949672960 bytes, 83886080 sectors
Units: sectors of 1 * 512=512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xe2eb87fa
Device Boot Start End Sectors Size Id Type
/dev/vda1 * 2048 83886046 83883999 40G 83 Linux
root@d000b330717d:/# mkdir /mnt1
root@d000b330717d:/# mount /dev/vda1 /mnt1
root@d000b330717d:/# cd /mnt1
root@d000b330717d:/mnt1# ls
bin etc initrd.img.old lost+found opt run sys var
boot home lib media proc sbin tmp vmlinuz
dev initrd.img lib64 mnt root srv usr vmlinuz.old
4.2 K8s Rolebinding添加用戶權限
K8s使用基于角色的訪問控制(RBAC)來進行操作鑒權,允許管理員通過 Kubernetes API 動態配置策略。某些情況下運維人員為了操作便利,會對普通用戶授予cluster-admin的角色,攻擊者如果收集到該用戶登錄憑證后,可直接以最高權限接管K8s集群。少數情況下,攻擊者可以先獲取角色綁定(RoleBinding)權限,并將其他用戶添加cluster-admin或其他高權限角色來完成提權。
4.3 利用掛載目錄逃逸
參考(3.2通過掛載目錄向宿主機寫入文件),攻擊者在容器內部可以利用掛載通道修改宿主機文件來實現逃逸。
4.4 利用操作系統內核漏洞逃逸
操作系統內核安全(如Linux內核)是容器安全體系的基石,是實現容器隔離設計的前提。內核漏洞的利用往往從用戶空間非法進入內核空間開始,在內核空間賦予當前或其他進程高權限以完成提權操作。在云原生場景中,云廠商會在VM層為操作系統內核漏洞進行補丁修復,避免用戶被已公開的內核漏洞攻擊。
4.5 利用Docker漏洞逃逸
Docker軟件歷史上出現過多個高危安全漏洞,目前仍有一定影響的是兩個2019年的漏洞:Docker runc RCE(CVE-2019-5736)和Docker cp RCE(CVE-2019-14271)。兩個漏洞均利用了Docker本身的功能設計缺陷,利用覆蓋容器內部runc文件、libnss庫,從而實現從容器到宿主機的逃逸行為。從攻擊者角度來看,這兩個漏洞均需要與宿主機交互才會觸發payload執行,實戰中并不高效,但Docker既要隔離又要通信的機制設計或許會在未來暴露出更多問題。在云服務商提供的托管K8s集群以及Serverless服務中,Docker服務自身安全性會由云服務商維護,相比自建,安全性會更有保障。
4.6 利用K8s漏洞進行提權
容器化基礎設施每一環的軟件漏洞都會帶來安全風險。Kubernetes特權升級漏洞(CVE-2018-1002105)允許普通用戶在一定前提下提升至K8s API Server的最高權限。該漏洞需要用戶擁有對某個namespace下pod的操作權限,同時需要client到API Server和kubelet的網絡通路來實施攻擊。同樣,該漏洞在云服務中已經被服務商修復,在自建的K8s集群中仍有發揮空間。
4.7 容器內訪問docker.sock逃逸
當docker.sock被掛載到容器內部時,攻擊者可以在容器內部訪問該socket,管理docker daemon。
docker -v /var/run/docker.sock:/var/run/docker.sock
此時容器內部可以與docker deamon通信,并另起一個高權限的惡意容器,從而拿到root shell。
示例:與docker deamon通信:
find / -name docker.sock
curl --unix-socket /var/run/docker.sock http://127.0.0.1/containers/json
4.8 利用Linux Capabilities逃逸
容器即隔離,容器在設計上使用cgroup、namespace等對宿主機的資源進行隔離及調度使用,同時也支持使用Linux capabilities做細粒度的權限管控。從這一角度來看,不安全的權限分配會為容器逃逸提供通路。
示例:K8s YAML配置中對capabilities的支持:
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
docker會以白名單方式賦予容器運行所需的capabilities權限,我們可以在docker run命令中使用 --cap-add 以及 --cap-drop 參數控制capabilities。以下命令對容器開放了宿主機的進程空間,同時賦予容器CAP_SYS_PTRACE權限,此時攻擊者在容器內部可以注入宿主機進程從而實現逃逸。
docker run -it --pid=host --cap-add=CAP_SYS_PTRACE ubuntu
5. DefenseEvasion/防御逃逸
5.1 容器及宿主機日志清理
攻擊者在獲得一定權限之后,可以擦除容器內部及宿主機的系統日志以及服務日志,為企業的入侵事件復盤以及溯源增加難度。目前容器運行時安全解決方案中均采用實時的日志采集、自保護方案以及日志采集異常的預警,來解決日志惡意擦除導致的溯源問題。同時,在云原生的容器攻防戰場中,惡意卸載安全產品agent以切斷日志采集能力也逐漸成為了常見的攻擊方式。
5.2 K8s Audit日志清理
Kubernetes Audit功能提供了與安全相關的按時間順序排列的記錄集,記錄單個用戶、管理員或系統其他組件影響系統的活動順序。日志提供了包括事件、時間、用戶、作用對象、發起者、執行結果等詳細信息,為運行時安全審計提供便利。攻擊者可以通過清理本地日志文件(用戶/服務商可自定義位置)以及切斷服務商/安全產品的日志上傳通道(卸載agent或者阻斷網絡通路)來隱藏對K8s集群的操作,一些容器安全產品通過K8s AuditSink功能將日志導出到外部審計,也可通過修改K8s配置進行開啟或關閉。
示例:阿里云容器服務KubernetesAudit審計中心:
5.3 利用系統Pod偽裝
K8s在部署時會在kube-system namespace中內置一些常見的功能性pod。在云廠商提供的容器服務中,集群還會默認攜帶一些云服務的組件(如日志采集、性能監控的agent)。攻擊者可以利用常見的K8s內置pod作為后門容器,或將后門代碼植入這些pod來實現隱蔽的持久化。
示例:阿里云托管版K8s服務內置pod:
xy@x-8 ~/D/test> kubectl get deployments --namespace=kube-system
NAME READY UP-TO-DATE AVAILABLE AGE
alibaba-log-controller 1/1 1 1 183d
alicloud-application-controller 1/1 1 1 183d
alicloud-disk-controller 1/1 1 1 183d
alicloud-monitor-controller 1/1 1 1 183d
aliyun-acr-credential-helper 1/1 1 1 183d
coredns 2/2 2 2 183d
metrics-server 1/1 1 1 183d
nginx-ingress-controller 2/2 2 2 183d
tiller-deploy 1/1 1 1 183d
5.4 通過代理或匿名網絡訪問K8s API Server
利用代理或匿名網絡執行攻擊是常見的反溯源行為,在K8s Audit日志中記錄了每個行為發起者的源IP,通過公網訪問API Server的IP將會被記錄并觸發異常檢測和威脅情報的預警。
示例:K8s Audit日志對pod exec行為的記錄:
5.5 清理安全產品Agent
目前主流容器運行時的安全產品部署方式有兩種:平行容器模式和主機agent模式。前者創建安全容器采集pod、K8s集群日志以及實現網絡代理;后者在VM層對容器層的進程網絡文件進行采集。攻擊者在獲取到集群管理權限或逃逸到宿主機時,可以通過清理掉安全產品植入的探針,破壞日志完整性,使后續攻擊行為無法被審計工具發現。在這一過程中,安全容器或主機agent異常離線往往會觸發保護性告警。
5.6 創建影子API Server
攻擊者可以復制原生API Server的配置,修改關鍵參數(例如關閉認證,允許匿名訪問,使用HTTP請求),再使用這些修改過的參數創建Pods。攻擊者可以通過這個影子API Server直接獲取etcd內存儲的內容,使后續滲透行為在審計日志中匿名。
5.7 創建超長annotations使K8s Audit日志解析失敗
一般情況下云廠商/安全產品會使用自身日志服務的agent對K8s Audit日志進行采集和解析,以便于與后續審計規則結合。在入侵檢測中,日志的采集-存儲-計算的過程會受限于agent的性能占用、Server端日志服務以及其他云產品/開源組件對存儲和計算的限制,過長的字段將有可能觸發截斷,導致敏感信息無法經過審計規則從而繞過入侵檢測,K8s API請求中允許攜帶1.5MiB的數據,但在Google StackDriver日志服務僅允許解析256KB的內容,這將導致Audit日志中的敏感信息(如創建Pod時的磁盤掛載配置項)繞過審計。
示例:通過無意義的超長annotations攻擊日志分析鏈路:
apiVersion: v1
kind: Pod
metadata:
name: annotations-bypass
annotations:
useless-key: useless-value(1 MiB)
...
6. Credential Access/竊取憑證
6.1 K8s Secret泄露
K8s使用Secret對象對access key、密碼、OAuth token和ssh key等敏感信息進行統一管理。pod定義時可以引用secret對象以便在運行時訪問。攻擊者可以通過pod內部service account或更高權限用戶來獲取這些secret內容,從中竊取其他服務的通信憑證。
示例:查看并下載K8s secret保存的憑據:
xy@x-8 ~> kubectl get secrets --namespace=kube-system
NAME TYPE DATA AGE
admin-token-ltbcr kubernetes.io/service-account-token 3 184d
alibaba-log-controller-token-9kv4m kubernetes.io/service-account-token 3 184d
aliyun-acr-credential-helper-token-vwmlw kubernetes.io/service-account-token 3 184d
attachdetach-controller-token-l5bfh kubernetes.io/service-account-token 3 184d
bootstrap-signer-token-qbrx7 kubernetes.io/service-account-token 3 184d
bootstrap-token-509e2b bootstrap.kubernetes.io/token 6 184d
certificate-controller-token-dgpjn kubernetes.io/service-account-token 3 184d
cloud-node-controller-token-647sw kubernetes.io/service-account-token 3 184d
...
xy@x-8 ~> kubectl get secret alibaba-log-controller-token-9kv4m --namespace=kube-system -o yaml
6.2 云產品AK泄露
云原生的應用部署流程中會涉及到各種云產品的API通信,當某應用被攻破后,攻擊者可以通過K8s secret或者掛載到本地的憑證文件來獲取相關服務的AK并進行橫向移動。一種常見的場景是:入侵WEB應用后獲取云存儲(OSS)、云數據庫(RDS)、日志服務的通信憑證,并進一步竊取數據。
示例:關于云產品AK的掃描規則已被工具化:
6.3 K8sService Account憑證泄露
此類場景多見于辦公網運維PC、跳板機以及通過SSH管理的master節點上。黑客在攻破此類服務器時,可以檢查本地是否存在kubectl鑒權所需的配置文件(一般在$HOME/.kube/config),該文件通常包含了登錄K8s集群的全部信息。
6.4 應用層API憑證泄露
在復雜業務場景以及微服務架構中,K8s各個服務之間、容器與VM之間會通過API方式進行通信,竊取其通信憑證可用于橫向滲透。
6.5 利用K8s準入控制器竊取信息
K8s準入控制器(Admission Controller)用于hook客戶端對API Server的請求。其中變更(mutating)控制器可以修改被其接受的對象;驗證(validating)控制器可以審計并判斷是否允許該請求通過。準入控制器是可以串聯的,在請求到達API Server之前,如有任何一個控制器拒絕了該請求,則整個請求將立即被拒絕,并向終端用戶返回一個錯誤。
為了便于用戶部署自己的準入服務,K8s提供了動態準入控制(Admission Webhook)功能,即用于接收準入請求并對其進行處理的HTTP回調機制。
一種利用動態準入控制實現持久化的方式:攻擊者在獲取cluster-admin權限后,可以創建惡意的準入控制器hook掉所有的API訪問,引用攻擊者的外部webhook作為validating服務,這樣k8s就會將攜帶敏感信息的API請求發送到攻擊者所用服務器。
示例:利用準入控制器后門,使用通配符hook全部操作,使用failurePolicy和timeoutSeconds參數做到用戶側無感,從而實現隱蔽的數據竊取(如:K8s secret創建時發送到API的AK信息)。
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
...
webhooks:
- name: my-webhook.example.com
failurePolicy: Ignore
timeoutSeconds: 2
rules:
- apiGroups: ["*"]
apiVersions: ["*"]
operations: ["*"]
resources: ["*/*"]
scope: "*"
...
7. Discovery/探測
7.1 訪問K8s API Server
(參考2.4利用Service Account連接API Server執行指令)攻擊者進入pod之后,可以通過curl或wget等http客戶端,或使用編譯好的報文構造工具,直接訪問K8s REST API,當service account具有高權限時可以直接下發命令進行橫向移動。而當用戶具有低權限時,也可能通過API Server探測到集群內部的資源信息、運行狀態以及secret,有利于尋找下一個突破點。
7.2 訪問Kubelet API
在kubernetes集群中,每個Node節點都會啟動Kubelet進程,用來處理Master節點下發到本節點的任務,管理Pod和其中的容器。包括10250端口的認證API、10255端口的只讀API以及10256端口的健康檢查API。
其中10255端口可以無需授權進行只讀訪問,攻擊者可以訪問/pods獲取到node、pod地址以及pod的掛載情況、環境變量等敏感信息,輔助還原業務場景和集群網絡拓撲,以尋找后續攻擊點。
關于Kubelet API官方并未提供文檔,更多接口可在Kubelet源碼中挖掘。一些有用的路徑:
http://{node_ip}:10255/pods
http://{node_ip}:10255/spec
10250的端口當前版本中默認需要認證,但在老版本的K8s集群中或在用戶權限(system:anonymous)被錯誤配置的情況下,可以嘗試直接通過10250端口下發指令。
示例:命令下發:
root@myappnew:/# curl --insecure https://192.168.0.237:10250/pods
Unauthorized
7.3 Cluster 內網掃描
黑客通常會對Node、Pod、Service三個網段進行主機存活探測和端口掃描,然后從K8s內置服務、用戶應用、第三方K8s插件等角度尋找更多攻擊面,同時會通過找到Node IP并訪問Kubelet API獲取pod的詳細拓撲信息。
阿里云容器服務默認CIDR:
7.4 訪問K8s Dashboard所在的Pod
Kubernetes Dashboard為用戶提供WEB界面,便于創建、修改和管理Kubernetes資源(如 Deployment,Job,DaemonSet等)。Dashboard的部署取決于云廠商和用戶自身的配置,在官方的部署流程中,dashboard會創建獨立的Namespace、Service、Role以及ServiceAccount。
示例:阿里云容器服務提供的dashboard:
由于K8s pod之間默認允許通信,攻擊者在進入某個pod之后,可以通過信息收集或內網掃描的方式發現K8s dashboard所在service地址,并通過kubernetes-dashboard service account進行認證操作。
7.5 訪問私有鏡像庫
參考1.8和3.4關于私有鏡像庫的攻擊面,攻擊者可以在K8s secret或本地配置文件中找到私有鏡像庫的連接方式,并在權限允許的情況下劫持私有鏡像庫中的鏡像,實現橫向移動和持久化。
7.6 訪問云廠商服務接口
(參考6.2云產品AK泄漏)在云原生的容器化應用中,服務往往會與多種內外部API進行交互,攻擊者可以通過收集這些API的登錄憑據或測試是否存在未授權訪問來進行攻擊準備。
此外,在某些云服務商提供的CaaS或Serverless容器中,為便于使用者與底層云基礎設施進行通信,廠商通過植入專用pod或者將API掛載到業務pod的方式提供額外的接口,這些接口也會成為攻擊者收集信息過程中的突破口。
7.7 通過NodePort訪問Service
K8s service的暴露方式由三種:ClusterIP,NodePort和LoadBalancer。其中LoadBalancer多與云廠商的負載均衡類產品集成,具有較強的流量審計能力。
一些業務場景中存在著K8s與VM并存的內網環境,當攻擊者通過非容器化的弱點進入內網時,可以借助NodePort進行橫向移動。在頻繁迭代的業務中,使用NodePort的服務相比ClusterIP更加固定,可用做控制通道來穿透網絡邊界管控以及防火墻的限制。
默認情況下,K8s集群NodePort分配的端口范圍為:30000-32767。
8. Lateral Movement/橫向移動
8.1 竊取憑證攻擊云服務
(參考6.2云產品AK泄漏)攻擊者利用容器內部文件或K8s secret中竊取到的云服務通信憑證進行橫向移動。
8.2 竊取憑證攻擊其他應用
參考第6節的各項內容。在基礎設施高度容器化的場景中,絕大部分服務都是API化的,這使憑證竊取成為擴展攻擊面、獲取目標數據的重要手段。K8s集群、云產品以及自建應用的通信憑證都是攻擊者竊取的目標。
8.3 通過Service Account訪問K8s API
(參考2.4利用Service Account連接API Server執行指令)攻擊者在容器內部可通過Service Account訪問K8s API刺探當前pod用戶權限,并在權限允許的前提下對API下發指令或利用K8s提權漏洞訪問集群中的其他資源。
8.4Cluster內網滲透
一般情況下,K8s會默認允許Cluster內部的pod與service之間直接通信,這構成了一個"大內網"環境。攻擊者在突破一個pod之后,可以通過內網掃描收集服務信息并通過應用漏洞、弱口令以及未授權訪問等方式滲透Cluster的其他資源。K8s支持通過自帶的網絡策略(NetworkPolicy)來定義pod的通信規則,一些網絡側插件、容器安全產品也支持東西向的通信審計與管控。
8.5 通過掛載目錄逃逸到宿主機
(參考3.2通過掛載目錄向宿主機寫入文件)攻擊者可以利用掛載到容器內部的目錄完成從pod到node的移動。
8.6 訪問K8sDashboard
(參考7.4訪問K8s Dashboard所在的Pod)攻擊者在進入某個pod之后,可以通過信息收集或內網掃描的方式發現K8s dashboard所在service地址,并在管理員權限配置失當的情況下通過K8s Dashboard下發指令。
8.7 攻擊第三方K8s插件
為了快速上手,很多K8s快速入門指南都會介紹一些好用的插件和配置方案,但教程的創建者很少考慮到真實生產業務中的安全問題,而這些插件往往在初始的幾個版本中存在鑒權方面的漏洞(如API默認允許未授權訪問),直到被攻擊者反復測試之后才會逐漸穩定可靠。這些不安全的配置以及使用的第三方K8s插件/工具會引入新的攻擊面,并為橫向移動提供便利。
示例:常見的利用第三方組件進行橫向移動的過程:
攻擊者進入pod后,通過未授權訪問或漏洞攻擊第三方組件,并利用這些組件的權限操縱K8s集群。
9. Impact/影響
9.1 破壞系統及數據
以破壞為目的的攻擊者可能會停止或禁用系統上的服務、刪除某些核心文件及數據以使合法用戶無法使用這些服務。停止關鍵服務可能會抑制防御方對事件的響應,并有利于攻擊者的最終目標。
9.2 劫持資源
常見于攻擊者通過自動化腳本入侵并植入挖礦程序進行獲利。
9.3 DoS
攻擊者會發起DoS攻擊,影響系統的可用性。容器化場景中的DoS攻擊包括對業務層、K8s API層的攻擊以及對Pod資源的搶占。
9.4 加密勒索
在傳統主機安全場景中,有經驗的攻擊者會找到企業核心數據并對其進行加密勒索。由于容器場景的資源彈性較大,且后端數據的產生、存儲、銷毀鏈路往往通過云服務API實現,而非在用戶磁盤上進行,企業可以通過云原生的快照與備份服務來實現資產備份,避免核心數據丟失。
阿里云容器安全解決方案
阿里云容器服務(ACK)提供高性能可伸縮的容器應用管理服務,支持企業級Kubernetes容器化應用的生命周期管理。阿里云容器鏡像服務(ACR)是云原生時代的重要基礎設施之一,支撐阿里巴巴經濟體容器鏡像托管,分鐘級分發萬節點。自2015年起,先后服務了數千家企業,托管了數 PB容器鏡像數據,支撐月均鏡像拉取數億次。
為了幫助云上客戶更好的做好容器安全建設,阿里云重點關注容器構建、容器部署和容器運行三大生命周期階段,結合容器ATT&CK矩陣,提供自動化的容器安全檢測和響應能力;同時聯合阿里云原生容器安全服務,共同面向客戶推出云上容器安全一體化方案,助力企業容器化進程。
借助云安全中心,阿里云可以為客戶提供自動化的安全編排與響應能力,全面提升容器安全易用性;同時為容器鏡像提供漏洞掃描和修復,并支持整合在容器構建流程中,避免部署存在風險的容器;對于運行時的容器被植入 Webshell、挖礦病毒等場景,自動化將隔離惡意樣本,并通過聯動云防火墻,針對存在漏洞的容器,提供虛擬補丁的能力,緩解安全風險。
寫在最后
理解容器ATT&CK矩陣是構建容器安全能力的第一步,除了上述涉及的能力和措施外,阿里云安全團隊建議用戶在實施容器化過程中需要遵循以下幾點安全規范,從不同角度緩解容器化帶來的風險:
在應用生命周期中關注您的鏡像,容器,主機,容器管理平臺以及相關云服務的安全性,了解潛在風險以及如何保護整體容器環境的運行免受危害。
收集并妥善保管K8s集群、第三方CI組件以及云服務的API通信憑證,避免因人工誤操作導致的AK泄露。
由于容器應用生態涉及到的中間件較多,系統管理者需要關注這些中間件的漏洞披露情況并及時做好脆弱性管理和補丁升級工作。
最后,針對上述容器ATT&CK矩陣,阿里云推出容器安全運行檢測清單,企業可以根據下圖中所展示的內容檢測自己的容器安全水位,以便及時發現問題及時修復。
內容致謝:
陳吳棟(自樸) 阿里云高級產品經理、魏俊欣(艾格) 阿里云高級安全專家、邱戈川(了哥) 阿里云高級技術專家、杜航(達丁) 阿里云容器解決方案架構師
鏈碼不需要"實例化",可以同時運行java和go鏈碼,同一個鏈碼多次實例化。
之前發的這篇一文帶大家了解Fabric 2.0的新特性被頭條彈窗了,但是寫的不夠詳細,今天特別把這篇文章補充完整。 此外歡迎大家關注我的github:https://github.com/haojunsheng
想要了解上面的特性,請看下面的分解。
Fabric 2.0 在2020年1月29號終于release了,我們來看下有哪些新的變化。
主要體現在:對新應用和隱私的支持,增強了智能合約的管理,增加了對節點的操作。
需要注意的是,只能由fabric-1.4.x升級到2.0。
ps:在網上有個翻譯,那一字一句的翻譯,真的讓我很難受。
下面我嘗試使用自己的理解來解讀。
fabric 2.0引入了智能合約的去中心化管理,在此之前,鏈碼的安裝和實例化都是一個由組織在操作,現在則發生了變化。新的鏈碼的生命周期中,只有多個組織達成了共識,才可以和賬本才可以進行交互。
· 多個組織必須同意鏈碼的參數。在2.0之前,一個組織可以為channel中的所有成員設置鏈碼的參數(例如實例化鏈碼時指定的背書策略),拒絕安裝鏈碼的組織將不能參與鏈碼的調用。在2.0中,同時提供中心化的模型和去中心化的模型。
· 鏈碼的升級更加安全。在之前的鏈碼生命周期中,一個組織即可升級鏈碼。在新的版本中,需要別的組織進行同意。
· 簡化了背書策略和private data的更新。我們不必重新打包/安裝鏈碼即可更新背書策略和private data集合的配置。同時我們設置了默認的背書策略,默認的背書策略在我們增加或者刪除組織的時候會自動生效。
· 打包鏈碼:會打包為tar文件,方便進行閱讀。
· 一次打包多次復用:之前鏈碼是通過名字+版本號來決定的,現在一次打包生成多個名字,可以多次安裝(在相同或者不同的通道上)
· 不需要所有人的同意即可打包chaincode:組織可以擴展鏈碼,不需要所有人的同意,只要符合背書要求,這些交易即可被更新到賬本中。這樣做的好處是,不需要所有人的同意,即可小規模的修改鏈碼的bug。
新的鏈碼周期要求組織對鏈碼的名字,版本,背書策略達成一致,需要執行以下四步,但不需要每個組織都執行:
· 打包鏈碼:一個或者每一個組織完成。
· 自己的節點安裝鏈碼。每個組織要執行,因為需要交易或者查詢賬本。
· 同意鏈碼的定義:需要滿足channel LifecycleEndorsment(默認是大多數)策略的足夠數量的組織來執行。
· 提交chaincode的定義:第一個收集到足夠數量的節點來執行。
下面來詳細的看上面4步:
鏈碼在安裝前需要打包為tar文件。我們可以使用peer命令,node sdk,或者第三方工具。
第三方的打包工具需要滿足以下要求:
· 鏈碼以tar.gz結尾;
· tar文件需要包含2個文件(不是目錄),元文件Chaincode-Package-Metadata.json和chaincode文件。
· Chaincode-Package-Metadata.json文件長成下面這樣。
· {"Path":"fabric-samples/chaincode/fabcar/go","Type":"golang","Label":"fabcarv1"}
一個demo如下。2個組織不需要使用相同的名字。
每個節點上都需要安裝。強烈建議每個組織只打包一次鏈碼,然后把該鏈碼安裝在該組織的所有節點上。如果一個channel想要保證所有的組織運行相同的鏈碼,那么打包命令應該由一個組織來進行。
安裝成功后會返回MYCC_1:hash.這樣的格式,我們需要進行保存,方便后面的使用,如果忘記了,可以進行查詢。
我的理解是,在上面,每個組織都給chaincode起了一個名字,這樣,在實際中是無法使用的,所以現在大家來投票來確定一個統一的名字,包含下面的參數:
· 名字
· 版本:chaincode打包的時候生成的。
· Sequence:用來追蹤鏈碼的升級過程。是自增的。
· 背書策略:哪些組織可以執行可以驗證交易。
· Collection Configuration:私有數據相關。
· Initialization:原來chaincode的默認的init函數不執行,現在可以了。
· ESCC/VSCC Plugins
一旦得到了絕大多數成員的同意,就可以提交鏈碼的定義了。
我們可以使用checkcommitreadiness命令來檢查是否已經有鏈碼的定義了,首先會發送給所有的peer節點,在發送給order節點。提交必須是組織的管理員來完成的。
Channel/Application/LifecycleEndorsement來管理認可的組織的數量,默認是大多數。LifecycleEndorsement和chaincode的背書策略是分離的,沒有任何關系的。
即使一個組織沒有安裝鏈碼,仍然可以響應鏈碼的定義。
當鏈碼的定義被確認后,將會在所有安裝鏈碼的節點上啟動鏈碼容器。如果我們在定義鏈碼的時候要求使用init函數,那么init函數將會被調用。
升級和安裝類似,我們既可以升級鏈碼的內容,還可以升級鏈碼的背書策略。
1. 打包鏈碼。只有在升級鏈碼內容的時候需要。
·
·
1. 安裝新鏈碼。同上。
·
·
1. 鏈碼定義投票。sequence將會自增1。
·
·
1. 提交定義。
·
·
將會啟動新的鏈碼容器。
下面是chaincode的比較完整的操作。來自。
## at first we package the chaincode
packageChaincode 1
## Install chaincode on peer0.org1 and peer0.org2
echo "Installing chaincode on peer0.org1..."
installChaincode 1
echo "Install chaincode on peer0.org2..."
installChaincode 2
## query whether the chaincode is installed
queryInstalled 1
## approve the definition for org1
approveForMyOrg 1
## check whether the chaincode definition is ready to be committed
## expect org1 to have approved and org2 not to
checkCommitReadiness 1 "\"Org1MSP\": true" "\"Org2MSP\": false"
checkCommitReadiness 2 "\"Org1MSP\": true" "\"Org2MSP\": false"
## now approve also for org2
approveForMyOrg 2
## check whether the chaincode definition is ready to be committed
## expect them both to have approved
checkCommitReadiness 1 "\"Org1MSP\": true" "\"Org2MSP\": true"
checkCommitReadiness 2 "\"Org1MSP\": true" "\"Org2MSP\": true"
## now that we know for sure both orgs have approved, commit the definition
commitChaincodeDefinition 1 2
## query on both orgs to see that the definition committed successfully
queryCommitted 1
queryCommitted 2
## Invoke the chaincode
chaincodeInvokeInit 1 2
sleep 10
## Invoke the chaincode
chaincodeInvoke 1 2
# Query chaincode on peer0.org1
echo "Querying chaincode on peer0.org1..."
chaincodeQuery 1
下面來看圖:
加入通道:如果一個channel已經有了定義好的chaincode,那么新加入的組織在安裝鏈碼后可以直接使用原來的名字。
如果背書策略是默認的大多數,那么背書策略會自動更新,把新的組織計算在內。
升級背書策略
我們不必重新打包或者安裝鏈碼即可升級背書策略。channel中的成員會重新生成一個chaincode定義。
新的背書策略在新的鏈碼定義通過后,即可生效,我們不必重啟容器即可更新背書策略。
無法安裝鏈碼即可同意鏈碼的定義:
不同意鏈碼定義的組織將不能使用鏈碼:
上圖中的組織三不可以使用鏈碼。
channel不認可鏈碼的定義:這里比較繞,說的是channel中的組織沒有對鏈碼的定義達成共識。
組織安裝了不同類型的鏈碼:這里的意思是說只要鏈碼產生相同的讀寫集,那么可以安裝不同語言寫的鏈碼,比如java和go。
一次打包,多次使用:
我們可以打包一次,給鏈碼創建不同的定義,從而運行多個智能合約實例(但是背書策略要有區別)。
做了個表格,把舊的聲明周期和新的進行了比較。
Fabric 2.0增強了private data,我們不需要創建私有數據集合即可使用私有數據。做了以下增強:
· 私有數據的共享和驗證。當私有數據向非原來的集合中的成員共享時,該成員可以通過GetPrivateDataHash() 函數來驗證hash是不是和鏈上保存的hash一致。
· 集合級別的背書策略。我們可以使用背書策略來定義私有數據集合。
· 每個組織都有暗含的私有數據集合。
在同一個channel中,A組織的數據不想給其他的組織看的數據。從v1.2開始,創造了private data collections,我們可以背書,提交和查詢私有數據,在不創建一個獨立channel的情況下。
private data collections由兩部分組成:
· 實際的私有數據。在不同的節點間通過gossip協議來發送。私有數據存儲在授權的peer節點上的sidedb數據庫中,可以通過Chaincode來訪問。order節點無法看到private data。注意,必須配置錨節點信息,設置COREPEERGOSSIP_EXTERNALENDPOINT變量。
· 私有數據的hash,會寫入到區塊鏈網絡中,其他人可以進行審計。
private-data.private-data
當集合中的成員需要把該私有數據向第三方共享時,第三方可以通過比較該數據的hash和鏈上保存的hash,看是否一致。
還有一些特殊情況,每個組織都可以創建一個私有數據集合,之后可以共享給其他成員。
我們把private data和channel進行一個比較。
· channel:所有的交易和賬本都是私密的。
· 私有數據集合:通道中組織的子集共享數據時。直接通過p2p來傳播每條具體的交易,而不是區塊,order節點無法看到真實的交易。
有下面5個角色:
Farmer出售商品,Distributor分銷商負責把商品運到海外,Shipper負責在兩個角色之間運貨,Wholesaler批發商從distributors批發商品,Retailer零售商從shippers和wholesaler購買商品。
場景是:
· Distributor想和Farmer,Shipper共享數據,但是不想讓Retailer和wholesaler看到數據;
· Distributor賣給Retailer和wholesaler的價格不同;
· wholesaler和Retailer,Shipper之間也需要共享數據;
為了滿足上面的場景,我們不需要建立這么多的channel,可以使用PDC。
· PDC1: Distributor, Farmer and Shipper
· PDC2: Distributor and Wholesaler
· PDC3: Wholesaler, Retailer and Shipper
上面場景下,peer節點的賬本如下,也稱為SideDB。
1. 客戶端發送提案給授權的背書節點,提案中加入transient 字段;
1. 私有數據存儲在transient data store(臨時的存儲在peer節點);
1. 背書節點發送提案響應到客戶端,響應的內容是private data的hash值;
1. 客戶端節點把hash值發送給order節點;
1. 在提交階段,授權的節點將會檢查策略,自己是否有權限訪問private data,如果有的話,將會檢查transient data store 字段,看看是否在背書階段拿到了private data。沒有的話,會從其他節點去拉取。在驗證和提交階段,private data將會被存儲到數據庫中,同時把transient data store 刪除。
我們可能會有把私有數據向其他組織或者其他集合共享的需求,接受方需要驗證hash:
· 只要滿足背書策略(fabric 2.0中,我們可以定義鏈碼級別,鍵和集合級別的背書策略),不需要是集合中的成員,即可訪問私有數據的鍵
· 我們可以使用GetPrivateDataHash()來驗證hash
在實際中,我們可能會創建大量的私有數據集合,這個不利于我們的維護。更好的情況是每個組織都是一個集合,然后共享就可以了。更好的是我們不必為此進行定義,因為在2.0中默認設置了。
下面這個是每個組織一個集合的模型:
· 使用相應的公鑰來追蹤公共狀態的變化:
· 鏈碼訪問控制:我們可以在鏈碼實現訪問控制,指定哪些客戶端可以查看私有數據。
· 共享私有數據:通過hash來確認;
· 和其他集合共享私有數據:
· 可以把私有數據轉移到其他的集合。這個時候會刪除原來的集合。
· 在交易達成之前,可以使用私有數據進行預請求;
· 保護交易者的隱私
把私有數據模型和鏈碼結合可以發揮出很大的作用,具體如下所示:
· 可以通過處于公共鏈碼狀態的UUID密鑰來跟蹤資產。僅記錄資產的所有權,關于資產的其他信息一無所知。
· 鏈碼將要求任何轉移請求都必須來自擁有權限的客戶,并且密鑰受基于狀態的認可約束,要求所有者組織和監管機構的同級必須認可任何轉移請求。
· 資產的所有者可以看到該資產的所有交易詳情,其他的組織只可以看到hash。
· 監管者可以保留私有數據。
具體的交易流如下所示:
1. 資產所有者和買家在線下達成交易價格;
1. 賣家需要證明資產的所有權。既可以線下提供私有數據的細節,也可以提供線上的憑證;
1. 賣家線上驗證hash;
1. 買家調用鏈碼記錄出價的細節到自己的private data中。監管者可能也需要記錄。
1. 賣家調用鏈碼轉移資產,需要資產和出價細節的隱私數據,需要賣家,買家,監管者參與,除此之外,還需要滿足背書策略;
1. 鏈碼會對上述信息進行驗證;
1. 賣家把公開的數據和私有數據的hash提交給order節點,打包成區塊;
1. 其他節點將會驗證是否滿足背書策略,私有數據的狀態是否被其他的交易更改;
1. 所有節點會進行記賬;
1. 至此交易完成,其他的節點可以查詢這筆資產的公開的信息,但無法獲取私有信息。
對于非常敏感的數據,比如政府要求的。我們可以從peer節點上徹底的刪除,只留下hash來證明該數據確實存在過。數據刪除后,無法從鏈碼進行查詢,其他的peer節點也不可查詢。
從fabric 2.0開始,在chaincode定義階段來進行定義:
· name:集合的名字;
· policy:private data的policy必須比鏈碼的背書策略更加廣泛,因為背書節點必須有private data才可以進行背書。比如一個channel里面包含了10個組織,5個組織需要有private data的權限,背書策略可以指定為5個中的三個;
· requiredPeerCount:在背書節點把提案響應返回到客戶端之前,最少把private data傳遞到其他節點的數量。不建議寫0,因為這樣的話,將會導致private data的丟失。
· maxPeerCount:如果設置為0,在背書階段,private data將不會傳播,在commit階段,數據才會傳播;
· blockToLive:私有數據的存活時間,到期自動刪除。設為0表示,永不刪除;
· memberOnlyRead:表示只有授權的人可以讀。
· memberOnlyWrite:
· endorsementPolicy:
我們可以使用自己喜歡的方式來構建和啟動鏈碼,不必使用docker。
· 解除了對docker daemon的依賴。之前的fabric要求peer節點可以訪問到docker daemon,而這在生產環境不一定是現實的。
· 容器的替代品:我們不一定在使用容器了。
· 鏈碼作為外部的服務。之前鏈碼是被peer啟動的,現在鏈碼可以作為單獨的外部服務。
在Hyperledger Fabric 2.0之前,用于構建和啟動鏈碼的過程是peer節點實現的一部分,無法輕松自定義。必須使用特定的語言。這種方法限制了鏈碼的語言,必須依賴容器,chaincode無法作為單獨運行的服務。
從2.0開始,我們在peer的core.yaml中,加入了一個externalBuilder的配置來自定義自己的服務。
fabric的構建器使用了。
外部構建和運行期由下面四個部分組成:
· bin/detect: 判斷是否由我們自定義的模型來運行。
· bin/build: 把打包后的鏈碼變為可執行版本。用來構建,編譯鏈碼。
· bin/release (optional): 提供chaincode的元數據。
· bin/run (optional): 運行鏈碼。
下面分別是四個腳本的內容:
#!/bin/bash
CHAINCODE_SOURCE_DIR="$1"
CHAINCODE_METADATA_DIR="$2"
BUILD_OUTPUT_DIR="$3"
# extract package path from metadata.json
GO_PACKAGE_PATH="$(jq -r .path "$CHAINCODE_METADATA_DIR/metadata.json")"
if [ -f "$CHAINCODE_SOURCE_DIR/src/go.mod" ]; then
cd "$CHAINCODE_SOURCE_DIR/src"
go build -v -mod=readonly -o "$BUILD_OUTPUT_DIR/chaincode" "$GO_PACKAGE_PATH"
else
GO111MODULE=off go build -v -o "$BUILD_OUTPUT_DIR/chaincode" "$GO_PACKAGE_PATH"
fi
# save statedb index metadata to provide at release
if [ -d "$CHAINCODE_SOURCE_DIR/META-INF" ]; then
cp -a "$CHAINCODE_SOURCE_DIR/META-INF" "$BUILD_OUTPUT_DIR/"
fi
#!/bin/bash
BUILD_OUTPUT_DIR="$1"
RELEASE_OUTPUT_DIR="$2"
# copy indexes from META-INF/* to the output directory
if [ -d "$BUILD_OUTPUT_DIR/META-INF" ] ; then
cp -a "$BUILD_OUTPUT_DIR/META-INF/"* "$RELEASE_OUTPUT_DIR/"
fi
上面說了,這個是在core.yaml中配置的,一個demo如下所示:
chaincode: externalBuilders: - name: my-golang-builder path: /builders/golang environmentWhitelist: - GOPROXY - GONOPROXY - GOSUMDB - GONOSUMDB - name: noop-builder path: /builders/binary
· 使用外部CouchDB狀態數據庫時,背書和驗證階段的讀取延遲歷來是性能瓶頸。
· fabric 2.0中,每個peer都進行了緩存,在core.yaml中的cacheSize來進行配置。
從 v2.0 開始,Hyperledger Fabric Docker 鏡像將使用 Alpine Linux 作為基礎鏡像,這是一個面向安全的輕量級 Linux 發行版。這意味著 Docker 鏡像現在要小得多,提供更快的下載和啟動時間,以及占用主機系統上更少的磁盤空間。Alpine Linux 的設計從一開始就考慮到了安全性,Alpine 發行版的最小化特性大大降低了安全漏洞的風險。
FAB-11237:去中心化的智能合約管理
新的應用程序模式:
· FAB-10889: Implicit org-specific collections
· FAB-15066: Endorsement policies for collections
· FAB-13581: memberOnlyWrite collection configuration option
· FAB-13527: GetPrivateDataHash chaincode API
· FAB-12043: Option to include private data in block events
FAB-103: State database cache for CouchDB
· FAB-5177: The ccenv build image no longer includes the shim
· FAB-15366: Logger removed from chaincode shim
· FAB-16213: The go chaincode entities extension has been removed
· FAB-12075: Client Identity (CID) library has moved
· FAB-14720: Support for CAR chaincode package format removed
· FAB-15285: Support for invoking system chaincodes from user chaincodes has been removed.
· FAB-15390: Support for peer's Admin service has been removed.
· FAB-16303: GetHistoryForKey returns results from newest to oldest
· FAB-16722: The 'provisional' genesis method of generating the system channel for orderers has been removed.
· FAB-16477 and FAB-17116: New configuration for orderer genesismethod and genesisfile
· FAB-15343: System Chaincode Plugins have been removed.
· FAB-11096: Docker images with Alpine Linux
· FAB-11096: Bash not available in Docker images with Alpine Linux
· 使用sh或者ash
· FAB-15499: Ledger data format upgrade
· FAB-16866: Chaincode built upon installation on peer
· FAB-15837: Orderer FileLedger location moved if specified with relative path
· FAB-14271: Policies must be specified in configtx.yaml
· FAB-17000: Warn when certificates are about to expire
· FAB-16987: Go version has been updated to 1.13.4.
· FAB-15754: The 'Solo' consensus type is deprecated.
· FAB-16408: The 'Kafka' consensus type is deprecated.
· FAB-7559: Support for specifying orderer endpoints at the global level in channel configuration is deprecated.
· FAB-17428: Support for configtxgen flag --outputAnchorPeersUpdate is deprecated.