注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

蒙奇D小豌豆的博客

蒙奇D小豌豆的学习记录

 
 
 

日志

 
 

Linux capability  

2012-06-10 20:30:05|  分类: userspace |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

Linux给普通用户尽可能低的权限,而把全部的系统权限赋予一个单一的帐户--rootroot帐户用来管理系统、安装软件、管理帐户、运行某些服务、安装/卸载文件系统、管理用户、安装软件等。这种依赖单一帐户执行特权操作的方式加大了系统的面临风险,而需要root权限的程序可能只是为了一个单一的操作,。例如,一个普通用户需要使用ping命令。这是一个SUID命令,会以root的权限运行。而实际上这个程序只是需要RAW套接字建立必要ICMP数据包,除此之外的其它root权限对这个程序都是没有必要的。如果程序编写不好,就可能被攻击者利用,获得系统的控制权。

Linux针对上述问题提出capability,将内核系统资源访问划分为许多的权利属性。使用能力(capability)可以减小这种风险。系统管理员为了系统的安全可以剥夺root权限程序的某些capability,这样即使该进程也将无法进行这些capability的操作。而这个过程又是不可逆的,也就是说如果一种能力被删除,无法重新添加被删除的能力。一个root进程在没有设置capability的时候,所有权利属性默认开启。当一个root进程通过运行execv类型的函数加载新的进程后,进程重新获取所有capability

Linux所特有的,这些能力在/usr/src/linux/include/linux/capability.h文件中定义。其细节如下:

CAP_CHOWN 0 允许改变文件的所有权

CAP_DAC_OVERRIDE 1 忽略对文件的所有DAC访问限制

CAP_DAC_READ_SEARCH 2 忽略所有对读、搜索操作的限制

。。。。。。。

       我们通过lcap库来实现root程序的权限分离:

Static int set_capabilities(cap_value_t cap_list[], int ncap)

{

       cap_t caps;

       int ret;

 

       /* caps should be initialized with all flags cleared... */

       caps = cap_init();

       if (!caps)

       {

              perror("cap_init");

              return -1;

       }

       /* ... but we better rely on cap_clear */

       if (cap_clear(caps))

       {

              perror("cap_clear");

              return -1;

       }

 

       if ((cap_list) && ncap)

       {

              if (cap_set_flag(caps, CAP_PERMITTED, ncap, cap_list, CAP_SET) != 0)

              {

                     perror("cap_set_flag CAP_PERMITTED");

                     cap_free(caps);

                     return -1;

              }

              if (cap_set_flag(caps, CAP_EFFECTIVE, ncap, cap_list, CAP_SET) != 0)

              {

                     perror("cap_set_flag CAP_EFFECTIVE");

                     cap_free(caps);

                     return -1;

              }

              if (cap_set_flag(caps, CAP_INHERITABLE, ncap, cap_list, CAP_SET) != 0)

              {

                     perror("cap_set_flag CAP_INHERITABLE");

                     cap_free(caps);

                     return -1;

              }

             

       }

 

       ret = cap_set_proc(caps);

 

       if (ret)

       {

              perror("cap_set_proc");

              cap_free(caps);

              return -1;

       }

 

       if (cap_free(caps))

       {

              perror("cap_free");

              return -1;

       }

 

       return 0;

}

 

Static int drop_capabilities(cap_value_t cap_list[], int ncap)

{

       cap_t caps;

       int ret;

 

       /* caps should be initialized with all flags cleared... */

       caps = cap_get_proc();

       if (!caps)

       {

              perror("cap_init");

              return -1;

       }

 

       if ((cap_list) && ncap)

       {

              if (cap_set_flag(caps, CAP_EFFECTIVE, ncap, cap_list, CAP_CLEAR) != 0)

              {

                     perror("cap_set_flag CAP_PERMITTED");

                     cap_free(caps);

                     return -1;

              }

              if (cap_set_flag(caps, CAP_PERMITTED, ncap, cap_list, CAP_CLEAR) != 0)

              {

                     perror("cap_set_flag CAP_EFFECTIVE");

                     cap_free(caps);

                     return -1;

              }

              if (cap_set_flag(caps, CAP_INHERITABLE, ncap, cap_list, CAP_CLEAR) != 0)

              {

                     perror("cap_set_flag CAP_INHERITABLE");

                     cap_free(caps);

                     return -1;

              }

       }

 

       ret = cap_set_proc(caps);

 

       if (ret)

       {

              perror("cap_set_proc");

              cap_free(caps);

              return -1;

       }

 

       return 0;

}

int main()

{

      

       int ch, ret = -1;

       cap_value_t cap_list[2];

       cap_t caps;

       cap_value_t drop_cap[2];

 

 

       /* capabilities we need */

       cap_list[0] = CAP_SETUID;

       cap_list[1] = CAP_NET_RAW;

 

       //set the cap we need

       if (set_capabilities(cap_list, sizeof(cap_list)/sizeof(cap_list[0])))

       {

              fprintf(stderr, "Could not adjust capabilities, aborting\n");

              return EXIT_FAILURE;

       }

 

       ret = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);

       assert(ret != -1);

       printf("ok, run raw socket sucessful\n");

 

       drop_cap[0] = CAP_SETUID;

       drop_cap[1] = CAP_NET_RAW;

 

       // drop the caps above

       if (drop_capabilities(drop_cap, sizeof(drop_cap)/sizeof(drop_cap[0])))

       {

              fprintf(stderr, "Could not adjust capabilities, aborting\n");

              return EXIT_FAILURE;

       }

      

       // must be can not raw socket ecause of the drop CAP_NET_RAW

       ret = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);

       assert(ret == -1);

 

       printf("ok, run raw socket failed\n");

      return 0;

}

gcc  –o  cap cap.c  -lcap

使用root用户运行cap程序,发现在设置了 CAP_NET_RAW时候程序能够进行raw socket操作,当drop掉它的时候系统不允许。

  评论这张
 
阅读(1362)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018