成人免费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

2015-01-07 15:49:21

大數據SSD

2017-08-18 14:47:31

DDD微服務架構

2017-06-28 11:34:55

銳捷 醫療 物聯網

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技術棧公眾號

主站蜘蛛池模板: 91九色网站 | 最新午夜综合福利视频 | 国产成人精品999在线观看 | 欧美日韩国产免费 | h肉视频| 久久天天躁狠狠躁夜夜躁2014 | 国产精品99一区二区 | 狠狠亚洲 | 亚洲欧美一区二区三区国产精品 | 精精国产xxxx视频在线 | 一级毛片免费完整视频 | 日韩不卡一区二区 | 国产在线资源 | 中文福利视频 | 亚洲国产一区二区三区, | 黄色大片毛片 | 免费成人高清在线视频 | 欧美成人一区二区三区片免费 | 伊人网伊人网 | 成人av一区| 中文字幕一区二区三区在线视频 | 午夜色婷婷 | 欧美日韩一区精品 | 99久久国产综合精品麻豆 | 亚洲综合色婷婷 | 久久99精品久久久久久噜噜 | 免费日韩av网站 | 日韩中文字幕av | 欧美日韩国产高清 | 国产福利视频导航 | 国产精品一区二区在线免费观看 | 91麻豆精品国产91久久久更新资源速度超快 | 亚洲国产高清高潮精品美女 | 99亚洲视频| 国产精品久久久久久久久久久久 | 欧美一区 | 久久日韩精品一区二区三区 | 国产精品久久久久久影院8一贰佰 | 亚洲+变态+欧美+另类+精品 | 亚洲一区不卡 | 99精品在线观看 |