欢迎光临
我们一直在努力

LIDS精通与进阶(下)

建站超值云服务器,限时71元/月

作者:chaobowang@sina.com

七、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 dont 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 siocsifhwbroadcast:

case siocsiftxqlen:

case siocsifname:

#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: ioctl sioc #%i",cmd);

#endif

return -eperm;

………

    你能发现,如果你要为嗅探改变状态的话, 你必须让cap_net_admin开启来实现这个功能。你可以在内核密封前启动cap_net_admin,然后在内核密封后禁止它。

    3、内核的检测端口扫描的功能

    为什么要在内核里需要一个端口扫描的检测?

    因为一个端口扫描的时候能检测到半连接的扫描。所以,端口扫描检测需要作为一个嗅探的程序来运行。如果我们需要检测端口扫描。我们又要开启允许嗅探程序的运行,在内核中的端口扫描检测很有用处。

    端口扫描的主要思想是在一段短的时间内扫描一个范围的端口,然后,它们会在扫描后记录那些端口是开放的。用这个方法,扫描器就可以检测到远端的机器开放了什么端口。在内核里,我们能发现下面的代码。

    内核中的端口扫描检测

    让我们看看tcp的端口扫描

/* in net/ipv4/tcp_ipv4.c */

int tcp_v4_rcv(struct sk_buff *skb, unsigned short len)

{

……..

__skb_queue_tail(&sk->back_log, skb);

return 0;

no_tcp_socket:

#ifdef config_lids

lids_check_scan(skb->nh.iph->saddr,ntohs(th->dest));

#endif

tcp_v4_send_reset(skb);

discard_it:

………

}

    lids_check_scan()有两个参数,一个是影响no_sock_srror的源地址,另外一个是你要通讯的机器上的端口。

    lids_check_scan()主要的任务是统计由同一个资源发出的错误信息。但是lids_check_scan()在源地址是一个端口扫描器的时候不会做检查,它会要timer来做。现在,让我们看看lids_check_scan()的代码。

/* in net/ipv4/lids_check_scan.c */

int lids_check_scan(__u32 addr,__u16 port)

{

………..

if((p = lids_find_scan(addr)) == null) {

p1 = &lids_scan_head;

p = (struct lids_scan*)kmalloc(sizeof(struct lids_scan),gfp_atomic);

if(p == null ) {

return -1;

}

while((p1->next)!=null)p1=p1->next;

/* init the structure. */

p1->next = p;

spin_unlock(p->lock);

p->next = null;

p->addr = addr;

p->counter = 0;

p->lower_counter = 0;

p->create_time = current_time;

/* init a timer to do the detect thing */

init_timer(&(p->timer));

p->timer.expires = lids_scan_timeout + current_time;

p->timer.data = (unsigned long) p;

p->timer.function = lids_proceed_scan ;

add_timer(&(p->timer));

}

/* add the counter when hit */

spin_lock(p->lock);

(p->counter)++;

/* we here defined the port < 1024 and > 1024 */

if(port < 1024)

(p->lower_counter)++;

spin_unlock(p->lock);

return 0;

}

    从上面的代码,我们能看到这个函数的主要是一个列表,所以它很快。为了防止在kmalloc()的dos的攻击,我们也需要来限制检测的列表。在这个代码里可能是错误的,但是因为记时的函数timer lids_proceed_scan能非常快的更新这个列表(每3秒一次)。所以dos攻击很难让内核迷惑扫描源的真实性

九、入侵响应系统

    当我们检测到了一些程序违反了我们定的规则,我们必须要对它做出响应。在当前的lids系统,我们可以用记录的功能来记录下所有的信息。我们也可以挂起这个用户用到的控制台。然后,我们就会给lids加上更多的响应系统,不但是在内核里,还是在用户区。

    1、允许用安全的方法登陆

    在传统的内核登陆模式,我们每次都是用printk在控制台打印信息。但是这样很容易会被dos攻击内核。他会让系统频繁的运行printk命令,我们可以在内核用security_alert()来实现报警响应功能。

    你可以看看/include/linux/kernel.h的代码。

    2、控制台挂起

    这个功能是用安全日志来挂起那些违反lids定义的安全规则的人的控制台。他们要继续必须重新登陆系统。但是他们所做的一切都已经被系统日志记录下来或是用e-mail的方法发送给了管理员。

    3、用e-mail或是传呼来报告管理员

    这个功能是boidi开发的。用这个工具,我们可以很容易的知道系统什么地方出错,我们可以及时的响应入侵。

    这些就是大概的lids的基本原理,它可能很多的涉及到了内核模块的编程。这个方面内容,大家可以到chinabyte的linux专区,那里有coolboy的关于可加载模块lkm的资料。很cool。 有什么问题,也可以e-mail给我chaobowang@sina.com。

赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 » LIDS精通与进阶(下)
分享到: 更多 (0)