|
網(wǎng)絡(luò)技術(shù)是從1990年代中期發(fā)展起來(lái)的新技術(shù),它把互聯(lián)網(wǎng)上分散的資源融為有機(jī)整體,實(shí)現(xiàn)資源的全面共享和有機(jī)協(xié)作,使人們能夠透明地使用資源的整體能力并按需獲取信息。資源包括高性能計(jì)算機(jī)、存儲(chǔ)資源、數(shù)據(jù)資源、信息資源、知識(shí)資源、專(zhuān)家資源、大型數(shù)據(jù)庫(kù)、網(wǎng)絡(luò)、傳感器等。 當(dāng)前的互聯(lián)網(wǎng)只限于信息共享,網(wǎng)絡(luò)則被認(rèn)為是互聯(lián)網(wǎng)發(fā)展的第三階段。 一、入侵 隨著Internet上的Linux主機(jī)的增加,越來(lái)越多的安全漏洞在當(dāng)前的GNU/Linux系統(tǒng)上發(fā)現(xiàn)。你也許在Internet上聽(tīng)說(shuō)過(guò) 在Linux下發(fā)現(xiàn)bug,它會(huì)導(dǎo)致系統(tǒng)很容易的被黑客攻擊。 因?yàn)長(zhǎng)inux是一個(gè)開(kāi)放代碼的系統(tǒng),漏洞很容易發(fā)現(xiàn) ,并且也會(huì)很快的有補(bǔ)丁出來(lái)。但是當(dāng)漏洞沒(méi)有公布的時(shí)候,并且管理員很懶,沒(méi)有去打補(bǔ)丁。黑客就會(huì)很容易的攻擊這個(gè)系統(tǒng),取得root權(quán)限,在現(xiàn)有的GNU/Linux下,他就可以做任何他想做的事情,F(xiàn)在你可以問(wèn),我們現(xiàn)在到底可以做些什么呢? 1.1 現(xiàn)在的GNU/Linux錯(cuò)誤在哪里? 超級(jí)用戶(hù)會(huì)濫用職權(quán),他能夠做所有他要做的事情。作為root。他會(huì)改變所有的東西。 許多系統(tǒng)文件很容易被更改。這些文件可能是很重要的文件,如/bin/login,如果一個(gè)黑客進(jìn)入,他可以上傳一個(gè)login程序來(lái)覆蓋/bin/login,這樣他就可以不用登陸名和密碼來(lái)登陸系統(tǒng)。但是這些文件不需要經(jīng)常改動(dòng),除非你要升級(jí)系統(tǒng)。 模塊modules很容易用來(lái)中斷內(nèi)核。模塊是為了讓Linux內(nèi)核更模塊話(huà)和更高效而設(shè)計(jì)的。但是當(dāng)模塊加入到內(nèi)核,它就會(huì)成為內(nèi)核的一部分并且能做原始內(nèi)核能做的工作。因此,一些不友好的代碼可以寫(xiě)成模塊來(lái)加入到內(nèi)核里,這些代碼就會(huì)重定向系統(tǒng)調(diào)用并且作為一個(gè)病毒來(lái)運(yùn)行。 進(jìn)程是不受保護(hù)的,一些進(jìn)程,如后臺(tái)的web服務(wù)器,一直都認(rèn)為是沒(méi)有嚴(yán)格保護(hù)的程序。因此,他們就會(huì)很容易被黑客攻擊。 1.2 LIDS的設(shè)想是什么。 保護(hù)重要文件。因?yàn)槲募苋菀妆籸oot更改,為什么不嚴(yán)格文件操作呢?因此,LIDS改變了文件系統(tǒng)在內(nèi)核里的安全系統(tǒng)調(diào)用。如果某個(gè)時(shí)候一些人訪(fǎng)問(wèn)一個(gè)文件,他就會(huì)進(jìn)入系統(tǒng)調(diào)用然后我們就可以檢查文件名并且看她們是否被保護(hù)。如果它已經(jīng)被保護(hù),我們就可以拒絕這個(gè)訪(fǎng)問(wèn)者的要求。 保護(hù)重要的進(jìn)程。這個(gè)和上面的保護(hù)進(jìn)程的想法不是一樣的。當(dāng)一個(gè)系統(tǒng)里運(yùn)行一個(gè)進(jìn)程,它會(huì)在/proc 文件系統(tǒng)里有一個(gè)用pid作為路徑名的入口。所以,如果你用“ps –axf”你就可以顯示出當(dāng)前運(yùn)行的進(jìn)程。你可以問(wèn)如果保護(hù)這些進(jìn)程。如果你要?dú)⑺酪粋(gè)進(jìn)程的話(huà),首先,你鍵入“ps”來(lái)得到進(jìn)程的PID,然后,你鍵入“kill 〈pid〉”來(lái)殺死它。但是,如果我不讓你看到進(jìn)程,你怎么來(lái)殺死這個(gè)進(jìn)程呢?因此,LIDS是用隱藏進(jìn)程來(lái)保護(hù)它的。 另外一個(gè)重要的方法就是不讓任何人可以殺死進(jìn)程,包括root用戶(hù)。LIDS能夠保護(hù)父進(jìn)程是init(pid=1)的所有進(jìn)程 。 封裝內(nèi)核。有時(shí)候我們需要要把一些必要的模塊加入到內(nèi)核里來(lái)使用,另外,我們也要拒絕任何人包括root用戶(hù)向內(nèi)核插入模塊。那么如何來(lái)平衡這個(gè)矛盾的問(wèn)題呢?我們可以只允許在系統(tǒng)啟動(dòng)的時(shí)候插入模塊,然后我們封裝模塊,在封裝后,內(nèi)核不允許任何人插入模塊到內(nèi)核里。通過(guò)這種封裝功能,我們能用它來(lái)保護(hù)重要的文件,進(jìn)程,我們可以在系統(tǒng)啟動(dòng)的時(shí)候只允許必要的進(jìn)程,只改變必要的文件。在封裝內(nèi)核后,我們就不能在對(duì)文件有任何的修改。 [page_break]二、保護(hù)文件系統(tǒng) 2.1 保護(hù)文件系統(tǒng)是LIDS的重要功能之一。這個(gè)功能是在內(nèi)核的VFS(虛擬文件系統(tǒng))層實(shí)現(xiàn)的,我們可以保護(hù)任何種類(lèi)的文件系統(tǒng),如EXT2,F(xiàn)AT。 在LIDS,保護(hù)的文件按種類(lèi)分為以下幾種: 只讀的文件或目錄。只讀文件意味著它們不被允許改寫(xiě),如,在目錄/usr/bin,/sbin。這些類(lèi)型的文件大多數(shù)都是二進(jìn)制系統(tǒng)程序或是系統(tǒng)配置文件,除了在升級(jí)系統(tǒng)的時(shí)候,我們不需要改變它們。 只可增加文件或目錄。這些文件是那些只可以增加大小的文件。大多數(shù)是系統(tǒng)的日值文件,如在/var/log里的只可增加文件。 額外的文件或目錄,這些文件沒(méi)有被保護(hù)。一般來(lái)說(shuō),你想要保護(hù)目錄下的所有文件,但是,還需要有一些特殊的文件不要被保護(hù)。所以我們可以定義這些文件作為額外的其他的只讀文件。 保護(hù)掛載或卸載文件系統(tǒng)。當(dāng)你在啟動(dòng)的時(shí)候掛載文件系統(tǒng)的時(shí)候,你可以禁止所有人,甚至是root,去卸載文件系統(tǒng)。你也可以禁止任何人在當(dāng)前文件系統(tǒng)下掛載文件系統(tǒng)來(lái)覆蓋它。 2.2 LIDS如何在內(nèi)核保護(hù)文件 在這部分,我們會(huì)看到一些內(nèi)核的代碼來(lái)理解LIDS是如何保護(hù)文件的。 Linux文件系統(tǒng)數(shù)據(jù)結(jié)構(gòu)程序 首先,我們必須了解Linux的虛擬文件系統(tǒng)。 在Linux里的每一個(gè)文件,不管是什么樣子的,都有一個(gè)結(jié)點(diǎn)inode數(shù),文件系統(tǒng)提供了以下數(shù)據(jù)結(jié)構(gòu)。 在/usr/src/Linux/include/Linux/fs.h 注意:用來(lái)鑒定一個(gè)結(jié)點(diǎn)inode。這個(gè)意思是你可以用一對(duì)來(lái)得到一個(gè)系統(tǒng)里獨(dú)一無(wú)二的inode。 struct dentry { int d_count; unsigned int d_flags; struct inode * d_inode; /* Where the name belongs to - NULL is negative */ struct dentry * d_parent; /* parent directory */ struct dentry * d_mounts; /* mount information */ struct dentry * d_covers; struct list_head d_hash; /* lookup hash list */ struct list_head d_lru; /* d_count = 0 LRU list */ struct list_head d_child; /* child of parent list */ struct list_head d_subdirs; /* our ...... } dentry是一個(gè)目錄文件的入口。通過(guò)這個(gè)入口,我們可以很容易的在文件的父目錄下移動(dòng)。 [page_break]LIDS保護(hù)數(shù)據(jù)結(jié)構(gòu) 在分析完Linux文件系統(tǒng)后,讓我們來(lái)看看LIDS是如何容VFS來(lái)保護(hù)文件和目錄的。 在/usr/src/Linux/fs/lids.c 上面的結(jié)構(gòu)用一對(duì)來(lái)存儲(chǔ)保護(hù)文件或目錄的結(jié)點(diǎn)!皌ype”是用來(lái)標(biāo)明保護(hù)結(jié)點(diǎn)文件類(lèi)型的。 int lids_add_inode(unsigned long int inode ,kdev_t dev , int type) { if ( last_secure == (LIDS_MAX_INODE-1)) return 0; secure[last_secure].ino = inode; secure[last_secure].dev = dev; secure[last_secure].type = type; secure[++last_secure].ino = 0; #ifdef VFS_SECURITY_DEBUG printk("lids_add_inode : return %d ",last_secure); #endif return last_secure; } 就象你在上面代碼上可以看到的,給secure_ino加到一個(gè)結(jié)點(diǎn)上是非常容易的。被保護(hù)的結(jié)點(diǎn)會(huì)在系統(tǒng)啟動(dòng)的時(shí)候初使化。初使化程序在/usr/src/Linux/fs/lids.c的init_vfs_security()里。 int do_truncate(struct dentry *dentry, unsigned long length) { struct inode *inode = dentry->d_inode; int error; struct iattr newattrs; /* Not pretty: "inode->i_size" shouldnt really be "off_t". But it is. */ if ((off_t) length < 0) return -EINVAL; #ifdef CONFIG_LIDS if (lids_load && lids_local_load) { error = lids_check_base(dentry,LIDS_READONLY); if (error) { lids_security_alert("Try to truncate a protected file (dev %d %d,inode %ld)", MAJOR(dentry->d_inode->i_dev), MINOR(dentry->d_inode->i_dev), dentry->d_inode->i_ino); ..................... 這個(gè)是LIDS加到內(nèi)核里做檢測(cè)的一個(gè)例子。你會(huì)看到lids_check_base()是LIDS保護(hù)方法的一個(gè)核心函數(shù)。 int lids_check_base(struct dentry *base, int flag) { .................. inode = base->d_inode; /* get the inode number */ parent = base->d_parent; /* get the parent diretory */ ................. ----> do { if ( inode == parent->d_inode) break; if ((retval = lids_search_inode(inode))) { if ( retval == LIDS_IGNORE || (retval == LIDS_DEVICE && flag != LIDS_DEVICE)) break; if ( flag == LIDS_READONLY || ( flag == LIDS_APPEND && retval >flag ) || ( flag == LIDS_DEVICE && flag == retval )) { return -EROFS; } break; } inode = parent->d_inode; } while( ((parent = parent->d_parent ) != NULL) ); return 0; } lids_check_base()會(huì)檢查一個(gè)給定文件的dentry和它的父目錄是否被保護(hù)。 注意:如果它的父目錄被保護(hù),它下面的文件也會(huì)被保護(hù)。 [page_break]在內(nèi)核保護(hù)系統(tǒng)調(diào)用 為了保護(hù)系統(tǒng),LIDS會(huì)在一些檢查臨界的系統(tǒng)調(diào)用的時(shí)候做檢查。因此,我們可以保護(hù)系統(tǒng)調(diào)用和限制文件系統(tǒng)的用戶(hù)調(diào)用。 這些是一些例子, open(),open是通過(guò)禁止一些權(quán)利來(lái)保護(hù)文件的打開(kāi)。 你可以在打開(kāi)調(diào)用open_namei()調(diào)用的時(shí)候LIDS在檢測(cè)它。 mknod(),mknod是用來(lái)在指定目錄下保護(hù)mknod。 unlink(), 在內(nèi)核代碼檢查do_unlink()。 三、保護(hù)設(shè)備 Linux的設(shè)備會(huì)在/dev/目錄下以文件的形式列出,我們可以用上面保護(hù)文件的方法來(lái)保護(hù)設(shè)備。但是在一些情況下,用戶(hù)也可以用IO操作來(lái)旁路文件系統(tǒng)來(lái)讀寫(xiě)設(shè)備,我們必須注意這個(gè)問(wèn)題。 3.1 設(shè)備,內(nèi)核I/O 在GNU/Linux系統(tǒng)下的設(shè)備會(huì)以文件的形式表達(dá),所以我們可以用保護(hù)文件系統(tǒng)那樣來(lái)保護(hù)設(shè)備。 用戶(hù)的I/O訪(fǎng)問(wèn)是通過(guò)系統(tǒng)調(diào)用sys_operm和sys_iopl來(lái)實(shí)現(xiàn)的。你可以看看/usr/src/Linux/arch/i386/kernel/ioport.。這個(gè)是要基于系統(tǒng)結(jié)構(gòu)的,要是到其他平臺(tái),就需要注意它們的變化。 3.2 如何用LIDS來(lái)保護(hù) 大多數(shù)情況下,程序不需要通過(guò)在/dev的設(shè)備文件名稱(chēng)來(lái)訪(fǎng)問(wèn)設(shè)備。但是,一些特殊的程序需要直接訪(fǎng)問(wèn),如X Server,這個(gè)會(huì)寫(xiě)到/dev/mem和甚至是I/O設(shè)備。我們需要一些額外的東西來(lái)保護(hù)設(shè)備。LIDS會(huì)在配置內(nèi)核的時(shí)候來(lái)定義這個(gè)功能。 CONFIG_LIDS_ALLOW_DEV_MEM,如果你選擇了開(kāi)啟這個(gè)功能,你就可以允許一些特殊程序來(lái)訪(fǎng)問(wèn)/dev/men和/dev/kmen這些內(nèi)核臨界的設(shè)備。如果你想要用內(nèi)核的X Server,選擇這個(gè)功能就會(huì)在配置內(nèi)核的時(shí)候提供整個(gè)路徑和文件名。 CONFIG_LIDS_ALLOW_RAW_DISKS,如果選擇這個(gè)開(kāi)啟,你就可以允許一些特殊的程序來(lái)訪(fǎng)問(wèn)物理磁盤(pán)。 CONFIG_LIDS_ALLOW_IO_PORTS,如果你選擇了開(kāi)啟這個(gè)功能,你就可以允許一些特殊的程序來(lái)訪(fǎng)I/O端口。 當(dāng)系統(tǒng)運(yùn)行fs/lids.c里的init_vfs_security()的時(shí)候初使化就被調(diào)用。 #ifdef CONFIG_LIDS_ALLOW_DEV_MEM 如果一個(gè)進(jìn)程或是程序要直接訪(fǎng)問(wèn)ip端口或是磁盤(pán)設(shè)備,LIDS就會(huì)檢查它在數(shù)組 allow_raw_disk,last_io_ports,等)。這個(gè)檢查是通過(guò)調(diào)用lids_check_base()里的lids_search_inode(inode)來(lái)實(shí)現(xiàn)的。 #ifdef CONFIG_LIDS_ALLOW_DEV_MEM for( i = 0 ; i < last_dev_mem ;i++ ) { if ( allow_dev_mem[i].ino == ino && allow_dev_mem[i].dev == dev) { return LIDS_READONLY; } } #endif #ifdef CONFIG_LIDS_ALLOW_RAW_DISKS 在allow_dev_mem包括了哪一個(gè)程序結(jié)點(diǎn)在系統(tǒng)啟動(dòng)的時(shí)候在init_vfs_security()里初使化。用同樣的方法,除了一些特殊程序,我們可以保護(hù)設(shè)備,I/O訪(fǎng)問(wèn)等等。 asmlinkage int sys_kill(int pid, int sig) { struct siginfo info; #ifdef CONFIG_LIDS_INIT_CHILDREN_LOCK pid_t this_pid; int i; #ifdef CONFIG_LIDS_ALLOW_KILL_INIT_CHILDREN if (!(current->flags & PF_KILLINITC)) #endif if (lids_load && lids_local_load && LIDS_FISSET(lids_flags,LIDS_FLAGS_LOCK_INIT_CHILDREN)) { this_pid = pid>0?pid:-pid; for(i=0;i if( this_pid == lids_protected_pid[i]) { lids_security_alert("Try to kill pid=%d,sig=%d ",pid,sig); return -EPERM; } } } #endif ... } 你可以在內(nèi)核里看到兩個(gè)標(biāo)簽,,CONFIG_LIDS_INIT_CHILDREN_LOCK 和CONFIG_LIDS_ALLOW_KILL_INIT_CHILDREN. 在CONFIG_LIDS_INIT_CHILDREN_LOCK的開(kāi)啟狀態(tài),LIDS能保護(hù)初使的運(yùn)行程序。如,如果你在系統(tǒng)里運(yùn)行inetd程序,你可以在隱藏內(nèi)核前運(yùn)行它,然后,你還可以殺死它。但是一些人如果telnet到你的機(jī)器,inetd就會(huì)創(chuàng)造子進(jìn)程來(lái)為用戶(hù)服務(wù),這個(gè)子進(jìn)程不會(huì)被LIDS保護(hù),因?yàn)橛脩?hù)在任何時(shí)候退出和殺死程序。 [page_break]4.2 隱藏進(jìn)程 另外一個(gè)保護(hù)進(jìn)程的方法就是隱藏進(jìn)程。當(dāng)一個(gè)黑客危機(jī)你的系統(tǒng)。他會(huì)登陸,然后會(huì)看看有沒(méi)有一些已知的進(jìn)程在監(jiān)視它。然后他就殺死它。如果你隱藏了這個(gè)功能的進(jìn)程,黑客就不會(huì)知道進(jìn)程的所有情況并且你可以記錄他在你系統(tǒng)上做的任何事情。 如何隱藏進(jìn)程 為了隱藏進(jìn)程,你必須在配置內(nèi)核的時(shí)候提供一個(gè)完全的路徑名。 當(dāng)內(nèi)核啟動(dòng)的時(shí)候,LIDS會(huì)訪(fǎng)問(wèn)文件結(jié)點(diǎn)到一個(gè)叫proc_to_hide[]的結(jié)構(gòu)里。 在include/Linux/sched.h里 PF_HIDDEN是否用戶(hù)可以用顯示進(jìn)程的命令(如“ps –a”)來(lái)顯示和檢查進(jìn)程,如果一個(gè)進(jìn)程被LIDS隱藏,當(dāng)他執(zhí)行的時(shí)候,進(jìn)程就會(huì)得到一個(gè)PF_HIDDEN的屬性。然后,當(dāng)系統(tǒng)輸出系統(tǒng)進(jìn)程信息到用戶(hù)的時(shí)候,它就會(huì)可以檢查當(dāng)前輸出進(jìn)程是否有PF_HIDDEN標(biāo)志。如果發(fā)現(xiàn)了,它就不會(huì)輸出這個(gè)進(jìn)程的信息。 int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs) { ... if (retval >= 0) { #ifdef CONFIG_LIDS_HIDE_PROC if (lids_search_proc_to_hide(dentry->d_inode)) current->flags |= PF_HIDDEN; ... 因?yàn)槊恳粋(gè)Linux的進(jìn)程都有一個(gè)在/proc文件系統(tǒng)的入口,我們?yōu)榱穗[藏進(jìn)程也需要修改proc的文件入口。 static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry) { ... inode = NULL; #ifdef CONFIG_LIDS_HIDE_PROC if ( pid && p && (! ((p->flags & PF_HIDDEN) && lids_load && lids_local_load)) ) { #else if (pid && p) { #endif unsigned long ino = (pid >> 16) + PROC_PID_INO; inode = proc_get_inode(dir->i_sb, ino, &proc_pid); if (!inode) return ERR_PTR(-EINVAL); inode->i_flags|=S_IMMUTABLE; } ... } 然后如果進(jìn)程被PF_HIDDEN標(biāo)記,它就不會(huì)在proc文件系統(tǒng)里顯示。 網(wǎng)絡(luò)的神奇作用吸引著越來(lái)越多的用戶(hù)加入其中,正因如此,網(wǎng)絡(luò)的承受能力也面臨著越來(lái)越嚴(yán)峻的考驗(yàn)―從硬件上、軟件上、所用標(biāo)準(zhǔn)上......,各項(xiàng)技術(shù)都需要適時(shí)應(yīng)勢(shì),對(duì)應(yīng)發(fā)展,這正是網(wǎng)絡(luò)迅速走向進(jìn)步的催化劑。 |
溫馨提示:喜歡本站的話(huà),請(qǐng)收藏一下本站!