作者:
[email protected]
七、LIDS在內核中的安全級別
一些時候,我們需要改變保護系統的配置。那樣我們該怎麼做呢?LIDS給我們提供了兩種方法。
我們可以重新啟動系統,在LILO:裡鍵入security=0.
我們可以在用lidsadm –S中用密碼來轉換安全級別。
1、在內核中的兩個安全級別
LIDS在內核中定義了兩個安全級別,安全的security和無安全的none_security.默認情況下,是設置成安全的級別。如果你需要改變它。就在啟動的時候鍵入security=0.
在內核中有一個全局變量lids_load。它表明是否lids的安全變量security被開啟。它默認是1。如果在系統啟動的時候在LILO:鍵入security=0 ,所有的LIDS的保護都會失效,就象那些沒有LIDS保護的系統一樣。
/* variant defined in fs/lids.c */
int lids_reload_conf=0;
int lids_load=0; /* it is raised to 1 when kernel boot */
int lids_local_on=1;
int lids_local_pid=0;
/* in init/main.c */
#ifdef CONFIG_LIDS
/*
* lids_setup , read lids info from the kernel.
*/
static void __init lids_setup(char *str, int *ints)
{
if (ints[0] > 0 && ints[1] >= 0)
====> _lids_load= ints[1];
}
#endif
....
/* init the LIDS when the system bootup up */
static void __init do_basic_setup(void)
{
......
/* Mount the root filesystem.. */
mount_root();
#ifdef CONFIG_LIDS
/* init the ids file system */
---> lids_load=_lids_load;
lids_local_on=_lids_load;
lids_flags=lids_load * (LIDS_FLAGS_LIDS_ON LIDS_FLAGS_LIDS_LOCAL_ON);
===> printk("Linux Intrusion Detection System %s n",lids_load==1?"starts":"stops");
init_vfs_security();
#endif
......
}
在系統啟動的時候,你可以看到”Linux Intrusion Detection System 0.9 starts”,表明LIDS的保護開啟了。當保護停止的時候,你可以看到”Linux Intrusion Detection System 0.9 stops”。這裡的0.9是當前的LIDS版本號。
2、用lidsadm來改變系統安全級別
一些時候,有也可以在線的時候改變你的安全級別,你必須把CONFIG_LIDS_ALLOW_SWITCH功能開啟。並且在編譯前配置內核的時候提供一個RipeMD-160 encrypted passWord 。
這個密碼可以用lidsadm –p 命令來獲得
用內核鑒定
用提供的密碼,LIDS可以鑒定用戶來區分哪個用戶可以轉換內核的安全級別。
這個功能也要用到lidsadm的-S參數。如。
# /sbin/lidsadm -S -- -LIDS
SWITCH
Password:xxxxxx
#
在輸入密碼後,我們就可以轉換LIDS的安全關閉。
讓我們看看內部的編碼來了解它是如何工作的,
/* in the fs/lids.c lids_proc_locks_sysctl() */
int lids_proc_locks_sysctl(ctl_table *table, int write, strUCt file *filp,
void *buffer, size_t *lenp, int conv, int op)
{
lids_locks_t locks;
byte hashcode[RMDsize/8];
char rmd160sig[170];
.......
locks.passwd[sizeof(passwd_t)-1]=0; /* We don't take the risk */
rmd160sig[0]=0;
#ifdef CONFIG_LIDS_ALLOW_SWITCH
if ((!lids_first_time) (locks.passwd[0])) {
RMD((byte *)locks.passwd,hashcode);
memset((char *)locks.passwd,'',sizeof(passwd_t));
for (i=0; i
sprintf(rmd160sig+2*i,"%02x", hashcode[i]);
}
if ( ((lids_first_time) && (!locks.passwd[0]))
----------> (!strncmp(rmd160sig,CONFIG_LIDS_RMD160_PASSWD,160)) ) {
#else
if ((lids_first_time) && (!locks.passwd[0])) {
#endif
/* Access granted ! */
number_failed=0;
if (lids_process_flags(locks.flags)) {
cap_bset=locks.cap_bset;
lids_security_alert("Changed: cap_bset=0x%x lids_flags=0x%x",cap_t(cap_bset),lids_flags);
}
lids_first_time=0;
}
........
}
在密碼檢查正確後。Lids_process_flag()就會改變當前的lids標記為關閉狀態,然後你就可以在不受保護的系統做你想要做的事情了。你可以看看fs/lids.c的lids_process_flag的代碼來了解它。
轉換LIDS和LIDA_GLOBAL
如果你把LIDS的保護關閉,你會有兩個結果,一,關閉後其它沒有被LIDS保護的控制台一樣不受保護,二,可以本地的關閉它們,在其它的控制台,所有的系統依然被LIDS保護。它們一樣很安全。
這些細節是fs/lids的lids_process_flag()來實現。
八、內核的網絡安全
用LIDS,你可以用下面的功能來保護你的網絡。
1、保護防火牆和路由的規則
如果你的主機包含一些防火牆規則。你可以用LIDS來保護它們。你可以開啟CONFIG_LIDS_ALLOW_CHANGE_ROUTESLAI 實現這個功能。你也必須在密封內核的時候關閉CAP_NET_ADMIN。
然後,你也可以允許程序更改路由規則。
讓我們來看看保護防火牆規則的代碼吧。每一個改變防火牆的請求都會調用內核的ip_setsockopt()函數。
int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen)
{
........
switch(optname)
{
.......
case IP_FW_DELETE_NUM:
case IP_FW_INSERT:
case IP_FW_FLUSH:
case IP_FW_ZERO:
case IP_FW_CHECK:
case IP_FW_CREATECHAIN:
case IP_FW_DELETECHAIN:
case IP_FW_POLICY:
#ifdef CONFIG_LIDS_ALLOW_CHANGE_ROUTES
if (!(capable(CAP_NET_ADMIN) (current->flags & PF_CHROUTES))) {
#else
if (!capable(CAP_NET_ADMIN)) {
#endif
#ifdef CONFIG_LIDS
lids_security_alert("CAP_NET_ADMIN violation: try to change IP firewall rules with option %d",optname);
#endif
return -EACCES;
}
........
從上面的代碼,我們可以看到如果有人要改變防火牆的規則,你必須把CAP_NET_ADMIN開啟,並且你要修改規則的程序必須用routing_changeable來標記。
2、禁止嗅探
這個功能也是在上面的changing_route來實現的。讓我們來看看net/core/dev.c的代碼。
int dev_ioctl(unsigned int cmd, void *arg)
{
........
switch(cmd)
{
........
case SIOCSIFMETRIC:
case SIOCSIFMTU:
case SIOCSIFMAP:
case SIOCSIFHWADDR:
case SIOCSIFSLAVE:
case SIOCADDMULTI:
case SIOCDELMULTI:
case SIO
2、禁止嗅探
這個功能也是在上面的changing_route來實現的。讓我們來看看net/core/dev.c的代碼。
int dev_ioctl(unsigned int cmd, void *arg)
{
........
switch(cmd)
{
........
case SIOCSIFMETRIC:
case SIOCSIFMTU:
case SIOCSIFMAP:
case SIOCSIFHWADDR:
case SIOCSIFSLAVE:
case SIOCADDMULTI:
case SIOCDELMULTI:
case SIO
{
........
case SIOCSIFMETRIC:
case SIOCSIFMTU:
case SIOCSIFMAP:
case SIOCSIFHWADDR:
case SIOCSIFSLAVE:
case SIOCADDMULTI:
case SIOCDELMULTI:
case SIO