荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: hellsolaris (qq), 信区: Security
标  题: LIDS精通与进阶(下)
发信站: 荔园晨风BBS站 (Sat Nov  1 12:54:11 2003), 站内信件

七、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":"s
tops");
init_vfs_security();
#endif
......
}
    在系统启动的时候,你可以看到”Linux Intrusion Detection System 0.9 start
s”,表明LIDS的保护开启了。当保护停止的时候,你可以看到”Linux Intrusion Dete
ction System 0.9 stops”。这里的0.9是当前的LIDS版本号。
    2、用lidsadm来改变系统安全级别
    一些时候,有也可以在线的时候改变你的安全级别,你必须把CONFIG_LIDS_ALLOW_
SWITCH功能开启。并且在编译前配置内核的时候提供一个RipeMD-160 encrypted passw
ord 。
    这个密码可以用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_proc
ess_flag的代码来了解它。
    转换LIDS和LIDA_GLOBAL
    如果你把LIDS的保护关闭,你会有两个结果,一,关闭后其它没有被LIDS保护的控
制台一样不受保护,二,可以本地的关闭它们,在其它的控制台,所有的系统依然被LI
DS保护。它们一样很安全。
    这些细节是fs/lids的lids_process_flag()来实现。
八、内核的网络安全
    用LIDS,你可以用下面的功能来保护你的网络。
    1、保护防火墙和路由的规则
    如果你的主机包含一些防火墙规则。你可以用LIDS来保护它们。你可以开启CONFIG
_LIDS_ALLOW_CHANGE_ROUTESLAI 实现这个功能。你也必须在密封内核的时候关闭CAP_N
ET_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 rule
s with option %d",optname);
#endif
return -EACCES;
}
........
    从上面的代码,我们可以看到如果有人要改变防火墙的规则,你必须把CAP_NET_AD
MIN开启,并且你要修改规则的程序必须用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_ch
eck_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开发的。用这个工具,我们可以很容易的知道系统什么地方出错,
我们可以及时的响应入侵。


--
※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.44.223]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店