科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网安全频道网络安全linux下的入侵监测系统LIDS原理 (3)

linux下的入侵监测系统LIDS原理 (3)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

 一些时候,我们需要改变保护系统的配置。那样我们该怎么做呢?LIDS给我们提供了两种方法。

来源:zdnet整理 2010年6月6日

关键字: 网络入侵 linux安全

  • 评论
  • 分享微博
  • 分享邮件

  七.LIDS在内核中的安全级别

  一些时候,我们需要改变保护系统的配置。那样我们该怎么做呢?LIDS给我们提供了两种方法。

  l 我们可以重新启动系统,在LILO:里键入security=0.

  l 我们可以在用lidsadm –S中用密码来转换安全级别。

  7.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版本号。

  7.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,你可以用下面的功能来保护你的网络。

  8.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来标记。

  8.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,然后在内核密封后禁止它。

  8.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攻击很难让内核迷惑扫描源的真实性。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章