日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
當(dāng)git遇上ssh——CVE-2017-1000117漏洞淺析

Git是一個(gè)開源的分布式版本控制系統(tǒng),主要用于項(xiàng)目管理。

成都創(chuàng)新互聯(lián)專業(yè)提供成都主機(jī)托管四川主機(jī)托管成都服務(wù)器托管四川服務(wù)器托管,支持按月付款!我們的承諾:貴族品質(zhì)、平民價(jià)格,機(jī)房位于中國(guó)電信/網(wǎng)通/移動(dòng)機(jī)房,成都服務(wù)器托管服務(wù)有保障!

而SSH是一種應(yīng)用層的安全通信協(xié)議,最常用的就是為通信雙方在在不安全網(wǎng)絡(luò)上提供安全的遠(yuǎn)程登錄。

當(dāng)他們二者相遇會(huì)發(fā)生什么有趣的事呢?這里以CVE-2017-1000117漏洞為例,簡(jiǎn)要剖析該漏洞的成因及防護(hù)方法。

漏洞相關(guān)信息:

版本控制軟件爆出遠(yuǎn)程命令執(zhí)行漏洞 涉及Git、SVN、Mercurial、CVS版本控制

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

背景知識(shí)

ssh客戶端登錄時(shí),有一個(gè)ProxyCommand選項(xiàng),該選項(xiàng)的指定鏈接服務(wù)器時(shí)執(zhí)行的命令。

 
 
 
 
  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. 

該選項(xiàng)常用的場(chǎng)景是通過代理服務(wù)器與目標(biāo)機(jī)器相連,因此被稱作ProxyCommand,如下圖。

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

因此在這種情況下,ssh客戶端可以采用ProxyCommand選項(xiàng),通過下面命令最終和目標(biāo)機(jī)器建立連接。

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

加上ProxyCommand選項(xiàng)后。ssh客戶端會(huì)先用當(dāng)前用戶的shell執(zhí)行ProxyCommand中的內(nèi)容。

例如下面的命令,在Linux桌面環(huán)境中執(zhí)行,就會(huì)彈出gedit文本編輯器。

 
 
 
 
  1. ssh -oProxyCommand=gedit user@Target 

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

好了介紹完了ProxyCommand,可以理解為這個(gè)選項(xiàng)如處理不當(dāng),是可以進(jìn)行命令注入的!

CVE-2017-1000117漏洞

CVE-2017-1000117這個(gè)漏洞就是沒有正確處理ssh鏈接的請(qǐng)求,導(dǎo)致受害人通過Git版本控制系統(tǒng),訪問惡意鏈接時(shí),存在安全隱患,一旦黑客攻擊成功,可在受害人機(jī)器上執(zhí)行任意命令。

git clone是Git版本控制系統(tǒng)中常用的將遠(yuǎn)程倉(cāng)庫(kù)克隆到本地的命令。當(dāng)使用git clone訪問下面的惡意ssh鏈接時(shí),會(huì)在本地執(zhí)行命令,彈出gedit。

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

下面我們來詳細(xì)看一看其中的過程,當(dāng)git遇上ssh后,最終是如何觸發(fā)這個(gè)漏洞執(zhí)行的。

git客戶端在執(zhí)行上面的命令后,通過一系列的參數(shù)解析后,進(jìn)入git_connect函數(shù),向git的服務(wù)端建立連接。

 
 
 
 
  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 = 0, tortoiseplink = 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函數(shù)的第二個(gè)參數(shù)url,即為傳入的ssh鏈接,在此例中為 “ssh://-oProxyCommand=gedit /tmp/xxx”。

在git_connect函數(shù)中通過parse_connect_url函數(shù)將待連接的url解析出來,返回url的主機(jī)名、相對(duì)路徑及url采用的協(xié)議。

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) 

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

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

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

在start_command函數(shù)中,最終調(diào)用exec系列函數(shù)執(zhí)行ssh,由于錯(cuò)誤的把 -oProxyCommand=gedit 作為遠(yuǎn)程待連接的host,最終引發(fā)了命令執(zhí)行。

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

修復(fù)防護(hù)方法

看完上面漏洞發(fā)生的成因,其實(shí)可以發(fā)現(xiàn)這個(gè)過程就是git處理ssh這類智能協(xié)議的傳輸過程:ssh遠(yuǎn)程登錄git服務(wù)器后,通過執(zhí)行g(shù)it-upload-pack處理下載的數(shù)據(jù),這種處理方式較http啞協(xié)議傳輸更高效。

但是在這過程中,對(duì)一些惡意的ssh鏈接,沒有正確識(shí)別,在解析時(shí)誤將 -oProxyCommand 這類參數(shù)當(dāng)做了遠(yuǎn)程主機(jī)名host,從而產(chǎn)生了漏洞。

在新版本中,我們看到增加了對(duì)host和path的識(shí)別過濾。

對(duì)包含疑似命令的host和path及時(shí)進(jìn)行了阻止,阻斷了漏洞的發(fā)生。

建議用戶及時(shí)排查,更新系統(tǒng)存在漏洞的Git版本,在日常通過Git進(jìn)行項(xiàng)目管理時(shí),仔細(xì)檢查項(xiàng)目中是否存在一些惡意ssh鏈接來預(yù)防安全問題。

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

【本文是專欄作者“綠盟科技博客”的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)通過聯(lián)系原作者獲取授權(quán)】


標(biāo)題名稱:當(dāng)git遇上ssh——CVE-2017-1000117漏洞淺析
文章來源:http://www.5511xx.com/article/djgjpsh.html