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

當git遇上ssh——CVE-2017-1000117漏洞淺析

安全 應用安全
Git是一個開源的分布式版本控制系統,主要用于項目管理。而SSH是一種應用層的安全通信協議,最常用的就是為通信雙方在在不安全網絡上提供安全的遠程登錄。當他們二者相遇會發生什么有趣的事呢?這里以CVE-2017-1000117漏洞為例,簡要剖析該漏洞的成因及防護方法。

Git是一個開源的分布式版本控制系統,主要用于項目管理。

而SSH是一種應用層的安全通信協議,最常用的就是為通信雙方在在不安全網絡上提供安全的遠程登錄。

當他們二者相遇會發生什么有趣的事呢?這里以CVE-2017-1000117漏洞為例,簡要剖析該漏洞的成因及防護方法。

Git

漏洞相關信息:

版本控制軟件爆出遠程命令執行漏洞 涉及Git、SVN、Mercurial、CVS版本控制

簡述:幾個流行的版本控制系統受到可能嚴重的遠程命令執行漏洞的影響。受影響產品的開發人員本周發布了更新補丁來修補安全漏洞。該缺陷影響版本控制軟件, 如 Git (CVE-2017-1000117)、Apache Subversion (CVE-2017-9800)、Mercurial (CVE-2017-1000116) 和 CVS。由于CVS 系統上次更新已經是9年前的事情了, 因此沒有為它分配 CVE 標識符。

背景知識

ssh客戶端登錄時,有一個ProxyCommand選項,該選項的指定鏈接服務器時執行的命令。

  1. ProxyCommand 
  2.  
  3.    Specifies the command to use to connect to the server.  The 
  4.  
  5.    command string extends to the end of the line, and is executed 
  6.  
  7.    with the user’s shell.  In the command string, any occurrence 
  8.  
  9.    of ‘%h’ will be substituted by the host name to connect,‘%p’ 
  10.  
  11.    by the port, and ‘%r’ by the remote user name. 

該選項常用的場景是通過代理服務器與目標機器相連,因此被稱作ProxyCommand,如下圖。

本地的機器(Local)無法直接與目標機器(Target)相連,必須通過一個代理機器(Proxy)才能和目標機器建立連接。此場景多見于企業或有較強訪問控制的需求的地方。

因此在這種情況下,ssh客戶端可以采用ProxyCommand選項,通過下面命令最終和目標機器建立連接。

  1. ssh -o ProxyCommand=’ssh user@proxy nc %h 22′ user@Target 

加上ProxyCommand選項后。ssh客戶端會先用當前用戶的shell執行ProxyCommand中的內容。

例如下面的命令,在Linux桌面環境中執行,就會彈出gedit文本編輯器。

  1. ssh -oProxyCommand=gedit user@Target 

即便最后的user@hostname不合法,也不會影響ProxyCommand中先執行的命令,照樣可以彈出gedit。

好了介紹完了ProxyCommand,可以理解為這個選項如處理不當,是可以進行命令注入的!

CVE-2017-1000117漏洞

CVE-2017-1000117這個漏洞就是沒有正確處理ssh鏈接的請求,導致受害人通過Git版本控制系統,訪問惡意鏈接時,存在安全隱患,一旦黑客攻擊成功,可在受害人機器上執行任意命令。

git clone是Git版本控制系統中常用的將遠程倉庫克隆到本地的命令。當使用git clone訪問下面的惡意ssh鏈接時,會在本地執行命令,彈出gedit。

  1. git clone ssh://-oProxyCommand=”gedit /tmp/xxx” 

下面我們來詳細看一看其中的過程,當git遇上ssh后,最終是如何觸發這個漏洞執行的。

 

git客戶端在執行上面的命令后,通過一系列的參數解析后,進入git_connect函數,向git的服務端建立連接。

  1. struct child_process *git_connect(int fd[2], const char *url, 
  2. const char *prog, int flags) 
  3.  
  4.  
  5. char *hostandport, *path; 
  6.  
  7. struct child_process *conn = &no_fork; 
  8.  
  9. enum protocol protocol; 
  10.  
  11. struct strbuf cmd = STRBUF_INIT
  12.  
  13.   
  14.  
  15. /* Without this we cannot rely on waitpid() to tell 
  16.  
  17. * what happened to our children. 
  18.  
  19. */ 
  20.  
  21. signal(SIGCHLD, SIG_DFL); 
  22.  
  23.   
  24.  
  25. protocol = parse_connect_url(url, &hostandport, &path); 
  26.  
  27. if ((flags & CONNECT_DIAG_URL) && (protocol != PROTO_SSH)) { 
  28.  
  29. printf(“Diag: url=%s\n”, url ? url : “NULL”); 
  30.  
  31. printf(“Diag: protocol=%s\n”, prot_name(protocol)); 
  32.  
  33. printf(“Diag: hostandport=%s\n”, hostandport ? hostandport : “NULL”); 
  34.  
  35. printf(“Diag: path=%s\n”, path ? path : “NULL”); 
  36.  
  37. conn = NULL
  38.  
  39. } else if (protocol == PROTO_GIT) { 
  40.  
  41. ….. 
  42.  
  43. } else { 
  44.  
  45. conn = xmalloc(sizeof(*conn)); 
  46.  
  47. child_process_init(conn); 
  48.  
  49.   
  50.  
  51. strbuf_addstr(&cmd, prog); 
  52.  
  53. strbuf_addch(&cmd, ‘ ‘); 
  54.  
  55. sq_quote_buf(&cmd, path); 
  56.  
  57.   
  58.  
  59. /* remove repo-local variables from the environment */ 
  60.  
  61. conn->env = local_repo_env
  62.  
  63. conn->use_shell = 1
  64.  
  65. conn->in = conn->out = -1; 
  66.  
  67. if (protocol == PROTO_SSH) { 
  68.  
  69. const char *ssh; 
  70.  
  71. int putty = 0tortoiseplink = 0
  72.  
  73. char *ssh_host = hostandport
  74.  
  75. const char *port = NULL
  76.  
  77. transport_check_allowed(“ssh”); 
  78.  
  79. get_host_and_port(&ssh_host, &port); 
  80.  
  81.   
  82.  
  83. if (!port) 
  84.  
  85. port = get_port(ssh_host); 
  86.  
  87.   
  88.  
  89. ssh = getenv(“GIT_SSH_COMMAND”); 
  90.  
  91. if (!ssh) { 
  92.  
  93. const char *base; 
  94.  
  95. char *ssh_dup; 
  96.  
  97. /* 
  98.  
  99. * GIT_SSH is the no-shell version of 
  100.  
  101. * GIT_SSH_COMMAND (and must remain so for 
  102.  
  103. * historical compatibility). 
  104.  
  105. */ 
  106.  
  107. conn->use_shell = 0
  108.  
  109.   
  110.  
  111. ssh = getenv(“GIT_SSH”); 
  112.  
  113. if (!ssh) 
  114.  
  115. ssh = “ssh”; 
  116.  
  117.   
  118.  
  119. ssh_dup = xstrdup(ssh); 
  120.  
  121. base = basename(ssh_dup); 
  122.  
  123.   
  124.  
  125. free(ssh_dup); 
  126.  
  127.  
  128.   
  129.  
  130. argv_array_push(&conn->args, ssh); 
  131.  
  132.   
  133.  
  134. if (port) { 
  135.  
  136. /* P is for PuTTY, p is for OpenSSH */ 
  137.  
  138. argv_array_push(&conn->args, putty ? “-P” : “-p”); 
  139.  
  140. argv_array_push(&conn->args, port); 
  141.  
  142.  
  143. argv_array_push(&conn->args, ssh_host); 
  144.  
  145. } else { 
  146.  
  147. transport_check_allowed(“file”); 
  148.  
  149.  
  150. argv_array_push(&conn->args, cmd.buf); 
  151.  
  152.   
  153.  
  154. if (start_command(conn)) 
  155.  
  156. die(“unable to fork”); 
  157.  
  158.   
  159.  
  160. ….. 
  161.  
  162.  
  163.   
  164.  

git_connect函數的第二個參數url,即為傳入的ssh鏈接,在此例中為 “ssh://-oProxyCommand=gedit /tmp/xxx”。

在git_connect函數中通過parse_connect_url函數將待連接的url解析出來,返回url的主機名、相對路徑及url采用的協議。

 

https://github.com/git/git/blob/master/connect.c#L620

  1. /* 
  2.  
  3. * Extract protocol and relevant parts from the specified connection URL. 
  4.  
  5. * The caller must free() the returned strings. 
  6.  
  7. */ 
  8.  
  9. static enum protocol parse_connect_url(const char *url_orig, char **ret_host,  char **ret_path) 

對于正常的ssh鏈接,如 ssh://user@host.xzy/path/to/repo.git/,經parse_connect_url解析后,其返回的ret_host和ret_path的值應該為 user@host.xzy 和 /path/to/repo.git/ 。

但由于沒有對ssh做正確過濾及識別,對于惡意的ssh鏈接,返回的ret_host和ret_path的值則是 -oProxyCommand=gedit 和 /tmp/xxx ,誤將 -oProxyCommand=gedit 作為了主機名ret_host。

在后續處理中,git_connect得到本地ssh的路徑,將上面獲取的ssh host和path填充到struct child_process *conn中,再通過start_command調用本地ssh執行。

在start_command函數中,最終調用exec系列函數執行ssh,由于錯誤的把 -oProxyCommand=gedit 作為遠程待連接的host,最終引發了命令執行。

但像上面ssh://-oProxyCommand=”gedit /tmp/xxx”的鏈接比較暴露,直接在鏈接中就出現命令。比較隱蔽的方法是,在正常倉庫的目錄下建立一個子模塊submodule,而將惡意的ssh鏈接藏在.gitmodule文件中。

修復防護方法

看完上面漏洞發生的成因,其實可以發現這個過程就是git處理ssh這類智能協議的傳輸過程:ssh遠程登錄git服務器后,通過執行git-upload-pack處理下載的數據,這種處理方式較http啞協議傳輸更高效。

但是在這過程中,對一些惡意的ssh鏈接,沒有正確識別,在解析時誤將 -oProxyCommand 這類參數當做了遠程主機名host,從而產生了漏洞。

在新版本中,我們看到增加了對host和path的識別過濾。

對包含疑似命令的host和path及時進行了阻止,阻斷了漏洞的發生。

 

建議用戶及時排查,更新系統存在漏洞的Git版本,在日常通過Git進行項目管理時,仔細檢查項目中是否存在一些惡意ssh鏈接來預防安全問題。

原文鏈接:http://blog.nsfocus.net/git-ssh-cve-2017-1000117/

【本文是51CTO專欄作者“綠盟科技博客”的原創稿件,轉載請通過51CTO聯系原作者獲取授權】

戳這里,看該作者更多好文

責任編輯:趙寧寧 來源: 51CTO專欄
相關推薦

2013-05-22 09:33:09

交互設計設計時間

2016-10-21 15:57:39

Rust編輯語言Fedora

2022-02-24 16:15:16

OpenHarmon鴻蒙OpenEuler

2017-05-25 22:20:05

2017-06-12 15:50:16

2017-06-28 11:34:55

銳捷 醫療 物聯網

2015-01-07 15:49:21

大數據SSD

2017-08-18 14:47:31

DDD微服務架構

2017-05-08 07:07:50

2017-05-27 10:22:37

2017-05-16 14:38:25

2009-03-21 16:43:29

SOA虛擬化IT

2011-03-16 14:51:35

2013-08-22 11:08:27

大數據商業只能Hadoop

2017-09-11 13:55:30

前端JavaScript物聯網

2013-11-08 09:15:32

大數據平板電腦

2022-06-27 13:56:10

設計模式緩存分布式系統

2016-10-21 09:45:20

RustFedoraJava

2017-07-12 11:15:25

2020-12-22 09:31:43

區塊鏈安全食品
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩中文字幕在线视频 | 欧美精品一区二区三区一线天视频 | 精品国产乱码久久久久久1区2区 | 亚洲在线中文字幕 | 日本高清不卡视频 | 国产伦精品一区二区三区精品视频 | 亚洲成人高清 | 中文字幕91av | 亚洲精品成人av | 精一区二区 | 夜夜草 | 国产精品视频在线播放 | 精精国产xxxx视频在线 | 日韩中文一区 | 午夜在线观看免费 | 国产91在线播放精品91 | 国产亚洲黄色片 | 麻豆视频在线免费看 | 台湾佬成人网 | 午夜精品久久久久久久久久久久 | 亚洲一区精品在线 | 中文字幕不卡在线88 | 免费观看成人鲁鲁鲁鲁鲁视频 | 色婷婷综合在线观看 | 美国一级片在线观看 | 久久久91| 日本福利在线 | 一道本视频 | 国产片淫级awww | 日韩亚洲一区二区 | 免费看欧美一级片 | 成人国产精品 | 精品国产乱码一区二区三 | 青娱乐一区二区 | 亚洲欧美综合精品久久成人 | 亚洲有码转帖 | 99国产精品久久久 | 一区二区免费高清视频 | 中文字幕免费在线 | 精品av | 亚洲高清在线 |